Thanks to visit codestin.com
Credit goes to chromium.googlesource.com

blob: 02a4d84e46c1600cc32044791d8cef356c8dc15e [file] [log] [blame]
drh75897232000-05-29 14:26:001/*
drhb19a2bc2001-09-16 00:13:262** 2001 September 15
drh75897232000-05-29 14:26:003**
drhb19a2bc2001-09-16 00:13:264** The author disclaims copyright to this source code. In place of
5** a legal notice, here is a blessing:
drh75897232000-05-29 14:26:006**
drhb19a2bc2001-09-16 00:13:267** May you do good and not evil.
8** May you find forgiveness for yourself and forgive others.
9** May you share freely, never taking more than you give.
drh75897232000-05-29 14:26:0010**
11*************************************************************************
drhbd08af42007-04-05 21:58:3312** A TCL Interface to SQLite. Append this file to sqlite3.c and
13** compile the whole thing to build a TCL-enabled version of SQLite.
drh57a02272009-10-22 20:52:0514**
15** Compile-time options:
16**
drh96a206f2017-10-13 20:14:0617** -DTCLSH Add a "main()" routine that works as a tclsh.
drh57a02272009-10-22 20:52:0518**
drh96a206f2017-10-13 20:14:0619** -DTCLSH_INIT_PROC=name
drh57a02272009-10-22 20:52:0520**
drh96a206f2017-10-13 20:14:0621** Invoke name(interp) to initialize the Tcl interpreter.
22** If name(interp) returns a non-NULL string, then run
23** that string as a Tcl script to launch the application.
24** If name(interp) returns NULL, then run the regular
25** tclsh-emulator code.
drh75897232000-05-29 14:26:0026*/
drh96a206f2017-10-13 20:14:0627#ifdef TCLSH_INIT_PROC
28# define TCLSH 1
29#endif
mistachkin27b2f052015-01-12 19:49:4630
31/*
32** If requested, include the SQLite compiler options file for MSVC.
33*/
34#if defined(INCLUDE_MSVC_H)
mistachkin52b1dbb2016-07-28 14:37:0435# include "msvc.h"
mistachkin27b2f052015-01-12 19:49:4636#endif
37
drhe388fc72024-07-31 10:59:1938/****** Copy of tclsqlite.h ******/
39#if defined(INCLUDE_SQLITE_TCL_H)
40# include "sqlite_tcl.h" /* Special case for Windows using STDCALL */
41#else
drh5addf9f2024-07-31 22:25:2542# include <tcl.h> /* All normal cases */
drhe388fc72024-07-31 10:59:1943# ifndef SQLITE_TCLAPI
44# define SQLITE_TCLAPI
45# endif
46#endif
47/* Compatability between Tcl8.6 and Tcl9.0 */
48#if TCL_MAJOR_VERSION==9
49# define CONST const
drh76e48f42024-10-22 16:19:1450#elif !defined(Tcl_Size)
drhe388fc72024-07-31 10:59:1951 typedef int Tcl_Size;
stephan10206572025-05-31 11:02:0652# ifndef Tcl_BounceRefCount
53# define Tcl_BounceRefCount(X) Tcl_IncrRefCount(X); Tcl_DecrRefCount(X)
54 /* https://www.tcl-lang.org/man/tcl9.0/TclLib/Object.html */
55# endif
drhe388fc72024-07-31 10:59:1956#endif
57/**** End copy of tclsqlite.h ****/
58
danielk1977b4e9af92007-05-01 17:49:4959#include <errno.h>
drhbd08af42007-04-05 21:58:3360
61/*
62** Some additional include files are needed if this file is not
63** appended to the amalgamation.
64*/
65#ifndef SQLITE_AMALGAMATION
drh65e8c822009-12-01 13:57:4866# include "sqlite3.h"
drhbd08af42007-04-05 21:58:3367# include <stdlib.h>
68# include <string.h>
69# include <assert.h>
drh65e8c822009-12-01 13:57:4870 typedef unsigned char u8;
drh8e5cef72023-06-17 15:42:4471# ifndef SQLITE_PTRSIZE
72# if defined(__SIZEOF_POINTER__)
73# define SQLITE_PTRSIZE __SIZEOF_POINTER__
74# elif defined(i386) || defined(__i386__) || defined(_M_IX86) || \
75 defined(_M_ARM) || defined(__arm__) || defined(__x86) || \
76 (defined(__APPLE__) && defined(__POWERPC__)) || \
77 (defined(__TOS_AIX__) && !defined(__64BIT__))
78# define SQLITE_PTRSIZE 4
79# else
80# define SQLITE_PTRSIZE 8
81# endif
82# endif /* SQLITE_PTRSIZE */
jan.nijtmans1f3207a2025-03-27 17:30:4983# if defined(HAVE_STDINT_H) || (defined(__STDC_VERSION__) && \
84 (__STDC_VERSION__ >= 199901L))
85# include <stdint.h>
drh8e5cef72023-06-17 15:42:4486 typedef uintptr_t uptr;
87# elif SQLITE_PTRSIZE==4
88 typedef unsigned int uptr;
89# else
90 typedef sqlite3_uint64 uptr;
91# endif
drhbd08af42007-04-05 21:58:3392#endif
drheb206382009-10-24 15:51:3393#include <ctype.h>
drh75897232000-05-29 14:26:0094
mistachkin1f28e072013-08-15 08:06:1595/* Used to get the current process ID */
96#if !defined(_WIN32)
mistachkin1e8487d2018-07-22 06:25:3597# include <signal.h>
mistachkin1f28e072013-08-15 08:06:1598# include <unistd.h>
99# define GETPID getpid
100#elif !defined(_WIN32_WCE)
101# ifndef SQLITE_AMALGAMATION
mistachkin176b3a02018-01-23 07:11:05102# ifndef WIN32_LEAN_AND_MEAN
103# define WIN32_LEAN_AND_MEAN
104# endif
mistachkin1f28e072013-08-15 08:06:15105# include <windows.h>
106# endif
mistachkin1e8487d2018-07-22 06:25:35107# include <io.h>
108# define isatty(h) _isatty(h)
mistachkin1f28e072013-08-15 08:06:15109# define GETPID (int)GetCurrentProcessId
110#endif
111
drhad6e1372006-07-10 21:15:51112/*
113 * Windows needs to know which symbols to export. Unix does not.
114 * BUILD_sqlite should be undefined for Unix.
115 */
116#ifdef BUILD_sqlite
117#undef TCL_STORAGE_CLASS
118#define TCL_STORAGE_CLASS DLLEXPORT
119#endif /* BUILD_sqlite */
drh29bc4612005-10-05 10:40:15120
danielk1977a21c6b62005-01-24 10:25:59121#define NUM_PREPARED_STMTS 10
drhfb7e7652005-01-24 00:28:42122#define MAX_PREPARED_STMTS 100
123
drhc45e6712012-10-03 11:02:33124/* Forward declaration */
125typedef struct SqliteDb SqliteDb;
drh98808ba2001-10-18 12:34:46126
127/*
drhcabb0812002-09-14 13:47:32128** New SQL functions can be created as TCL scripts. Each such function
129** is described by an instance of the following structure.
dan89d24932019-02-27 16:38:19130**
131** Variable eType may be set to SQLITE_INTEGER, SQLITE_FLOAT, SQLITE_TEXT,
132** SQLITE_BLOB or SQLITE_NULL. If it is SQLITE_NULL, then the implementation
133** attempts to determine the type of the result based on the Tcl object.
134** If it is SQLITE_TEXT or SQLITE_BLOB, then a text (sqlite3_result_text())
135** or blob (sqlite3_result_blob()) is returned. If it is SQLITE_INTEGER
136** or SQLITE_FLOAT, then an attempt is made to return an integer or float
137** value, falling back to float and then text if this is not possible.
drhcabb0812002-09-14 13:47:32138*/
139typedef struct SqlFunc SqlFunc;
140struct SqlFunc {
141 Tcl_Interp *interp; /* The TCL interpret to execute the function */
drhd1e47332005-06-26 17:55:33142 Tcl_Obj *pScript; /* The Tcl_Obj representation of the script */
drhc45e6712012-10-03 11:02:33143 SqliteDb *pDb; /* Database connection that owns this function */
drhd1e47332005-06-26 17:55:33144 int useEvalObjv; /* True if it is safe to use Tcl_EvalObjv */
dan89d24932019-02-27 16:38:19145 int eType; /* Type of value to return */
drhd1e47332005-06-26 17:55:33146 char *zName; /* Name of this function */
drhcabb0812002-09-14 13:47:32147 SqlFunc *pNext; /* Next function on the list of them all */
148};
149
150/*
danielk19770202b292004-06-09 09:55:16151** New collation sequences function can be created as TCL scripts. Each such
152** function is described by an instance of the following structure.
153*/
154typedef struct SqlCollate SqlCollate;
155struct SqlCollate {
156 Tcl_Interp *interp; /* The TCL interpret to execute the function */
157 char *zScript; /* The script to be run */
drhd1e47332005-06-26 17:55:33158 SqlCollate *pNext; /* Next function on the list of them all */
danielk19770202b292004-06-09 09:55:16159};
160
161/*
drhfb7e7652005-01-24 00:28:42162** Prepared statements are cached for faster execution. Each prepared
163** statement is described by an instance of the following structure.
164*/
165typedef struct SqlPreparedStmt SqlPreparedStmt;
166struct SqlPreparedStmt {
167 SqlPreparedStmt *pNext; /* Next in linked list */
168 SqlPreparedStmt *pPrev; /* Previous on the list */
169 sqlite3_stmt *pStmt; /* The prepared statement */
170 int nSql; /* chars in zSql[] */
danielk1977d0e2a852007-11-14 06:48:48171 const char *zSql; /* Text of the SQL statement */
dan4a4c11a2009-10-06 14:59:02172 int nParm; /* Size of apParm array */
173 Tcl_Obj **apParm; /* Array of referenced object pointers */
drhfb7e7652005-01-24 00:28:42174};
175
danielk1977d04417962007-05-02 13:16:30176typedef struct IncrblobChannel IncrblobChannel;
177
drhfb7e7652005-01-24 00:28:42178/*
drhbec3f402000-08-04 13:49:02179** There is one instance of this structure for each SQLite database
180** that has been opened by the SQLite TCL interface.
danc431fd52011-06-27 16:55:50181**
182** If this module is built with SQLITE_TEST defined (to create the SQLite
183** testfixture executable), then it may be configured to use either
184** sqlite3_prepare_v2() or sqlite3_prepare() to prepare SQL statements.
185** If SqliteDb.bLegacyPrepare is true, sqlite3_prepare() is used.
drhbec3f402000-08-04 13:49:02186*/
drhbec3f402000-08-04 13:49:02187struct SqliteDb {
drhdddca282006-01-03 00:33:50188 sqlite3 *db; /* The "real" database structure. MUST BE FIRST */
drhd1e47332005-06-26 17:55:33189 Tcl_Interp *interp; /* The interpreter used for this database */
190 char *zBusy; /* The busy callback routine */
191 char *zCommit; /* The commit hook callback routine */
192 char *zTrace; /* The trace callback routine */
mistachkinb56660f2016-07-14 21:26:09193 char *zTraceV2; /* The trace_v2 callback routine */
drh19e2d372005-08-29 23:00:03194 char *zProfile; /* The profile callback routine */
drhd1e47332005-06-26 17:55:33195 char *zProgress; /* The progress callback routine */
drhc06ede12019-02-28 17:29:19196 char *zBindFallback; /* Callback to invoke on a binding miss */
drhd1e47332005-06-26 17:55:33197 char *zAuth; /* The authorization callback routine */
drh1f1549f2008-08-26 21:33:34198 int disableAuth; /* Disable the authorizer if it exists */
drhd1e47332005-06-26 17:55:33199 char *zNull; /* Text to substitute for an SQL NULL value */
200 SqlFunc *pFunc; /* List of SQL functions */
danielk197794eb6a12005-12-15 15:22:08201 Tcl_Obj *pUpdateHook; /* Update hook script (if any) */
dan46c47d42011-03-01 18:42:07202 Tcl_Obj *pPreUpdateHook; /* Pre-update hook script (if any) */
danielk197771fd80b2005-12-16 06:54:01203 Tcl_Obj *pRollbackHook; /* Rollback hook script (if any) */
drh5def0842010-05-05 20:00:25204 Tcl_Obj *pWalHook; /* WAL hook script (if any) */
danielk1977404ca072009-03-16 13:19:36205 Tcl_Obj *pUnlockNotify; /* Unlock notify script (if any) */
drhd1e47332005-06-26 17:55:33206 SqlCollate *pCollate; /* List of SQL collation functions */
207 int rc; /* Return code of most recent sqlite3_exec() */
208 Tcl_Obj *pCollateNeeded; /* Collation needed script */
drhfb7e7652005-01-24 00:28:42209 SqlPreparedStmt *stmtList; /* List of prepared statements*/
210 SqlPreparedStmt *stmtLast; /* Last statement in the list */
211 int maxStmt; /* The next maximum number of stmtList */
212 int nStmt; /* Number of statements in stmtList */
danielk1977d04417962007-05-02 13:16:30213 IncrblobChannel *pIncrblob;/* Linked list of open incrblob channels */
drh3c379b02010-04-07 19:31:59214 int nStep, nSort, nIndex; /* Statistics for most recent operation */
danc456a762017-06-22 16:51:16215 int nVMStep; /* Another statistic for most recent operation */
danielk1977cd38d522009-01-02 17:33:46216 int nTransaction; /* Number of nested [transaction] methods */
drh147ef392016-01-22 23:17:51217 int openFlags; /* Flags used to open. (SQLITE_OPEN_URI) */
danbea28c72021-09-16 14:17:14218 int nRef; /* Delete object when this reaches 0 */
danc431fd52011-06-27 16:55:50219#ifdef SQLITE_TEST
220 int bLegacyPrepare; /* True to use sqlite3_prepare() */
221#endif
drh98808ba2001-10-18 12:34:46222};
drh297ecf12001-04-05 15:57:13223
danielk1977b4e9af92007-05-01 17:49:49224struct IncrblobChannel {
danielk1977d04417962007-05-02 13:16:30225 sqlite3_blob *pBlob; /* sqlite3 blob handle */
danielk1977dcbb5d32007-05-04 18:36:44226 SqliteDb *pDb; /* Associated database connection */
drh1c2ad462024-07-30 18:15:59227 sqlite3_int64 iSeek; /* Current seek offset */
228 unsigned int isClosed; /* TCL_CLOSE_READ or TCL_CLOSE_WRITE */
danielk1977d04417962007-05-02 13:16:30229 Tcl_Channel channel; /* Channel identifier */
230 IncrblobChannel *pNext; /* Linked list of all open incrblob channels */
231 IncrblobChannel *pPrev; /* Linked list of all open incrblob channels */
danielk1977b4e9af92007-05-01 17:49:49232};
233
drhea678832008-12-10 19:26:22234/*
235** Compute a string length that is limited to what can be stored in
236** lower 30 bits of a 32-bit signed integer.
237*/
drh4f21c4a2008-12-10 22:15:00238static int strlen30(const char *z){
drhea678832008-12-10 19:26:22239 const char *z2 = z;
240 while( *z2 ){ z2++; }
241 return 0x3fffffff & (int)(z2 - z);
242}
drhea678832008-12-10 19:26:22243
244
danielk197732a0d8b2007-05-04 19:03:02245#ifndef SQLITE_OMIT_INCRBLOB
danielk1977b4e9af92007-05-01 17:49:49246/*
danielk1977d04417962007-05-02 13:16:30247** Close all incrblob channels opened using database connection pDb.
248** This is called when shutting down the database connection.
249*/
250static void closeIncrblobChannels(SqliteDb *pDb){
251 IncrblobChannel *p;
252 IncrblobChannel *pNext;
253
254 for(p=pDb->pIncrblob; p; p=pNext){
255 pNext = p->pNext;
256
mistachkinb56660f2016-07-14 21:26:09257 /* Note: Calling unregister here call Tcl_Close on the incrblob channel,
danielk1977d04417962007-05-02 13:16:30258 ** which deletes the IncrblobChannel structure at *p. So do not
259 ** call Tcl_Free() here.
260 */
261 Tcl_UnregisterChannel(pDb->interp, p->channel);
262 }
263}
264
265/*
danielk1977b4e9af92007-05-01 17:49:49266** Close an incremental blob channel.
267*/
drh1631c642024-07-30 16:51:51268static int SQLITE_TCLAPI incrblobClose2(
mistachkin7617e4a2016-07-28 17:11:20269 ClientData instanceData,
drh1631c642024-07-30 16:51:51270 Tcl_Interp *interp,
271 int flags
mistachkin7617e4a2016-07-28 17:11:20272){
danielk1977b4e9af92007-05-01 17:49:49273 IncrblobChannel *p = (IncrblobChannel *)instanceData;
drh1631c642024-07-30 16:51:51274 int rc;
danielk197792d4d7a2007-05-04 12:05:56275 sqlite3 *db = p->pDb->db;
danielk1977d04417962007-05-02 13:16:30276
drh1631c642024-07-30 16:51:51277 if( flags ){
278 p->isClosed |= flags;
drha28a7842024-07-30 18:49:20279 return TCL_OK;
drh1631c642024-07-30 16:51:51280 }
281
282 /* If we reach this point, then we really do need to close the channel */
283 rc = sqlite3_blob_close(p->pBlob);
284
danielk1977d04417962007-05-02 13:16:30285 /* Remove the channel from the SqliteDb.pIncrblob list. */
286 if( p->pNext ){
287 p->pNext->pPrev = p->pPrev;
288 }
289 if( p->pPrev ){
290 p->pPrev->pNext = p->pNext;
291 }
292 if( p->pDb->pIncrblob==p ){
293 p->pDb->pIncrblob = p->pNext;
294 }
295
danielk197792d4d7a2007-05-04 12:05:56296 /* Free the IncrblobChannel structure */
danielk1977b4e9af92007-05-01 17:49:49297 Tcl_Free((char *)p);
danielk197792d4d7a2007-05-04 12:05:56298
299 if( rc!=SQLITE_OK ){
300 Tcl_SetResult(interp, (char *)sqlite3_errmsg(db), TCL_VOLATILE);
301 return TCL_ERROR;
302 }
danielk1977b4e9af92007-05-01 17:49:49303 return TCL_OK;
304}
drh1631c642024-07-30 16:51:51305static int SQLITE_TCLAPI incrblobClose(
306 ClientData instanceData,
307 Tcl_Interp *interp
308){
309 return incrblobClose2(instanceData, interp, 0);
310}
311
danielk1977b4e9af92007-05-01 17:49:49312
313/*
314** Read data from an incremental blob channel.
315*/
mistachkin7617e4a2016-07-28 17:11:20316static int SQLITE_TCLAPI incrblobInput(
mistachkinb56660f2016-07-14 21:26:09317 ClientData instanceData,
318 char *buf,
danielk1977b4e9af92007-05-01 17:49:49319 int bufSize,
320 int *errorCodePtr
321){
322 IncrblobChannel *p = (IncrblobChannel *)instanceData;
drh1c2ad462024-07-30 18:15:59323 sqlite3_int64 nRead = bufSize; /* Number of bytes to read */
324 sqlite3_int64 nBlob; /* Total size of the blob */
325 int rc; /* sqlite error code */
danielk1977b4e9af92007-05-01 17:49:49326
327 nBlob = sqlite3_blob_bytes(p->pBlob);
328 if( (p->iSeek+nRead)>nBlob ){
329 nRead = nBlob-p->iSeek;
330 }
331 if( nRead<=0 ){
332 return 0;
333 }
334
drh1c2ad462024-07-30 18:15:59335 rc = sqlite3_blob_read(p->pBlob, (void *)buf, (int)nRead, (int)p->iSeek);
danielk1977b4e9af92007-05-01 17:49:49336 if( rc!=SQLITE_OK ){
337 *errorCodePtr = rc;
338 return -1;
339 }
340
341 p->iSeek += nRead;
342 return nRead;
343}
344
danielk1977d04417962007-05-02 13:16:30345/*
346** Write data to an incremental blob channel.
347*/
mistachkin7617e4a2016-07-28 17:11:20348static int SQLITE_TCLAPI incrblobOutput(
mistachkinb56660f2016-07-14 21:26:09349 ClientData instanceData,
drh4a689632025-01-07 00:17:54350 const char *buf,
danielk1977b4e9af92007-05-01 17:49:49351 int toWrite,
352 int *errorCodePtr
353){
354 IncrblobChannel *p = (IncrblobChannel *)instanceData;
drh1c2ad462024-07-30 18:15:59355 sqlite3_int64 nWrite = toWrite; /* Number of bytes to write */
356 sqlite3_int64 nBlob; /* Total size of the blob */
357 int rc; /* sqlite error code */
danielk1977b4e9af92007-05-01 17:49:49358
359 nBlob = sqlite3_blob_bytes(p->pBlob);
360 if( (p->iSeek+nWrite)>nBlob ){
361 *errorCodePtr = EINVAL;
362 return -1;
363 }
364 if( nWrite<=0 ){
365 return 0;
366 }
367
drh1c2ad462024-07-30 18:15:59368 rc = sqlite3_blob_write(p->pBlob, (void*)buf,(int)nWrite, (int)p->iSeek);
danielk1977b4e9af92007-05-01 17:49:49369 if( rc!=SQLITE_OK ){
370 *errorCodePtr = EIO;
371 return -1;
372 }
373
374 p->iSeek += nWrite;
375 return nWrite;
376}
377
drh58c5a952024-08-01 23:00:37378/* The datatype of Tcl_DriverWideSeekProc changes between tcl8.6 and tcl9.0 */
379#if TCL_MAJOR_VERSION==9
drhbb99e732024-08-01 23:30:29380# define WideSeekProcType long long
drh58c5a952024-08-01 23:00:37381#else
382# define WideSeekProcType Tcl_WideInt
383#endif
384
danielk1977b4e9af92007-05-01 17:49:49385/*
386** Seek an incremental blob channel.
387*/
drh58c5a952024-08-01 23:00:37388static WideSeekProcType SQLITE_TCLAPI incrblobWideSeek(
mistachkinb56660f2016-07-14 21:26:09389 ClientData instanceData,
drh58c5a952024-08-01 23:00:37390 WideSeekProcType offset,
danielk1977b4e9af92007-05-01 17:49:49391 int seekMode,
392 int *errorCodePtr
393){
394 IncrblobChannel *p = (IncrblobChannel *)instanceData;
395
396 switch( seekMode ){
397 case SEEK_SET:
398 p->iSeek = offset;
399 break;
400 case SEEK_CUR:
401 p->iSeek += offset;
402 break;
403 case SEEK_END:
404 p->iSeek = sqlite3_blob_bytes(p->pBlob) + offset;
405 break;
406
407 default: assert(!"Bad seekMode");
408 }
409
410 return p->iSeek;
411}
drh1c2ad462024-07-30 18:15:59412static int SQLITE_TCLAPI incrblobSeek(
413 ClientData instanceData,
414 long offset,
415 int seekMode,
416 int *errorCodePtr
417){
418 return incrblobWideSeek(instanceData,offset,seekMode,errorCodePtr);
419}
danielk1977b4e9af92007-05-01 17:49:49420
421
mistachkin7617e4a2016-07-28 17:11:20422static void SQLITE_TCLAPI incrblobWatch(
423 ClientData instanceData,
424 int mode
425){
mistachkinb56660f2016-07-14 21:26:09426 /* NO-OP */
danielk1977b4e9af92007-05-01 17:49:49427}
mistachkin7617e4a2016-07-28 17:11:20428static int SQLITE_TCLAPI incrblobHandle(
429 ClientData instanceData,
430 int dir,
431 ClientData *hPtr
432){
danielk1977b4e9af92007-05-01 17:49:49433 return TCL_ERROR;
434}
435
436static Tcl_ChannelType IncrblobChannelType = {
437 "incrblob", /* typeName */
drh064b6812024-07-30 15:49:02438 TCL_CHANNEL_VERSION_5, /* version */
danielk1977b4e9af92007-05-01 17:49:49439 incrblobClose, /* closeProc */
440 incrblobInput, /* inputProc */
441 incrblobOutput, /* outputProc */
442 incrblobSeek, /* seekProc */
443 0, /* setOptionProc */
444 0, /* getOptionProc */
445 incrblobWatch, /* watchProc (this is a no-op) */
446 incrblobHandle, /* getHandleProc (always returns error) */
drh1631c642024-07-30 16:51:51447 incrblobClose2, /* close2Proc */
danielk1977b4e9af92007-05-01 17:49:49448 0, /* blockModeProc */
449 0, /* flushProc */
450 0, /* handlerProc */
drh1c2ad462024-07-30 18:15:59451 incrblobWideSeek, /* wideSeekProc */
danielk1977b4e9af92007-05-01 17:49:49452};
453
454/*
455** Create a new incrblob channel.
456*/
457static int createIncrblobChannel(
mistachkinb56660f2016-07-14 21:26:09458 Tcl_Interp *interp,
459 SqliteDb *pDb,
danielk1977b4e9af92007-05-01 17:49:49460 const char *zDb,
mistachkinb56660f2016-07-14 21:26:09461 const char *zTable,
462 const char *zColumn,
danielk19778cbadb02007-05-03 16:31:26463 sqlite_int64 iRow,
464 int isReadonly
danielk1977b4e9af92007-05-01 17:49:49465){
466 IncrblobChannel *p;
danielk19778cbadb02007-05-03 16:31:26467 sqlite3 *db = pDb->db;
danielk1977b4e9af92007-05-01 17:49:49468 sqlite3_blob *pBlob;
469 int rc;
danielk19778cbadb02007-05-03 16:31:26470 int flags = TCL_READABLE|(isReadonly ? 0 : TCL_WRITABLE);
danielk1977b4e9af92007-05-01 17:49:49471
472 /* This variable is used to name the channels: "incrblob_[incr count]" */
473 static int count = 0;
474 char zChannel[64];
475
danielk19778cbadb02007-05-03 16:31:26476 rc = sqlite3_blob_open(db, zDb, zTable, zColumn, iRow, !isReadonly, &pBlob);
danielk1977b4e9af92007-05-01 17:49:49477 if( rc!=SQLITE_OK ){
478 Tcl_SetResult(interp, (char *)sqlite3_errmsg(pDb->db), TCL_VOLATILE);
479 return TCL_ERROR;
480 }
481
482 p = (IncrblobChannel *)Tcl_Alloc(sizeof(IncrblobChannel));
drh1c2ad462024-07-30 18:15:59483 memset(p, 0, sizeof(*p));
danielk1977b4e9af92007-05-01 17:49:49484 p->pBlob = pBlob;
drh1631c642024-07-30 16:51:51485 if( (flags & TCL_WRITABLE)==0 ) p->isClosed |= TCL_CLOSE_WRITE;
danielk1977b4e9af92007-05-01 17:49:49486
drh5bb3eb92007-05-04 13:15:55487 sqlite3_snprintf(sizeof(zChannel), zChannel, "incrblob_%d", ++count);
danielk1977d04417962007-05-02 13:16:30488 p->channel = Tcl_CreateChannel(&IncrblobChannelType, zChannel, p, flags);
489 Tcl_RegisterChannel(interp, p->channel);
danielk1977b4e9af92007-05-01 17:49:49490
danielk1977d04417962007-05-02 13:16:30491 /* Link the new channel into the SqliteDb.pIncrblob list. */
492 p->pNext = pDb->pIncrblob;
493 p->pPrev = 0;
494 if( p->pNext ){
495 p->pNext->pPrev = p;
496 }
497 pDb->pIncrblob = p;
498 p->pDb = pDb;
499
500 Tcl_SetResult(interp, (char *)Tcl_GetChannelName(p->channel), TCL_VOLATILE);
danielk1977b4e9af92007-05-01 17:49:49501 return TCL_OK;
502}
danielk197732a0d8b2007-05-04 19:03:02503#else /* else clause for "#ifndef SQLITE_OMIT_INCRBLOB" */
504 #define closeIncrblobChannels(pDb)
505#endif
danielk1977b4e9af92007-05-01 17:49:49506
drh6d313162000-09-21 13:01:35507/*
drhd1e47332005-06-26 17:55:33508** Look at the script prefix in pCmd. We will be executing this script
509** after first appending one or more arguments. This routine analyzes
510** the script to see if it is safe to use Tcl_EvalObjv() on the script
511** rather than the more general Tcl_EvalEx(). Tcl_EvalObjv() is much
512** faster.
513**
514** Scripts that are safe to use with Tcl_EvalObjv() consists of a
515** command name followed by zero or more arguments with no [...] or $
516** or {...} or ; to be seen anywhere. Most callback scripts consist
517** of just a single procedure name and they meet this requirement.
518*/
drh8bffd492025-01-30 16:07:51519static int safeToUseEvalObjv(Tcl_Obj *pCmd){
drhd1e47332005-06-26 17:55:33520 /* We could try to do something with Tcl_Parse(). But we will instead
521 ** just do a search for forbidden characters. If any of the forbidden
522 ** characters appear in pCmd, we will report the string as unsafe.
523 */
524 const char *z;
drh064b6812024-07-30 15:49:02525 Tcl_Size n;
drhd1e47332005-06-26 17:55:33526 z = Tcl_GetStringFromObj(pCmd, &n);
527 while( n-- > 0 ){
528 int c = *(z++);
529 if( c=='$' || c=='[' || c==';' ) return 0;
530 }
531 return 1;
532}
533
534/*
535** Find an SqlFunc structure with the given name. Or create a new
536** one if an existing one cannot be found. Return a pointer to the
537** structure.
538*/
539static SqlFunc *findSqlFunc(SqliteDb *pDb, const char *zName){
540 SqlFunc *p, *pNew;
drh0425f182013-11-26 16:48:04541 int nName = strlen30(zName);
542 pNew = (SqlFunc*)Tcl_Alloc( sizeof(*pNew) + nName + 1 );
drhd1e47332005-06-26 17:55:33543 pNew->zName = (char*)&pNew[1];
drh0425f182013-11-26 16:48:04544 memcpy(pNew->zName, zName, nName+1);
mistachkinb56660f2016-07-14 21:26:09545 for(p=pDb->pFunc; p; p=p->pNext){
drh0425f182013-11-26 16:48:04546 if( sqlite3_stricmp(p->zName, pNew->zName)==0 ){
drhd1e47332005-06-26 17:55:33547 Tcl_Free((char*)pNew);
548 return p;
549 }
550 }
551 pNew->interp = pDb->interp;
drhc45e6712012-10-03 11:02:33552 pNew->pDb = pDb;
drhd1e47332005-06-26 17:55:33553 pNew->pScript = 0;
554 pNew->pNext = pDb->pFunc;
555 pDb->pFunc = pNew;
556 return pNew;
557}
558
559/*
danc431fd52011-06-27 16:55:50560** Free a single SqlPreparedStmt object.
561*/
562static void dbFreeStmt(SqlPreparedStmt *pStmt){
563#ifdef SQLITE_TEST
564 if( sqlite3_sql(pStmt->pStmt)==0 ){
565 Tcl_Free((char *)pStmt->zSql);
566 }
567#endif
568 sqlite3_finalize(pStmt->pStmt);
569 Tcl_Free((char *)pStmt);
570}
571
572/*
drhfb7e7652005-01-24 00:28:42573** Finalize and free a list of prepared statements
574*/
danc431fd52011-06-27 16:55:50575static void flushStmtCache(SqliteDb *pDb){
drhfb7e7652005-01-24 00:28:42576 SqlPreparedStmt *pPreStmt;
danc431fd52011-06-27 16:55:50577 SqlPreparedStmt *pNext;
drhfb7e7652005-01-24 00:28:42578
danc431fd52011-06-27 16:55:50579 for(pPreStmt = pDb->stmtList; pPreStmt; pPreStmt=pNext){
580 pNext = pPreStmt->pNext;
581 dbFreeStmt(pPreStmt);
drhfb7e7652005-01-24 00:28:42582 }
583 pDb->nStmt = 0;
584 pDb->stmtLast = 0;
danc431fd52011-06-27 16:55:50585 pDb->stmtList = 0;
drhfb7e7652005-01-24 00:28:42586}
587
588/*
danbea28c72021-09-16 14:17:14589** Increment the reference counter on the SqliteDb object. The reference
590** should be released by calling delDatabaseRef().
591*/
592static void addDatabaseRef(SqliteDb *pDb){
593 pDb->nRef++;
594}
595
596/*
597** Decrement the reference counter associated with the SqliteDb object.
598** If it reaches zero, delete the object.
599*/
600static void delDatabaseRef(SqliteDb *pDb){
601 assert( pDb->nRef>0 );
602 pDb->nRef--;
603 if( pDb->nRef==0 ){
604 flushStmtCache(pDb);
605 closeIncrblobChannels(pDb);
606 sqlite3_close(pDb->db);
607 while( pDb->pFunc ){
608 SqlFunc *pFunc = pDb->pFunc;
609 pDb->pFunc = pFunc->pNext;
610 assert( pFunc->pDb==pDb );
611 Tcl_DecrRefCount(pFunc->pScript);
612 Tcl_Free((char*)pFunc);
613 }
614 while( pDb->pCollate ){
615 SqlCollate *pCollate = pDb->pCollate;
616 pDb->pCollate = pCollate->pNext;
617 Tcl_Free((char*)pCollate);
618 }
619 if( pDb->zBusy ){
620 Tcl_Free(pDb->zBusy);
621 }
622 if( pDb->zTrace ){
623 Tcl_Free(pDb->zTrace);
624 }
625 if( pDb->zTraceV2 ){
626 Tcl_Free(pDb->zTraceV2);
627 }
628 if( pDb->zProfile ){
629 Tcl_Free(pDb->zProfile);
630 }
631 if( pDb->zBindFallback ){
632 Tcl_Free(pDb->zBindFallback);
633 }
634 if( pDb->zAuth ){
635 Tcl_Free(pDb->zAuth);
636 }
637 if( pDb->zNull ){
638 Tcl_Free(pDb->zNull);
639 }
640 if( pDb->pUpdateHook ){
641 Tcl_DecrRefCount(pDb->pUpdateHook);
642 }
643 if( pDb->pPreUpdateHook ){
644 Tcl_DecrRefCount(pDb->pPreUpdateHook);
645 }
646 if( pDb->pRollbackHook ){
647 Tcl_DecrRefCount(pDb->pRollbackHook);
648 }
649 if( pDb->pWalHook ){
650 Tcl_DecrRefCount(pDb->pWalHook);
651 }
652 if( pDb->pCollateNeeded ){
653 Tcl_DecrRefCount(pDb->pCollateNeeded);
654 }
655 Tcl_Free((char*)pDb);
656 }
657}
658
659/*
drh895d7472004-08-20 16:02:39660** TCL calls this procedure when an sqlite3 database command is
661** deleted.
drh75897232000-05-29 14:26:00662*/
mistachkin7617e4a2016-07-28 17:11:20663static void SQLITE_TCLAPI DbDeleteCmd(void *db){
drhbec3f402000-08-04 13:49:02664 SqliteDb *pDb = (SqliteDb*)db;
danbea28c72021-09-16 14:17:14665 delDatabaseRef(pDb);
drhbec3f402000-08-04 13:49:02666}
667
668/*
669** This routine is called when a database file is locked while trying
670** to execute SQL.
671*/
danielk19772a764eb2004-06-12 01:43:26672static int DbBusyHandler(void *cd, int nTries){
drhbec3f402000-08-04 13:49:02673 SqliteDb *pDb = (SqliteDb*)cd;
674 int rc;
675 char zVal[30];
drhbec3f402000-08-04 13:49:02676
drh5bb3eb92007-05-04 13:15:55677 sqlite3_snprintf(sizeof(zVal), zVal, "%d", nTries);
drhd1e47332005-06-26 17:55:33678 rc = Tcl_VarEval(pDb->interp, pDb->zBusy, " ", zVal, (char*)0);
drhbec3f402000-08-04 13:49:02679 if( rc!=TCL_OK || atoi(Tcl_GetStringResult(pDb->interp)) ){
680 return 0;
681 }
682 return 1;
drh75897232000-05-29 14:26:00683}
684
drh26e4a8b2008-05-01 17:16:52685#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
drh75897232000-05-29 14:26:00686/*
danielk1977348bb5d2003-10-18 09:37:26687** This routine is invoked as the 'progress callback' for the database.
688*/
689static int DbProgressHandler(void *cd){
690 SqliteDb *pDb = (SqliteDb*)cd;
691 int rc;
692
693 assert( pDb->zProgress );
694 rc = Tcl_Eval(pDb->interp, pDb->zProgress);
695 if( rc!=TCL_OK || atoi(Tcl_GetStringResult(pDb->interp)) ){
696 return 1;
697 }
698 return 0;
699}
drh26e4a8b2008-05-01 17:16:52700#endif
danielk1977348bb5d2003-10-18 09:37:26701
drh2eb22af2016-09-10 19:51:40702#if !defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_OMIT_FLOATING_POINT) && \
703 !defined(SQLITE_OMIT_DEPRECATED)
danielk1977348bb5d2003-10-18 09:37:26704/*
drhb5a20d32003-04-23 12:25:23705** This routine is called by the SQLite trace handler whenever a new
706** block of SQL is executed. The TCL script in pDb->zTrace is executed.
drh0d1a6432003-04-03 15:46:04707*/
drhb5a20d32003-04-23 12:25:23708static void DbTraceHandler(void *cd, const char *zSql){
drh0d1a6432003-04-03 15:46:04709 SqliteDb *pDb = (SqliteDb*)cd;
drhb5a20d32003-04-23 12:25:23710 Tcl_DString str;
drh0d1a6432003-04-03 15:46:04711
drhb5a20d32003-04-23 12:25:23712 Tcl_DStringInit(&str);
713 Tcl_DStringAppend(&str, pDb->zTrace, -1);
714 Tcl_DStringAppendElement(&str, zSql);
715 Tcl_Eval(pDb->interp, Tcl_DStringValue(&str));
716 Tcl_DStringFree(&str);
717 Tcl_ResetResult(pDb->interp);
drh0d1a6432003-04-03 15:46:04718}
drhd1167392006-01-23 13:00:35719#endif
drh0d1a6432003-04-03 15:46:04720
drhd1167392006-01-23 13:00:35721#ifndef SQLITE_OMIT_TRACE
drh0d1a6432003-04-03 15:46:04722/*
mistachkinb56660f2016-07-14 21:26:09723** This routine is called by the SQLite trace_v2 handler whenever a new
724** supported event is generated. Unsupported event types are ignored.
725** The TCL script in pDb->zTraceV2 is executed, with the arguments for
726** the event appended to it (as list elements).
727*/
728static int DbTraceV2Handler(
729 unsigned type, /* One of the SQLITE_TRACE_* event types. */
730 void *cd, /* The original context data pointer. */
731 void *pd, /* Primary event data, depends on event type. */
732 void *xd /* Extra event data, depends on event type. */
733){
734 SqliteDb *pDb = (SqliteDb*)cd;
735 Tcl_Obj *pCmd;
736
737 switch( type ){
738 case SQLITE_TRACE_STMT: {
739 sqlite3_stmt *pStmt = (sqlite3_stmt *)pd;
740 char *zSql = (char *)xd;
741
742 pCmd = Tcl_NewStringObj(pDb->zTraceV2, -1);
743 Tcl_IncrRefCount(pCmd);
744 Tcl_ListObjAppendElement(pDb->interp, pCmd,
drh8e5cef72023-06-17 15:42:44745 Tcl_NewWideIntObj((Tcl_WideInt)(uptr)pStmt));
mistachkinb56660f2016-07-14 21:26:09746 Tcl_ListObjAppendElement(pDb->interp, pCmd,
747 Tcl_NewStringObj(zSql, -1));
748 Tcl_EvalObjEx(pDb->interp, pCmd, TCL_EVAL_DIRECT);
749 Tcl_DecrRefCount(pCmd);
750 Tcl_ResetResult(pDb->interp);
751 break;
752 }
753 case SQLITE_TRACE_PROFILE: {
754 sqlite3_stmt *pStmt = (sqlite3_stmt *)pd;
drhffdab722018-03-10 20:25:08755 sqlite3_int64 ns = *(sqlite3_int64*)xd;
mistachkinb56660f2016-07-14 21:26:09756
757 pCmd = Tcl_NewStringObj(pDb->zTraceV2, -1);
758 Tcl_IncrRefCount(pCmd);
759 Tcl_ListObjAppendElement(pDb->interp, pCmd,
drh8e5cef72023-06-17 15:42:44760 Tcl_NewWideIntObj((Tcl_WideInt)(uptr)pStmt));
mistachkinb56660f2016-07-14 21:26:09761 Tcl_ListObjAppendElement(pDb->interp, pCmd,
762 Tcl_NewWideIntObj((Tcl_WideInt)ns));
763 Tcl_EvalObjEx(pDb->interp, pCmd, TCL_EVAL_DIRECT);
764 Tcl_DecrRefCount(pCmd);
765 Tcl_ResetResult(pDb->interp);
766 break;
767 }
768 case SQLITE_TRACE_ROW: {
769 sqlite3_stmt *pStmt = (sqlite3_stmt *)pd;
770
771 pCmd = Tcl_NewStringObj(pDb->zTraceV2, -1);
772 Tcl_IncrRefCount(pCmd);
773 Tcl_ListObjAppendElement(pDb->interp, pCmd,
drh8e5cef72023-06-17 15:42:44774 Tcl_NewWideIntObj((Tcl_WideInt)(uptr)pStmt));
mistachkinb56660f2016-07-14 21:26:09775 Tcl_EvalObjEx(pDb->interp, pCmd, TCL_EVAL_DIRECT);
776 Tcl_DecrRefCount(pCmd);
777 Tcl_ResetResult(pDb->interp);
778 break;
779 }
780 case SQLITE_TRACE_CLOSE: {
781 sqlite3 *db = (sqlite3 *)pd;
782
783 pCmd = Tcl_NewStringObj(pDb->zTraceV2, -1);
784 Tcl_IncrRefCount(pCmd);
785 Tcl_ListObjAppendElement(pDb->interp, pCmd,
drh8e5cef72023-06-17 15:42:44786 Tcl_NewWideIntObj((Tcl_WideInt)(uptr)db));
mistachkinb56660f2016-07-14 21:26:09787 Tcl_EvalObjEx(pDb->interp, pCmd, TCL_EVAL_DIRECT);
788 Tcl_DecrRefCount(pCmd);
789 Tcl_ResetResult(pDb->interp);
790 break;
791 }
792 }
793 return SQLITE_OK;
794}
795#endif
796
drh2eb22af2016-09-10 19:51:40797#if !defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_OMIT_FLOATING_POINT) && \
798 !defined(SQLITE_OMIT_DEPRECATED)
mistachkinb56660f2016-07-14 21:26:09799/*
drh19e2d372005-08-29 23:00:03800** This routine is called by the SQLite profile handler after a statement
801** SQL has executed. The TCL script in pDb->zProfile is evaluated.
802*/
803static void DbProfileHandler(void *cd, const char *zSql, sqlite_uint64 tm){
804 SqliteDb *pDb = (SqliteDb*)cd;
805 Tcl_DString str;
806 char zTm[100];
807
808 sqlite3_snprintf(sizeof(zTm)-1, zTm, "%lld", tm);
809 Tcl_DStringInit(&str);
810 Tcl_DStringAppend(&str, pDb->zProfile, -1);
811 Tcl_DStringAppendElement(&str, zSql);
812 Tcl_DStringAppendElement(&str, zTm);
813 Tcl_Eval(pDb->interp, Tcl_DStringValue(&str));
814 Tcl_DStringFree(&str);
815 Tcl_ResetResult(pDb->interp);
816}
drhd1167392006-01-23 13:00:35817#endif
drh19e2d372005-08-29 23:00:03818
819/*
drhaa940ea2004-01-15 02:44:03820** This routine is called when a transaction is committed. The
821** TCL script in pDb->zCommit is executed. If it returns non-zero or
822** if it throws an exception, the transaction is rolled back instead
823** of being committed.
824*/
825static int DbCommitHandler(void *cd){
826 SqliteDb *pDb = (SqliteDb*)cd;
827 int rc;
828
829 rc = Tcl_Eval(pDb->interp, pDb->zCommit);
830 if( rc!=TCL_OK || atoi(Tcl_GetStringResult(pDb->interp)) ){
831 return 1;
832 }
833 return 0;
834}
835
danielk197771fd80b2005-12-16 06:54:01836static void DbRollbackHandler(void *clientData){
837 SqliteDb *pDb = (SqliteDb*)clientData;
838 assert(pDb->pRollbackHook);
839 if( TCL_OK!=Tcl_EvalObjEx(pDb->interp, pDb->pRollbackHook, 0) ){
840 Tcl_BackgroundError(pDb->interp);
841 }
842}
843
drh5def0842010-05-05 20:00:25844/*
845** This procedure handles wal_hook callbacks.
846*/
847static int DbWalHandler(
mistachkinb56660f2016-07-14 21:26:09848 void *clientData,
849 sqlite3 *db,
850 const char *zDb,
dan8d22a172010-04-19 18:03:51851 int nEntry
852){
drh5def0842010-05-05 20:00:25853 int ret = SQLITE_OK;
dan8d22a172010-04-19 18:03:51854 Tcl_Obj *p;
855 SqliteDb *pDb = (SqliteDb*)clientData;
856 Tcl_Interp *interp = pDb->interp;
drh5def0842010-05-05 20:00:25857 assert(pDb->pWalHook);
dan8d22a172010-04-19 18:03:51858
dan6e45e0c2014-12-10 20:29:49859 assert( db==pDb->db );
drh5def0842010-05-05 20:00:25860 p = Tcl_DuplicateObj(pDb->pWalHook);
dan8d22a172010-04-19 18:03:51861 Tcl_IncrRefCount(p);
862 Tcl_ListObjAppendElement(interp, p, Tcl_NewStringObj(zDb, -1));
863 Tcl_ListObjAppendElement(interp, p, Tcl_NewIntObj(nEntry));
mistachkinb56660f2016-07-14 21:26:09864 if( TCL_OK!=Tcl_EvalObjEx(interp, p, 0)
dan8d22a172010-04-19 18:03:51865 || TCL_OK!=Tcl_GetIntFromObj(interp, Tcl_GetObjResult(interp), &ret)
866 ){
867 Tcl_BackgroundError(interp);
868 }
869 Tcl_DecrRefCount(p);
870
871 return ret;
872}
873
drhbcf4f482009-03-27 12:44:35874#if defined(SQLITE_TEST) && defined(SQLITE_ENABLE_UNLOCK_NOTIFY)
danielk1977404ca072009-03-16 13:19:36875static void setTestUnlockNotifyVars(Tcl_Interp *interp, int iArg, int nArg){
876 char zBuf[64];
drh65545b52015-01-19 00:35:53877 sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", iArg);
danielk1977404ca072009-03-16 13:19:36878 Tcl_SetVar(interp, "sqlite_unlock_notify_arg", zBuf, TCL_GLOBAL_ONLY);
drh65545b52015-01-19 00:35:53879 sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", nArg);
danielk1977404ca072009-03-16 13:19:36880 Tcl_SetVar(interp, "sqlite_unlock_notify_argcount", zBuf, TCL_GLOBAL_ONLY);
881}
882#else
drhbcf4f482009-03-27 12:44:35883# define setTestUnlockNotifyVars(x,y,z)
danielk1977404ca072009-03-16 13:19:36884#endif
885
drh69910da2009-03-27 12:32:54886#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
danielk1977404ca072009-03-16 13:19:36887static void DbUnlockNotify(void **apArg, int nArg){
888 int i;
889 for(i=0; i<nArg; i++){
890 const int flags = (TCL_EVAL_GLOBAL|TCL_EVAL_DIRECT);
891 SqliteDb *pDb = (SqliteDb *)apArg[i];
892 setTestUnlockNotifyVars(pDb->interp, i, nArg);
893 assert( pDb->pUnlockNotify);
894 Tcl_EvalObjEx(pDb->interp, pDb->pUnlockNotify, flags);
895 Tcl_DecrRefCount(pDb->pUnlockNotify);
896 pDb->pUnlockNotify = 0;
897 }
898}
drh69910da2009-03-27 12:32:54899#endif
danielk1977404ca072009-03-16 13:19:36900
drh9b1c62d2011-03-30 21:04:43901#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
dan46c47d42011-03-01 18:42:07902/*
903** Pre-update hook callback.
904*/
905static void DbPreUpdateHandler(
mistachkinb56660f2016-07-14 21:26:09906 void *p,
dan46c47d42011-03-01 18:42:07907 sqlite3 *db,
908 int op,
mistachkinb56660f2016-07-14 21:26:09909 const char *zDb,
910 const char *zTbl,
dan46c47d42011-03-01 18:42:07911 sqlite_int64 iKey1,
912 sqlite_int64 iKey2
913){
914 SqliteDb *pDb = (SqliteDb *)p;
915 Tcl_Obj *pCmd;
916 static const char *azStr[] = {"DELETE", "INSERT", "UPDATE"};
917
918 assert( (SQLITE_DELETE-1)/9 == 0 );
919 assert( (SQLITE_INSERT-1)/9 == 1 );
920 assert( (SQLITE_UPDATE-1)/9 == 2 );
921 assert( pDb->pPreUpdateHook );
922 assert( db==pDb->db );
923 assert( op==SQLITE_INSERT || op==SQLITE_UPDATE || op==SQLITE_DELETE );
924
925 pCmd = Tcl_DuplicateObj(pDb->pPreUpdateHook);
926 Tcl_IncrRefCount(pCmd);
927 Tcl_ListObjAppendElement(0, pCmd, Tcl_NewStringObj(azStr[(op-1)/9], -1));
928 Tcl_ListObjAppendElement(0, pCmd, Tcl_NewStringObj(zDb, -1));
929 Tcl_ListObjAppendElement(0, pCmd, Tcl_NewStringObj(zTbl, -1));
930 Tcl_ListObjAppendElement(0, pCmd, Tcl_NewWideIntObj(iKey1));
931 Tcl_ListObjAppendElement(0, pCmd, Tcl_NewWideIntObj(iKey2));
932 Tcl_EvalObjEx(pDb->interp, pCmd, TCL_EVAL_DIRECT);
933 Tcl_DecrRefCount(pCmd);
934}
drh9b1c62d2011-03-30 21:04:43935#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */
dan46c47d42011-03-01 18:42:07936
danielk197794eb6a12005-12-15 15:22:08937static void DbUpdateHandler(
mistachkinb56660f2016-07-14 21:26:09938 void *p,
danielk197794eb6a12005-12-15 15:22:08939 int op,
mistachkinb56660f2016-07-14 21:26:09940 const char *zDb,
941 const char *zTbl,
danielk197794eb6a12005-12-15 15:22:08942 sqlite_int64 rowid
943){
944 SqliteDb *pDb = (SqliteDb *)p;
945 Tcl_Obj *pCmd;
dan46c47d42011-03-01 18:42:07946 static const char *azStr[] = {"DELETE", "INSERT", "UPDATE"};
947
948 assert( (SQLITE_DELETE-1)/9 == 0 );
949 assert( (SQLITE_INSERT-1)/9 == 1 );
950 assert( (SQLITE_UPDATE-1)/9 == 2 );
danielk197794eb6a12005-12-15 15:22:08951
952 assert( pDb->pUpdateHook );
953 assert( op==SQLITE_INSERT || op==SQLITE_UPDATE || op==SQLITE_DELETE );
954
955 pCmd = Tcl_DuplicateObj(pDb->pUpdateHook);
956 Tcl_IncrRefCount(pCmd);
dan46c47d42011-03-01 18:42:07957 Tcl_ListObjAppendElement(0, pCmd, Tcl_NewStringObj(azStr[(op-1)/9], -1));
danielk197794eb6a12005-12-15 15:22:08958 Tcl_ListObjAppendElement(0, pCmd, Tcl_NewStringObj(zDb, -1));
959 Tcl_ListObjAppendElement(0, pCmd, Tcl_NewStringObj(zTbl, -1));
960 Tcl_ListObjAppendElement(0, pCmd, Tcl_NewWideIntObj(rowid));
961 Tcl_EvalObjEx(pDb->interp, pCmd, TCL_EVAL_DIRECT);
drhefdde162010-10-27 15:36:21962 Tcl_DecrRefCount(pCmd);
danielk197794eb6a12005-12-15 15:22:08963}
964
danielk19777cedc8d2004-06-10 10:50:08965static void tclCollateNeeded(
966 void *pCtx,
drh9bb575f2004-09-06 17:24:11967 sqlite3 *db,
danielk19777cedc8d2004-06-10 10:50:08968 int enc,
969 const char *zName
970){
971 SqliteDb *pDb = (SqliteDb *)pCtx;
972 Tcl_Obj *pScript = Tcl_DuplicateObj(pDb->pCollateNeeded);
973 Tcl_IncrRefCount(pScript);
974 Tcl_ListObjAppendElement(0, pScript, Tcl_NewStringObj(zName, -1));
975 Tcl_EvalObjEx(pDb->interp, pScript, 0);
976 Tcl_DecrRefCount(pScript);
977}
978
drhaa940ea2004-01-15 02:44:03979/*
danielk19770202b292004-06-09 09:55:16980** This routine is called to evaluate an SQL collation function implemented
981** using TCL script.
982*/
983static int tclSqlCollate(
984 void *pCtx,
985 int nA,
986 const void *zA,
987 int nB,
988 const void *zB
989){
990 SqlCollate *p = (SqlCollate *)pCtx;
991 Tcl_Obj *pCmd;
992
993 pCmd = Tcl_NewStringObj(p->zScript, -1);
994 Tcl_IncrRefCount(pCmd);
995 Tcl_ListObjAppendElement(p->interp, pCmd, Tcl_NewStringObj(zA, nA));
996 Tcl_ListObjAppendElement(p->interp, pCmd, Tcl_NewStringObj(zB, nB));
drhd1e47332005-06-26 17:55:33997 Tcl_EvalObjEx(p->interp, pCmd, TCL_EVAL_DIRECT);
danielk19770202b292004-06-09 09:55:16998 Tcl_DecrRefCount(pCmd);
999 return (atoi(Tcl_GetStringResult(p->interp)));
1000}
1001
1002/*
drhcabb0812002-09-14 13:47:321003** This routine is called to evaluate an SQL function implemented
1004** using TCL script.
1005*/
drhfb7e7652005-01-24 00:28:421006static void tclSqlFunc(sqlite3_context *context, int argc, sqlite3_value**argv){
danielk19776f8a5032004-05-10 10:34:511007 SqlFunc *p = sqlite3_user_data(context);
drhd1e47332005-06-26 17:55:331008 Tcl_Obj *pCmd;
drhcabb0812002-09-14 13:47:321009 int i;
1010 int rc;
1011
drhd1e47332005-06-26 17:55:331012 if( argc==0 ){
1013 /* If there are no arguments to the function, call Tcl_EvalObjEx on the
1014 ** script object directly. This allows the TCL compiler to generate
1015 ** bytecode for the command on the first invocation and thus make
1016 ** subsequent invocations much faster. */
1017 pCmd = p->pScript;
1018 Tcl_IncrRefCount(pCmd);
1019 rc = Tcl_EvalObjEx(p->interp, pCmd, 0);
1020 Tcl_DecrRefCount(pCmd);
1021 }else{
1022 /* If there are arguments to the function, make a shallow copy of the
1023 ** script object, lappend the arguments, then evaluate the copy.
1024 **
peter.d.reid60ec9142014-09-06 16:39:461025 ** By "shallow" copy, we mean only the outer list Tcl_Obj is duplicated.
mistachkinb56660f2016-07-14 21:26:091026 ** The new Tcl_Obj contains pointers to the original list elements.
drhd1e47332005-06-26 17:55:331027 ** That way, when Tcl_EvalObjv() is run and shimmers the first element
1028 ** of the list to tclCmdNameType, that alternate representation will
1029 ** be preserved and reused on the next invocation.
1030 */
1031 Tcl_Obj **aArg;
drh064b6812024-07-30 15:49:021032 Tcl_Size nArg;
drhd1e47332005-06-26 17:55:331033 if( Tcl_ListObjGetElements(p->interp, p->pScript, &nArg, &aArg) ){
mistachkinb56660f2016-07-14 21:26:091034 sqlite3_result_error(context, Tcl_GetStringResult(p->interp), -1);
drhd1e47332005-06-26 17:55:331035 return;
mistachkinb56660f2016-07-14 21:26:091036 }
drhd1e47332005-06-26 17:55:331037 pCmd = Tcl_NewListObj(nArg, aArg);
1038 Tcl_IncrRefCount(pCmd);
1039 for(i=0; i<argc; i++){
1040 sqlite3_value *pIn = argv[i];
1041 Tcl_Obj *pVal;
mistachkinb56660f2016-07-14 21:26:091042
drhd1e47332005-06-26 17:55:331043 /* Set pVal to contain the i'th column of this row. */
1044 switch( sqlite3_value_type(pIn) ){
1045 case SQLITE_BLOB: {
1046 int bytes = sqlite3_value_bytes(pIn);
1047 pVal = Tcl_NewByteArrayObj(sqlite3_value_blob(pIn), bytes);
1048 break;
1049 }
1050 case SQLITE_INTEGER: {
1051 sqlite_int64 v = sqlite3_value_int64(pIn);
1052 if( v>=-2147483647 && v<=2147483647 ){
drh7fd33922011-06-20 19:00:301053 pVal = Tcl_NewIntObj((int)v);
drhd1e47332005-06-26 17:55:331054 }else{
1055 pVal = Tcl_NewWideIntObj(v);
1056 }
1057 break;
1058 }
1059 case SQLITE_FLOAT: {
1060 double r = sqlite3_value_double(pIn);
1061 pVal = Tcl_NewDoubleObj(r);
1062 break;
1063 }
1064 case SQLITE_NULL: {
drhc45e6712012-10-03 11:02:331065 pVal = Tcl_NewStringObj(p->pDb->zNull, -1);
drhd1e47332005-06-26 17:55:331066 break;
1067 }
1068 default: {
1069 int bytes = sqlite3_value_bytes(pIn);
danielk197700fd9572005-12-07 06:27:431070 pVal = Tcl_NewStringObj((char *)sqlite3_value_text(pIn), bytes);
drhd1e47332005-06-26 17:55:331071 break;
1072 }
1073 }
1074 rc = Tcl_ListObjAppendElement(p->interp, pCmd, pVal);
1075 if( rc ){
1076 Tcl_DecrRefCount(pCmd);
mistachkinb56660f2016-07-14 21:26:091077 sqlite3_result_error(context, Tcl_GetStringResult(p->interp), -1);
drhd1e47332005-06-26 17:55:331078 return;
1079 }
danielk197751ad0ec2004-05-24 12:39:021080 }
drhd1e47332005-06-26 17:55:331081 if( !p->useEvalObjv ){
1082 /* Tcl_EvalObjEx() will automatically call Tcl_EvalObjv() if pCmd
1083 ** is a list without a string representation. To prevent this from
1084 ** happening, make sure pCmd has a valid string representation */
1085 Tcl_GetString(pCmd);
1086 }
1087 rc = Tcl_EvalObjEx(p->interp, pCmd, TCL_EVAL_DIRECT);
1088 Tcl_DecrRefCount(pCmd);
drhcabb0812002-09-14 13:47:321089 }
danielk1977562e8d32005-05-20 09:40:551090
stephan10206572025-05-31 11:02:061091 if( TCL_BREAK==rc ){
1092 sqlite3_result_null(context);
1093 }else if( rc && rc!=TCL_RETURN ){
mistachkinb56660f2016-07-14 21:26:091094 sqlite3_result_error(context, Tcl_GetStringResult(p->interp), -1);
drhcabb0812002-09-14 13:47:321095 }else{
drhc7f269d2005-05-05 10:30:291096 Tcl_Obj *pVar = Tcl_GetObjResult(p->interp);
drh064b6812024-07-30 15:49:021097 Tcl_Size n;
drhc7f269d2005-05-05 10:30:291098 u8 *data;
dan4a4c11a2009-10-06 14:59:021099 const char *zType = (pVar->typePtr ? pVar->typePtr->name : "");
drhc7f269d2005-05-05 10:30:291100 char c = zType[0];
dan89d24932019-02-27 16:38:191101 int eType = p->eType;
1102
1103 if( eType==SQLITE_NULL ){
1104 if( c=='b' && strcmp(zType,"bytearray")==0 && pVar->bytes==0 ){
1105 /* Only return a BLOB type if the Tcl variable is a bytearray and
1106 ** has no string representation. */
1107 eType = SQLITE_BLOB;
drhfd11e5c2025-01-07 16:36:471108 }else if( (c=='b' && pVar->bytes==0 && strcmp(zType,"boolean")==0 )
1109 || (c=='b' && pVar->bytes==0 && strcmp(zType,"booleanString")==0 )
dan89d24932019-02-27 16:38:191110 || (c=='w' && strcmp(zType,"wideInt")==0)
stephan10206572025-05-31 11:02:061111 || (c=='i' && strcmp(zType,"int")==0)
dan89d24932019-02-27 16:38:191112 ){
1113 eType = SQLITE_INTEGER;
1114 }else if( c=='d' && strcmp(zType,"double")==0 ){
1115 eType = SQLITE_FLOAT;
1116 }else{
1117 eType = SQLITE_TEXT;
1118 }
drhc7f269d2005-05-05 10:30:291119 }
dan89d24932019-02-27 16:38:191120
1121 switch( eType ){
1122 case SQLITE_BLOB: {
1123 data = Tcl_GetByteArrayFromObj(pVar, &n);
1124 sqlite3_result_blob(context, data, n, SQLITE_TRANSIENT);
1125 break;
1126 }
1127 case SQLITE_INTEGER: {
1128 Tcl_WideInt v;
1129 if( TCL_OK==Tcl_GetWideIntFromObj(0, pVar, &v) ){
1130 sqlite3_result_int64(context, v);
1131 break;
1132 }
1133 /* fall-through */
1134 }
1135 case SQLITE_FLOAT: {
1136 double r;
1137 if( TCL_OK==Tcl_GetDoubleFromObj(0, pVar, &r) ){
1138 sqlite3_result_double(context, r);
1139 break;
1140 }
1141 /* fall-through */
1142 }
1143 default: {
1144 data = (unsigned char *)Tcl_GetStringFromObj(pVar, &n);
drhe57527c2024-12-09 20:46:361145 sqlite3_result_text64(context, (char *)data, n, SQLITE_TRANSIENT,
1146 SQLITE_UTF8);
dan89d24932019-02-27 16:38:191147 break;
1148 }
1149 }
1150
drhcabb0812002-09-14 13:47:321151 }
1152}
drh895d7472004-08-20 16:02:391153
drhe22a3342003-04-22 20:30:371154#ifndef SQLITE_OMIT_AUTHORIZATION
1155/*
1156** This is the authentication function. It appends the authentication
1157** type code and the two arguments to zCmd[] then invokes the result
1158** on the interpreter. The reply is examined to determine if the
1159** authentication fails or succeeds.
1160*/
1161static int auth_callback(
1162 void *pArg,
1163 int code,
1164 const char *zArg1,
1165 const char *zArg2,
1166 const char *zArg3,
1167 const char *zArg4
drhe22a3342003-04-22 20:30:371168){
mistachkin6ef5e122014-01-24 17:03:551169 const char *zCode;
drhe22a3342003-04-22 20:30:371170 Tcl_DString str;
1171 int rc;
1172 const char *zReply;
drh94189212017-05-11 13:43:571173 /* EVIDENCE-OF: R-38590-62769 The first parameter to the authorizer
1174 ** callback is a copy of the third parameter to the
1175 ** sqlite3_set_authorizer() interface.
1176 */
drhe22a3342003-04-22 20:30:371177 SqliteDb *pDb = (SqliteDb*)pArg;
drh1f1549f2008-08-26 21:33:341178 if( pDb->disableAuth ) return SQLITE_OK;
drhe22a3342003-04-22 20:30:371179
drh94189212017-05-11 13:43:571180 /* EVIDENCE-OF: R-56518-44310 The second parameter to the callback is an
1181 ** integer action code that specifies the particular action to be
1182 ** authorized. */
drhe22a3342003-04-22 20:30:371183 switch( code ){
1184 case SQLITE_COPY : zCode="SQLITE_COPY"; break;
1185 case SQLITE_CREATE_INDEX : zCode="SQLITE_CREATE_INDEX"; break;
1186 case SQLITE_CREATE_TABLE : zCode="SQLITE_CREATE_TABLE"; break;
1187 case SQLITE_CREATE_TEMP_INDEX : zCode="SQLITE_CREATE_TEMP_INDEX"; break;
1188 case SQLITE_CREATE_TEMP_TABLE : zCode="SQLITE_CREATE_TEMP_TABLE"; break;
1189 case SQLITE_CREATE_TEMP_TRIGGER: zCode="SQLITE_CREATE_TEMP_TRIGGER"; break;
1190 case SQLITE_CREATE_TEMP_VIEW : zCode="SQLITE_CREATE_TEMP_VIEW"; break;
1191 case SQLITE_CREATE_TRIGGER : zCode="SQLITE_CREATE_TRIGGER"; break;
1192 case SQLITE_CREATE_VIEW : zCode="SQLITE_CREATE_VIEW"; break;
1193 case SQLITE_DELETE : zCode="SQLITE_DELETE"; break;
1194 case SQLITE_DROP_INDEX : zCode="SQLITE_DROP_INDEX"; break;
1195 case SQLITE_DROP_TABLE : zCode="SQLITE_DROP_TABLE"; break;
1196 case SQLITE_DROP_TEMP_INDEX : zCode="SQLITE_DROP_TEMP_INDEX"; break;
1197 case SQLITE_DROP_TEMP_TABLE : zCode="SQLITE_DROP_TEMP_TABLE"; break;
1198 case SQLITE_DROP_TEMP_TRIGGER : zCode="SQLITE_DROP_TEMP_TRIGGER"; break;
1199 case SQLITE_DROP_TEMP_VIEW : zCode="SQLITE_DROP_TEMP_VIEW"; break;
1200 case SQLITE_DROP_TRIGGER : zCode="SQLITE_DROP_TRIGGER"; break;
1201 case SQLITE_DROP_VIEW : zCode="SQLITE_DROP_VIEW"; break;
1202 case SQLITE_INSERT : zCode="SQLITE_INSERT"; break;
1203 case SQLITE_PRAGMA : zCode="SQLITE_PRAGMA"; break;
1204 case SQLITE_READ : zCode="SQLITE_READ"; break;
1205 case SQLITE_SELECT : zCode="SQLITE_SELECT"; break;
1206 case SQLITE_TRANSACTION : zCode="SQLITE_TRANSACTION"; break;
1207 case SQLITE_UPDATE : zCode="SQLITE_UPDATE"; break;
drh81e293b2003-06-06 19:00:421208 case SQLITE_ATTACH : zCode="SQLITE_ATTACH"; break;
1209 case SQLITE_DETACH : zCode="SQLITE_DETACH"; break;
danielk19771c8c23c2004-11-12 15:53:371210 case SQLITE_ALTER_TABLE : zCode="SQLITE_ALTER_TABLE"; break;
danielk19771d54df82004-11-23 15:41:161211 case SQLITE_REINDEX : zCode="SQLITE_REINDEX"; break;
drhe6e04962005-07-23 02:17:031212 case SQLITE_ANALYZE : zCode="SQLITE_ANALYZE"; break;
danielk1977f1a381e2006-06-16 08:01:021213 case SQLITE_CREATE_VTABLE : zCode="SQLITE_CREATE_VTABLE"; break;
1214 case SQLITE_DROP_VTABLE : zCode="SQLITE_DROP_VTABLE"; break;
drh5169bbc2006-08-24 14:59:451215 case SQLITE_FUNCTION : zCode="SQLITE_FUNCTION"; break;
danielk1977ab9b7032008-12-30 06:24:581216 case SQLITE_SAVEPOINT : zCode="SQLITE_SAVEPOINT"; break;
drh65a2aaa2014-01-16 22:40:021217 case SQLITE_RECURSIVE : zCode="SQLITE_RECURSIVE"; break;
drhe22a3342003-04-22 20:30:371218 default : zCode="????"; break;
1219 }
1220 Tcl_DStringInit(&str);
1221 Tcl_DStringAppend(&str, pDb->zAuth, -1);
1222 Tcl_DStringAppendElement(&str, zCode);
1223 Tcl_DStringAppendElement(&str, zArg1 ? zArg1 : "");
1224 Tcl_DStringAppendElement(&str, zArg2 ? zArg2 : "");
1225 Tcl_DStringAppendElement(&str, zArg3 ? zArg3 : "");
1226 Tcl_DStringAppendElement(&str, zArg4 ? zArg4 : "");
drhe22a3342003-04-22 20:30:371227 rc = Tcl_GlobalEval(pDb->interp, Tcl_DStringValue(&str));
1228 Tcl_DStringFree(&str);
drhb07028f2011-10-14 21:49:181229 zReply = rc==TCL_OK ? Tcl_GetStringResult(pDb->interp) : "SQLITE_DENY";
drhe22a3342003-04-22 20:30:371230 if( strcmp(zReply,"SQLITE_OK")==0 ){
1231 rc = SQLITE_OK;
1232 }else if( strcmp(zReply,"SQLITE_DENY")==0 ){
1233 rc = SQLITE_DENY;
1234 }else if( strcmp(zReply,"SQLITE_IGNORE")==0 ){
1235 rc = SQLITE_IGNORE;
1236 }else{
1237 rc = 999;
1238 }
1239 return rc;
1240}
1241#endif /* SQLITE_OMIT_AUTHORIZATION */
drhcabb0812002-09-14 13:47:321242
stephane34ad2b2025-03-04 21:25:181243#if 0
drhcabb0812002-09-14 13:47:321244/*
tpoindex1067fe12004-12-17 15:41:111245** This routine reads a line of text from FILE in, stores
1246** the text in memory obtained from malloc() and returns a pointer
1247** to the text. NULL is returned at end of file, or if malloc()
1248** fails.
1249**
1250** The interface is like "readline" but no command-line editing
1251** is done.
1252**
1253** copied from shell.c from '.import' command
1254*/
1255static char *local_getline(char *zPrompt, FILE *in){
1256 char *zLine;
1257 int nLine;
1258 int n;
tpoindex1067fe12004-12-17 15:41:111259
1260 nLine = 100;
1261 zLine = malloc( nLine );
1262 if( zLine==0 ) return 0;
1263 n = 0;
drhb07028f2011-10-14 21:49:181264 while( 1 ){
tpoindex1067fe12004-12-17 15:41:111265 if( n+100>nLine ){
1266 nLine = nLine*2 + 100;
1267 zLine = realloc(zLine, nLine);
1268 if( zLine==0 ) return 0;
1269 }
1270 if( fgets(&zLine[n], nLine - n, in)==0 ){
1271 if( n==0 ){
1272 free(zLine);
1273 return 0;
1274 }
1275 zLine[n] = 0;
tpoindex1067fe12004-12-17 15:41:111276 break;
1277 }
1278 while( zLine[n] ){ n++; }
1279 if( n>0 && zLine[n-1]=='\n' ){
1280 n--;
1281 zLine[n] = 0;
drhb07028f2011-10-14 21:49:181282 break;
tpoindex1067fe12004-12-17 15:41:111283 }
1284 }
1285 zLine = realloc( zLine, n+1 );
1286 return zLine;
1287}
stephane34ad2b2025-03-04 21:25:181288#endif
tpoindex1067fe12004-12-17 15:41:111289
danielk19778e556522007-11-13 10:30:241290
1291/*
dan4a4c11a2009-10-06 14:59:021292** This function is part of the implementation of the command:
danielk19778e556522007-11-13 10:30:241293**
dan4a4c11a2009-10-06 14:59:021294** $db transaction [-deferred|-immediate|-exclusive] SCRIPT
danielk19778e556522007-11-13 10:30:241295**
dan4a4c11a2009-10-06 14:59:021296** It is invoked after evaluating the script SCRIPT to commit or rollback
1297** the transaction or savepoint opened by the [transaction] command.
1298*/
mistachkina121cc72016-07-28 18:06:521299static int SQLITE_TCLAPI DbTransPostCmd(
dan4a4c11a2009-10-06 14:59:021300 ClientData data[], /* data[0] is the Sqlite3Db* for $db */
1301 Tcl_Interp *interp, /* Tcl interpreter */
1302 int result /* Result of evaluating SCRIPT */
1303){
mistachkin6ef5e122014-01-24 17:03:551304 static const char *const azEnd[] = {
dan4a4c11a2009-10-06 14:59:021305 "RELEASE _tcl_transaction", /* rc==TCL_ERROR, nTransaction!=0 */
1306 "COMMIT", /* rc!=TCL_ERROR, nTransaction==0 */
1307 "ROLLBACK TO _tcl_transaction ; RELEASE _tcl_transaction",
1308 "ROLLBACK" /* rc==TCL_ERROR, nTransaction==0 */
1309 };
1310 SqliteDb *pDb = (SqliteDb*)data[0];
1311 int rc = result;
1312 const char *zEnd;
1313
1314 pDb->nTransaction--;
1315 zEnd = azEnd[(rc==TCL_ERROR)*2 + (pDb->nTransaction==0)];
1316
1317 pDb->disableAuth++;
1318 if( sqlite3_exec(pDb->db, zEnd, 0, 0, 0) ){
1319 /* This is a tricky scenario to handle. The most likely cause of an
mistachkinb56660f2016-07-14 21:26:091320 ** error is that the exec() above was an attempt to commit the
dan4a4c11a2009-10-06 14:59:021321 ** top-level transaction that returned SQLITE_BUSY. Or, less likely,
mistachkin48864df2013-03-21 21:20:321322 ** that an IO-error has occurred. In either case, throw a Tcl exception
dan4a4c11a2009-10-06 14:59:021323 ** and try to rollback the transaction.
1324 **
mistachkinb56660f2016-07-14 21:26:091325 ** But it could also be that the user executed one or more BEGIN,
dan4a4c11a2009-10-06 14:59:021326 ** COMMIT, SAVEPOINT, RELEASE or ROLLBACK commands that are confusing
1327 ** this method's logic. Not clear how this would be best handled.
1328 */
1329 if( rc!=TCL_ERROR ){
drha198f2b2014-02-07 19:26:131330 Tcl_AppendResult(interp, sqlite3_errmsg(pDb->db), (char*)0);
dan4a4c11a2009-10-06 14:59:021331 rc = TCL_ERROR;
1332 }
1333 sqlite3_exec(pDb->db, "ROLLBACK", 0, 0, 0);
1334 }
1335 pDb->disableAuth--;
1336
danbea28c72021-09-16 14:17:141337 delDatabaseRef(pDb);
dan4a4c11a2009-10-06 14:59:021338 return rc;
1339}
1340
1341/*
danc431fd52011-06-27 16:55:501342** Unless SQLITE_TEST is defined, this function is a simple wrapper around
1343** sqlite3_prepare_v2(). If SQLITE_TEST is defined, then it uses either
1344** sqlite3_prepare_v2() or legacy interface sqlite3_prepare(), depending
mistachkinb56660f2016-07-14 21:26:091345** on whether or not the [db_use_legacy_prepare] command has been used to
danc431fd52011-06-27 16:55:501346** configure the connection.
1347*/
1348static int dbPrepare(
1349 SqliteDb *pDb, /* Database object */
1350 const char *zSql, /* SQL to compile */
1351 sqlite3_stmt **ppStmt, /* OUT: Prepared statement */
1352 const char **pzOut /* OUT: Pointer to next SQL statement */
1353){
drh2c2f3922017-06-01 00:54:351354 unsigned int prepFlags = 0;
danc431fd52011-06-27 16:55:501355#ifdef SQLITE_TEST
1356 if( pDb->bLegacyPrepare ){
1357 return sqlite3_prepare(pDb->db, zSql, -1, ppStmt, pzOut);
1358 }
1359#endif
drh2c2f3922017-06-01 00:54:351360 /* If the statement cache is large, use the SQLITE_PREPARE_PERSISTENT
1361 ** flags, which uses less lookaside memory. But if the cache is small,
1362 ** omit that flag to make full use of lookaside */
1363 if( pDb->maxStmt>5 ) prepFlags = SQLITE_PREPARE_PERSISTENT;
1364
1365 return sqlite3_prepare_v3(pDb->db, zSql, -1, prepFlags, ppStmt, pzOut);
danc431fd52011-06-27 16:55:501366}
1367
1368/*
dan4a4c11a2009-10-06 14:59:021369** Search the cache for a prepared-statement object that implements the
1370** first SQL statement in the buffer pointed to by parameter zIn. If
1371** no such prepared-statement can be found, allocate and prepare a new
1372** one. In either case, bind the current values of the relevant Tcl
1373** variables to any $var, :var or @var variables in the statement. Before
1374** returning, set *ppPreStmt to point to the prepared-statement object.
1375**
1376** Output parameter *pzOut is set to point to the next SQL statement in
1377** buffer zIn, or to the '\0' byte at the end of zIn if there is no
1378** next statement.
1379**
1380** If successful, TCL_OK is returned. Otherwise, TCL_ERROR is returned
1381** and an error message loaded into interpreter pDb->interp.
1382*/
1383static int dbPrepareAndBind(
1384 SqliteDb *pDb, /* Database object */
1385 char const *zIn, /* SQL to compile */
1386 char const **pzOut, /* OUT: Pointer to next SQL statement */
1387 SqlPreparedStmt **ppPreStmt /* OUT: Object used to cache statement */
1388){
1389 const char *zSql = zIn; /* Pointer to first SQL statement in zIn */
mistachkin7bb22ac2015-01-12 19:59:121390 sqlite3_stmt *pStmt = 0; /* Prepared statement object */
dan4a4c11a2009-10-06 14:59:021391 SqlPreparedStmt *pPreStmt; /* Pointer to cached statement */
1392 int nSql; /* Length of zSql in bytes */
mistachkin7bb22ac2015-01-12 19:59:121393 int nVar = 0; /* Number of variables in statement */
dan4a4c11a2009-10-06 14:59:021394 int iParm = 0; /* Next free entry in apParm */
drh0425f182013-11-26 16:48:041395 char c;
dan4a4c11a2009-10-06 14:59:021396 int i;
drhc06ede12019-02-28 17:29:191397 int needResultReset = 0; /* Need to invoke Tcl_ResetResult() */
1398 int rc = SQLITE_OK; /* Value to return */
dan4a4c11a2009-10-06 14:59:021399 Tcl_Interp *interp = pDb->interp;
1400
1401 *ppPreStmt = 0;
1402
1403 /* Trim spaces from the start of zSql and calculate the remaining length. */
drh0425f182013-11-26 16:48:041404 while( (c = zSql[0])==' ' || c=='\t' || c=='\r' || c=='\n' ){ zSql++; }
dan4a4c11a2009-10-06 14:59:021405 nSql = strlen30(zSql);
1406
1407 for(pPreStmt = pDb->stmtList; pPreStmt; pPreStmt=pPreStmt->pNext){
1408 int n = pPreStmt->nSql;
mistachkinb56660f2016-07-14 21:26:091409 if( nSql>=n
dan4a4c11a2009-10-06 14:59:021410 && memcmp(pPreStmt->zSql, zSql, n)==0
1411 && (zSql[n]==0 || zSql[n-1]==';')
1412 ){
1413 pStmt = pPreStmt->pStmt;
1414 *pzOut = &zSql[pPreStmt->nSql];
1415
1416 /* When a prepared statement is found, unlink it from the
1417 ** cache list. It will later be added back to the beginning
1418 ** of the cache list in order to implement LRU replacement.
1419 */
1420 if( pPreStmt->pPrev ){
1421 pPreStmt->pPrev->pNext = pPreStmt->pNext;
1422 }else{
1423 pDb->stmtList = pPreStmt->pNext;
1424 }
1425 if( pPreStmt->pNext ){
1426 pPreStmt->pNext->pPrev = pPreStmt->pPrev;
1427 }else{
1428 pDb->stmtLast = pPreStmt->pPrev;
1429 }
1430 pDb->nStmt--;
1431 nVar = sqlite3_bind_parameter_count(pStmt);
1432 break;
1433 }
1434 }
mistachkinb56660f2016-07-14 21:26:091435
dan4a4c11a2009-10-06 14:59:021436 /* If no prepared statement was found. Compile the SQL text. Also allocate
1437 ** a new SqlPreparedStmt structure. */
1438 if( pPreStmt==0 ){
1439 int nByte;
1440
danc431fd52011-06-27 16:55:501441 if( SQLITE_OK!=dbPrepare(pDb, zSql, &pStmt, pzOut) ){
drhc45e6712012-10-03 11:02:331442 Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3_errmsg(pDb->db), -1));
dan4a4c11a2009-10-06 14:59:021443 return TCL_ERROR;
1444 }
1445 if( pStmt==0 ){
1446 if( SQLITE_OK!=sqlite3_errcode(pDb->db) ){
1447 /* A compile-time error in the statement. */
drhc45e6712012-10-03 11:02:331448 Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3_errmsg(pDb->db), -1));
dan4a4c11a2009-10-06 14:59:021449 return TCL_ERROR;
1450 }else{
1451 /* The statement was a no-op. Continue to the next statement
1452 ** in the SQL string.
1453 */
1454 return TCL_OK;
1455 }
1456 }
1457
1458 assert( pPreStmt==0 );
1459 nVar = sqlite3_bind_parameter_count(pStmt);
1460 nByte = sizeof(SqlPreparedStmt) + nVar*sizeof(Tcl_Obj *);
1461 pPreStmt = (SqlPreparedStmt*)Tcl_Alloc(nByte);
1462 memset(pPreStmt, 0, nByte);
1463
1464 pPreStmt->pStmt = pStmt;
drh7ed243b2012-04-19 17:19:511465 pPreStmt->nSql = (int)(*pzOut - zSql);
dan4a4c11a2009-10-06 14:59:021466 pPreStmt->zSql = sqlite3_sql(pStmt);
1467 pPreStmt->apParm = (Tcl_Obj **)&pPreStmt[1];
danc431fd52011-06-27 16:55:501468#ifdef SQLITE_TEST
1469 if( pPreStmt->zSql==0 ){
1470 char *zCopy = Tcl_Alloc(pPreStmt->nSql + 1);
1471 memcpy(zCopy, zSql, pPreStmt->nSql);
1472 zCopy[pPreStmt->nSql] = '\0';
1473 pPreStmt->zSql = zCopy;
1474 }
1475#endif
dan4a4c11a2009-10-06 14:59:021476 }
1477 assert( pPreStmt );
1478 assert( strlen30(pPreStmt->zSql)==pPreStmt->nSql );
1479 assert( 0==memcmp(pPreStmt->zSql, zSql, pPreStmt->nSql) );
1480
mistachkinb56660f2016-07-14 21:26:091481 /* Bind values to parameters that begin with $ or : */
dan4a4c11a2009-10-06 14:59:021482 for(i=1; i<=nVar; i++){
1483 const char *zVar = sqlite3_bind_parameter_name(pStmt, i);
1484 if( zVar!=0 && (zVar[0]=='$' || zVar[0]==':' || zVar[0]=='@') ){
1485 Tcl_Obj *pVar = Tcl_GetVar2Ex(interp, &zVar[1], 0, 0);
drhc06ede12019-02-28 17:29:191486 if( pVar==0 && pDb->zBindFallback!=0 ){
1487 Tcl_Obj *pCmd;
1488 int rx;
1489 pCmd = Tcl_NewStringObj(pDb->zBindFallback, -1);
1490 Tcl_IncrRefCount(pCmd);
1491 Tcl_ListObjAppendElement(interp, pCmd, Tcl_NewStringObj(zVar,-1));
1492 if( needResultReset ) Tcl_ResetResult(interp);
1493 needResultReset = 1;
1494 rx = Tcl_EvalObjEx(interp, pCmd, TCL_EVAL_DIRECT);
1495 Tcl_DecrRefCount(pCmd);
1496 if( rx==TCL_OK ){
1497 pVar = Tcl_GetObjResult(interp);
1498 }else if( rx==TCL_ERROR ){
1499 rc = TCL_ERROR;
1500 break;
1501 }else{
1502 pVar = 0;
1503 }
1504 }
dan4a4c11a2009-10-06 14:59:021505 if( pVar ){
drh064b6812024-07-30 15:49:021506 Tcl_Size n;
dan4a4c11a2009-10-06 14:59:021507 u8 *data;
1508 const char *zType = (pVar->typePtr ? pVar->typePtr->name : "");
mistachkin8e189222015-04-19 21:43:161509 c = zType[0];
dan4a4c11a2009-10-06 14:59:021510 if( zVar[0]=='@' ||
1511 (c=='b' && strcmp(zType,"bytearray")==0 && pVar->bytes==0) ){
1512 /* Load a BLOB type if the Tcl variable is a bytearray and
1513 ** it has no string representation or the host
1514 ** parameter name begins with "@". */
1515 data = Tcl_GetByteArrayFromObj(pVar, &n);
1516 sqlite3_bind_blob(pStmt, i, data, n, SQLITE_STATIC);
1517 Tcl_IncrRefCount(pVar);
1518 pPreStmt->apParm[iParm++] = pVar;
drhfd11e5c2025-01-07 16:36:471519 }else if( c=='b' && pVar->bytes==0
1520 && (strcmp(zType,"booleanString")==0
1521 || strcmp(zType,"boolean")==0)
1522 ){
drh064b6812024-07-30 15:49:021523 int nn;
drhfd11e5c2025-01-07 16:36:471524 Tcl_GetBooleanFromObj(interp, pVar, &nn);
drh064b6812024-07-30 15:49:021525 sqlite3_bind_int(pStmt, i, nn);
dan4a4c11a2009-10-06 14:59:021526 }else if( c=='d' && strcmp(zType,"double")==0 ){
1527 double r;
1528 Tcl_GetDoubleFromObj(interp, pVar, &r);
1529 sqlite3_bind_double(pStmt, i, r);
1530 }else if( (c=='w' && strcmp(zType,"wideInt")==0) ||
1531 (c=='i' && strcmp(zType,"int")==0) ){
1532 Tcl_WideInt v;
1533 Tcl_GetWideIntFromObj(interp, pVar, &v);
1534 sqlite3_bind_int64(pStmt, i, v);
1535 }else{
1536 data = (unsigned char *)Tcl_GetStringFromObj(pVar, &n);
drhe57527c2024-12-09 20:46:361537 sqlite3_bind_text64(pStmt, i, (char *)data, n, SQLITE_STATIC,
1538 SQLITE_UTF8);
dan4a4c11a2009-10-06 14:59:021539 Tcl_IncrRefCount(pVar);
1540 pPreStmt->apParm[iParm++] = pVar;
1541 }
1542 }else{
1543 sqlite3_bind_null(pStmt, i);
1544 }
drhc06ede12019-02-28 17:29:191545 if( needResultReset ) Tcl_ResetResult(pDb->interp);
dan4a4c11a2009-10-06 14:59:021546 }
1547 }
1548 pPreStmt->nParm = iParm;
1549 *ppPreStmt = pPreStmt;
drhc06ede12019-02-28 17:29:191550 if( needResultReset && rc==TCL_OK ) Tcl_ResetResult(pDb->interp);
dan937d0de2009-10-15 18:35:381551
drhc06ede12019-02-28 17:29:191552 return rc;
dan4a4c11a2009-10-06 14:59:021553}
1554
dan4a4c11a2009-10-06 14:59:021555/*
1556** Release a statement reference obtained by calling dbPrepareAndBind().
1557** There should be exactly one call to this function for each call to
1558** dbPrepareAndBind().
1559**
1560** If the discard parameter is non-zero, then the statement is deleted
1561** immediately. Otherwise it is added to the LRU list and may be returned
1562** by a subsequent call to dbPrepareAndBind().
1563*/
1564static void dbReleaseStmt(
1565 SqliteDb *pDb, /* Database handle */
1566 SqlPreparedStmt *pPreStmt, /* Prepared statement handle to release */
1567 int discard /* True to delete (not cache) the pPreStmt */
1568){
1569 int i;
1570
1571 /* Free the bound string and blob parameters */
1572 for(i=0; i<pPreStmt->nParm; i++){
1573 Tcl_DecrRefCount(pPreStmt->apParm[i]);
1574 }
1575 pPreStmt->nParm = 0;
1576
1577 if( pDb->maxStmt<=0 || discard ){
1578 /* If the cache is turned off, deallocated the statement */
danc431fd52011-06-27 16:55:501579 dbFreeStmt(pPreStmt);
dan4a4c11a2009-10-06 14:59:021580 }else{
1581 /* Add the prepared statement to the beginning of the cache list. */
1582 pPreStmt->pNext = pDb->stmtList;
1583 pPreStmt->pPrev = 0;
1584 if( pDb->stmtList ){
1585 pDb->stmtList->pPrev = pPreStmt;
1586 }
1587 pDb->stmtList = pPreStmt;
1588 if( pDb->stmtLast==0 ){
1589 assert( pDb->nStmt==0 );
1590 pDb->stmtLast = pPreStmt;
1591 }else{
1592 assert( pDb->nStmt>0 );
1593 }
1594 pDb->nStmt++;
mistachkinb56660f2016-07-14 21:26:091595
1596 /* If we have too many statement in cache, remove the surplus from
dan4a4c11a2009-10-06 14:59:021597 ** the end of the cache list. */
1598 while( pDb->nStmt>pDb->maxStmt ){
danc431fd52011-06-27 16:55:501599 SqlPreparedStmt *pLast = pDb->stmtLast;
1600 pDb->stmtLast = pLast->pPrev;
dan4a4c11a2009-10-06 14:59:021601 pDb->stmtLast->pNext = 0;
1602 pDb->nStmt--;
danc431fd52011-06-27 16:55:501603 dbFreeStmt(pLast);
dan4a4c11a2009-10-06 14:59:021604 }
1605 }
1606}
1607
1608/*
1609** Structure used with dbEvalXXX() functions:
1610**
1611** dbEvalInit()
1612** dbEvalStep()
1613** dbEvalFinalize()
1614** dbEvalRowInfo()
1615** dbEvalColumnValue()
1616*/
1617typedef struct DbEvalContext DbEvalContext;
1618struct DbEvalContext {
1619 SqliteDb *pDb; /* Database handle */
1620 Tcl_Obj *pSql; /* Object holding string zSql */
1621 const char *zSql; /* Remaining SQL to execute */
1622 SqlPreparedStmt *pPreStmt; /* Current statement */
1623 int nCol; /* Number of columns returned by pStmt */
drhaf38cdb2017-06-26 21:08:321624 int evalFlags; /* Flags used */
stephan10206572025-05-31 11:02:061625 Tcl_Obj *pVarName; /* Name of target array/dict variable */
dan4a4c11a2009-10-06 14:59:021626 Tcl_Obj **apColName; /* Array of column names */
1627};
1628
drhaf38cdb2017-06-26 21:08:321629#define SQLITE_EVAL_WITHOUTNULLS 0x00001 /* Unset array(*) for NULL */
stephan10206572025-05-31 11:02:061630#define SQLITE_EVAL_ASDICT 0x00002 /* Use dict instead of array */
drhaf38cdb2017-06-26 21:08:321631
dan4a4c11a2009-10-06 14:59:021632/*
1633** Release any cache of column names currently held as part of
1634** the DbEvalContext structure passed as the first argument.
1635*/
1636static void dbReleaseColumnNames(DbEvalContext *p){
1637 if( p->apColName ){
1638 int i;
1639 for(i=0; i<p->nCol; i++){
1640 Tcl_DecrRefCount(p->apColName[i]);
1641 }
1642 Tcl_Free((char *)p->apColName);
1643 p->apColName = 0;
1644 }
1645 p->nCol = 0;
1646}
1647
1648/*
1649** Initialize a DbEvalContext structure.
danielk19778e556522007-11-13 10:30:241650**
stephan10206572025-05-31 11:02:061651** If pVarName is not NULL, then it contains the name of a Tcl array
danielk19778e556522007-11-13 10:30:241652** variable. The "*" member of this array is set to a list containing
dan4a4c11a2009-10-06 14:59:021653** the names of the columns returned by the statement as part of each
mistachkinb56660f2016-07-14 21:26:091654** call to dbEvalStep(), in order from left to right. e.g. if the names
1655** of the returned columns are a, b and c, it does the equivalent of the
dan4a4c11a2009-10-06 14:59:021656** tcl command:
danielk19778e556522007-11-13 10:30:241657**
stephan10206572025-05-31 11:02:061658** set ${pVarName}(*) {a b c}
danielk19778e556522007-11-13 10:30:241659*/
dan4a4c11a2009-10-06 14:59:021660static void dbEvalInit(
1661 DbEvalContext *p, /* Pointer to structure to initialize */
1662 SqliteDb *pDb, /* Database handle */
1663 Tcl_Obj *pSql, /* Object containing SQL script */
stephan10206572025-05-31 11:02:061664 Tcl_Obj *pVarName, /* Name of Tcl array to set (*) element of */
drhaf38cdb2017-06-26 21:08:321665 int evalFlags /* Flags controlling evaluation */
danielk19778e556522007-11-13 10:30:241666){
dan4a4c11a2009-10-06 14:59:021667 memset(p, 0, sizeof(DbEvalContext));
1668 p->pDb = pDb;
1669 p->zSql = Tcl_GetString(pSql);
1670 p->pSql = pSql;
1671 Tcl_IncrRefCount(pSql);
stephan10206572025-05-31 11:02:061672 if( pVarName ){
1673 p->pVarName = pVarName;
1674 Tcl_IncrRefCount(pVarName);
dan4a4c11a2009-10-06 14:59:021675 }
drhaf38cdb2017-06-26 21:08:321676 p->evalFlags = evalFlags;
danbea28c72021-09-16 14:17:141677 addDatabaseRef(p->pDb);
dan4a4c11a2009-10-06 14:59:021678}
danielk19778e556522007-11-13 10:30:241679
dan4a4c11a2009-10-06 14:59:021680/*
1681** Obtain information about the row that the DbEvalContext passed as the
1682** first argument currently points to.
1683*/
1684static void dbEvalRowInfo(
1685 DbEvalContext *p, /* Evaluation context */
1686 int *pnCol, /* OUT: Number of column names */
1687 Tcl_Obj ***papColName /* OUT: Array of column names */
1688){
danielk19778e556522007-11-13 10:30:241689 /* Compute column names */
dan4a4c11a2009-10-06 14:59:021690 if( 0==p->apColName ){
1691 sqlite3_stmt *pStmt = p->pPreStmt->pStmt;
1692 int i; /* Iterator variable */
1693 int nCol; /* Number of columns returned by pStmt */
1694 Tcl_Obj **apColName = 0; /* Array of column names */
1695
1696 p->nCol = nCol = sqlite3_column_count(pStmt);
stephan10206572025-05-31 11:02:061697 if( nCol>0 && (papColName || p->pVarName) ){
dan4a4c11a2009-10-06 14:59:021698 apColName = (Tcl_Obj**)Tcl_Alloc( sizeof(Tcl_Obj*)*nCol );
1699 for(i=0; i<nCol; i++){
drhc45e6712012-10-03 11:02:331700 apColName[i] = Tcl_NewStringObj(sqlite3_column_name(pStmt,i), -1);
dan4a4c11a2009-10-06 14:59:021701 Tcl_IncrRefCount(apColName[i]);
1702 }
1703 p->apColName = apColName;
danielk19778e556522007-11-13 10:30:241704 }
1705
stephan10206572025-05-31 11:02:061706 /* If results are being stored in a variable then create the
1707 ** array(*) or dict(*) entry for that variable.
danielk19778e556522007-11-13 10:30:241708 */
stephan10206572025-05-31 11:02:061709 if( p->pVarName ){
dan4a4c11a2009-10-06 14:59:021710 Tcl_Interp *interp = p->pDb->interp;
danielk19778e556522007-11-13 10:30:241711 Tcl_Obj *pColList = Tcl_NewObj();
1712 Tcl_Obj *pStar = Tcl_NewStringObj("*", -1);
dan4a4c11a2009-10-06 14:59:021713
stephan10206572025-05-31 11:02:061714 Tcl_IncrRefCount(pColList);
1715 Tcl_IncrRefCount(pStar);
danielk19778e556522007-11-13 10:30:241716 for(i=0; i<nCol; i++){
1717 Tcl_ListObjAppendElement(interp, pColList, apColName[i]);
1718 }
stephan10206572025-05-31 11:02:061719 if( 0==(SQLITE_EVAL_ASDICT & p->evalFlags) ){
1720 Tcl_ObjSetVar2(interp, p->pVarName, pStar, pColList, 0);
1721 }else{
1722 Tcl_Obj * pDict = Tcl_ObjGetVar2(interp, p->pVarName, NULL, 0);
1723 if( !pDict ){
1724 pDict = Tcl_NewDictObj();
1725 }else if( Tcl_IsShared(pDict) ){
1726 pDict = Tcl_DuplicateObj(pDict);
1727 }
1728 if( Tcl_DictObjPut(interp, pDict, pStar, pColList)==TCL_OK ){
1729 Tcl_ObjSetVar2(interp, p->pVarName, NULL, pDict, 0);
1730 }
1731 Tcl_BounceRefCount(pDict);
1732 }
danielk19778e556522007-11-13 10:30:241733 Tcl_DecrRefCount(pStar);
stephan10206572025-05-31 11:02:061734 Tcl_DecrRefCount(pColList);
danielk19778e556522007-11-13 10:30:241735 }
danielk19778e556522007-11-13 10:30:241736 }
1737
dan4a4c11a2009-10-06 14:59:021738 if( papColName ){
1739 *papColName = p->apColName;
1740 }
1741 if( pnCol ){
1742 *pnCol = p->nCol;
1743 }
1744}
1745
1746/*
1747** Return one of TCL_OK, TCL_BREAK or TCL_ERROR. If TCL_ERROR is
1748** returned, then an error message is stored in the interpreter before
1749** returning.
1750**
1751** A return value of TCL_OK means there is a row of data available. The
1752** data may be accessed using dbEvalRowInfo() and dbEvalColumnValue(). This
1753** is analogous to a return of SQLITE_ROW from sqlite3_step(). If TCL_BREAK
1754** is returned, then the SQL script has finished executing and there are
1755** no further rows available. This is similar to SQLITE_DONE.
1756*/
1757static int dbEvalStep(DbEvalContext *p){
danc431fd52011-06-27 16:55:501758 const char *zPrevSql = 0; /* Previous value of p->zSql */
1759
dan4a4c11a2009-10-06 14:59:021760 while( p->zSql[0] || p->pPreStmt ){
1761 int rc;
1762 if( p->pPreStmt==0 ){
danc431fd52011-06-27 16:55:501763 zPrevSql = (p->zSql==zPrevSql ? 0 : p->zSql);
dan4a4c11a2009-10-06 14:59:021764 rc = dbPrepareAndBind(p->pDb, p->zSql, &p->zSql, &p->pPreStmt);
1765 if( rc!=TCL_OK ) return rc;
1766 }else{
1767 int rcs;
1768 SqliteDb *pDb = p->pDb;
1769 SqlPreparedStmt *pPreStmt = p->pPreStmt;
1770 sqlite3_stmt *pStmt = pPreStmt->pStmt;
1771
1772 rcs = sqlite3_step(pStmt);
1773 if( rcs==SQLITE_ROW ){
1774 return TCL_OK;
1775 }
stephan10206572025-05-31 11:02:061776 if( p->pVarName ){
dan4a4c11a2009-10-06 14:59:021777 dbEvalRowInfo(p, 0, 0);
1778 }
1779 rcs = sqlite3_reset(pStmt);
1780
1781 pDb->nStep = sqlite3_stmt_status(pStmt,SQLITE_STMTSTATUS_FULLSCAN_STEP,1);
1782 pDb->nSort = sqlite3_stmt_status(pStmt,SQLITE_STMTSTATUS_SORT,1);
drh3c379b02010-04-07 19:31:591783 pDb->nIndex = sqlite3_stmt_status(pStmt,SQLITE_STMTSTATUS_AUTOINDEX,1);
danc456a762017-06-22 16:51:161784 pDb->nVMStep = sqlite3_stmt_status(pStmt,SQLITE_STMTSTATUS_VM_STEP,1);
dan4a4c11a2009-10-06 14:59:021785 dbReleaseColumnNames(p);
1786 p->pPreStmt = 0;
1787
1788 if( rcs!=SQLITE_OK ){
1789 /* If a run-time error occurs, report the error and stop reading
1790 ** the SQL. */
dan4a4c11a2009-10-06 14:59:021791 dbReleaseStmt(pDb, pPreStmt, 1);
danc431fd52011-06-27 16:55:501792#if SQLITE_TEST
1793 if( p->pDb->bLegacyPrepare && rcs==SQLITE_SCHEMA && zPrevSql ){
1794 /* If the runtime error was an SQLITE_SCHEMA, and the database
mistachkinb56660f2016-07-14 21:26:091795 ** handle is configured to use the legacy sqlite3_prepare()
danc431fd52011-06-27 16:55:501796 ** interface, retry prepare()/step() on the same SQL statement.
1797 ** This only happens once. If there is a second SQLITE_SCHEMA
1798 ** error, the error will be returned to the caller. */
1799 p->zSql = zPrevSql;
1800 continue;
1801 }
1802#endif
drhc45e6712012-10-03 11:02:331803 Tcl_SetObjResult(pDb->interp,
1804 Tcl_NewStringObj(sqlite3_errmsg(pDb->db), -1));
dan4a4c11a2009-10-06 14:59:021805 return TCL_ERROR;
1806 }else{
1807 dbReleaseStmt(pDb, pPreStmt, 0);
1808 }
1809 }
1810 }
1811
1812 /* Finished */
1813 return TCL_BREAK;
1814}
1815
1816/*
1817** Free all resources currently held by the DbEvalContext structure passed
1818** as the first argument. There should be exactly one call to this function
1819** for each call to dbEvalInit().
1820*/
1821static void dbEvalFinalize(DbEvalContext *p){
1822 if( p->pPreStmt ){
1823 sqlite3_reset(p->pPreStmt->pStmt);
1824 dbReleaseStmt(p->pDb, p->pPreStmt, 0);
1825 p->pPreStmt = 0;
1826 }
stephan10206572025-05-31 11:02:061827 if( p->pVarName ){
1828 Tcl_DecrRefCount(p->pVarName);
1829 p->pVarName = 0;
dan4a4c11a2009-10-06 14:59:021830 }
1831 Tcl_DecrRefCount(p->pSql);
1832 dbReleaseColumnNames(p);
danbea28c72021-09-16 14:17:141833 delDatabaseRef(p->pDb);
dan4a4c11a2009-10-06 14:59:021834}
1835
1836/*
1837** Return a pointer to a Tcl_Obj structure with ref-count 0 that contains
1838** the value for the iCol'th column of the row currently pointed to by
1839** the DbEvalContext structure passed as the first argument.
1840*/
1841static Tcl_Obj *dbEvalColumnValue(DbEvalContext *p, int iCol){
1842 sqlite3_stmt *pStmt = p->pPreStmt->pStmt;
1843 switch( sqlite3_column_type(pStmt, iCol) ){
1844 case SQLITE_BLOB: {
1845 int bytes = sqlite3_column_bytes(pStmt, iCol);
1846 const char *zBlob = sqlite3_column_blob(pStmt, iCol);
1847 if( !zBlob ) bytes = 0;
1848 return Tcl_NewByteArrayObj((u8*)zBlob, bytes);
1849 }
1850 case SQLITE_INTEGER: {
1851 sqlite_int64 v = sqlite3_column_int64(pStmt, iCol);
1852 if( v>=-2147483647 && v<=2147483647 ){
drh7fd33922011-06-20 19:00:301853 return Tcl_NewIntObj((int)v);
dan4a4c11a2009-10-06 14:59:021854 }else{
1855 return Tcl_NewWideIntObj(v);
1856 }
1857 }
1858 case SQLITE_FLOAT: {
1859 return Tcl_NewDoubleObj(sqlite3_column_double(pStmt, iCol));
1860 }
1861 case SQLITE_NULL: {
drhc45e6712012-10-03 11:02:331862 return Tcl_NewStringObj(p->pDb->zNull, -1);
dan4a4c11a2009-10-06 14:59:021863 }
1864 }
1865
drh325eff52012-10-03 12:56:181866 return Tcl_NewStringObj((char*)sqlite3_column_text(pStmt, iCol), -1);
dan4a4c11a2009-10-06 14:59:021867}
1868
1869/*
1870** If using Tcl version 8.6 or greater, use the NR functions to avoid
larrybrbc917382023-06-07 08:40:311871** recursive evaluation of scripts by the [db eval] and [db trans]
dan4a4c11a2009-10-06 14:59:021872** commands. Even if the headers used while compiling the extension
1873** are 8.6 or newer, the code still tests the Tcl version at runtime.
1874** This allows stubs-enabled builds to be used with older Tcl libraries.
1875*/
drh4a689632025-01-07 00:17:541876#if TCL_MAJOR_VERSION>8 || !defined(TCL_MINOR_VERSION) \
drhe5339322025-01-07 11:54:431877 || TCL_MINOR_VERSION>=6
drha2c8a952009-10-13 18:38:341878# define SQLITE_TCL_NRE 1
dan4a4c11a2009-10-06 14:59:021879static int DbUseNre(void){
1880 int major, minor;
1881 Tcl_GetVersion(&major, &minor, 0, 0);
1882 return( (major==8 && minor>=6) || major>8 );
1883}
1884#else
mistachkinb56660f2016-07-14 21:26:091885/*
dan4a4c11a2009-10-06 14:59:021886** Compiling using headers earlier than 8.6. In this case NR cannot be
1887** used, so DbUseNre() to always return zero. Add #defines for the other
1888** Tcl_NRxxx() functions to prevent them from causing compilation errors,
mistachkinb56660f2016-07-14 21:26:091889** even though the only invocations of them are within conditional blocks
dan4a4c11a2009-10-06 14:59:021890** of the form:
1891**
1892** if( DbUseNre() ) { ... }
1893*/
drha2c8a952009-10-13 18:38:341894# define SQLITE_TCL_NRE 0
dan4a4c11a2009-10-06 14:59:021895# define DbUseNre() 0
drha47941f2013-12-20 18:57:441896# define Tcl_NRAddCallback(a,b,c,d,e,f) (void)0
dan4a4c11a2009-10-06 14:59:021897# define Tcl_NREvalObj(a,b,c) 0
drha47941f2013-12-20 18:57:441898# define Tcl_NRCreateCommand(a,b,c,d,e,f) (void)0
dan4a4c11a2009-10-06 14:59:021899#endif
1900
1901/*
1902** This function is part of the implementation of the command:
1903**
stephan10206572025-05-31 11:02:061904** $db eval SQL ?TGT-NAME? SCRIPT
dan4a4c11a2009-10-06 14:59:021905*/
mistachkina121cc72016-07-28 18:06:521906static int SQLITE_TCLAPI DbEvalNextCmd(
dan4a4c11a2009-10-06 14:59:021907 ClientData data[], /* data[0] is the (DbEvalContext*) */
1908 Tcl_Interp *interp, /* Tcl interpreter */
1909 int result /* Result so far */
1910){
1911 int rc = result; /* Return code */
1912
1913 /* The first element of the data[] array is a pointer to a DbEvalContext
1914 ** structure allocated using Tcl_Alloc(). The second element of data[]
1915 ** is a pointer to a Tcl_Obj containing the script to run for each row
1916 ** returned by the queries encapsulated in data[0]. */
1917 DbEvalContext *p = (DbEvalContext *)data[0];
stephan10206572025-05-31 11:02:061918 Tcl_Obj * const pScript = (Tcl_Obj *)data[1];
1919 Tcl_Obj * const pVarName = p->pVarName;
dan4a4c11a2009-10-06 14:59:021920
1921 while( (rc==TCL_OK || rc==TCL_CONTINUE) && TCL_OK==(rc = dbEvalStep(p)) ){
1922 int i;
1923 int nCol;
1924 Tcl_Obj **apColName;
1925 dbEvalRowInfo(p, &nCol, &apColName);
1926 for(i=0; i<nCol; i++){
stephan10206572025-05-31 11:02:061927 if( pVarName==0 ){
drhaf38cdb2017-06-26 21:08:321928 Tcl_ObjSetVar2(interp, apColName[i], 0, dbEvalColumnValue(p,i), 0);
1929 }else if( (p->evalFlags & SQLITE_EVAL_WITHOUTNULLS)!=0
stephan10206572025-05-31 11:02:061930 && sqlite3_column_type(p->pPreStmt->pStmt, i)==SQLITE_NULL
drhaf38cdb2017-06-26 21:08:321931 ){
stephan10206572025-05-31 11:02:061932 /* Remove NULL-containing column from the target container... */
1933 if( 0==(SQLITE_EVAL_ASDICT & p->evalFlags) ){
1934 /* Target is an array */
1935 Tcl_UnsetVar2(interp, Tcl_GetString(pVarName),
1936 Tcl_GetString(apColName[i]), 0);
1937 }else{
1938 /* Target is a dict */
1939 Tcl_Obj *pDict = Tcl_ObjGetVar2(interp, pVarName, NULL, 0);
1940 if( pDict ){
1941 if( Tcl_IsShared(pDict) ){
1942 pDict = Tcl_DuplicateObj(pDict);
1943 }
1944 if( Tcl_DictObjRemove(interp, pDict, apColName[i])==TCL_OK ){
1945 Tcl_ObjSetVar2(interp, pVarName, NULL, pDict, 0);
1946 }
1947 Tcl_BounceRefCount(pDict);
1948 }
1949 }
1950 }else if( 0==(SQLITE_EVAL_ASDICT & p->evalFlags) ){
1951 /* Target is an array: set target(colName) = colValue */
1952 Tcl_ObjSetVar2(interp, pVarName, apColName[i],
1953 dbEvalColumnValue(p,i), 0);
dan4a4c11a2009-10-06 14:59:021954 }else{
stephan10206572025-05-31 11:02:061955 /* Target is a dict: set target(colName) = colValue */
1956 Tcl_Obj *pDict = Tcl_ObjGetVar2(interp, pVarName, NULL, 0);
1957 if( !pDict ){
1958 pDict = Tcl_NewDictObj();
1959 }else if( Tcl_IsShared(pDict) ){
1960 pDict = Tcl_DuplicateObj(pDict);
1961 }
1962 if( Tcl_DictObjPut(interp, pDict, apColName[i],
1963 dbEvalColumnValue(p,i))==TCL_OK ){
1964 Tcl_ObjSetVar2(interp, pVarName, NULL, pDict, 0);
1965 }
1966 Tcl_BounceRefCount(pDict);
dan4a4c11a2009-10-06 14:59:021967 }
1968 }
1969
mistachkinb56660f2016-07-14 21:26:091970 /* The required interpreter variables are now populated with the data
dan4a4c11a2009-10-06 14:59:021971 ** from the current row. If using NRE, schedule callbacks to evaluate
1972 ** script pScript, then to invoke this function again to fetch the next
1973 ** row (or clean up if there is no next row or the script throws an
mistachkinb56660f2016-07-14 21:26:091974 ** exception). After scheduling the callbacks, return control to the
dan4a4c11a2009-10-06 14:59:021975 ** caller.
1976 **
1977 ** If not using NRE, evaluate pScript directly and continue with the
1978 ** next iteration of this while(...) loop. */
1979 if( DbUseNre() ){
1980 Tcl_NRAddCallback(interp, DbEvalNextCmd, (void*)p, (void*)pScript, 0, 0);
1981 return Tcl_NREvalObj(interp, pScript, 0);
1982 }else{
1983 rc = Tcl_EvalObjEx(interp, pScript, 0);
1984 }
1985 }
1986
1987 Tcl_DecrRefCount(pScript);
1988 dbEvalFinalize(p);
1989 Tcl_Free((char *)p);
1990
1991 if( rc==TCL_OK || rc==TCL_BREAK ){
1992 Tcl_ResetResult(interp);
1993 rc = TCL_OK;
1994 }
1995 return rc;
danielk19778e556522007-11-13 10:30:241996}
1997
tpoindex1067fe12004-12-17 15:41:111998/*
mistachkinb56660f2016-07-14 21:26:091999** This function is used by the implementations of the following database
dan46c47d42011-03-01 18:42:072000** handle sub-commands:
2001**
2002** $db update_hook ?SCRIPT?
2003** $db wal_hook ?SCRIPT?
2004** $db commit_hook ?SCRIPT?
2005** $db preupdate hook ?SCRIPT?
2006*/
2007static void DbHookCmd(
2008 Tcl_Interp *interp, /* Tcl interpreter */
2009 SqliteDb *pDb, /* Database handle */
2010 Tcl_Obj *pArg, /* SCRIPT argument (or NULL) */
2011 Tcl_Obj **ppHook /* Pointer to member of SqliteDb */
2012){
2013 sqlite3 *db = pDb->db;
2014
2015 if( *ppHook ){
2016 Tcl_SetObjResult(interp, *ppHook);
2017 if( pArg ){
2018 Tcl_DecrRefCount(*ppHook);
2019 *ppHook = 0;
2020 }
2021 }
2022 if( pArg ){
2023 assert( !(*ppHook) );
drhd0db5ed2025-01-21 11:10:162024 if( Tcl_GetString(pArg)[0] ){
dan46c47d42011-03-01 18:42:072025 *ppHook = pArg;
2026 Tcl_IncrRefCount(*ppHook);
2027 }
2028 }
2029
drh9b1c62d2011-03-30 21:04:432030#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
dan46c47d42011-03-01 18:42:072031 sqlite3_preupdate_hook(db, (pDb->pPreUpdateHook?DbPreUpdateHandler:0), pDb);
drh9b1c62d2011-03-30 21:04:432032#endif
dan46c47d42011-03-01 18:42:072033 sqlite3_update_hook(db, (pDb->pUpdateHook?DbUpdateHandler:0), pDb);
2034 sqlite3_rollback_hook(db, (pDb->pRollbackHook?DbRollbackHandler:0), pDb);
2035 sqlite3_wal_hook(db, (pDb->pWalHook?DbWalHandler:0), pDb);
2036}
2037
2038/*
drh75897232000-05-29 14:26:002039** The "sqlite" command below creates a new Tcl command for each
2040** connection it opens to an SQLite database. This routine is invoked
2041** whenever one of those connection-specific commands is executed
2042** in Tcl. For example, if you run Tcl code like this:
2043**
drh9bb575f2004-09-06 17:24:112044** sqlite3 db1 "my_database"
drh75897232000-05-29 14:26:002045** db1 close
2046**
2047** The first command opens a connection to the "my_database" database
2048** and calls that connection "db1". The second command causes this
2049** subroutine to be invoked.
2050*/
mistachkin7617e4a2016-07-28 17:11:202051static int SQLITE_TCLAPI DbObjCmd(
2052 void *cd,
2053 Tcl_Interp *interp,
2054 int objc,
2055 Tcl_Obj *const*objv
2056){
drhbec3f402000-08-04 13:49:022057 SqliteDb *pDb = (SqliteDb*)cd;
drh6d313162000-09-21 13:01:352058 int choice;
drh22fbcb82004-02-01 01:22:502059 int rc = TCL_OK;
drh0de8c112002-07-06 16:32:142060 static const char *DB_strs[] = {
drhc06ede12019-02-28 17:29:192061 "authorizer", "backup", "bind_fallback",
2062 "busy", "cache", "changes",
2063 "close", "collate", "collation_needed",
drh11d88e62019-08-15 21:27:202064 "commit_hook", "complete", "config",
2065 "copy", "deserialize", "enable_load_extension",
drhbe4e3c82022-02-16 15:11:012066 "errorcode", "erroroffset", "eval",
2067 "exists", "function", "incrblob",
2068 "interrupt", "last_insert_rowid", "nullvalue",
2069 "onecolumn", "preupdate", "profile",
2070 "progress", "rekey", "restore",
2071 "rollback_hook", "serialize", "status",
2072 "timeout", "total_changes", "trace",
2073 "trace_v2", "transaction", "unlock_notify",
2074 "update_hook", "version", "wal_hook",
stephan10206572025-05-31 11:02:062075 0
drh6d313162000-09-21 13:01:352076 };
drh411995d2002-06-25 19:31:182077 enum DB_enum {
drhc06ede12019-02-28 17:29:192078 DB_AUTHORIZER, DB_BACKUP, DB_BIND_FALLBACK,
2079 DB_BUSY, DB_CACHE, DB_CHANGES,
2080 DB_CLOSE, DB_COLLATE, DB_COLLATION_NEEDED,
drh11d88e62019-08-15 21:27:202081 DB_COMMIT_HOOK, DB_COMPLETE, DB_CONFIG,
2082 DB_COPY, DB_DESERIALIZE, DB_ENABLE_LOAD_EXTENSION,
drhbe4e3c82022-02-16 15:11:012083 DB_ERRORCODE, DB_ERROROFFSET, DB_EVAL,
2084 DB_EXISTS, DB_FUNCTION, DB_INCRBLOB,
2085 DB_INTERRUPT, DB_LAST_INSERT_ROWID, DB_NULLVALUE,
2086 DB_ONECOLUMN, DB_PREUPDATE, DB_PROFILE,
2087 DB_PROGRESS, DB_REKEY, DB_RESTORE,
2088 DB_ROLLBACK_HOOK, DB_SERIALIZE, DB_STATUS,
2089 DB_TIMEOUT, DB_TOTAL_CHANGES, DB_TRACE,
2090 DB_TRACE_V2, DB_TRANSACTION, DB_UNLOCK_NOTIFY,
2091 DB_UPDATE_HOOK, DB_VERSION, DB_WAL_HOOK,
drh6d313162000-09-21 13:01:352092 };
tpoindex1067fe12004-12-17 15:41:112093 /* don't leave trailing commas on DB_enum, it confuses the AIX xlc compiler */
drh6d313162000-09-21 13:01:352094
2095 if( objc<2 ){
2096 Tcl_WrongNumArgs(interp, 1, objv, "SUBCOMMAND ...");
drh75897232000-05-29 14:26:002097 return TCL_ERROR;
2098 }
drh411995d2002-06-25 19:31:182099 if( Tcl_GetIndexFromObj(interp, objv[1], DB_strs, "option", 0, &choice) ){
drh6d313162000-09-21 13:01:352100 return TCL_ERROR;
2101 }
2102
drh411995d2002-06-25 19:31:182103 switch( (enum DB_enum)choice ){
drh75897232000-05-29 14:26:002104
drhe22a3342003-04-22 20:30:372105 /* $db authorizer ?CALLBACK?
2106 **
2107 ** Invoke the given callback to authorize each SQL operation as it is
2108 ** compiled. 5 arguments are appended to the callback before it is
2109 ** invoked:
2110 **
2111 ** (1) The authorization type (ex: SQLITE_CREATE_TABLE, SQLITE_INSERT, ...)
2112 ** (2) First descriptive name (depends on authorization type)
2113 ** (3) Second descriptive name
2114 ** (4) Name of the database (ex: "main", "temp")
2115 ** (5) Name of trigger that is doing the access
2116 **
stephan3ce81092025-03-04 06:29:032117 ** The callback should return one of the following strings: SQLITE_OK,
drhe22a3342003-04-22 20:30:372118 ** SQLITE_IGNORE, or SQLITE_DENY. Any other return value is an error.
2119 **
2120 ** If this method is invoked with no arguments, the current authorization
2121 ** callback string is returned.
2122 */
2123 case DB_AUTHORIZER: {
drh1211de32004-07-26 12:24:222124#ifdef SQLITE_OMIT_AUTHORIZATION
drha198f2b2014-02-07 19:26:132125 Tcl_AppendResult(interp, "authorization not available in this build",
2126 (char*)0);
drh1211de32004-07-26 12:24:222127 return TCL_ERROR;
2128#else
drhe22a3342003-04-22 20:30:372129 if( objc>3 ){
2130 Tcl_WrongNumArgs(interp, 2, objv, "?CALLBACK?");
drh0f14e2e2004-06-29 12:39:082131 return TCL_ERROR;
drhe22a3342003-04-22 20:30:372132 }else if( objc==2 ){
drhb5a20d32003-04-23 12:25:232133 if( pDb->zAuth ){
drha198f2b2014-02-07 19:26:132134 Tcl_AppendResult(interp, pDb->zAuth, (char*)0);
drhe22a3342003-04-22 20:30:372135 }
2136 }else{
2137 char *zAuth;
drh064b6812024-07-30 15:49:022138 Tcl_Size len;
drhe22a3342003-04-22 20:30:372139 if( pDb->zAuth ){
2140 Tcl_Free(pDb->zAuth);
2141 }
2142 zAuth = Tcl_GetStringFromObj(objv[2], &len);
2143 if( zAuth && len>0 ){
2144 pDb->zAuth = Tcl_Alloc( len + 1 );
drh5bb3eb92007-05-04 13:15:552145 memcpy(pDb->zAuth, zAuth, len+1);
drhe22a3342003-04-22 20:30:372146 }else{
2147 pDb->zAuth = 0;
2148 }
drhe22a3342003-04-22 20:30:372149 if( pDb->zAuth ){
drh32c6a482014-09-11 13:44:522150 typedef int (*sqlite3_auth_cb)(
2151 void*,int,const char*,const char*,
2152 const char*,const char*);
drhe22a3342003-04-22 20:30:372153 pDb->interp = interp;
drh32c6a482014-09-11 13:44:522154 sqlite3_set_authorizer(pDb->db,(sqlite3_auth_cb)auth_callback,pDb);
drhe22a3342003-04-22 20:30:372155 }else{
danielk19776f8a5032004-05-10 10:34:512156 sqlite3_set_authorizer(pDb->db, 0, 0);
drhe22a3342003-04-22 20:30:372157 }
drhe22a3342003-04-22 20:30:372158 }
drh1211de32004-07-26 12:24:222159#endif
drhe22a3342003-04-22 20:30:372160 break;
2161 }
2162
drhdc2c4912009-02-04 22:46:472163 /* $db backup ?DATABASE? FILENAME
2164 **
2165 ** Open or create a database file named FILENAME. Transfer the
2166 ** content of local database DATABASE (default: "main") into the
2167 ** FILENAME database.
2168 */
2169 case DB_BACKUP: {
2170 const char *zDestFile;
2171 const char *zSrcDb;
2172 sqlite3 *pDest;
2173 sqlite3_backup *pBackup;
2174
2175 if( objc==3 ){
2176 zSrcDb = "main";
2177 zDestFile = Tcl_GetString(objv[2]);
2178 }else if( objc==4 ){
2179 zSrcDb = Tcl_GetString(objv[2]);
2180 zDestFile = Tcl_GetString(objv[3]);
2181 }else{
2182 Tcl_WrongNumArgs(interp, 2, objv, "?DATABASE? FILENAME");
2183 return TCL_ERROR;
2184 }
drh147ef392016-01-22 23:17:512185 rc = sqlite3_open_v2(zDestFile, &pDest,
2186 SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE| pDb->openFlags, 0);
drhdc2c4912009-02-04 22:46:472187 if( rc!=SQLITE_OK ){
2188 Tcl_AppendResult(interp, "cannot open target database: ",
2189 sqlite3_errmsg(pDest), (char*)0);
2190 sqlite3_close(pDest);
2191 return TCL_ERROR;
2192 }
2193 pBackup = sqlite3_backup_init(pDest, "main", pDb->db, zSrcDb);
2194 if( pBackup==0 ){
2195 Tcl_AppendResult(interp, "backup failed: ",
2196 sqlite3_errmsg(pDest), (char*)0);
2197 sqlite3_close(pDest);
2198 return TCL_ERROR;
2199 }
2200 while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK ){}
2201 sqlite3_backup_finish(pBackup);
2202 if( rc==SQLITE_DONE ){
2203 rc = TCL_OK;
2204 }else{
2205 Tcl_AppendResult(interp, "backup failed: ",
2206 sqlite3_errmsg(pDest), (char*)0);
2207 rc = TCL_ERROR;
2208 }
2209 sqlite3_close(pDest);
2210 break;
2211 }
2212
drhc06ede12019-02-28 17:29:192213 /* $db bind_fallback ?CALLBACK?
2214 **
2215 ** When resolving bind parameters in an SQL statement, if the parameter
2216 ** cannot be associated with a TCL variable then invoke CALLBACK with a
2217 ** single argument that is the name of the parameter and use the return
2218 ** value of the CALLBACK as the binding. If CALLBACK returns something
2219 ** other than TCL_OK or TCL_ERROR then bind a NULL.
2220 **
2221 ** If CALLBACK is an empty string, then revert to the default behavior
2222 ** which is to set the binding to NULL.
2223 **
2224 ** If CALLBACK returns an error, that causes the statement execution to
2225 ** abort. Hence, to configure a connection so that it throws an error
2226 ** on an attempt to bind an unknown variable, do something like this:
2227 **
2228 ** proc bind_error {name} {error "no such variable: $name"}
2229 ** db bind_fallback bind_error
2230 */
2231 case DB_BIND_FALLBACK: {
2232 if( objc>3 ){
2233 Tcl_WrongNumArgs(interp, 2, objv, "?CALLBACK?");
2234 return TCL_ERROR;
2235 }else if( objc==2 ){
2236 if( pDb->zBindFallback ){
2237 Tcl_AppendResult(interp, pDb->zBindFallback, (char*)0);
2238 }
2239 }else{
2240 char *zCallback;
drh064b6812024-07-30 15:49:022241 Tcl_Size len;
drhc06ede12019-02-28 17:29:192242 if( pDb->zBindFallback ){
2243 Tcl_Free(pDb->zBindFallback);
2244 }
2245 zCallback = Tcl_GetStringFromObj(objv[2], &len);
2246 if( zCallback && len>0 ){
2247 pDb->zBindFallback = Tcl_Alloc( len + 1 );
2248 memcpy(pDb->zBindFallback, zCallback, len+1);
2249 }else{
2250 pDb->zBindFallback = 0;
2251 }
2252 }
2253 break;
2254 }
2255
drhbec3f402000-08-04 13:49:022256 /* $db busy ?CALLBACK?
2257 **
2258 ** Invoke the given callback if an SQL statement attempts to open
2259 ** a locked database file.
2260 */
drh6d313162000-09-21 13:01:352261 case DB_BUSY: {
2262 if( objc>3 ){
2263 Tcl_WrongNumArgs(interp, 2, objv, "CALLBACK");
drhbec3f402000-08-04 13:49:022264 return TCL_ERROR;
drh6d313162000-09-21 13:01:352265 }else if( objc==2 ){
drhbec3f402000-08-04 13:49:022266 if( pDb->zBusy ){
drha198f2b2014-02-07 19:26:132267 Tcl_AppendResult(interp, pDb->zBusy, (char*)0);
drhbec3f402000-08-04 13:49:022268 }
2269 }else{
drh6d313162000-09-21 13:01:352270 char *zBusy;
drh064b6812024-07-30 15:49:022271 Tcl_Size len;
drhbec3f402000-08-04 13:49:022272 if( pDb->zBusy ){
2273 Tcl_Free(pDb->zBusy);
drhbec3f402000-08-04 13:49:022274 }
drh6d313162000-09-21 13:01:352275 zBusy = Tcl_GetStringFromObj(objv[2], &len);
2276 if( zBusy && len>0 ){
2277 pDb->zBusy = Tcl_Alloc( len + 1 );
drh5bb3eb92007-05-04 13:15:552278 memcpy(pDb->zBusy, zBusy, len+1);
drh6d313162000-09-21 13:01:352279 }else{
2280 pDb->zBusy = 0;
drhbec3f402000-08-04 13:49:022281 }
2282 if( pDb->zBusy ){
2283 pDb->interp = interp;
danielk19776f8a5032004-05-10 10:34:512284 sqlite3_busy_handler(pDb->db, DbBusyHandler, pDb);
drh6d313162000-09-21 13:01:352285 }else{
danielk19776f8a5032004-05-10 10:34:512286 sqlite3_busy_handler(pDb->db, 0, 0);
drhbec3f402000-08-04 13:49:022287 }
2288 }
drh6d313162000-09-21 13:01:352289 break;
2290 }
drhbec3f402000-08-04 13:49:022291
drhfb7e7652005-01-24 00:28:422292 /* $db cache flush
2293 ** $db cache size n
2294 **
2295 ** Flush the prepared statement cache, or set the maximum number of
2296 ** cached statements.
2297 */
2298 case DB_CACHE: {
2299 char *subCmd;
2300 int n;
2301
2302 if( objc<=2 ){
2303 Tcl_WrongNumArgs(interp, 1, objv, "cache option ?arg?");
2304 return TCL_ERROR;
2305 }
2306 subCmd = Tcl_GetStringFromObj( objv[2], 0 );
2307 if( *subCmd=='f' && strcmp(subCmd,"flush")==0 ){
2308 if( objc!=3 ){
2309 Tcl_WrongNumArgs(interp, 2, objv, "flush");
2310 return TCL_ERROR;
2311 }else{
2312 flushStmtCache( pDb );
2313 }
2314 }else if( *subCmd=='s' && strcmp(subCmd,"size")==0 ){
2315 if( objc!=4 ){
2316 Tcl_WrongNumArgs(interp, 2, objv, "size n");
2317 return TCL_ERROR;
2318 }else{
2319 if( TCL_ERROR==Tcl_GetIntFromObj(interp, objv[3], &n) ){
mistachkinb56660f2016-07-14 21:26:092320 Tcl_AppendResult( interp, "cannot convert \"",
drha198f2b2014-02-07 19:26:132321 Tcl_GetStringFromObj(objv[3],0), "\" to integer", (char*)0);
drhfb7e7652005-01-24 00:28:422322 return TCL_ERROR;
2323 }else{
2324 if( n<0 ){
2325 flushStmtCache( pDb );
2326 n = 0;
2327 }else if( n>MAX_PREPARED_STMTS ){
2328 n = MAX_PREPARED_STMTS;
2329 }
2330 pDb->maxStmt = n;
2331 }
2332 }
2333 }else{
mistachkinb56660f2016-07-14 21:26:092334 Tcl_AppendResult( interp, "bad option \"",
drha198f2b2014-02-07 19:26:132335 Tcl_GetStringFromObj(objv[2],0), "\": must be flush or size",
2336 (char*)0);
drhfb7e7652005-01-24 00:28:422337 return TCL_ERROR;
2338 }
2339 break;
2340 }
2341
danielk1977b28af712004-06-21 06:50:262342 /* $db changes
drhc8d30ac2002-04-12 10:08:592343 **
2344 ** Return the number of rows that were modified, inserted, or deleted by
mistachkinb56660f2016-07-14 21:26:092345 ** the most recent INSERT, UPDATE or DELETE statement, not including
danielk1977b28af712004-06-21 06:50:262346 ** any changes made by trigger programs.
drhc8d30ac2002-04-12 10:08:592347 */
2348 case DB_CHANGES: {
2349 Tcl_Obj *pResult;
drhc8d30ac2002-04-12 10:08:592350 if( objc!=2 ){
2351 Tcl_WrongNumArgs(interp, 2, objv, "");
2352 return TCL_ERROR;
2353 }
drhc8d30ac2002-04-12 10:08:592354 pResult = Tcl_GetObjResult(interp);
dan2c718872021-06-22 18:32:052355 Tcl_SetWideIntObj(pResult, sqlite3_changes64(pDb->db));
rdcf146a772004-02-25 22:51:062356 break;
2357 }
2358
drh75897232000-05-29 14:26:002359 /* $db close
2360 **
2361 ** Shutdown the database
2362 */
drh6d313162000-09-21 13:01:352363 case DB_CLOSE: {
2364 Tcl_DeleteCommand(interp, Tcl_GetStringFromObj(objv[0], 0));
2365 break;
2366 }
drh75897232000-05-29 14:26:002367
drh0f14e2e2004-06-29 12:39:082368 /*
2369 ** $db collate NAME SCRIPT
2370 **
2371 ** Create a new SQL collation function called NAME. Whenever
2372 ** that function is called, invoke SCRIPT to evaluate the function.
2373 */
2374 case DB_COLLATE: {
2375 SqlCollate *pCollate;
2376 char *zName;
2377 char *zScript;
drh064b6812024-07-30 15:49:022378 Tcl_Size nScript;
drh0f14e2e2004-06-29 12:39:082379 if( objc!=4 ){
2380 Tcl_WrongNumArgs(interp, 2, objv, "NAME SCRIPT");
2381 return TCL_ERROR;
2382 }
2383 zName = Tcl_GetStringFromObj(objv[2], 0);
2384 zScript = Tcl_GetStringFromObj(objv[3], &nScript);
2385 pCollate = (SqlCollate*)Tcl_Alloc( sizeof(*pCollate) + nScript + 1 );
2386 if( pCollate==0 ) return TCL_ERROR;
2387 pCollate->interp = interp;
2388 pCollate->pNext = pDb->pCollate;
2389 pCollate->zScript = (char*)&pCollate[1];
2390 pDb->pCollate = pCollate;
drh5bb3eb92007-05-04 13:15:552391 memcpy(pCollate->zScript, zScript, nScript+1);
mistachkinb56660f2016-07-14 21:26:092392 if( sqlite3_create_collation(pDb->db, zName, SQLITE_UTF8,
drh0f14e2e2004-06-29 12:39:082393 pCollate, tclSqlCollate) ){
danielk19779636c4e2005-01-25 04:27:542394 Tcl_SetResult(interp, (char *)sqlite3_errmsg(pDb->db), TCL_VOLATILE);
drh0f14e2e2004-06-29 12:39:082395 return TCL_ERROR;
2396 }
2397 break;
2398 }
2399
2400 /*
2401 ** $db collation_needed SCRIPT
2402 **
2403 ** Create a new SQL collation function called NAME. Whenever
2404 ** that function is called, invoke SCRIPT to evaluate the function.
2405 */
2406 case DB_COLLATION_NEEDED: {
2407 if( objc!=3 ){
2408 Tcl_WrongNumArgs(interp, 2, objv, "SCRIPT");
2409 return TCL_ERROR;
2410 }
2411 if( pDb->pCollateNeeded ){
2412 Tcl_DecrRefCount(pDb->pCollateNeeded);
2413 }
2414 pDb->pCollateNeeded = Tcl_DuplicateObj(objv[2]);
2415 Tcl_IncrRefCount(pDb->pCollateNeeded);
2416 sqlite3_collation_needed(pDb->db, pDb, tclCollateNeeded);
2417 break;
2418 }
2419
drh19e2d372005-08-29 23:00:032420 /* $db commit_hook ?CALLBACK?
2421 **
2422 ** Invoke the given callback just before committing every SQL transaction.
2423 ** If the callback throws an exception or returns non-zero, then the
2424 ** transaction is aborted. If CALLBACK is an empty string, the callback
2425 ** is disabled.
2426 */
2427 case DB_COMMIT_HOOK: {
2428 if( objc>3 ){
2429 Tcl_WrongNumArgs(interp, 2, objv, "?CALLBACK?");
2430 return TCL_ERROR;
2431 }else if( objc==2 ){
2432 if( pDb->zCommit ){
drha198f2b2014-02-07 19:26:132433 Tcl_AppendResult(interp, pDb->zCommit, (char*)0);
drh19e2d372005-08-29 23:00:032434 }
2435 }else{
mistachkin6ef5e122014-01-24 17:03:552436 const char *zCommit;
drh064b6812024-07-30 15:49:022437 Tcl_Size len;
drh19e2d372005-08-29 23:00:032438 if( pDb->zCommit ){
2439 Tcl_Free(pDb->zCommit);
2440 }
2441 zCommit = Tcl_GetStringFromObj(objv[2], &len);
2442 if( zCommit && len>0 ){
2443 pDb->zCommit = Tcl_Alloc( len + 1 );
drh5bb3eb92007-05-04 13:15:552444 memcpy(pDb->zCommit, zCommit, len+1);
drh19e2d372005-08-29 23:00:032445 }else{
2446 pDb->zCommit = 0;
2447 }
2448 if( pDb->zCommit ){
2449 pDb->interp = interp;
2450 sqlite3_commit_hook(pDb->db, DbCommitHandler, pDb);
2451 }else{
2452 sqlite3_commit_hook(pDb->db, 0, 0);
2453 }
2454 }
2455 break;
2456 }
2457
drh75897232000-05-29 14:26:002458 /* $db complete SQL
2459 **
2460 ** Return TRUE if SQL is a complete SQL statement. Return FALSE if
2461 ** additional lines of input are needed. This is similar to the
2462 ** built-in "info complete" command of Tcl.
2463 */
drh6d313162000-09-21 13:01:352464 case DB_COMPLETE: {
drhccae6022005-02-26 17:31:262465#ifndef SQLITE_OMIT_COMPLETE
drh6d313162000-09-21 13:01:352466 Tcl_Obj *pResult;
2467 int isComplete;
2468 if( objc!=3 ){
2469 Tcl_WrongNumArgs(interp, 2, objv, "SQL");
drh75897232000-05-29 14:26:002470 return TCL_ERROR;
2471 }
danielk19776f8a5032004-05-10 10:34:512472 isComplete = sqlite3_complete( Tcl_GetStringFromObj(objv[2], 0) );
drh6d313162000-09-21 13:01:352473 pResult = Tcl_GetObjResult(interp);
2474 Tcl_SetBooleanObj(pResult, isComplete);
drhccae6022005-02-26 17:31:262475#endif
drh6d313162000-09-21 13:01:352476 break;
2477 }
drhdcd997e2003-01-31 17:21:492478
drh11d88e62019-08-15 21:27:202479 /* $db config ?OPTION? ?BOOLEAN?
2480 **
2481 ** Configure the database connection using the sqlite3_db_config()
2482 ** interface.
2483 */
2484 case DB_CONFIG: {
2485 static const struct DbConfigChoices {
2486 const char *zName;
2487 int op;
2488 } aDbConfig[] = {
drh76a1fce2020-01-18 22:20:142489 { "defensive", SQLITE_DBCONFIG_DEFENSIVE },
2490 { "dqs_ddl", SQLITE_DBCONFIG_DQS_DDL },
2491 { "dqs_dml", SQLITE_DBCONFIG_DQS_DML },
drh11d88e62019-08-15 21:27:202492 { "enable_fkey", SQLITE_DBCONFIG_ENABLE_FKEY },
drh76a1fce2020-01-18 22:20:142493 { "enable_qpsg", SQLITE_DBCONFIG_ENABLE_QPSG },
drh11d88e62019-08-15 21:27:202494 { "enable_trigger", SQLITE_DBCONFIG_ENABLE_TRIGGER },
2495 { "enable_view", SQLITE_DBCONFIG_ENABLE_VIEW },
2496 { "fts3_tokenizer", SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER },
drh76a1fce2020-01-18 22:20:142497 { "legacy_alter_table", SQLITE_DBCONFIG_LEGACY_ALTER_TABLE },
2498 { "legacy_file_format", SQLITE_DBCONFIG_LEGACY_FILE_FORMAT },
drh11d88e62019-08-15 21:27:202499 { "load_extension", SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION },
2500 { "no_ckpt_on_close", SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE },
drh11d88e62019-08-15 21:27:202501 { "reset_database", SQLITE_DBCONFIG_RESET_DATABASE },
drh76a1fce2020-01-18 22:20:142502 { "trigger_eqp", SQLITE_DBCONFIG_TRIGGER_EQP },
2503 { "trusted_schema", SQLITE_DBCONFIG_TRUSTED_SCHEMA },
drh11d88e62019-08-15 21:27:202504 { "writable_schema", SQLITE_DBCONFIG_WRITABLE_SCHEMA },
drh11d88e62019-08-15 21:27:202505 };
2506 Tcl_Obj *pResult;
2507 int ii;
2508 if( objc>4 ){
2509 Tcl_WrongNumArgs(interp, 2, objv, "?OPTION? ?BOOLEAN?");
2510 return TCL_ERROR;
2511 }
2512 if( objc==2 ){
2513 /* With no arguments, list all configuration options and with the
2514 ** current value */
2515 pResult = Tcl_NewListObj(0,0);
2516 for(ii=0; ii<sizeof(aDbConfig)/sizeof(aDbConfig[0]); ii++){
2517 int v = 0;
drh4043cfe2019-08-15 23:11:422518 sqlite3_db_config(pDb->db, aDbConfig[ii].op, -1, &v);
drh11d88e62019-08-15 21:27:202519 Tcl_ListObjAppendElement(interp, pResult,
2520 Tcl_NewStringObj(aDbConfig[ii].zName,-1));
2521 Tcl_ListObjAppendElement(interp, pResult,
2522 Tcl_NewIntObj(v));
2523 }
2524 }else{
2525 const char *zOpt = Tcl_GetString(objv[2]);
drh11d88e62019-08-15 21:27:202526 int onoff = -1;
2527 int v = 0;
2528 if( zOpt[0]=='-' ) zOpt++;
2529 for(ii=0; ii<sizeof(aDbConfig)/sizeof(aDbConfig[0]); ii++){
2530 if( strcmp(aDbConfig[ii].zName, zOpt)==0 ) break;
2531 }
2532 if( ii>=sizeof(aDbConfig)/sizeof(aDbConfig[0]) ){
2533 Tcl_AppendResult(interp, "unknown config option: \"", zOpt,
2534 "\"", (void*)0);
2535 return TCL_ERROR;
2536 }
2537 if( objc==4 ){
2538 if( Tcl_GetBooleanFromObj(interp, objv[3], &onoff) ){
2539 return TCL_ERROR;
2540 }
2541 }
drh4043cfe2019-08-15 23:11:422542 sqlite3_db_config(pDb->db, aDbConfig[ii].op, onoff, &v);
drh11d88e62019-08-15 21:27:202543 pResult = Tcl_NewIntObj(v);
2544 }
2545 Tcl_SetObjResult(interp, pResult);
2546 break;
2547 }
2548
drh19e2d372005-08-29 23:00:032549 /* $db copy conflict-algorithm table filename ?SEPARATOR? ?NULLINDICATOR?
2550 **
2551 ** Copy data into table from filename, optionally using SEPARATOR
2552 ** as column separators. If a column contains a null string, or the
2553 ** value of NULLINDICATOR, a NULL is inserted for the column.
2554 ** conflict-algorithm is one of the sqlite conflict algorithms:
2555 ** rollback, abort, fail, ignore, replace
2556 ** On success, return the number of lines processed, not necessarily same
2557 ** as 'db changes' due to conflict-algorithm selected.
2558 **
2559 ** This code is basically an implementation/enhancement of
2560 ** the sqlite3 shell.c ".import" command.
2561 **
2562 ** This command usage is equivalent to the sqlite2.x COPY statement,
2563 ** which imports file data into a table using the PostgreSQL COPY file format:
larrybrbc917382023-06-07 08:40:312564 ** $db copy $conflict_algorithm $table_name $filename \t \\N
drh19e2d372005-08-29 23:00:032565 */
2566 case DB_COPY: {
2567 char *zTable; /* Insert data into this table */
2568 char *zFile; /* The file from which to extract data */
2569 char *zConflict; /* The conflict algorithm to use */
2570 sqlite3_stmt *pStmt; /* A statement */
drh19e2d372005-08-29 23:00:032571 int nCol; /* Number of columns in the table */
2572 int nByte; /* Number of bytes in an SQL string */
2573 int i, j; /* Loop counters */
2574 int nSep; /* Number of bytes in zSep[] */
2575 int nNull; /* Number of bytes in zNull[] */
2576 char *zSql; /* An SQL statement */
2577 char *zLine; /* A single line of input from the file */
2578 char **azCol; /* zLine[] broken up into columns */
mistachkin6ef5e122014-01-24 17:03:552579 const char *zCommit; /* How to commit changes */
stephane34ad2b2025-03-04 21:25:182580 Tcl_Channel in; /* The input file */
drh19e2d372005-08-29 23:00:032581 int lineno = 0; /* Line number of input file */
2582 char zLineNum[80]; /* Line number print buffer */
jan.nijtmans1f3207a2025-03-27 17:30:492583 Tcl_Obj *str;
drh19e2d372005-08-29 23:00:032584 Tcl_Obj *pResult; /* interp result */
2585
mistachkin6ef5e122014-01-24 17:03:552586 const char *zSep;
2587 const char *zNull;
drh19e2d372005-08-29 23:00:032588 if( objc<5 || objc>7 ){
mistachkinb56660f2016-07-14 21:26:092589 Tcl_WrongNumArgs(interp, 2, objv,
drh19e2d372005-08-29 23:00:032590 "CONFLICT-ALGORITHM TABLE FILENAME ?SEPARATOR? ?NULLINDICATOR?");
2591 return TCL_ERROR;
2592 }
2593 if( objc>=6 ){
2594 zSep = Tcl_GetStringFromObj(objv[5], 0);
2595 }else{
2596 zSep = "\t";
2597 }
2598 if( objc>=7 ){
2599 zNull = Tcl_GetStringFromObj(objv[6], 0);
2600 }else{
2601 zNull = "";
2602 }
2603 zConflict = Tcl_GetStringFromObj(objv[2], 0);
2604 zTable = Tcl_GetStringFromObj(objv[3], 0);
2605 zFile = Tcl_GetStringFromObj(objv[4], 0);
drh4f21c4a2008-12-10 22:15:002606 nSep = strlen30(zSep);
2607 nNull = strlen30(zNull);
drh19e2d372005-08-29 23:00:032608 if( nSep==0 ){
drha198f2b2014-02-07 19:26:132609 Tcl_AppendResult(interp,"Error: non-null separator required for copy",
2610 (char*)0);
drh19e2d372005-08-29 23:00:032611 return TCL_ERROR;
2612 }
drh3e59c012008-09-23 10:12:132613 if(strcmp(zConflict, "rollback") != 0 &&
2614 strcmp(zConflict, "abort" ) != 0 &&
2615 strcmp(zConflict, "fail" ) != 0 &&
2616 strcmp(zConflict, "ignore" ) != 0 &&
2617 strcmp(zConflict, "replace" ) != 0 ) {
mistachkinb56660f2016-07-14 21:26:092618 Tcl_AppendResult(interp, "Error: \"", zConflict,
drh19e2d372005-08-29 23:00:032619 "\", conflict-algorithm must be one of: rollback, "
drha198f2b2014-02-07 19:26:132620 "abort, fail, ignore, or replace", (char*)0);
drh19e2d372005-08-29 23:00:032621 return TCL_ERROR;
2622 }
2623 zSql = sqlite3_mprintf("SELECT * FROM '%q'", zTable);
2624 if( zSql==0 ){
drha198f2b2014-02-07 19:26:132625 Tcl_AppendResult(interp, "Error: no such table: ", zTable, (char*)0);
drh19e2d372005-08-29 23:00:032626 return TCL_ERROR;
2627 }
drh4f21c4a2008-12-10 22:15:002628 nByte = strlen30(zSql);
drh3e701a12007-02-01 01:53:442629 rc = sqlite3_prepare(pDb->db, zSql, -1, &pStmt, 0);
drh19e2d372005-08-29 23:00:032630 sqlite3_free(zSql);
2631 if( rc ){
drha198f2b2014-02-07 19:26:132632 Tcl_AppendResult(interp, "Error: ", sqlite3_errmsg(pDb->db), (char*)0);
drh19e2d372005-08-29 23:00:032633 nCol = 0;
2634 }else{
2635 nCol = sqlite3_column_count(pStmt);
2636 }
2637 sqlite3_finalize(pStmt);
2638 if( nCol==0 ) {
2639 return TCL_ERROR;
2640 }
2641 zSql = malloc( nByte + 50 + nCol*2 );
2642 if( zSql==0 ) {
drha198f2b2014-02-07 19:26:132643 Tcl_AppendResult(interp, "Error: can't malloc()", (char*)0);
drh19e2d372005-08-29 23:00:032644 return TCL_ERROR;
2645 }
2646 sqlite3_snprintf(nByte+50, zSql, "INSERT OR %q INTO '%q' VALUES(?",
2647 zConflict, zTable);
drh4f21c4a2008-12-10 22:15:002648 j = strlen30(zSql);
drh19e2d372005-08-29 23:00:032649 for(i=1; i<nCol; i++){
2650 zSql[j++] = ',';
2651 zSql[j++] = '?';
2652 }
2653 zSql[j++] = ')';
2654 zSql[j] = 0;
drh3e701a12007-02-01 01:53:442655 rc = sqlite3_prepare(pDb->db, zSql, -1, &pStmt, 0);
drh19e2d372005-08-29 23:00:032656 free(zSql);
2657 if( rc ){
drha198f2b2014-02-07 19:26:132658 Tcl_AppendResult(interp, "Error: ", sqlite3_errmsg(pDb->db), (char*)0);
drh19e2d372005-08-29 23:00:032659 sqlite3_finalize(pStmt);
2660 return TCL_ERROR;
2661 }
stephane34ad2b2025-03-04 21:25:182662 in = Tcl_OpenFileChannel(interp, zFile, "rb", 0666);
drh19e2d372005-08-29 23:00:032663 if( in==0 ){
drh19e2d372005-08-29 23:00:032664 sqlite3_finalize(pStmt);
2665 return TCL_ERROR;
2666 }
jan.nijtmans1f3207a2025-03-27 17:30:492667 Tcl_SetChannelOption(NULL, in, "-translation", "auto");
drh19e2d372005-08-29 23:00:032668 azCol = malloc( sizeof(azCol[0])*(nCol+1) );
2669 if( azCol==0 ) {
drha198f2b2014-02-07 19:26:132670 Tcl_AppendResult(interp, "Error: can't malloc()", (char*)0);
stephane34ad2b2025-03-04 21:25:182671 Tcl_Close(interp, in);
drh19e2d372005-08-29 23:00:032672 return TCL_ERROR;
2673 }
jan.nijtmans1f3207a2025-03-27 17:30:492674 str = Tcl_NewObj();
2675 Tcl_IncrRefCount(str);
drh37527852006-03-16 16:19:562676 (void)sqlite3_exec(pDb->db, "BEGIN", 0, 0, 0);
drh19e2d372005-08-29 23:00:032677 zCommit = "COMMIT";
jan.nijtmans1f3207a2025-03-27 17:30:492678 while( Tcl_GetsObj(in, str)>=0 ) {
drh19e2d372005-08-29 23:00:032679 char *z;
jan.nijtmans1f3207a2025-03-27 17:30:492680 Tcl_Size byteLen;
drh19e2d372005-08-29 23:00:032681 lineno++;
jan.nijtmans1f3207a2025-03-27 17:30:492682 zLine = (char *)Tcl_GetByteArrayFromObj(str, &byteLen);
drh19e2d372005-08-29 23:00:032683 azCol[0] = zLine;
2684 for(i=0, z=zLine; *z; z++){
2685 if( *z==zSep[0] && strncmp(z, zSep, nSep)==0 ){
2686 *z = 0;
2687 i++;
2688 if( i<nCol ){
2689 azCol[i] = &z[nSep];
2690 z += nSep-1;
2691 }
2692 }
2693 }
2694 if( i+1!=nCol ){
2695 char *zErr;
drh4f21c4a2008-12-10 22:15:002696 int nErr = strlen30(zFile) + 200;
drh5bb3eb92007-05-04 13:15:552697 zErr = malloc(nErr);
drhc1f44942006-05-10 14:39:132698 if( zErr ){
drh5bb3eb92007-05-04 13:15:552699 sqlite3_snprintf(nErr, zErr,
drhc1f44942006-05-10 14:39:132700 "Error: %s line %d: expected %d columns of data but found %d",
2701 zFile, lineno, nCol, i+1);
drha198f2b2014-02-07 19:26:132702 Tcl_AppendResult(interp, zErr, (char*)0);
drhc1f44942006-05-10 14:39:132703 free(zErr);
2704 }
drh19e2d372005-08-29 23:00:032705 zCommit = "ROLLBACK";
2706 break;
2707 }
2708 for(i=0; i<nCol; i++){
2709 /* check for null data, if so, bind as null */
drhea678832008-12-10 19:26:222710 if( (nNull>0 && strcmp(azCol[i], zNull)==0)
mistachkinb56660f2016-07-14 21:26:092711 || strlen30(azCol[i])==0
drhea678832008-12-10 19:26:222712 ){
drh19e2d372005-08-29 23:00:032713 sqlite3_bind_null(pStmt, i+1);
2714 }else{
2715 sqlite3_bind_text(pStmt, i+1, azCol[i], -1, SQLITE_STATIC);
2716 }
2717 }
2718 sqlite3_step(pStmt);
2719 rc = sqlite3_reset(pStmt);
jan.nijtmans1f3207a2025-03-27 17:30:492720 Tcl_SetObjLength(str, 0);
drh19e2d372005-08-29 23:00:032721 if( rc!=SQLITE_OK ){
drha198f2b2014-02-07 19:26:132722 Tcl_AppendResult(interp,"Error: ", sqlite3_errmsg(pDb->db), (char*)0);
drh19e2d372005-08-29 23:00:032723 zCommit = "ROLLBACK";
2724 break;
2725 }
2726 }
jan.nijtmans1f3207a2025-03-27 17:30:492727 Tcl_DecrRefCount(str);
drh19e2d372005-08-29 23:00:032728 free(azCol);
stephane34ad2b2025-03-04 21:25:182729 Tcl_Close(interp, in);
drh19e2d372005-08-29 23:00:032730 sqlite3_finalize(pStmt);
drh37527852006-03-16 16:19:562731 (void)sqlite3_exec(pDb->db, zCommit, 0, 0, 0);
drh19e2d372005-08-29 23:00:032732
2733 if( zCommit[0] == 'C' ){
2734 /* success, set result as number of lines processed */
2735 pResult = Tcl_GetObjResult(interp);
2736 Tcl_SetIntObj(pResult, lineno);
2737 rc = TCL_OK;
2738 }else{
2739 /* failure, append lineno where failed */
drh5bb3eb92007-05-04 13:15:552740 sqlite3_snprintf(sizeof(zLineNum), zLineNum,"%d",lineno);
drha198f2b2014-02-07 19:26:132741 Tcl_AppendResult(interp,", failed while processing line: ",zLineNum,
2742 (char*)0);
drh19e2d372005-08-29 23:00:032743 rc = TCL_ERROR;
2744 }
2745 break;
2746 }
2747
drhdcd997e2003-01-31 17:21:492748 /*
drh6ca64482019-01-22 16:06:202749 ** $db deserialize ?-maxsize N? ?-readonly BOOL? ?DATABASE? VALUE
drhcb7d5412018-01-03 16:49:522750 **
2751 ** Reopen DATABASE (default "main") using the content in $VALUE
2752 */
2753 case DB_DESERIALIZE: {
drh8d889af2021-05-08 17:18:232754#ifdef SQLITE_OMIT_DESERIALIZE
drh3ec86652018-01-03 19:03:312755 Tcl_AppendResult(interp, "MEMDB not available in this build",
2756 (char*)0);
2757 rc = TCL_ERROR;
2758#else
drh6ca64482019-01-22 16:06:202759 const char *zSchema = 0;
2760 Tcl_Obj *pValue = 0;
drh3ec86652018-01-03 19:03:312761 unsigned char *pBA;
2762 unsigned char *pData;
drh064b6812024-07-30 15:49:022763 Tcl_Size len;
2764 int xrc;
drh6ca64482019-01-22 16:06:202765 sqlite3_int64 mxSize = 0;
2766 int i;
2767 int isReadonly = 0;
2768
2769
2770 if( objc<3 ){
drh3ec86652018-01-03 19:03:312771 Tcl_WrongNumArgs(interp, 2, objv, "?DATABASE? VALUE");
2772 rc = TCL_ERROR;
2773 break;
2774 }
drh6ca64482019-01-22 16:06:202775 for(i=2; i<objc-1; i++){
2776 const char *z = Tcl_GetString(objv[i]);
2777 if( strcmp(z,"-maxsize")==0 && i<objc-2 ){
drh7907d372021-11-23 12:59:252778 Tcl_WideInt x;
2779 rc = Tcl_GetWideIntFromObj(interp, objv[++i], &x);
drh6ca64482019-01-22 16:06:202780 if( rc ) goto deserialize_error;
drh7907d372021-11-23 12:59:252781 mxSize = x;
drh6ca64482019-01-22 16:06:202782 continue;
2783 }
2784 if( strcmp(z,"-readonly")==0 && i<objc-2 ){
2785 rc = Tcl_GetBooleanFromObj(interp, objv[++i], &isReadonly);
2786 if( rc ) goto deserialize_error;
2787 continue;
2788 }
2789 if( zSchema==0 && i==objc-2 && z[0]!='-' ){
2790 zSchema = z;
2791 continue;
2792 }
2793 Tcl_AppendResult(interp, "unknown option: ", z, (char*)0);
2794 rc = TCL_ERROR;
2795 goto deserialize_error;
2796 }
2797 pValue = objv[objc-1];
drh3ec86652018-01-03 19:03:312798 pBA = Tcl_GetByteArrayFromObj(pValue, &len);
2799 pData = sqlite3_malloc64( len );
drha5bb4352018-01-03 23:40:022800 if( pData==0 && len>0 ){
drh3ec86652018-01-03 19:03:312801 Tcl_AppendResult(interp, "out of memory", (char*)0);
2802 rc = TCL_ERROR;
2803 }else{
drh6ca64482019-01-22 16:06:202804 int flags;
drha5bb4352018-01-03 23:40:022805 if( len>0 ) memcpy(pData, pBA, len);
drh6ca64482019-01-22 16:06:202806 if( isReadonly ){
2807 flags = SQLITE_DESERIALIZE_FREEONCLOSE | SQLITE_DESERIALIZE_READONLY;
2808 }else{
2809 flags = SQLITE_DESERIALIZE_FREEONCLOSE | SQLITE_DESERIALIZE_RESIZEABLE;
2810 }
2811 xrc = sqlite3_deserialize(pDb->db, zSchema, pData, len, len, flags);
drh3ec86652018-01-03 19:03:312812 if( xrc ){
2813 Tcl_AppendResult(interp, "unable to set MEMDB content", (char*)0);
2814 rc = TCL_ERROR;
2815 }
drh6ca64482019-01-22 16:06:202816 if( mxSize>0 ){
2817 sqlite3_file_control(pDb->db, zSchema,SQLITE_FCNTL_SIZE_LIMIT,&mxSize);
2818 }
drh3ec86652018-01-03 19:03:312819 }
drh6ca64482019-01-22 16:06:202820deserialize_error:
drh3ec86652018-01-03 19:03:312821#endif
drhcb7d5412018-01-03 16:49:522822 break;
2823 }
2824
2825 /*
drh41449052006-07-06 17:08:482826 ** $db enable_load_extension BOOLEAN
2827 **
2828 ** Turn the extension loading feature on or off. It if off by
2829 ** default.
2830 */
2831 case DB_ENABLE_LOAD_EXTENSION: {
drhf533acc2006-12-19 18:57:112832#ifndef SQLITE_OMIT_LOAD_EXTENSION
drh41449052006-07-06 17:08:482833 int onoff;
2834 if( objc!=3 ){
2835 Tcl_WrongNumArgs(interp, 2, objv, "BOOLEAN");
2836 return TCL_ERROR;
2837 }
2838 if( Tcl_GetBooleanFromObj(interp, objv[2], &onoff) ){
2839 return TCL_ERROR;
2840 }
2841 sqlite3_enable_load_extension(pDb->db, onoff);
2842 break;
drhf533acc2006-12-19 18:57:112843#else
2844 Tcl_AppendResult(interp, "extension loading is turned off at compile-time",
drha198f2b2014-02-07 19:26:132845 (char*)0);
drhf533acc2006-12-19 18:57:112846 return TCL_ERROR;
2847#endif
drh41449052006-07-06 17:08:482848 }
2849
2850 /*
drhdcd997e2003-01-31 17:21:492851 ** $db errorcode
2852 **
2853 ** Return the numeric error code that was returned by the most recent
danielk19776f8a5032004-05-10 10:34:512854 ** call to sqlite3_exec().
drhdcd997e2003-01-31 17:21:492855 */
2856 case DB_ERRORCODE: {
danielk1977f3ce83f2004-06-14 11:43:462857 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_errcode(pDb->db)));
drhdcd997e2003-01-31 17:21:492858 break;
2859 }
dan4a4c11a2009-10-06 14:59:022860
2861 /*
drhbe4e3c82022-02-16 15:11:012862 ** $db erroroffset
2863 **
2864 ** Return the numeric error code that was returned by the most recent
2865 ** call to sqlite3_exec().
2866 */
2867 case DB_ERROROFFSET: {
2868 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_error_offset(pDb->db)));
2869 break;
2870 }
2871
2872 /*
dan4a4c11a2009-10-06 14:59:022873 ** $db exists $sql
2874 ** $db onecolumn $sql
2875 **
2876 ** The onecolumn method is the equivalent of:
2877 ** lindex [$db eval $sql] 0
2878 */
mistachkinb56660f2016-07-14 21:26:092879 case DB_EXISTS:
dan4a4c11a2009-10-06 14:59:022880 case DB_ONECOLUMN: {
drhedc40242016-06-13 12:34:382881 Tcl_Obj *pResult = 0;
dan4a4c11a2009-10-06 14:59:022882 DbEvalContext sEval;
2883 if( objc!=3 ){
2884 Tcl_WrongNumArgs(interp, 2, objv, "SQL");
2885 return TCL_ERROR;
2886 }
2887
drhaf38cdb2017-06-26 21:08:322888 dbEvalInit(&sEval, pDb, objv[2], 0, 0);
dan4a4c11a2009-10-06 14:59:022889 rc = dbEvalStep(&sEval);
2890 if( choice==DB_ONECOLUMN ){
2891 if( rc==TCL_OK ){
drhedc40242016-06-13 12:34:382892 pResult = dbEvalColumnValue(&sEval, 0);
dand5f12cd2011-08-18 17:47:572893 }else if( rc==TCL_BREAK ){
2894 Tcl_ResetResult(interp);
dan4a4c11a2009-10-06 14:59:022895 }
2896 }else if( rc==TCL_BREAK || rc==TCL_OK ){
drhedc40242016-06-13 12:34:382897 pResult = Tcl_NewBooleanObj(rc==TCL_OK);
dan4a4c11a2009-10-06 14:59:022898 }
2899 dbEvalFinalize(&sEval);
drhedc40242016-06-13 12:34:382900 if( pResult ) Tcl_SetObjResult(interp, pResult);
dan4a4c11a2009-10-06 14:59:022901
2902 if( rc==TCL_BREAK ){
2903 rc = TCL_OK;
2904 }
2905 break;
2906 }
mistachkinb56660f2016-07-14 21:26:092907
drh75897232000-05-29 14:26:002908 /*
stephan10206572025-05-31 11:02:062909 ** $db eval ?options? $sql ?varName? ?{ ...code... }?
drh75897232000-05-29 14:26:002910 **
stephan10206572025-05-31 11:02:062911 ** The SQL statement in $sql is evaluated. For each row, the values
2912 ** are placed in elements of the array or dict named $varName and
2913 ** ...code... is executed. If $varName and $code are omitted, then
2914 ** no callback is ever invoked. If $varName is an empty string,
2915 ** then the values are placed in variables that have the same name
2916 ** as the fields extracted by the query, and those variables are
2917 ** accessible during the eval of $code.
drh75897232000-05-29 14:26:002918 */
dan4a4c11a2009-10-06 14:59:022919 case DB_EVAL: {
drhaf38cdb2017-06-26 21:08:322920 int evalFlags = 0;
2921 const char *zOpt;
2922 while( objc>3 && (zOpt = Tcl_GetString(objv[2]))!=0 && zOpt[0]=='-' ){
2923 if( strcmp(zOpt, "-withoutnulls")==0 ){
2924 evalFlags |= SQLITE_EVAL_WITHOUTNULLS;
stephan10206572025-05-31 11:02:062925 }else if( strcmp(zOpt, "-asdict")==0 ){
2926 evalFlags |= SQLITE_EVAL_ASDICT;
2927 }else{
drhaf38cdb2017-06-26 21:08:322928 Tcl_AppendResult(interp, "unknown option: \"", zOpt, "\"", (void*)0);
2929 return TCL_ERROR;
2930 }
2931 objc--;
2932 objv++;
2933 }
dan4a4c11a2009-10-06 14:59:022934 if( objc<3 || objc>5 ){
stephan10206572025-05-31 11:02:062935 Tcl_WrongNumArgs(interp, 2, objv,
2936 "?OPTIONS? SQL ?VAR-NAME? ?SCRIPT?");
dan4a4c11a2009-10-06 14:59:022937 return TCL_ERROR;
danielk197730ccda12004-05-27 12:11:312938 }
dan4a4c11a2009-10-06 14:59:022939
drh92febd92004-08-20 18:34:202940 if( objc==3 ){
dan4a4c11a2009-10-06 14:59:022941 DbEvalContext sEval;
2942 Tcl_Obj *pRet = Tcl_NewObj();
2943 Tcl_IncrRefCount(pRet);
drhaf38cdb2017-06-26 21:08:322944 dbEvalInit(&sEval, pDb, objv[2], 0, 0);
dan4a4c11a2009-10-06 14:59:022945 while( TCL_OK==(rc = dbEvalStep(&sEval)) ){
2946 int i;
2947 int nCol;
2948 dbEvalRowInfo(&sEval, &nCol, 0);
drh92febd92004-08-20 18:34:202949 for(i=0; i<nCol; i++){
dan4a4c11a2009-10-06 14:59:022950 Tcl_ListObjAppendElement(interp, pRet, dbEvalColumnValue(&sEval, i));
danielk197730ccda12004-05-27 12:11:312951 }
2952 }
dan4a4c11a2009-10-06 14:59:022953 dbEvalFinalize(&sEval);
drh90b6bb12004-09-13 13:16:312954 if( rc==TCL_BREAK ){
dan4a4c11a2009-10-06 14:59:022955 Tcl_SetObjResult(interp, pRet);
drh90b6bb12004-09-13 13:16:312956 rc = TCL_OK;
2957 }
drh1807ce32004-09-07 13:20:352958 Tcl_DecrRefCount(pRet);
dan4a4c11a2009-10-06 14:59:022959 }else{
mistachkin8e189222015-04-19 21:43:162960 ClientData cd2[2];
dan4a4c11a2009-10-06 14:59:022961 DbEvalContext *p;
stephan10206572025-05-31 11:02:062962 Tcl_Obj *pVarName = 0;
dan4a4c11a2009-10-06 14:59:022963 Tcl_Obj *pScript;
2964
drhaf38cdb2017-06-26 21:08:322965 if( objc>=5 && *(char *)Tcl_GetString(objv[3]) ){
stephan10206572025-05-31 11:02:062966 pVarName = objv[3];
dan4a4c11a2009-10-06 14:59:022967 }
2968 pScript = objv[objc-1];
2969 Tcl_IncrRefCount(pScript);
mistachkinb56660f2016-07-14 21:26:092970
dan4a4c11a2009-10-06 14:59:022971 p = (DbEvalContext *)Tcl_Alloc(sizeof(DbEvalContext));
stephan10206572025-05-31 11:02:062972 dbEvalInit(p, pDb, objv[2], pVarName, evalFlags);
dan4a4c11a2009-10-06 14:59:022973
mistachkin8e189222015-04-19 21:43:162974 cd2[0] = (void *)p;
2975 cd2[1] = (void *)pScript;
2976 rc = DbEvalNextCmd(cd2, interp, TCL_OK);
danielk197730ccda12004-05-27 12:11:312977 }
danielk197730ccda12004-05-27 12:11:312978 break;
2979 }
drhbec3f402000-08-04 13:49:022980
2981 /*
drh42d2fce2019-08-15 20:04:092982 ** $db function NAME [OPTIONS] SCRIPT
drhcabb0812002-09-14 13:47:322983 **
2984 ** Create a new SQL function called NAME. Whenever that function is
2985 ** called, invoke SCRIPT to evaluate the function.
drh42d2fce2019-08-15 20:04:092986 **
2987 ** Options:
2988 ** --argcount N Function has exactly N arguments
2989 ** --deterministic The function is pure
2990 ** --directonly Prohibit use inside triggers and views
drh15f3eac2020-01-08 15:44:102991 ** --innocuous Has no side effects or information leaks
drh42d2fce2019-08-15 20:04:092992 ** --returntype TYPE Specify the return type of the function
drhcabb0812002-09-14 13:47:322993 */
2994 case DB_FUNCTION: {
dan3df30592015-03-13 08:31:542995 int flags = SQLITE_UTF8;
drhcabb0812002-09-14 13:47:322996 SqlFunc *pFunc;
drhd1e47332005-06-26 17:55:332997 Tcl_Obj *pScript;
drhcabb0812002-09-14 13:47:322998 char *zName;
drhe3602be2008-09-09 12:31:332999 int nArg = -1;
dan3df30592015-03-13 08:31:543000 int i;
dan89d24932019-02-27 16:38:193001 int eType = SQLITE_NULL;
dan3df30592015-03-13 08:31:543002 if( objc<4 ){
3003 Tcl_WrongNumArgs(interp, 2, objv, "NAME ?SWITCHES? SCRIPT");
3004 return TCL_ERROR;
3005 }
3006 for(i=3; i<(objc-1); i++){
3007 const char *z = Tcl_GetString(objv[i]);
drh4f21c4a2008-12-10 22:15:003008 int n = strlen30(z);
dan89d24932019-02-27 16:38:193009 if( n>1 && strncmp(z, "-argcount",n)==0 ){
dan3df30592015-03-13 08:31:543010 if( i==(objc-2) ){
drhea8f0a12017-01-12 11:50:083011 Tcl_AppendResult(interp, "option requires an argument: ", z,(char*)0);
dan3df30592015-03-13 08:31:543012 return TCL_ERROR;
3013 }
3014 if( Tcl_GetIntFromObj(interp, objv[i+1], &nArg) ) return TCL_ERROR;
drhe3602be2008-09-09 12:31:333015 if( nArg<0 ){
3016 Tcl_AppendResult(interp, "number of arguments must be non-negative",
3017 (char*)0);
3018 return TCL_ERROR;
3019 }
dan3df30592015-03-13 08:31:543020 i++;
3021 }else
dan89d24932019-02-27 16:38:193022 if( n>1 && strncmp(z, "-deterministic",n)==0 ){
dan3df30592015-03-13 08:31:543023 flags |= SQLITE_DETERMINISTIC;
dan89d24932019-02-27 16:38:193024 }else
drh42d2fce2019-08-15 20:04:093025 if( n>1 && strncmp(z, "-directonly",n)==0 ){
3026 flags |= SQLITE_DIRECTONLY;
3027 }else
drh15f3eac2020-01-08 15:44:103028 if( n>1 && strncmp(z, "-innocuous",n)==0 ){
3029 flags |= SQLITE_INNOCUOUS;
3030 }else
dan89d24932019-02-27 16:38:193031 if( n>1 && strncmp(z, "-returntype", n)==0 ){
3032 const char *azType[] = {"integer", "real", "text", "blob", "any", 0};
3033 assert( SQLITE_INTEGER==1 && SQLITE_FLOAT==2 && SQLITE_TEXT==3 );
3034 assert( SQLITE_BLOB==4 && SQLITE_NULL==5 );
3035 if( i==(objc-2) ){
3036 Tcl_AppendResult(interp, "option requires an argument: ", z,(char*)0);
3037 return TCL_ERROR;
3038 }
3039 i++;
3040 if( Tcl_GetIndexFromObj(interp, objv[i], azType, "type", 0, &eType) ){
3041 return TCL_ERROR;
3042 }
3043 eType++;
dan3df30592015-03-13 08:31:543044 }else{
mistachkinb56660f2016-07-14 21:26:093045 Tcl_AppendResult(interp, "bad option \"", z,
drh42d2fce2019-08-15 20:04:093046 "\": must be -argcount, -deterministic, -directonly,"
drh15f3eac2020-01-08 15:44:103047 " -innocuous, or -returntype", (char*)0
dan3df30592015-03-13 08:31:543048 );
3049 return TCL_ERROR;
drhe3602be2008-09-09 12:31:333050 }
drhcabb0812002-09-14 13:47:323051 }
dan3df30592015-03-13 08:31:543052
3053 pScript = objv[objc-1];
drhcabb0812002-09-14 13:47:323054 zName = Tcl_GetStringFromObj(objv[2], 0);
drhd1e47332005-06-26 17:55:333055 pFunc = findSqlFunc(pDb, zName);
drhcabb0812002-09-14 13:47:323056 if( pFunc==0 ) return TCL_ERROR;
drhd1e47332005-06-26 17:55:333057 if( pFunc->pScript ){
3058 Tcl_DecrRefCount(pFunc->pScript);
3059 }
3060 pFunc->pScript = pScript;
3061 Tcl_IncrRefCount(pScript);
drh8bffd492025-01-30 16:07:513062 pFunc->useEvalObjv = safeToUseEvalObjv(pScript);
dan89d24932019-02-27 16:38:193063 pFunc->eType = eType;
dan3df30592015-03-13 08:31:543064 rc = sqlite3_create_function(pDb->db, zName, nArg, flags,
danielk1977d8123362004-06-12 09:25:123065 pFunc, tclSqlFunc, 0, 0);
drhfb7e7652005-01-24 00:28:423066 if( rc!=SQLITE_OK ){
danielk19779636c4e2005-01-25 04:27:543067 rc = TCL_ERROR;
3068 Tcl_SetResult(interp, (char *)sqlite3_errmsg(pDb->db), TCL_VOLATILE);
drhfb7e7652005-01-24 00:28:423069 }
drhcabb0812002-09-14 13:47:323070 break;
3071 }
3072
3073 /*
danielk19778cbadb02007-05-03 16:31:263074 ** $db incrblob ?-readonly? ?DB? TABLE COLUMN ROWID
danielk1977b4e9af92007-05-01 17:49:493075 */
3076 case DB_INCRBLOB: {
danielk197732a0d8b2007-05-04 19:03:023077#ifdef SQLITE_OMIT_INCRBLOB
drha198f2b2014-02-07 19:26:133078 Tcl_AppendResult(interp, "incrblob not available in this build", (char*)0);
danielk197732a0d8b2007-05-04 19:03:023079 return TCL_ERROR;
3080#else
danielk19778cbadb02007-05-03 16:31:263081 int isReadonly = 0;
danielk1977b4e9af92007-05-01 17:49:493082 const char *zDb = "main";
3083 const char *zTable;
3084 const char *zColumn;
drhb3f787f2012-09-29 14:45:543085 Tcl_WideInt iRow;
danielk1977b4e9af92007-05-01 17:49:493086
danielk19778cbadb02007-05-03 16:31:263087 /* Check for the -readonly option */
3088 if( objc>3 && strcmp(Tcl_GetString(objv[2]), "-readonly")==0 ){
3089 isReadonly = 1;
3090 }
3091
3092 if( objc!=(5+isReadonly) && objc!=(6+isReadonly) ){
3093 Tcl_WrongNumArgs(interp, 2, objv, "?-readonly? ?DB? TABLE COLUMN ROWID");
danielk1977b4e9af92007-05-01 17:49:493094 return TCL_ERROR;
3095 }
3096
danielk19778cbadb02007-05-03 16:31:263097 if( objc==(6+isReadonly) ){
danf74f4ed2022-06-01 14:32:053098 zDb = Tcl_GetString(objv[2+isReadonly]);
danielk1977b4e9af92007-05-01 17:49:493099 }
3100 zTable = Tcl_GetString(objv[objc-3]);
3101 zColumn = Tcl_GetString(objv[objc-2]);
3102 rc = Tcl_GetWideIntFromObj(interp, objv[objc-1], &iRow);
3103
3104 if( rc==TCL_OK ){
danielk19778cbadb02007-05-03 16:31:263105 rc = createIncrblobChannel(
danedf5b162014-08-19 09:15:413106 interp, pDb, zDb, zTable, zColumn, (sqlite3_int64)iRow, isReadonly
danielk19778cbadb02007-05-03 16:31:263107 );
danielk1977b4e9af92007-05-01 17:49:493108 }
danielk197732a0d8b2007-05-04 19:03:023109#endif
danielk1977b4e9af92007-05-01 17:49:493110 break;
3111 }
3112
3113 /*
drhf11bded2006-07-17 00:02:443114 ** $db interrupt
3115 **
3116 ** Interrupt the execution of the inner-most SQL interpreter. This
3117 ** causes the SQL statement to return an error of SQLITE_INTERRUPT.
3118 */
3119 case DB_INTERRUPT: {
3120 sqlite3_interrupt(pDb->db);
3121 break;
3122 }
3123
3124 /*
drh19e2d372005-08-29 23:00:033125 ** $db nullvalue ?STRING?
3126 **
3127 ** Change text used when a NULL comes back from the database. If ?STRING?
3128 ** is not present, then the current string used for NULL is returned.
3129 ** If STRING is present, then STRING is returned.
3130 **
3131 */
3132 case DB_NULLVALUE: {
3133 if( objc!=2 && objc!=3 ){
3134 Tcl_WrongNumArgs(interp, 2, objv, "NULLVALUE");
3135 return TCL_ERROR;
3136 }
3137 if( objc==3 ){
drh064b6812024-07-30 15:49:023138 Tcl_Size len;
drh19e2d372005-08-29 23:00:033139 char *zNull = Tcl_GetStringFromObj(objv[2], &len);
3140 if( pDb->zNull ){
3141 Tcl_Free(pDb->zNull);
3142 }
3143 if( zNull && len>0 ){
3144 pDb->zNull = Tcl_Alloc( len + 1 );
drh7fd33922011-06-20 19:00:303145 memcpy(pDb->zNull, zNull, len);
drh19e2d372005-08-29 23:00:033146 pDb->zNull[len] = '\0';
3147 }else{
3148 pDb->zNull = 0;
3149 }
3150 }
drhc45e6712012-10-03 11:02:333151 Tcl_SetObjResult(interp, Tcl_NewStringObj(pDb->zNull, -1));
drh19e2d372005-08-29 23:00:033152 break;
3153 }
3154
3155 /*
mistachkinb56660f2016-07-14 21:26:093156 ** $db last_insert_rowid
drhaf9ff332002-01-16 21:00:273157 **
3158 ** Return an integer which is the ROWID for the most recent insert.
3159 */
3160 case DB_LAST_INSERT_ROWID: {
3161 Tcl_Obj *pResult;
drhf7e678d2006-06-21 19:30:343162 Tcl_WideInt rowid;
drhaf9ff332002-01-16 21:00:273163 if( objc!=2 ){
3164 Tcl_WrongNumArgs(interp, 2, objv, "");
3165 return TCL_ERROR;
3166 }
danielk19776f8a5032004-05-10 10:34:513167 rowid = sqlite3_last_insert_rowid(pDb->db);
drhaf9ff332002-01-16 21:00:273168 pResult = Tcl_GetObjResult(interp);
drhf7e678d2006-06-21 19:30:343169 Tcl_SetWideIntObj(pResult, rowid);
drhaf9ff332002-01-16 21:00:273170 break;
3171 }
3172
3173 /*
dan4a4c11a2009-10-06 14:59:023174 ** The DB_ONECOLUMN method is implemented together with DB_EXISTS.
drh5d9d7572003-08-19 14:31:013175 */
drh1807ce32004-09-07 13:20:353176
3177 /* $db progress ?N CALLBACK?
mistachkinb56660f2016-07-14 21:26:093178 **
drh1807ce32004-09-07 13:20:353179 ** Invoke the given callback every N virtual machine opcodes while executing
3180 ** queries.
3181 */
3182 case DB_PROGRESS: {
3183 if( objc==2 ){
3184 if( pDb->zProgress ){
drha198f2b2014-02-07 19:26:133185 Tcl_AppendResult(interp, pDb->zProgress, (char*)0);
drh1807ce32004-09-07 13:20:353186 }
drh2fc9dc92023-01-12 19:51:493187#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
3188 sqlite3_progress_handler(pDb->db, 0, 0, 0);
3189#endif
drh1807ce32004-09-07 13:20:353190 }else if( objc==4 ){
3191 char *zProgress;
drh064b6812024-07-30 15:49:023192 Tcl_Size len;
drh1807ce32004-09-07 13:20:353193 int N;
3194 if( TCL_OK!=Tcl_GetIntFromObj(interp, objv[2], &N) ){
drhfd131da2007-08-07 17:13:033195 return TCL_ERROR;
drh1807ce32004-09-07 13:20:353196 };
3197 if( pDb->zProgress ){
3198 Tcl_Free(pDb->zProgress);
3199 }
3200 zProgress = Tcl_GetStringFromObj(objv[3], &len);
3201 if( zProgress && len>0 ){
3202 pDb->zProgress = Tcl_Alloc( len + 1 );
drh5bb3eb92007-05-04 13:15:553203 memcpy(pDb->zProgress, zProgress, len+1);
drh1807ce32004-09-07 13:20:353204 }else{
3205 pDb->zProgress = 0;
3206 }
3207#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
3208 if( pDb->zProgress ){
3209 pDb->interp = interp;
3210 sqlite3_progress_handler(pDb->db, N, DbProgressHandler, pDb);
3211 }else{
3212 sqlite3_progress_handler(pDb->db, 0, 0, 0);
3213 }
3214#endif
3215 }else{
3216 Tcl_WrongNumArgs(interp, 2, objv, "N CALLBACK");
drh5d9d7572003-08-19 14:31:013217 return TCL_ERROR;
3218 }
drh5d9d7572003-08-19 14:31:013219 break;
3220 }
3221
drh19e2d372005-08-29 23:00:033222 /* $db profile ?CALLBACK?
3223 **
3224 ** Make arrangements to invoke the CALLBACK routine after each SQL statement
3225 ** that has run. The text of the SQL and the amount of elapse time are
3226 ** appended to CALLBACK before the script is run.
3227 */
3228 case DB_PROFILE: {
3229 if( objc>3 ){
3230 Tcl_WrongNumArgs(interp, 2, objv, "?CALLBACK?");
3231 return TCL_ERROR;
3232 }else if( objc==2 ){
3233 if( pDb->zProfile ){
drha198f2b2014-02-07 19:26:133234 Tcl_AppendResult(interp, pDb->zProfile, (char*)0);
drh19e2d372005-08-29 23:00:033235 }
3236 }else{
3237 char *zProfile;
drh064b6812024-07-30 15:49:023238 Tcl_Size len;
drh19e2d372005-08-29 23:00:033239 if( pDb->zProfile ){
3240 Tcl_Free(pDb->zProfile);
3241 }
3242 zProfile = Tcl_GetStringFromObj(objv[2], &len);
3243 if( zProfile && len>0 ){
3244 pDb->zProfile = Tcl_Alloc( len + 1 );
drh5bb3eb92007-05-04 13:15:553245 memcpy(pDb->zProfile, zProfile, len+1);
drh19e2d372005-08-29 23:00:033246 }else{
3247 pDb->zProfile = 0;
3248 }
drh2eb22af2016-09-10 19:51:403249#if !defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_OMIT_FLOATING_POINT) && \
3250 !defined(SQLITE_OMIT_DEPRECATED)
drh19e2d372005-08-29 23:00:033251 if( pDb->zProfile ){
3252 pDb->interp = interp;
3253 sqlite3_profile(pDb->db, DbProfileHandler, pDb);
3254 }else{
3255 sqlite3_profile(pDb->db, 0, 0);
3256 }
3257#endif
3258 }
3259 break;
3260 }
3261
drh5d9d7572003-08-19 14:31:013262 /*
drh22fbcb82004-02-01 01:22:503263 ** $db rekey KEY
3264 **
3265 ** Change the encryption key on the currently open database.
3266 */
3267 case DB_REKEY: {
drh22fbcb82004-02-01 01:22:503268 if( objc!=3 ){
3269 Tcl_WrongNumArgs(interp, 2, objv, "KEY");
3270 return TCL_ERROR;
3271 }
drh22fbcb82004-02-01 01:22:503272 break;
3273 }
3274
drhdc2c4912009-02-04 22:46:473275 /* $db restore ?DATABASE? FILENAME
3276 **
mistachkinb56660f2016-07-14 21:26:093277 ** Open a database file named FILENAME. Transfer the content
drhdc2c4912009-02-04 22:46:473278 ** of FILENAME into the local database DATABASE (default: "main").
3279 */
3280 case DB_RESTORE: {
3281 const char *zSrcFile;
3282 const char *zDestDb;
3283 sqlite3 *pSrc;
3284 sqlite3_backup *pBackup;
3285 int nTimeout = 0;
3286
3287 if( objc==3 ){
3288 zDestDb = "main";
3289 zSrcFile = Tcl_GetString(objv[2]);
3290 }else if( objc==4 ){
3291 zDestDb = Tcl_GetString(objv[2]);
3292 zSrcFile = Tcl_GetString(objv[3]);
3293 }else{
3294 Tcl_WrongNumArgs(interp, 2, objv, "?DATABASE? FILENAME");
3295 return TCL_ERROR;
3296 }
drh147ef392016-01-22 23:17:513297 rc = sqlite3_open_v2(zSrcFile, &pSrc,
3298 SQLITE_OPEN_READONLY | pDb->openFlags, 0);
drhdc2c4912009-02-04 22:46:473299 if( rc!=SQLITE_OK ){
3300 Tcl_AppendResult(interp, "cannot open source database: ",
3301 sqlite3_errmsg(pSrc), (char*)0);
3302 sqlite3_close(pSrc);
3303 return TCL_ERROR;
3304 }
3305 pBackup = sqlite3_backup_init(pDb->db, zDestDb, pSrc, "main");
3306 if( pBackup==0 ){
3307 Tcl_AppendResult(interp, "restore failed: ",
3308 sqlite3_errmsg(pDb->db), (char*)0);
3309 sqlite3_close(pSrc);
3310 return TCL_ERROR;
3311 }
3312 while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK
3313 || rc==SQLITE_BUSY ){
3314 if( rc==SQLITE_BUSY ){
3315 if( nTimeout++ >= 3 ) break;
3316 sqlite3_sleep(100);
3317 }
3318 }
3319 sqlite3_backup_finish(pBackup);
3320 if( rc==SQLITE_DONE ){
3321 rc = TCL_OK;
3322 }else if( rc==SQLITE_BUSY || rc==SQLITE_LOCKED ){
3323 Tcl_AppendResult(interp, "restore failed: source database busy",
3324 (char*)0);
3325 rc = TCL_ERROR;
3326 }else{
3327 Tcl_AppendResult(interp, "restore failed: ",
3328 sqlite3_errmsg(pDb->db), (char*)0);
3329 rc = TCL_ERROR;
3330 }
3331 sqlite3_close(pSrc);
3332 break;
3333 }
3334
drh22fbcb82004-02-01 01:22:503335 /*
drhcb7d5412018-01-03 16:49:523336 ** $db serialize ?DATABASE?
3337 **
3338 ** Return a serialization of a database.
3339 */
3340 case DB_SERIALIZE: {
drh8d889af2021-05-08 17:18:233341#ifdef SQLITE_OMIT_DESERIALIZE
drhcb7d5412018-01-03 16:49:523342 Tcl_AppendResult(interp, "MEMDB not available in this build",
3343 (char*)0);
3344 rc = TCL_ERROR;
3345#else
3346 const char *zSchema = objc>=3 ? Tcl_GetString(objv[2]) : "main";
3347 sqlite3_int64 sz = 0;
3348 unsigned char *pData;
3349 if( objc!=2 && objc!=3 ){
3350 Tcl_WrongNumArgs(interp, 2, objv, "?DATABASE?");
3351 rc = TCL_ERROR;
3352 }else{
3353 int needFree;
3354 pData = sqlite3_serialize(pDb->db, zSchema, &sz, SQLITE_SERIALIZE_NOCOPY);
3355 if( pData ){
3356 needFree = 0;
3357 }else{
3358 pData = sqlite3_serialize(pDb->db, zSchema, &sz, 0);
3359 needFree = 1;
3360 }
3361 Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(pData,sz));
3362 if( needFree ) sqlite3_free(pData);
3363 }
3364#endif
3365 break;
3366 }
3367
3368 /*
danc456a762017-06-22 16:51:163369 ** $db status (step|sort|autoindex|vmstep)
drhd1d38482008-10-07 23:46:383370 **
mistachkinb56660f2016-07-14 21:26:093371 ** Display SQLITE_STMTSTATUS_FULLSCAN_STEP or
drhd1d38482008-10-07 23:46:383372 ** SQLITE_STMTSTATUS_SORT for the most recent eval.
3373 */
3374 case DB_STATUS: {
drhd1d38482008-10-07 23:46:383375 int v;
3376 const char *zOp;
3377 if( objc!=3 ){
drh1c320a42010-08-01 22:41:323378 Tcl_WrongNumArgs(interp, 2, objv, "(step|sort|autoindex)");
drhd1d38482008-10-07 23:46:383379 return TCL_ERROR;
3380 }
3381 zOp = Tcl_GetString(objv[2]);
3382 if( strcmp(zOp, "step")==0 ){
3383 v = pDb->nStep;
3384 }else if( strcmp(zOp, "sort")==0 ){
3385 v = pDb->nSort;
drh3c379b02010-04-07 19:31:593386 }else if( strcmp(zOp, "autoindex")==0 ){
3387 v = pDb->nIndex;
danc456a762017-06-22 16:51:163388 }else if( strcmp(zOp, "vmstep")==0 ){
3389 v = pDb->nVMStep;
drhd1d38482008-10-07 23:46:383390 }else{
mistachkinb56660f2016-07-14 21:26:093391 Tcl_AppendResult(interp,
danc456a762017-06-22 16:51:163392 "bad argument: should be autoindex, step, sort or vmstep",
drhd1d38482008-10-07 23:46:383393 (char*)0);
3394 return TCL_ERROR;
3395 }
3396 Tcl_SetObjResult(interp, Tcl_NewIntObj(v));
3397 break;
3398 }
mistachkinb56660f2016-07-14 21:26:093399
drhd1d38482008-10-07 23:46:383400 /*
drhbec3f402000-08-04 13:49:023401 ** $db timeout MILLESECONDS
3402 **
3403 ** Delay for the number of milliseconds specified when a file is locked.
3404 */
drh6d313162000-09-21 13:01:353405 case DB_TIMEOUT: {
drhbec3f402000-08-04 13:49:023406 int ms;
drh6d313162000-09-21 13:01:353407 if( objc!=3 ){
3408 Tcl_WrongNumArgs(interp, 2, objv, "MILLISECONDS");
drhbec3f402000-08-04 13:49:023409 return TCL_ERROR;
3410 }
drh6d313162000-09-21 13:01:353411 if( Tcl_GetIntFromObj(interp, objv[2], &ms) ) return TCL_ERROR;
danielk19776f8a5032004-05-10 10:34:513412 sqlite3_busy_timeout(pDb->db, ms);
drh6d313162000-09-21 13:01:353413 break;
drh75897232000-05-29 14:26:003414 }
mistachkinb56660f2016-07-14 21:26:093415
danielk197755c45f22005-04-03 23:54:433416 /*
drh0f14e2e2004-06-29 12:39:083417 ** $db total_changes
3418 **
mistachkinb56660f2016-07-14 21:26:093419 ** Return the number of rows that were modified, inserted, or deleted
drh0f14e2e2004-06-29 12:39:083420 ** since the database handle was created.
3421 */
3422 case DB_TOTAL_CHANGES: {
3423 Tcl_Obj *pResult;
3424 if( objc!=2 ){
3425 Tcl_WrongNumArgs(interp, 2, objv, "");
3426 return TCL_ERROR;
3427 }
3428 pResult = Tcl_GetObjResult(interp);
dan2c718872021-06-22 18:32:053429 Tcl_SetWideIntObj(pResult, sqlite3_total_changes64(pDb->db));
drh0f14e2e2004-06-29 12:39:083430 break;
3431 }
3432
drhb5a20d32003-04-23 12:25:233433 /* $db trace ?CALLBACK?
3434 **
3435 ** Make arrangements to invoke the CALLBACK routine for each SQL statement
3436 ** that is executed. The text of the SQL is appended to CALLBACK before
3437 ** it is executed.
3438 */
3439 case DB_TRACE: {
3440 if( objc>3 ){
3441 Tcl_WrongNumArgs(interp, 2, objv, "?CALLBACK?");
drhb97759e2004-06-29 11:26:593442 return TCL_ERROR;
drhb5a20d32003-04-23 12:25:233443 }else if( objc==2 ){
3444 if( pDb->zTrace ){
drha198f2b2014-02-07 19:26:133445 Tcl_AppendResult(interp, pDb->zTrace, (char*)0);
drhb5a20d32003-04-23 12:25:233446 }
3447 }else{
3448 char *zTrace;
drh064b6812024-07-30 15:49:023449 Tcl_Size len;
drhb5a20d32003-04-23 12:25:233450 if( pDb->zTrace ){
3451 Tcl_Free(pDb->zTrace);
3452 }
3453 zTrace = Tcl_GetStringFromObj(objv[2], &len);
3454 if( zTrace && len>0 ){
3455 pDb->zTrace = Tcl_Alloc( len + 1 );
drh5bb3eb92007-05-04 13:15:553456 memcpy(pDb->zTrace, zTrace, len+1);
drhb5a20d32003-04-23 12:25:233457 }else{
3458 pDb->zTrace = 0;
3459 }
drh2eb22af2016-09-10 19:51:403460#if !defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_OMIT_FLOATING_POINT) && \
3461 !defined(SQLITE_OMIT_DEPRECATED)
drhb5a20d32003-04-23 12:25:233462 if( pDb->zTrace ){
3463 pDb->interp = interp;
danielk19776f8a5032004-05-10 10:34:513464 sqlite3_trace(pDb->db, DbTraceHandler, pDb);
drhb5a20d32003-04-23 12:25:233465 }else{
danielk19776f8a5032004-05-10 10:34:513466 sqlite3_trace(pDb->db, 0, 0);
drhb5a20d32003-04-23 12:25:233467 }
drh19e2d372005-08-29 23:00:033468#endif
drhb5a20d32003-04-23 12:25:233469 }
3470 break;
3471 }
3472
mistachkinb56660f2016-07-14 21:26:093473 /* $db trace_v2 ?CALLBACK? ?MASK?
3474 **
3475 ** Make arrangements to invoke the CALLBACK routine for each trace event
3476 ** matching the mask that is generated. The parameters are appended to
3477 ** CALLBACK before it is executed.
3478 */
3479 case DB_TRACE_V2: {
3480 if( objc>4 ){
3481 Tcl_WrongNumArgs(interp, 2, objv, "?CALLBACK? ?MASK?");
3482 return TCL_ERROR;
3483 }else if( objc==2 ){
3484 if( pDb->zTraceV2 ){
3485 Tcl_AppendResult(interp, pDb->zTraceV2, (char*)0);
3486 }
3487 }else{
mistachkinb56660f2016-07-14 21:26:093488 char *zTraceV2;
drh064b6812024-07-30 15:49:023489 Tcl_Size len;
mistachkinb52dcd82016-07-14 23:17:033490 Tcl_WideInt wMask = 0;
mistachkinb56660f2016-07-14 21:26:093491 if( objc==4 ){
mistachkinb52dcd82016-07-14 23:17:033492 static const char *TTYPE_strs[] = {
3493 "statement", "profile", "row", "close", 0
3494 };
3495 enum TTYPE_enum {
3496 TTYPE_STMT, TTYPE_PROFILE, TTYPE_ROW, TTYPE_CLOSE
3497 };
drhe57527c2024-12-09 20:46:363498 Tcl_Size i;
mistachkinb52dcd82016-07-14 23:17:033499 if( TCL_OK!=Tcl_ListObjLength(interp, objv[3], &len) ){
mistachkinb56660f2016-07-14 21:26:093500 return TCL_ERROR;
3501 }
mistachkinb52dcd82016-07-14 23:17:033502 for(i=0; i<len; i++){
3503 Tcl_Obj *pObj;
3504 int ttype;
3505 if( TCL_OK!=Tcl_ListObjIndex(interp, objv[3], i, &pObj) ){
3506 return TCL_ERROR;
3507 }
3508 if( Tcl_GetIndexFromObj(interp, pObj, TTYPE_strs, "trace type",
3509 0, &ttype)!=TCL_OK ){
3510 Tcl_WideInt wType;
3511 Tcl_Obj *pError = Tcl_DuplicateObj(Tcl_GetObjResult(interp));
3512 Tcl_IncrRefCount(pError);
3513 if( TCL_OK==Tcl_GetWideIntFromObj(interp, pObj, &wType) ){
3514 Tcl_DecrRefCount(pError);
3515 wMask |= wType;
3516 }else{
3517 Tcl_SetObjResult(interp, pError);
3518 Tcl_DecrRefCount(pError);
3519 return TCL_ERROR;
3520 }
3521 }else{
3522 switch( (enum TTYPE_enum)ttype ){
3523 case TTYPE_STMT: wMask |= SQLITE_TRACE_STMT; break;
3524 case TTYPE_PROFILE: wMask |= SQLITE_TRACE_PROFILE; break;
3525 case TTYPE_ROW: wMask |= SQLITE_TRACE_ROW; break;
3526 case TTYPE_CLOSE: wMask |= SQLITE_TRACE_CLOSE; break;
3527 }
3528 }
3529 }
mistachkinb56660f2016-07-14 21:26:093530 }else{
mistachkinb52dcd82016-07-14 23:17:033531 wMask = SQLITE_TRACE_STMT; /* use the "legacy" default */
mistachkinb56660f2016-07-14 21:26:093532 }
3533 if( pDb->zTraceV2 ){
3534 Tcl_Free(pDb->zTraceV2);
3535 }
3536 zTraceV2 = Tcl_GetStringFromObj(objv[2], &len);
3537 if( zTraceV2 && len>0 ){
3538 pDb->zTraceV2 = Tcl_Alloc( len + 1 );
3539 memcpy(pDb->zTraceV2, zTraceV2, len+1);
3540 }else{
3541 pDb->zTraceV2 = 0;
3542 }
3543#if !defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_OMIT_FLOATING_POINT)
3544 if( pDb->zTraceV2 ){
3545 pDb->interp = interp;
3546 sqlite3_trace_v2(pDb->db, (unsigned)wMask, DbTraceV2Handler, pDb);
3547 }else{
3548 sqlite3_trace_v2(pDb->db, 0, 0, 0);
3549 }
3550#endif
3551 }
3552 break;
3553 }
3554
drh3d214232005-08-02 12:21:083555 /* $db transaction [-deferred|-immediate|-exclusive] SCRIPT
3556 **
3557 ** Start a new transaction (if we are not already in the midst of a
3558 ** transaction) and execute the TCL script SCRIPT. After SCRIPT
3559 ** completes, either commit the transaction or roll it back if SCRIPT
larrybrbc917382023-06-07 08:40:313560 ** throws an exception. Or if no new transaction was started, do nothing.
drh3d214232005-08-02 12:21:083561 ** pass the exception on up the stack.
3562 **
3563 ** This command was inspired by Dave Thomas's talk on Ruby at the
3564 ** 2005 O'Reilly Open Source Convention (OSCON).
3565 */
3566 case DB_TRANSACTION: {
drh3d214232005-08-02 12:21:083567 Tcl_Obj *pScript;
danielk1977cd38d522009-01-02 17:33:463568 const char *zBegin = "SAVEPOINT _tcl_transaction";
drh3d214232005-08-02 12:21:083569 if( objc!=3 && objc!=4 ){
3570 Tcl_WrongNumArgs(interp, 2, objv, "[TYPE] SCRIPT");
3571 return TCL_ERROR;
3572 }
danielk1977cd38d522009-01-02 17:33:463573
dan4a4c11a2009-10-06 14:59:023574 if( pDb->nTransaction==0 && objc==4 ){
drh3d214232005-08-02 12:21:083575 static const char *TTYPE_strs[] = {
drhce604012005-08-16 11:11:343576 "deferred", "exclusive", "immediate", 0
drh3d214232005-08-02 12:21:083577 };
3578 enum TTYPE_enum {
3579 TTYPE_DEFERRED, TTYPE_EXCLUSIVE, TTYPE_IMMEDIATE
3580 };
3581 int ttype;
drhb5555e72005-08-02 17:15:143582 if( Tcl_GetIndexFromObj(interp, objv[2], TTYPE_strs, "transaction type",
drh3d214232005-08-02 12:21:083583 0, &ttype) ){
3584 return TCL_ERROR;
3585 }
3586 switch( (enum TTYPE_enum)ttype ){
3587 case TTYPE_DEFERRED: /* no-op */; break;
3588 case TTYPE_EXCLUSIVE: zBegin = "BEGIN EXCLUSIVE"; break;
3589 case TTYPE_IMMEDIATE: zBegin = "BEGIN IMMEDIATE"; break;
3590 }
drh3d214232005-08-02 12:21:083591 }
danielk1977cd38d522009-01-02 17:33:463592 pScript = objv[objc-1];
3593
dan4a4c11a2009-10-06 14:59:023594 /* Run the SQLite BEGIN command to open a transaction or savepoint. */
danielk1977cd38d522009-01-02 17:33:463595 pDb->disableAuth++;
3596 rc = sqlite3_exec(pDb->db, zBegin, 0, 0, 0);
3597 pDb->disableAuth--;
3598 if( rc!=SQLITE_OK ){
drha198f2b2014-02-07 19:26:133599 Tcl_AppendResult(interp, sqlite3_errmsg(pDb->db), (char*)0);
danielk1977cd38d522009-01-02 17:33:463600 return TCL_ERROR;
drh3d214232005-08-02 12:21:083601 }
danielk1977cd38d522009-01-02 17:33:463602 pDb->nTransaction++;
danielk1977cd38d522009-01-02 17:33:463603
dan4a4c11a2009-10-06 14:59:023604 /* If using NRE, schedule a callback to invoke the script pScript, then
3605 ** a second callback to commit (or rollback) the transaction or savepoint
3606 ** opened above. If not using NRE, evaluate the script directly, then
mistachkinb56660f2016-07-14 21:26:093607 ** call function DbTransPostCmd() to commit (or rollback) the transaction
dan4a4c11a2009-10-06 14:59:023608 ** or savepoint. */
danbea28c72021-09-16 14:17:143609 addDatabaseRef(pDb); /* DbTransPostCmd() calls delDatabaseRef() */
dan4a4c11a2009-10-06 14:59:023610 if( DbUseNre() ){
3611 Tcl_NRAddCallback(interp, DbTransPostCmd, cd, 0, 0, 0);
drha47941f2013-12-20 18:57:443612 (void)Tcl_NREvalObj(interp, pScript, 0);
danielk1977cd38d522009-01-02 17:33:463613 }else{
dan4a4c11a2009-10-06 14:59:023614 rc = DbTransPostCmd(&cd, interp, Tcl_EvalObjEx(interp, pScript, 0));
drh3d214232005-08-02 12:21:083615 }
drh3d214232005-08-02 12:21:083616 break;
3617 }
3618
danielk197794eb6a12005-12-15 15:22:083619 /*
danielk1977404ca072009-03-16 13:19:363620 ** $db unlock_notify ?script?
3621 */
3622 case DB_UNLOCK_NOTIFY: {
3623#ifndef SQLITE_ENABLE_UNLOCK_NOTIFY
drha198f2b2014-02-07 19:26:133624 Tcl_AppendResult(interp, "unlock_notify not available in this build",
3625 (char*)0);
danielk1977404ca072009-03-16 13:19:363626 rc = TCL_ERROR;
3627#else
3628 if( objc!=2 && objc!=3 ){
3629 Tcl_WrongNumArgs(interp, 2, objv, "?SCRIPT?");
3630 rc = TCL_ERROR;
3631 }else{
3632 void (*xNotify)(void **, int) = 0;
3633 void *pNotifyArg = 0;
3634
3635 if( pDb->pUnlockNotify ){
3636 Tcl_DecrRefCount(pDb->pUnlockNotify);
3637 pDb->pUnlockNotify = 0;
3638 }
mistachkinb56660f2016-07-14 21:26:093639
danielk1977404ca072009-03-16 13:19:363640 if( objc==3 ){
3641 xNotify = DbUnlockNotify;
3642 pNotifyArg = (void *)pDb;
3643 pDb->pUnlockNotify = objv[2];
3644 Tcl_IncrRefCount(pDb->pUnlockNotify);
3645 }
mistachkinb56660f2016-07-14 21:26:093646
danielk1977404ca072009-03-16 13:19:363647 if( sqlite3_unlock_notify(pDb->db, xNotify, pNotifyArg) ){
drha198f2b2014-02-07 19:26:133648 Tcl_AppendResult(interp, sqlite3_errmsg(pDb->db), (char*)0);
danielk1977404ca072009-03-16 13:19:363649 rc = TCL_ERROR;
3650 }
3651 }
3652#endif
3653 break;
3654 }
3655
drh304637c2011-03-18 16:47:273656 /*
3657 ** $db preupdate_hook count
3658 ** $db preupdate_hook hook ?SCRIPT?
3659 ** $db preupdate_hook new INDEX
3660 ** $db preupdate_hook old INDEX
3661 */
dan46c47d42011-03-01 18:42:073662 case DB_PREUPDATE: {
drh9b1c62d2011-03-30 21:04:433663#ifndef SQLITE_ENABLE_PREUPDATE_HOOK
dan2b519ab2016-12-06 19:33:423664 Tcl_AppendResult(interp, "preupdate_hook was omitted at compile-time",
3665 (char*)0);
drh9b1c62d2011-03-30 21:04:433666 rc = TCL_ERROR;
3667#else
dan1e7a2d42011-03-22 18:45:293668 static const char *azSub[] = {"count", "depth", "hook", "new", "old", 0};
dan46c47d42011-03-01 18:42:073669 enum DbPreupdateSubCmd {
dan1e7a2d42011-03-22 18:45:293670 PRE_COUNT, PRE_DEPTH, PRE_HOOK, PRE_NEW, PRE_OLD
dan46c47d42011-03-01 18:42:073671 };
3672 int iSub;
3673
3674 if( objc<3 ){
3675 Tcl_WrongNumArgs(interp, 2, objv, "SUB-COMMAND ?ARGS?");
3676 }
3677 if( Tcl_GetIndexFromObj(interp, objv[2], azSub, "sub-command", 0, &iSub) ){
3678 return TCL_ERROR;
3679 }
3680
3681 switch( (enum DbPreupdateSubCmd)iSub ){
3682 case PRE_COUNT: {
3683 int nCol = sqlite3_preupdate_count(pDb->db);
3684 Tcl_SetObjResult(interp, Tcl_NewIntObj(nCol));
3685 break;
3686 }
3687
3688 case PRE_HOOK: {
3689 if( objc>4 ){
3690 Tcl_WrongNumArgs(interp, 2, objv, "hook ?SCRIPT?");
3691 return TCL_ERROR;
3692 }
3693 DbHookCmd(interp, pDb, (objc==4 ? objv[3] : 0), &pDb->pPreUpdateHook);
3694 break;
3695 }
3696
dan1e7a2d42011-03-22 18:45:293697 case PRE_DEPTH: {
3698 Tcl_Obj *pRet;
3699 if( objc!=3 ){
3700 Tcl_WrongNumArgs(interp, 3, objv, "");
3701 return TCL_ERROR;
3702 }
3703 pRet = Tcl_NewIntObj(sqlite3_preupdate_depth(pDb->db));
3704 Tcl_SetObjResult(interp, pRet);
3705 break;
3706 }
3707
dan37db03b2011-03-16 19:59:183708 case PRE_NEW:
dan46c47d42011-03-01 18:42:073709 case PRE_OLD: {
3710 int iIdx;
dan37db03b2011-03-16 19:59:183711 sqlite3_value *pValue;
dan46c47d42011-03-01 18:42:073712 if( objc!=4 ){
3713 Tcl_WrongNumArgs(interp, 3, objv, "INDEX");
3714 return TCL_ERROR;
3715 }
3716 if( Tcl_GetIntFromObj(interp, objv[3], &iIdx) ){
3717 return TCL_ERROR;
3718 }
3719
dan37db03b2011-03-16 19:59:183720 if( iSub==PRE_OLD ){
dan46c47d42011-03-01 18:42:073721 rc = sqlite3_preupdate_old(pDb->db, iIdx, &pValue);
dan37db03b2011-03-16 19:59:183722 }else{
3723 assert( iSub==PRE_NEW );
3724 rc = sqlite3_preupdate_new(pDb->db, iIdx, &pValue);
dan46c47d42011-03-01 18:42:073725 }
3726
dan37db03b2011-03-16 19:59:183727 if( rc==SQLITE_OK ){
drh304637c2011-03-18 16:47:273728 Tcl_Obj *pObj;
3729 pObj = Tcl_NewStringObj((char*)sqlite3_value_text(pValue), -1);
dan37db03b2011-03-16 19:59:183730 Tcl_SetObjResult(interp, pObj);
3731 }else{
drhea8f0a12017-01-12 11:50:083732 Tcl_AppendResult(interp, sqlite3_errmsg(pDb->db), (char*)0);
dan46c47d42011-03-01 18:42:073733 return TCL_ERROR;
3734 }
3735 }
3736 }
drh9b1c62d2011-03-30 21:04:433737#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */
dan46c47d42011-03-01 18:42:073738 break;
3739 }
3740
danielk1977404ca072009-03-16 13:19:363741 /*
drh833bf962010-04-28 14:42:193742 ** $db wal_hook ?script?
danielk197794eb6a12005-12-15 15:22:083743 ** $db update_hook ?script?
danielk197771fd80b2005-12-16 06:54:013744 ** $db rollback_hook ?script?
danielk197794eb6a12005-12-15 15:22:083745 */
mistachkinb56660f2016-07-14 21:26:093746 case DB_WAL_HOOK:
3747 case DB_UPDATE_HOOK:
dan6566ebe2011-03-16 09:49:143748 case DB_ROLLBACK_HOOK: {
mistachkinb56660f2016-07-14 21:26:093749 /* set ppHook to point at pUpdateHook or pRollbackHook, depending on
danielk197771fd80b2005-12-16 06:54:013750 ** whether [$db update_hook] or [$db rollback_hook] was invoked.
3751 */
mistachkinb56660f2016-07-14 21:26:093752 Tcl_Obj **ppHook = 0;
dan46c47d42011-03-01 18:42:073753 if( choice==DB_WAL_HOOK ) ppHook = &pDb->pWalHook;
3754 if( choice==DB_UPDATE_HOOK ) ppHook = &pDb->pUpdateHook;
3755 if( choice==DB_ROLLBACK_HOOK ) ppHook = &pDb->pRollbackHook;
3756 if( objc>3 ){
danielk197794eb6a12005-12-15 15:22:083757 Tcl_WrongNumArgs(interp, 2, objv, "?SCRIPT?");
3758 return TCL_ERROR;
3759 }
danielk197771fd80b2005-12-16 06:54:013760
dan46c47d42011-03-01 18:42:073761 DbHookCmd(interp, pDb, (objc==3 ? objv[2] : 0), ppHook);
danielk197794eb6a12005-12-15 15:22:083762 break;
3763 }
3764
danielk19774397de52005-01-12 12:44:033765 /* $db version
3766 **
3767 ** Return the version string for this database.
3768 */
3769 case DB_VERSION: {
drh1df64702017-10-13 15:56:263770 int i;
3771 for(i=2; i<objc; i++){
3772 const char *zArg = Tcl_GetString(objv[i]);
3773 /* Optional arguments to $db version are used for testing purpose */
3774#ifdef SQLITE_TEST
3775 /* $db version -use-legacy-prepare BOOLEAN
3776 **
3777 ** Turn the use of legacy sqlite3_prepare() on or off.
3778 */
3779 if( strcmp(zArg, "-use-legacy-prepare")==0 && i+1<objc ){
3780 i++;
3781 if( Tcl_GetBooleanFromObj(interp, objv[i], &pDb->bLegacyPrepare) ){
3782 return TCL_ERROR;
3783 }
3784 }else
3785
3786 /* $db version -last-stmt-ptr
3787 **
3788 ** Return a string which is a hex encoding of the pointer to the
3789 ** most recent sqlite3_stmt in the statement cache.
3790 */
3791 if( strcmp(zArg, "-last-stmt-ptr")==0 ){
3792 char zBuf[100];
3793 sqlite3_snprintf(sizeof(zBuf), zBuf, "%p",
3794 pDb->stmtList ? pDb->stmtList->pStmt: 0);
3795 Tcl_SetResult(interp, zBuf, TCL_VOLATILE);
3796 }else
3797#endif /* SQLITE_TEST */
3798 {
3799 Tcl_AppendResult(interp, "unknown argument: ", zArg, (char*)0);
3800 return TCL_ERROR;
3801 }
3802 }
3803 if( i==2 ){
3804 Tcl_SetResult(interp, (char *)sqlite3_libversion(), TCL_STATIC);
3805 }
danielk19774397de52005-01-12 12:44:033806 break;
3807 }
3808
tpoindex1067fe12004-12-17 15:41:113809
drh6d313162000-09-21 13:01:353810 } /* End of the SWITCH statement */
drh22fbcb82004-02-01 01:22:503811 return rc;
drh75897232000-05-29 14:26:003812}
3813
drha2c8a952009-10-13 18:38:343814#if SQLITE_TCL_NRE
3815/*
3816** Adaptor that provides an objCmd interface to the NRE-enabled
3817** interface implementation.
3818*/
mistachkina121cc72016-07-28 18:06:523819static int SQLITE_TCLAPI DbObjCmdAdaptor(
drha2c8a952009-10-13 18:38:343820 void *cd,
3821 Tcl_Interp *interp,
3822 int objc,
3823 Tcl_Obj *const*objv
3824){
3825 return Tcl_NRCallObjProc(interp, DbObjCmd, cd, objc, objv);
3826}
3827#endif /* SQLITE_TCL_NRE */
3828
drh75897232000-05-29 14:26:003829/*
drh4dcac402018-01-03 13:20:023830** Issue the usage message when the "sqlite3" command arguments are
3831** incorrect.
3832*/
3833static int sqliteCmdUsage(
3834 Tcl_Interp *interp,
3835 Tcl_Obj *const*objv
3836){
3837 Tcl_WrongNumArgs(interp, 1, objv,
3838 "HANDLE ?FILENAME? ?-vfs VFSNAME? ?-readonly BOOLEAN? ?-create BOOLEAN?"
drh0933aad2019-11-18 17:46:383839 " ?-nofollow BOOLEAN?"
drh4dcac402018-01-03 13:20:023840 " ?-nomutex BOOLEAN? ?-fullmutex BOOLEAN? ?-uri BOOLEAN?"
drh4dcac402018-01-03 13:20:023841 );
3842 return TCL_ERROR;
3843}
3844
3845/*
drh3570ad92007-08-31 14:31:443846** sqlite3 DBNAME FILENAME ?-vfs VFSNAME? ?-key KEY? ?-readonly BOOLEAN?
danielk19779a6284c2008-07-10 17:52:493847** ?-create BOOLEAN? ?-nomutex BOOLEAN?
drh0933aad2019-11-18 17:46:383848** ?-nofollow BOOLEAN?
drh75897232000-05-29 14:26:003849**
3850** This is the main Tcl command. When the "sqlite" Tcl command is
3851** invoked, this routine runs to process that command.
3852**
3853** The first argument, DBNAME, is an arbitrary name for a new
3854** database connection. This command creates a new command named
3855** DBNAME that is used to control that connection. The database
3856** connection is deleted when the DBNAME command is deleted.
3857**
drh3570ad92007-08-31 14:31:443858** The second argument is the name of the database file.
drhfbc3eab2001-04-06 16:13:423859**
drh75897232000-05-29 14:26:003860*/
mistachkin7617e4a2016-07-28 17:11:203861static int SQLITE_TCLAPI DbMain(
3862 void *cd,
3863 Tcl_Interp *interp,
3864 int objc,
3865 Tcl_Obj *const*objv
3866){
drhbec3f402000-08-04 13:49:023867 SqliteDb *p;
drh22fbcb82004-02-01 01:22:503868 const char *zArg;
drh75897232000-05-29 14:26:003869 char *zErrMsg;
drh3570ad92007-08-31 14:31:443870 int i;
drh4dcac402018-01-03 13:20:023871 const char *zFile = 0;
drh3570ad92007-08-31 14:31:443872 const char *zVfs = 0;
drhd9da78a2009-03-24 15:08:093873 int flags;
mistachkina8e41ec2020-05-15 01:18:073874 int bTranslateFileName = 1;
drh882e8e42006-08-24 02:42:273875 Tcl_DString translatedFilename;
mistachkin540ebf82012-09-10 07:29:293876 int rc;
drhd9da78a2009-03-24 15:08:093877
3878 /* In normal use, each TCL interpreter runs in a single thread. So
drh4dcac402018-01-03 13:20:023879 ** by default, we can turn off mutexing on SQLite database connections.
drhd9da78a2009-03-24 15:08:093880 ** However, for testing purposes it is useful to have mutexes turned
3881 ** on. So, by default, mutexes default off. But if compiled with
3882 ** SQLITE_TCL_DEFAULT_FULLMUTEX then mutexes default on.
3883 */
3884#ifdef SQLITE_TCL_DEFAULT_FULLMUTEX
3885 flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_FULLMUTEX;
3886#else
3887 flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_NOMUTEX;
3888#endif
3889
drhc6727c82018-09-19 15:08:213890 if( objc==1 ) return sqliteCmdUsage(interp, objv);
drh22fbcb82004-02-01 01:22:503891 if( objc==2 ){
3892 zArg = Tcl_GetStringFromObj(objv[1], 0);
drh22fbcb82004-02-01 01:22:503893 if( strcmp(zArg,"-version")==0 ){
drha198f2b2014-02-07 19:26:133894 Tcl_AppendResult(interp,sqlite3_libversion(), (char*)0);
drh647cb0e2002-11-04 19:32:253895 return TCL_OK;
3896 }
drh72bf6a32016-01-07 02:06:553897 if( strcmp(zArg,"-sourceid")==0 ){
3898 Tcl_AppendResult(interp,sqlite3_sourceid(), (char*)0);
3899 return TCL_OK;
3900 }
drh9eb9e262004-02-11 02:18:053901 if( strcmp(zArg,"-has-codec")==0 ){
drha198f2b2014-02-07 19:26:133902 Tcl_AppendResult(interp,"0",(char*)0);
drh22fbcb82004-02-01 01:22:503903 return TCL_OK;
3904 }
drh4dcac402018-01-03 13:20:023905 if( zArg[0]=='-' ) return sqliteCmdUsage(interp, objv);
drhfbc3eab2001-04-06 16:13:423906 }
drh4dcac402018-01-03 13:20:023907 for(i=2; i<objc; i++){
drh3570ad92007-08-31 14:31:443908 zArg = Tcl_GetString(objv[i]);
drh4dcac402018-01-03 13:20:023909 if( zArg[0]!='-' ){
3910 if( zFile!=0 ) return sqliteCmdUsage(interp, objv);
3911 zFile = zArg;
3912 continue;
3913 }
3914 if( i==objc-1 ) return sqliteCmdUsage(interp, objv);
3915 i++;
drh22fbcb82004-02-01 01:22:503916 if( strcmp(zArg,"-key")==0 ){
drhb48c0d52020-02-07 01:12:533917 /* no-op */
drh3570ad92007-08-31 14:31:443918 }else if( strcmp(zArg, "-vfs")==0 ){
drh4dcac402018-01-03 13:20:023919 zVfs = Tcl_GetString(objv[i]);
drh3570ad92007-08-31 14:31:443920 }else if( strcmp(zArg, "-readonly")==0 ){
3921 int b;
drh4dcac402018-01-03 13:20:023922 if( Tcl_GetBooleanFromObj(interp, objv[i], &b) ) return TCL_ERROR;
drh3570ad92007-08-31 14:31:443923 if( b ){
drh33f4e022007-09-03 15:19:343924 flags &= ~(SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE);
drh3570ad92007-08-31 14:31:443925 flags |= SQLITE_OPEN_READONLY;
3926 }else{
3927 flags &= ~SQLITE_OPEN_READONLY;
3928 flags |= SQLITE_OPEN_READWRITE;
3929 }
3930 }else if( strcmp(zArg, "-create")==0 ){
3931 int b;
drh4dcac402018-01-03 13:20:023932 if( Tcl_GetBooleanFromObj(interp, objv[i], &b) ) return TCL_ERROR;
drh33f4e022007-09-03 15:19:343933 if( b && (flags & SQLITE_OPEN_READONLY)==0 ){
drh3570ad92007-08-31 14:31:443934 flags |= SQLITE_OPEN_CREATE;
3935 }else{
3936 flags &= ~SQLITE_OPEN_CREATE;
3937 }
drh0933aad2019-11-18 17:46:383938 }else if( strcmp(zArg, "-nofollow")==0 ){
3939 int b;
3940 if( Tcl_GetBooleanFromObj(interp, objv[i], &b) ) return TCL_ERROR;
3941 if( b ){
3942 flags |= SQLITE_OPEN_NOFOLLOW;
3943 }else{
3944 flags &= ~SQLITE_OPEN_NOFOLLOW;
3945 }
danielk19779a6284c2008-07-10 17:52:493946 }else if( strcmp(zArg, "-nomutex")==0 ){
3947 int b;
drh4dcac402018-01-03 13:20:023948 if( Tcl_GetBooleanFromObj(interp, objv[i], &b) ) return TCL_ERROR;
danielk19779a6284c2008-07-10 17:52:493949 if( b ){
3950 flags |= SQLITE_OPEN_NOMUTEX;
drh039963a2008-09-03 00:43:153951 flags &= ~SQLITE_OPEN_FULLMUTEX;
danielk19779a6284c2008-07-10 17:52:493952 }else{
3953 flags &= ~SQLITE_OPEN_NOMUTEX;
3954 }
danc431fd52011-06-27 16:55:503955 }else if( strcmp(zArg, "-fullmutex")==0 ){
drh039963a2008-09-03 00:43:153956 int b;
drh4dcac402018-01-03 13:20:023957 if( Tcl_GetBooleanFromObj(interp, objv[i], &b) ) return TCL_ERROR;
drh039963a2008-09-03 00:43:153958 if( b ){
3959 flags |= SQLITE_OPEN_FULLMUTEX;
3960 flags &= ~SQLITE_OPEN_NOMUTEX;
3961 }else{
3962 flags &= ~SQLITE_OPEN_FULLMUTEX;
3963 }
drhf12b3f62011-12-21 14:42:293964 }else if( strcmp(zArg, "-uri")==0 ){
3965 int b;
drh4dcac402018-01-03 13:20:023966 if( Tcl_GetBooleanFromObj(interp, objv[i], &b) ) return TCL_ERROR;
drhf12b3f62011-12-21 14:42:293967 if( b ){
3968 flags |= SQLITE_OPEN_URI;
3969 }else{
3970 flags &= ~SQLITE_OPEN_URI;
3971 }
mistachkina8e41ec2020-05-15 01:18:073972 }else if( strcmp(zArg, "-translatefilename")==0 ){
3973 if( Tcl_GetBooleanFromObj(interp, objv[i], &bTranslateFileName) ){
3974 return TCL_ERROR;
3975 }
drh3570ad92007-08-31 14:31:443976 }else{
3977 Tcl_AppendResult(interp, "unknown option: ", zArg, (char*)0);
3978 return TCL_ERROR;
drh22fbcb82004-02-01 01:22:503979 }
3980 }
drh75897232000-05-29 14:26:003981 zErrMsg = 0;
drh4cdc9e82000-08-04 14:56:243982 p = (SqliteDb*)Tcl_Alloc( sizeof(*p) );
drhbec3f402000-08-04 13:49:023983 memset(p, 0, sizeof(*p));
drh3ec86652018-01-03 19:03:313984 if( zFile==0 ) zFile = "";
mistachkina8e41ec2020-05-15 01:18:073985 if( bTranslateFileName ){
3986 zFile = Tcl_TranslateFileName(interp, zFile, &translatedFilename);
3987 }
drh3ec86652018-01-03 19:03:313988 rc = sqlite3_open_v2(zFile, &p->db, flags, zVfs);
mistachkina8e41ec2020-05-15 01:18:073989 if( bTranslateFileName ){
3990 Tcl_DStringFree(&translatedFilename);
3991 }
mistachkin540ebf82012-09-10 07:29:293992 if( p->db ){
3993 if( SQLITE_OK!=sqlite3_errcode(p->db) ){
3994 zErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(p->db));
3995 sqlite3_close(p->db);
3996 p->db = 0;
3997 }
3998 }else{
mistachkin5dac8432012-09-11 02:00:253999 zErrMsg = sqlite3_mprintf("%s", sqlite3_errstr(rc));
danielk197780290862004-05-22 09:21:214000 }
drhbec3f402000-08-04 13:49:024001 if( p->db==0 ){
drh75897232000-05-29 14:26:004002 Tcl_SetResult(interp, zErrMsg, TCL_VOLATILE);
drhbec3f402000-08-04 13:49:024003 Tcl_Free((char*)p);
drh9404d502006-12-19 18:46:084004 sqlite3_free(zErrMsg);
drh75897232000-05-29 14:26:004005 return TCL_ERROR;
4006 }
drhfb7e7652005-01-24 00:28:424007 p->maxStmt = NUM_PREPARED_STMTS;
drh147ef392016-01-22 23:17:514008 p->openFlags = flags & SQLITE_OPEN_URI;
drh5169bbc2006-08-24 14:59:454009 p->interp = interp;
drh22fbcb82004-02-01 01:22:504010 zArg = Tcl_GetStringFromObj(objv[1], 0);
dan4a4c11a2009-10-06 14:59:024011 if( DbUseNre() ){
drha2c8a952009-10-13 18:38:344012 Tcl_NRCreateCommand(interp, zArg, DbObjCmdAdaptor, DbObjCmd,
4013 (char*)p, DbDeleteCmd);
dan4a4c11a2009-10-06 14:59:024014 }else{
4015 Tcl_CreateObjCommand(interp, zArg, DbObjCmd, (char*)p, DbDeleteCmd);
4016 }
danbea28c72021-09-16 14:17:144017 p->nRef = 1;
drh75897232000-05-29 14:26:004018 return TCL_OK;
4019}
4020
4021/*
drh90ca9752001-09-28 17:47:144022** Provide a dummy Tcl_InitStubs if we are using this as a static
4023** library.
4024*/
4025#ifndef USE_TCL_STUBS
4026# undef Tcl_InitStubs
drh0e85ccf2013-06-03 12:34:464027# define Tcl_InitStubs(a,b,c) TCL_VERSION
drh90ca9752001-09-28 17:47:144028#endif
4029
4030/*
drh29bc4612005-10-05 10:40:154031** Make sure we have a PACKAGE_VERSION macro defined. This will be
4032** defined automatically by the TEA makefile. But other makefiles
4033** do not define it.
4034*/
4035#ifndef PACKAGE_VERSION
4036# define PACKAGE_VERSION SQLITE_VERSION
4037#endif
4038
4039/*
drh75897232000-05-29 14:26:004040** Initialize this module.
4041**
4042** This Tcl module contains only a single new Tcl command named "sqlite".
4043** (Hence there is no namespace. There is no point in using a namespace
4044** if the extension only supplies one new name!) The "sqlite" command is
4045** used to open a new SQLite database. See the DbMain() routine above
4046** for additional information.
drhb652f432010-08-26 16:46:574047**
4048** The EXTERN macros are required by TCL in order to work on windows.
drh75897232000-05-29 14:26:004049*/
drhb652f432010-08-26 16:46:574050EXTERN int Sqlite3_Init(Tcl_Interp *interp){
drh7b179a32024-10-10 10:33:314051 int rc = Tcl_InitStubs(interp, "8.5-", 0) ? TCL_OK : TCL_ERROR;
drh6dc8cbe2013-05-31 15:36:074052 if( rc==TCL_OK ){
4053 Tcl_CreateObjCommand(interp, "sqlite3", (Tcl_ObjCmdProc*)DbMain, 0, 0);
drh1cca0d22010-08-25 20:35:514054#ifndef SQLITE_3_SUFFIX_ONLY
drh6dc8cbe2013-05-31 15:36:074055 /* The "sqlite" alias is undocumented. It is here only to support
4056 ** legacy scripts. All new scripts should use only the "sqlite3"
4057 ** command. */
4058 Tcl_CreateObjCommand(interp, "sqlite", (Tcl_ObjCmdProc*)DbMain, 0, 0);
drh4c0f1642010-08-25 19:39:194059#endif
drh6dc8cbe2013-05-31 15:36:074060 rc = Tcl_PkgProvide(interp, "sqlite3", PACKAGE_VERSION);
4061 }
4062 return rc;
drh90ca9752001-09-28 17:47:144063}
drhb652f432010-08-26 16:46:574064EXTERN int Tclsqlite3_Init(Tcl_Interp *interp){ return Sqlite3_Init(interp); }
drhb652f432010-08-26 16:46:574065EXTERN int Sqlite3_Unload(Tcl_Interp *interp, int flags){ return TCL_OK; }
4066EXTERN int Tclsqlite3_Unload(Tcl_Interp *interp, int flags){ return TCL_OK; }
drhe2c3a652008-09-23 09:58:464067
drhd878cab2012-03-20 15:10:424068/* Because it accesses the file-system and uses persistent state, SQLite
drhe75a9eb2016-02-13 18:54:104069** is not considered appropriate for safe interpreters. Hence, we cause
4070** the _SafeInit() interfaces return TCL_ERROR.
drhd878cab2012-03-20 15:10:424071*/
drhe75a9eb2016-02-13 18:54:104072EXTERN int Sqlite3_SafeInit(Tcl_Interp *interp){ return TCL_ERROR; }
4073EXTERN int Sqlite3_SafeUnload(Tcl_Interp *interp, int flags){return TCL_ERROR;}
4074
drh064b6812024-07-30 15:49:024075/*
4076** Versions of all of the above entry points that omit the "3" at the end
4077** of the name. Years ago (circa 2004) the "3" was necessary to distinguish
4078** SQLite version 3 from Sqlite version 2. But two decades have elapsed.
4079** SQLite2 is not longer a conflict. So it is ok to omit the "3".
4080**
4081** Omitting the "3" helps TCL find the entry point.
4082*/
4083EXTERN int Sqlite_Init(Tcl_Interp *interp){ return Sqlite3_Init(interp);}
4084EXTERN int Tclsqlite_Init(Tcl_Interp *interp){ return Sqlite3_Init(interp); }
4085EXTERN int Sqlite_Unload(Tcl_Interp *interp, int flags){ return TCL_OK; }
4086EXTERN int Tclsqlite_Unload(Tcl_Interp *interp, int flags){ return TCL_OK; }
4087EXTERN int Sqlite_SafeInit(Tcl_Interp *interp){ return TCL_ERROR; }
4088EXTERN int Sqlite_SafeUnload(Tcl_Interp *interp, int flags){return TCL_ERROR;}
drh75897232000-05-29 14:26:004089
drh000e39e2025-01-30 16:00:284090/* Also variants with a lowercase "s". I'm told that these are
4091** deprecated in Tcl9, but they continue to be included for backwards
4092** compatibility. */
drhe388fc72024-07-31 10:59:194093EXTERN int sqlite3_Init(Tcl_Interp *interp){ return Sqlite3_Init(interp);}
4094EXTERN int sqlite_Init(Tcl_Interp *interp){ return Sqlite3_Init(interp);}
4095
4096
drhc318f732017-10-13 15:06:064097/*
drh96a206f2017-10-13 20:14:064098** If the TCLSH macro is defined, add code to make a stand-alone program.
drhc318f732017-10-13 15:06:064099*/
drh96a206f2017-10-13 20:14:064100#if defined(TCLSH)
drh57a02272009-10-22 20:52:054101
drh96a206f2017-10-13 20:14:064102/* This is the main routine for an ordinary TCL shell. If there are
stephan45fa2342025-05-26 07:15:204103** arguments, run the first argument as a script. Otherwise, read TCL
4104** commands from standard input
drh348784e2000-05-29 20:41:494105*/
dan0ae479df2011-09-21 16:43:074106static const char *tclsh_main_loop(void){
4107 static const char zMainloop[] =
drh96a206f2017-10-13 20:14:064108 "if {[llength $argv]>=1} {\n"
drh17408fb2024-10-11 17:02:374109#ifdef WIN32
4110 "set new [list]\n"
4111 "foreach arg $argv {\n"
drh8ff67df2024-11-22 17:41:004112 "if {[string match -* $arg] || [file exists $arg]} {\n"
drh17408fb2024-10-11 17:02:374113 "lappend new $arg\n"
4114 "} else {\n"
drh18689b82024-11-16 17:39:344115 "set once 0\n"
drh17408fb2024-10-11 17:02:374116 "foreach match [lsort [glob -nocomplain $arg]] {\n"
4117 "lappend new $match\n"
drh18689b82024-11-16 17:39:344118 "set once 1\n"
drh17408fb2024-10-11 17:02:374119 "}\n"
drh18689b82024-11-16 17:39:344120 "if {!$once} {lappend new $arg}\n"
drh17408fb2024-10-11 17:02:374121 "}\n"
4122 "}\n"
4123 "set argv $new\n"
4124 "unset new\n"
4125#endif
drh96a206f2017-10-13 20:14:064126 "set argv0 [lindex $argv 0]\n"
4127 "set argv [lrange $argv 1 end]\n"
4128 "source $argv0\n"
4129 "} else {\n"
4130 "set line {}\n"
4131 "while {![eof stdin]} {\n"
4132 "if {$line!=\"\"} {\n"
4133 "puts -nonewline \"> \"\n"
4134 "} else {\n"
4135 "puts -nonewline \"% \"\n"
dan0ae479df2011-09-21 16:43:074136 "}\n"
drh96a206f2017-10-13 20:14:064137 "flush stdout\n"
4138 "append line [gets stdin]\n"
4139 "if {[info complete $line]} {\n"
4140 "if {[catch {uplevel #0 $line} result]} {\n"
4141 "puts stderr \"Error: $result\"\n"
4142 "} elseif {$result!=\"\"} {\n"
4143 "puts $result\n"
4144 "}\n"
4145 "set line {}\n"
4146 "} else {\n"
4147 "append line \\n\n"
4148 "}\n"
dan0ae479df2011-09-21 16:43:074149 "}\n"
drh348784e2000-05-29 20:41:494150 "}\n"
dan0ae479df2011-09-21 16:43:074151 ;
4152 return zMainloop;
4153}
drh3e27c022004-07-23 00:01:384154
drh5e907942021-11-18 20:56:594155#ifndef TCLSH_MAIN
4156# define TCLSH_MAIN main
4157#endif
mistachkin69def7f2016-07-28 04:14:374158int SQLITE_CDECL TCLSH_MAIN(int argc, char **argv){
danc1a60c52010-06-07 14:28:164159 Tcl_Interp *interp;
drh96a206f2017-10-13 20:14:064160 int i;
4161 const char *zScript = 0;
4162 char zArgc[32];
4163#if defined(TCLSH_INIT_PROC)
4164 extern const char *TCLSH_INIT_PROC(Tcl_Interp*);
4165#endif
mistachkin1f28e072013-08-15 08:06:154166
4167#if !defined(_WIN32_WCE)
mistachkin1e8487d2018-07-22 06:25:354168 if( getenv("SQLITE_DEBUG_BREAK") ){
4169 if( isatty(0) && isatty(2) ){
4170 fprintf(stderr,
4171 "attach debugger to process %d and press any key to continue.\n",
4172 GETPID());
4173 fgetc(stdin);
4174 }else{
4175#if defined(_WIN32) || defined(WIN32)
4176 DebugBreak();
4177#elif defined(SIGTRAP)
4178 raise(SIGTRAP);
4179#endif
4180 }
mistachkin1f28e072013-08-15 08:06:154181 }
4182#endif
4183
danc1a60c52010-06-07 14:28:164184 /* Call sqlite3_shutdown() once before doing anything else. This is to
4185 ** test that sqlite3_shutdown() can be safely called by a process before
4186 ** sqlite3_initialize() is. */
4187 sqlite3_shutdown();
4188
dan0ae479df2011-09-21 16:43:074189 Tcl_FindExecutable(argv[0]);
mistachkin2953ba92014-02-14 00:25:034190 Tcl_SetSystemEncoding(NULL, "utf-8");
dan0ae479df2011-09-21 16:43:074191 interp = Tcl_CreateInterp();
drhc318f732017-10-13 15:06:064192 Sqlite3_Init(interp);
drh96a206f2017-10-13 20:14:064193
4194 sqlite3_snprintf(sizeof(zArgc), zArgc, "%d", argc-1);
4195 Tcl_SetVar(interp,"argc", zArgc, TCL_GLOBAL_ONLY);
4196 Tcl_SetVar(interp,"argv0",argv[0],TCL_GLOBAL_ONLY);
4197 Tcl_SetVar(interp,"argv", "", TCL_GLOBAL_ONLY);
4198 for(i=1; i<argc; i++){
4199 Tcl_SetVar(interp, "argv", argv[i],
4200 TCL_GLOBAL_ONLY | TCL_LIST_ELEMENT | TCL_APPEND_VALUE);
drhc318f732017-10-13 15:06:064201 }
drh96a206f2017-10-13 20:14:064202#if defined(TCLSH_INIT_PROC)
4203 zScript = TCLSH_INIT_PROC(interp);
4204#endif
4205 if( zScript==0 ){
4206 zScript = tclsh_main_loop();
drh3e27c022004-07-23 00:01:384207 }
drh96a206f2017-10-13 20:14:064208 if( Tcl_GlobalEval(interp, zScript)!=TCL_OK ){
4209 const char *zInfo = Tcl_GetVar(interp, "errorInfo", TCL_GLOBAL_ONLY);
4210 if( zInfo==0 ) zInfo = Tcl_GetStringResult(interp);
4211 fprintf(stderr,"%s: %s\n", *argv, zInfo);
4212 return 1;
drh348784e2000-05-29 20:41:494213 }
4214 return 0;
4215}
4216#endif /* TCLSH */