AryaWu/sqlite
0
1/*2** 2001 September 153**4** The author disclaims copyright to this source code. In place of5** a legal notice, here is a blessing:6**7** 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.10**11*************************************************************************12** A TCL Interface to SQLite. Append this file to sqlite3.c and13** compile the whole thing to build a TCL-enabled version of SQLite.14**15** Compile-time options:16**17** -DTCLSH Add a "main()" routine that works as a tclsh.18**19** -DTCLSH_INIT_PROC=name20**21** Invoke name(interp) to initialize the Tcl interpreter.22** If name(interp) returns a non-NULL string, then run23** that string as a Tcl script to launch the application.24** If name(interp) returns NULL, then run the regular25** tclsh-emulator code.26*/27#ifdef TCLSH_INIT_PROC28# define TCLSH 129#endif30 31/*32** If requested, include the SQLite compiler options file for MSVC.33*/34#if defined(INCLUDE_MSVC_H)35# include "msvc.h"36#endif37 38/****** Copy of tclsqlite.h ******/39#if defined(INCLUDE_SQLITE_TCL_H)40# include "sqlite_tcl.h" /* Special case for Windows using STDCALL */41#else42# include <tcl.h> /* All normal cases */43# ifndef SQLITE_TCLAPI44# define SQLITE_TCLAPI45# endif46#endif47/* Compatability between Tcl8.6 and Tcl9.0 */48#if TCL_MAJOR_VERSION==949# define CONST const50#elif !defined(Tcl_Size)51 typedef int Tcl_Size;52# ifndef Tcl_BounceRefCount53# define Tcl_BounceRefCount(X) Tcl_IncrRefCount(X); Tcl_DecrRefCount(X)54 /* https://www.tcl-lang.org/man/tcl9.0/TclLib/Object.html */55# endif56#endif57/**** End copy of tclsqlite.h ****/58 59#include <errno.h>60 61/*62** Some additional include files are needed if this file is not63** appended to the amalgamation.64*/65#ifndef SQLITE_AMALGAMATION66# include "sqlite3.h"67# include <stdlib.h>68# include <string.h>69# include <assert.h>70 typedef unsigned char u8;71# ifndef SQLITE_PTRSIZE72# 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 479# else80# define SQLITE_PTRSIZE 881# endif82# endif /* SQLITE_PTRSIZE */83# if defined(HAVE_STDINT_H) || (defined(__STDC_VERSION__) && \84 (__STDC_VERSION__ >= 199901L))85# include <stdint.h>86 typedef uintptr_t uptr;87# elif SQLITE_PTRSIZE==488 typedef unsigned int uptr;89# else90 typedef sqlite3_uint64 uptr;91# endif92#endif93#include <ctype.h>94 95/* Used to get the current process ID */96#if !defined(_WIN32)97# include <signal.h>98# include <unistd.h>99# define GETPID getpid100#elif !defined(_WIN32_WCE)101# ifndef SQLITE_AMALGAMATION102# ifndef WIN32_LEAN_AND_MEAN103# define WIN32_LEAN_AND_MEAN104# endif105# include <windows.h>106# endif107# include <io.h>108# define isatty(h) _isatty(h)109# define GETPID (int)GetCurrentProcessId110#endif111 112/*113 * Windows needs to know which symbols to export. Unix does not.114 * BUILD_sqlite should be undefined for Unix.115 */116#ifdef BUILD_sqlite117#undef TCL_STORAGE_CLASS118#define TCL_STORAGE_CLASS DLLEXPORT119#endif /* BUILD_sqlite */120 121#define NUM_PREPARED_STMTS 10122#define MAX_PREPARED_STMTS 100123 124/* Forward declaration */125typedef struct SqliteDb SqliteDb;126 127/* Add -DSQLITE_ENABLE_QRF_IN_TCL to add the Query Result Formatter (QRF)128** into the build of the TCL extension, when building using separate129** source files. The QRF is included automatically when building from130** the tclsqlite3.c amalgamation.131*/132#if defined(SQLITE_ENABLE_QRF_IN_TCL)133#include "qrf.h"134#endif135 136/*137** New SQL functions can be created as TCL scripts. Each such function138** is described by an instance of the following structure.139**140** Variable eType may be set to SQLITE_INTEGER, SQLITE_FLOAT, SQLITE_TEXT,141** SQLITE_BLOB or SQLITE_NULL. If it is SQLITE_NULL, then the implementation142** attempts to determine the type of the result based on the Tcl object.143** If it is SQLITE_TEXT or SQLITE_BLOB, then a text (sqlite3_result_text())144** or blob (sqlite3_result_blob()) is returned. If it is SQLITE_INTEGER145** or SQLITE_FLOAT, then an attempt is made to return an integer or float146** value, falling back to float and then text if this is not possible.147*/148typedef struct SqlFunc SqlFunc;149struct SqlFunc {150 Tcl_Interp *interp; /* The TCL interpret to execute the function */151 Tcl_Obj *pScript; /* The Tcl_Obj representation of the script */152 SqliteDb *pDb; /* Database connection that owns this function */153 int useEvalObjv; /* True if it is safe to use Tcl_EvalObjv */154 int eType; /* Type of value to return */155 char *zName; /* Name of this function */156 SqlFunc *pNext; /* Next function on the list of them all */157};158 159/*160** New collation sequences function can be created as TCL scripts. Each such161** function is described by an instance of the following structure.162*/163typedef struct SqlCollate SqlCollate;164struct SqlCollate {165 Tcl_Interp *interp; /* The TCL interpret to execute the function */166 char *zScript; /* The script to be run */167 SqlCollate *pNext; /* Next function on the list of them all */168};169 170/*171** Prepared statements are cached for faster execution. Each prepared172** statement is described by an instance of the following structure.173*/174typedef struct SqlPreparedStmt SqlPreparedStmt;175struct SqlPreparedStmt {176 SqlPreparedStmt *pNext; /* Next in linked list */177 SqlPreparedStmt *pPrev; /* Previous on the list */178 sqlite3_stmt *pStmt; /* The prepared statement */179 int nSql; /* chars in zSql[] */180 const char *zSql; /* Text of the SQL statement */181 int nParm; /* Size of apParm array */182 Tcl_Obj **apParm; /* Array of referenced object pointers */183};184 185typedef struct IncrblobChannel IncrblobChannel;186 187/*188** There is one instance of this structure for each SQLite database189** that has been opened by the SQLite TCL interface.190**191** If this module is built with SQLITE_TEST defined (to create the SQLite192** testfixture executable), then it may be configured to use either193** sqlite3_prepare_v2() or sqlite3_prepare() to prepare SQL statements.194** If SqliteDb.bLegacyPrepare is true, sqlite3_prepare() is used.195*/196struct SqliteDb {197 sqlite3 *db; /* The "real" database structure. MUST BE FIRST */198 Tcl_Interp *interp; /* The interpreter used for this database */199 char *zBusy; /* The busy callback routine */200 char *zCommit; /* The commit hook callback routine */201 char *zTrace; /* The trace callback routine */202 char *zTraceV2; /* The trace_v2 callback routine */203 char *zProfile; /* The profile callback routine */204 char *zProgress; /* The progress callback routine */205 char *zBindFallback; /* Callback to invoke on a binding miss */206 char *zAuth; /* The authorization callback routine */207 int disableAuth; /* Disable the authorizer if it exists */208 char *zNull; /* Text to substitute for an SQL NULL value */209 SqlFunc *pFunc; /* List of SQL functions */210 Tcl_Obj *pUpdateHook; /* Update hook script (if any) */211 Tcl_Obj *pPreUpdateHook; /* Pre-update hook script (if any) */212 Tcl_Obj *pRollbackHook; /* Rollback hook script (if any) */213 Tcl_Obj *pWalHook; /* WAL hook script (if any) */214 Tcl_Obj *pUnlockNotify; /* Unlock notify script (if any) */215 SqlCollate *pCollate; /* List of SQL collation functions */216 int rc; /* Return code of most recent sqlite3_exec() */217 Tcl_Obj *pCollateNeeded; /* Collation needed script */218 SqlPreparedStmt *stmtList; /* List of prepared statements*/219 SqlPreparedStmt *stmtLast; /* Last statement in the list */220 int maxStmt; /* The next maximum number of stmtList */221 int nStmt; /* Number of statements in stmtList */222 IncrblobChannel *pIncrblob;/* Linked list of open incrblob channels */223 int nStep, nSort, nIndex; /* Statistics for most recent operation */224 int nVMStep; /* Another statistic for most recent operation */225 int nTransaction; /* Number of nested [transaction] methods */226 int openFlags; /* Flags used to open. (SQLITE_OPEN_URI) */227 int nRef; /* Delete object when this reaches 0 */228#ifdef SQLITE_TEST229 int bLegacyPrepare; /* True to use sqlite3_prepare() */230#endif231};232 233struct IncrblobChannel {234 sqlite3_blob *pBlob; /* sqlite3 blob handle */235 SqliteDb *pDb; /* Associated database connection */236 sqlite3_int64 iSeek; /* Current seek offset */237 unsigned int isClosed; /* TCL_CLOSE_READ or TCL_CLOSE_WRITE */238 Tcl_Channel channel; /* Channel identifier */239 IncrblobChannel *pNext; /* Linked list of all open incrblob channels */240 IncrblobChannel *pPrev; /* Linked list of all open incrblob channels */241};242 243/*244** Compute a string length that is limited to what can be stored in245** lower 30 bits of a 32-bit signed integer.246*/247static int strlen30(const char *z){248 const char *z2 = z;249 while( *z2 ){ z2++; }250 return 0x3fffffff & (int)(z2 - z);251}252 253 254#ifndef SQLITE_OMIT_INCRBLOB255/*256** Close all incrblob channels opened using database connection pDb.257** This is called when shutting down the database connection.258*/259static void closeIncrblobChannels(SqliteDb *pDb){260 IncrblobChannel *p;261 IncrblobChannel *pNext;262 263 for(p=pDb->pIncrblob; p; p=pNext){264 pNext = p->pNext;265 266 /* Note: Calling unregister here call Tcl_Close on the incrblob channel,267 ** which deletes the IncrblobChannel structure at *p. So do not268 ** call Tcl_Free() here.269 */270 Tcl_UnregisterChannel(pDb->interp, p->channel);271 }272}273 274/*275** Close an incremental blob channel.276*/277static int SQLITE_TCLAPI incrblobClose2(278 ClientData instanceData,279 Tcl_Interp *interp,280 int flags281){282 IncrblobChannel *p = (IncrblobChannel *)instanceData;283 int rc;284 sqlite3 *db = p->pDb->db;285 286 if( flags ){287 p->isClosed |= flags;288 return TCL_OK;289 }290 291 /* If we reach this point, then we really do need to close the channel */292 rc = sqlite3_blob_close(p->pBlob);293 294 /* Remove the channel from the SqliteDb.pIncrblob list. */295 if( p->pNext ){296 p->pNext->pPrev = p->pPrev;297 }298 if( p->pPrev ){299 p->pPrev->pNext = p->pNext;300 }301 if( p->pDb->pIncrblob==p ){302 p->pDb->pIncrblob = p->pNext;303 }304 305 /* Free the IncrblobChannel structure */306 Tcl_Free((char *)p);307 308 if( rc!=SQLITE_OK ){309 Tcl_SetResult(interp, (char *)sqlite3_errmsg(db), TCL_VOLATILE);310 return TCL_ERROR;311 }312 return TCL_OK;313}314static int SQLITE_TCLAPI incrblobClose(315 ClientData instanceData,316 Tcl_Interp *interp317){318 return incrblobClose2(instanceData, interp, 0);319}320 321 322/*323** Read data from an incremental blob channel.324*/325static int SQLITE_TCLAPI incrblobInput(326 ClientData instanceData,327 char *buf,328 int bufSize,329 int *errorCodePtr330){331 IncrblobChannel *p = (IncrblobChannel *)instanceData;332 sqlite3_int64 nRead = bufSize; /* Number of bytes to read */333 sqlite3_int64 nBlob; /* Total size of the blob */334 int rc; /* sqlite error code */335 336 nBlob = sqlite3_blob_bytes(p->pBlob);337 if( (p->iSeek+nRead)>nBlob ){338 nRead = nBlob-p->iSeek;339 }340 if( nRead<=0 ){341 return 0;342 }343 344 rc = sqlite3_blob_read(p->pBlob, (void *)buf, (int)nRead, (int)p->iSeek);345 if( rc!=SQLITE_OK ){346 *errorCodePtr = rc;347 return -1;348 }349 350 p->iSeek += nRead;351 return nRead;352}353 354/*355** Write data to an incremental blob channel.356*/357static int SQLITE_TCLAPI incrblobOutput(358 ClientData instanceData,359 const char *buf,360 int toWrite,361 int *errorCodePtr362){363 IncrblobChannel *p = (IncrblobChannel *)instanceData;364 sqlite3_int64 nWrite = toWrite; /* Number of bytes to write */365 sqlite3_int64 nBlob; /* Total size of the blob */366 int rc; /* sqlite error code */367 368 nBlob = sqlite3_blob_bytes(p->pBlob);369 if( (p->iSeek+nWrite)>nBlob ){370 *errorCodePtr = EINVAL;371 return -1;372 }373 if( nWrite<=0 ){374 return 0;375 }376 377 rc = sqlite3_blob_write(p->pBlob, (void*)buf,(int)nWrite, (int)p->iSeek);378 if( rc!=SQLITE_OK ){379 *errorCodePtr = EIO;380 return -1;381 }382 383 p->iSeek += nWrite;384 return nWrite;385}386 387/* The datatype of Tcl_DriverWideSeekProc changes between tcl8.6 and tcl9.0 */388#if TCL_MAJOR_VERSION==9389# define WideSeekProcType long long390#else391# define WideSeekProcType Tcl_WideInt392#endif393 394/*395** Seek an incremental blob channel.396*/397static WideSeekProcType SQLITE_TCLAPI incrblobWideSeek(398 ClientData instanceData,399 WideSeekProcType offset,400 int seekMode,401 int *errorCodePtr402){403 IncrblobChannel *p = (IncrblobChannel *)instanceData;404 405 switch( seekMode ){406 case SEEK_SET:407 p->iSeek = offset;408 break;409 case SEEK_CUR:410 p->iSeek += offset;411 break;412 case SEEK_END:413 p->iSeek = sqlite3_blob_bytes(p->pBlob) + offset;414 break;415 416 default: assert(!"Bad seekMode");417 }418 419 return p->iSeek;420}421static int SQLITE_TCLAPI incrblobSeek(422 ClientData instanceData,423 long offset,424 int seekMode,425 int *errorCodePtr426){427 return incrblobWideSeek(instanceData,offset,seekMode,errorCodePtr);428}429 430 431static void SQLITE_TCLAPI incrblobWatch(432 ClientData instanceData,433 int mode434){435 /* NO-OP */436}437static int SQLITE_TCLAPI incrblobHandle(438 ClientData instanceData,439 int dir,440 ClientData *hPtr441){442 return TCL_ERROR;443}444 445static Tcl_ChannelType IncrblobChannelType = {446 "incrblob", /* typeName */447 TCL_CHANNEL_VERSION_5, /* version */448 incrblobClose, /* closeProc */449 incrblobInput, /* inputProc */450 incrblobOutput, /* outputProc */451 incrblobSeek, /* seekProc */452 0, /* setOptionProc */453 0, /* getOptionProc */454 incrblobWatch, /* watchProc (this is a no-op) */455 incrblobHandle, /* getHandleProc (always returns error) */456 incrblobClose2, /* close2Proc */457 0, /* blockModeProc */458 0, /* flushProc */459 0, /* handlerProc */460 incrblobWideSeek, /* wideSeekProc */461};462 463/*464** Create a new incrblob channel.465*/466static int createIncrblobChannel(467 Tcl_Interp *interp,468 SqliteDb *pDb,469 const char *zDb,470 const char *zTable,471 const char *zColumn,472 sqlite_int64 iRow,473 int isReadonly474){475 IncrblobChannel *p;476 sqlite3 *db = pDb->db;477 sqlite3_blob *pBlob;478 int rc;479 int flags = TCL_READABLE|(isReadonly ? 0 : TCL_WRITABLE);480 481 /* This variable is used to name the channels: "incrblob_[incr count]" */482 static int count = 0;483 char zChannel[64];484 485 rc = sqlite3_blob_open(db, zDb, zTable, zColumn, iRow, !isReadonly, &pBlob);486 if( rc!=SQLITE_OK ){487 Tcl_SetResult(interp, (char *)sqlite3_errmsg(pDb->db), TCL_VOLATILE);488 return TCL_ERROR;489 }490 491 p = (IncrblobChannel *)Tcl_Alloc(sizeof(IncrblobChannel));492 memset(p, 0, sizeof(*p));493 p->pBlob = pBlob;494 if( (flags & TCL_WRITABLE)==0 ) p->isClosed |= TCL_CLOSE_WRITE;495 496 sqlite3_snprintf(sizeof(zChannel), zChannel, "incrblob_%d", ++count);497 p->channel = Tcl_CreateChannel(&IncrblobChannelType, zChannel, p, flags);498 Tcl_RegisterChannel(interp, p->channel);499 500 /* Link the new channel into the SqliteDb.pIncrblob list. */501 p->pNext = pDb->pIncrblob;502 p->pPrev = 0;503 if( p->pNext ){504 p->pNext->pPrev = p;505 }506 pDb->pIncrblob = p;507 p->pDb = pDb;508 509 Tcl_SetResult(interp, (char *)Tcl_GetChannelName(p->channel), TCL_VOLATILE);510 return TCL_OK;511}512#else /* else clause for "#ifndef SQLITE_OMIT_INCRBLOB" */513 #define closeIncrblobChannels(pDb)514#endif515 516/*517** Look at the script prefix in pCmd. We will be executing this script518** after first appending one or more arguments. This routine analyzes519** the script to see if it is safe to use Tcl_EvalObjv() on the script520** rather than the more general Tcl_EvalEx(). Tcl_EvalObjv() is much521** faster.522**523** Scripts that are safe to use with Tcl_EvalObjv() consists of a524** command name followed by zero or more arguments with no [...] or $525** or {...} or ; to be seen anywhere. Most callback scripts consist526** of just a single procedure name and they meet this requirement.527*/528static int safeToUseEvalObjv(Tcl_Obj *pCmd){529 /* We could try to do something with Tcl_Parse(). But we will instead530 ** just do a search for forbidden characters. If any of the forbidden531 ** characters appear in pCmd, we will report the string as unsafe.532 */533 const char *z;534 Tcl_Size n;535 z = Tcl_GetStringFromObj(pCmd, &n);536 while( n-- > 0 ){537 int c = *(z++);538 if( c=='$' || c=='[' || c==';' ) return 0;539 }540 return 1;541}542 543/*544** Find an SqlFunc structure with the given name. Or create a new545** one if an existing one cannot be found. Return a pointer to the546** structure.547*/548static SqlFunc *findSqlFunc(SqliteDb *pDb, const char *zName){549 SqlFunc *p, *pNew;550 int nName = strlen30(zName);551 pNew = (SqlFunc*)Tcl_Alloc( sizeof(*pNew) + nName + 1 );552 pNew->zName = (char*)&pNew[1];553 memcpy(pNew->zName, zName, nName+1);554 for(p=pDb->pFunc; p; p=p->pNext){555 if( sqlite3_stricmp(p->zName, pNew->zName)==0 ){556 Tcl_Free((char*)pNew);557 return p;558 }559 }560 pNew->interp = pDb->interp;561 pNew->pDb = pDb;562 pNew->pScript = 0;563 pNew->pNext = pDb->pFunc;564 pDb->pFunc = pNew;565 return pNew;566}567 568/*569** Free a single SqlPreparedStmt object.570*/571static void dbFreeStmt(SqlPreparedStmt *pStmt){572#ifdef SQLITE_TEST573 if( sqlite3_sql(pStmt->pStmt)==0 ){574 Tcl_Free((char *)pStmt->zSql);575 }576#endif577 sqlite3_finalize(pStmt->pStmt);578 Tcl_Free((char *)pStmt);579}580 581/*582** Finalize and free a list of prepared statements583*/584static void flushStmtCache(SqliteDb *pDb){585 SqlPreparedStmt *pPreStmt;586 SqlPreparedStmt *pNext;587 588 for(pPreStmt = pDb->stmtList; pPreStmt; pPreStmt=pNext){589 pNext = pPreStmt->pNext;590 dbFreeStmt(pPreStmt);591 }592 pDb->nStmt = 0;593 pDb->stmtLast = 0;594 pDb->stmtList = 0;595}596 597/*598** Increment the reference counter on the SqliteDb object. The reference599** should be released by calling delDatabaseRef().600*/601static void addDatabaseRef(SqliteDb *pDb){602 pDb->nRef++;603}604 605/*606** Decrement the reference counter associated with the SqliteDb object.607** If it reaches zero, delete the object.608*/609static void delDatabaseRef(SqliteDb *pDb){610 assert( pDb->nRef>0 );611 pDb->nRef--;612 if( pDb->nRef==0 ){613 flushStmtCache(pDb);614 closeIncrblobChannels(pDb);615 sqlite3_close(pDb->db);616 while( pDb->pFunc ){617 SqlFunc *pFunc = pDb->pFunc;618 pDb->pFunc = pFunc->pNext;619 assert( pFunc->pDb==pDb );620 Tcl_DecrRefCount(pFunc->pScript);621 Tcl_Free((char*)pFunc);622 }623 while( pDb->pCollate ){624 SqlCollate *pCollate = pDb->pCollate;625 pDb->pCollate = pCollate->pNext;626 Tcl_Free((char*)pCollate);627 }628 if( pDb->zBusy ){629 Tcl_Free(pDb->zBusy);630 }631 if( pDb->zTrace ){632 Tcl_Free(pDb->zTrace);633 }634 if( pDb->zTraceV2 ){635 Tcl_Free(pDb->zTraceV2);636 }637 if( pDb->zProfile ){638 Tcl_Free(pDb->zProfile);639 }640 if( pDb->zBindFallback ){641 Tcl_Free(pDb->zBindFallback);642 }643 if( pDb->zAuth ){644 Tcl_Free(pDb->zAuth);645 }646 if( pDb->zNull ){647 Tcl_Free(pDb->zNull);648 }649 if( pDb->pUpdateHook ){650 Tcl_DecrRefCount(pDb->pUpdateHook);651 }652 if( pDb->pPreUpdateHook ){653 Tcl_DecrRefCount(pDb->pPreUpdateHook);654 }655 if( pDb->pRollbackHook ){656 Tcl_DecrRefCount(pDb->pRollbackHook);657 }658 if( pDb->pWalHook ){659 Tcl_DecrRefCount(pDb->pWalHook);660 }661 if( pDb->pCollateNeeded ){662 Tcl_DecrRefCount(pDb->pCollateNeeded);663 }664 Tcl_Free((char*)pDb);665 }666}667 668/*669** TCL calls this procedure when an sqlite3 database command is670** deleted.671*/672static void SQLITE_TCLAPI DbDeleteCmd(void *db){673 SqliteDb *pDb = (SqliteDb*)db;674 delDatabaseRef(pDb);675}676 677/*678** This routine is called when a database file is locked while trying679** to execute SQL.680*/681static int DbBusyHandler(void *cd, int nTries){682 SqliteDb *pDb = (SqliteDb*)cd;683 int rc;684 char zVal[30];685 686 sqlite3_snprintf(sizeof(zVal), zVal, "%d", nTries);687 rc = Tcl_VarEval(pDb->interp, pDb->zBusy, " ", zVal, (char*)0);688 if( rc!=TCL_OK || atoi(Tcl_GetStringResult(pDb->interp)) ){689 return 0;690 }691 return 1;692}693 694#ifndef SQLITE_OMIT_PROGRESS_CALLBACK695/*696** This routine is invoked as the 'progress callback' for the database.697*/698static int DbProgressHandler(void *cd){699 SqliteDb *pDb = (SqliteDb*)cd;700 int rc;701 702 assert( pDb->zProgress );703 rc = Tcl_Eval(pDb->interp, pDb->zProgress);704 if( rc!=TCL_OK || atoi(Tcl_GetStringResult(pDb->interp)) ){705 return 1;706 }707 return 0;708}709#endif710 711#if !defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_OMIT_FLOATING_POINT) && \712 !defined(SQLITE_OMIT_DEPRECATED)713/*714** This routine is called by the SQLite trace handler whenever a new715** block of SQL is executed. The TCL script in pDb->zTrace is executed.716*/717static void DbTraceHandler(void *cd, const char *zSql){718 SqliteDb *pDb = (SqliteDb*)cd;719 Tcl_DString str;720 721 Tcl_DStringInit(&str);722 Tcl_DStringAppend(&str, pDb->zTrace, -1);723 Tcl_DStringAppendElement(&str, zSql);724 Tcl_Eval(pDb->interp, Tcl_DStringValue(&str));725 Tcl_DStringFree(&str);726 Tcl_ResetResult(pDb->interp);727}728#endif729 730#ifndef SQLITE_OMIT_TRACE731/*732** This routine is called by the SQLite trace_v2 handler whenever a new733** supported event is generated. Unsupported event types are ignored.734** The TCL script in pDb->zTraceV2 is executed, with the arguments for735** the event appended to it (as list elements).736*/737static int DbTraceV2Handler(738 unsigned type, /* One of the SQLITE_TRACE_* event types. */739 void *cd, /* The original context data pointer. */740 void *pd, /* Primary event data, depends on event type. */741 void *xd /* Extra event data, depends on event type. */742){743 SqliteDb *pDb = (SqliteDb*)cd;744 Tcl_Obj *pCmd;745 746 switch( type ){747 case SQLITE_TRACE_STMT: {748 sqlite3_stmt *pStmt = (sqlite3_stmt *)pd;749 char *zSql = (char *)xd;750 751 pCmd = Tcl_NewStringObj(pDb->zTraceV2, -1);752 Tcl_IncrRefCount(pCmd);753 Tcl_ListObjAppendElement(pDb->interp, pCmd,754 Tcl_NewWideIntObj((Tcl_WideInt)(uptr)pStmt));755 Tcl_ListObjAppendElement(pDb->interp, pCmd,756 Tcl_NewStringObj(zSql, -1));757 Tcl_EvalObjEx(pDb->interp, pCmd, TCL_EVAL_DIRECT);758 Tcl_DecrRefCount(pCmd);759 Tcl_ResetResult(pDb->interp);760 break;761 }762 case SQLITE_TRACE_PROFILE: {763 sqlite3_stmt *pStmt = (sqlite3_stmt *)pd;764 sqlite3_int64 ns = *(sqlite3_int64*)xd;765 766 pCmd = Tcl_NewStringObj(pDb->zTraceV2, -1);767 Tcl_IncrRefCount(pCmd);768 Tcl_ListObjAppendElement(pDb->interp, pCmd,769 Tcl_NewWideIntObj((Tcl_WideInt)(uptr)pStmt));770 Tcl_ListObjAppendElement(pDb->interp, pCmd,771 Tcl_NewWideIntObj((Tcl_WideInt)ns));772 Tcl_EvalObjEx(pDb->interp, pCmd, TCL_EVAL_DIRECT);773 Tcl_DecrRefCount(pCmd);774 Tcl_ResetResult(pDb->interp);775 break;776 }777 case SQLITE_TRACE_ROW: {778 sqlite3_stmt *pStmt = (sqlite3_stmt *)pd;779 780 pCmd = Tcl_NewStringObj(pDb->zTraceV2, -1);781 Tcl_IncrRefCount(pCmd);782 Tcl_ListObjAppendElement(pDb->interp, pCmd,783 Tcl_NewWideIntObj((Tcl_WideInt)(uptr)pStmt));784 Tcl_EvalObjEx(pDb->interp, pCmd, TCL_EVAL_DIRECT);785 Tcl_DecrRefCount(pCmd);786 Tcl_ResetResult(pDb->interp);787 break;788 }789 case SQLITE_TRACE_CLOSE: {790 sqlite3 *db = (sqlite3 *)pd;791 792 pCmd = Tcl_NewStringObj(pDb->zTraceV2, -1);793 Tcl_IncrRefCount(pCmd);794 Tcl_ListObjAppendElement(pDb->interp, pCmd,795 Tcl_NewWideIntObj((Tcl_WideInt)(uptr)db));796 Tcl_EvalObjEx(pDb->interp, pCmd, TCL_EVAL_DIRECT);797 Tcl_DecrRefCount(pCmd);798 Tcl_ResetResult(pDb->interp);799 break;800 }801 }802 return SQLITE_OK;803}804#endif805 806#if !defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_OMIT_FLOATING_POINT) && \807 !defined(SQLITE_OMIT_DEPRECATED)808/*809** This routine is called by the SQLite profile handler after a statement810** SQL has executed. The TCL script in pDb->zProfile is evaluated.811*/812static void DbProfileHandler(void *cd, const char *zSql, sqlite_uint64 tm){813 SqliteDb *pDb = (SqliteDb*)cd;814 Tcl_DString str;815 char zTm[100];816 817 sqlite3_snprintf(sizeof(zTm)-1, zTm, "%lld", tm);818 Tcl_DStringInit(&str);819 Tcl_DStringAppend(&str, pDb->zProfile, -1);820 Tcl_DStringAppendElement(&str, zSql);821 Tcl_DStringAppendElement(&str, zTm);822 Tcl_Eval(pDb->interp, Tcl_DStringValue(&str));823 Tcl_DStringFree(&str);824 Tcl_ResetResult(pDb->interp);825}826#endif827 828/*829** This routine is called when a transaction is committed. The830** TCL script in pDb->zCommit is executed. If it returns non-zero or831** if it throws an exception, the transaction is rolled back instead832** of being committed.833*/834static int DbCommitHandler(void *cd){835 SqliteDb *pDb = (SqliteDb*)cd;836 int rc;837 838 rc = Tcl_Eval(pDb->interp, pDb->zCommit);839 if( rc!=TCL_OK || atoi(Tcl_GetStringResult(pDb->interp)) ){840 return 1;841 }842 return 0;843}844 845static void DbRollbackHandler(void *clientData){846 SqliteDb *pDb = (SqliteDb*)clientData;847 assert(pDb->pRollbackHook);848 if( TCL_OK!=Tcl_EvalObjEx(pDb->interp, pDb->pRollbackHook, 0) ){849 Tcl_BackgroundError(pDb->interp);850 }851}852 853/*854** This procedure handles wal_hook callbacks.855*/856static int DbWalHandler(857 void *clientData,858 sqlite3 *db,859 const char *zDb,860 int nEntry861){862 int ret = SQLITE_OK;863 Tcl_Obj *p;864 SqliteDb *pDb = (SqliteDb*)clientData;865 Tcl_Interp *interp = pDb->interp;866 assert(pDb->pWalHook);867 868 assert( db==pDb->db );869 p = Tcl_DuplicateObj(pDb->pWalHook);870 Tcl_IncrRefCount(p);871 Tcl_ListObjAppendElement(interp, p, Tcl_NewStringObj(zDb, -1));872 Tcl_ListObjAppendElement(interp, p, Tcl_NewIntObj(nEntry));873 if( TCL_OK!=Tcl_EvalObjEx(interp, p, 0)874 || TCL_OK!=Tcl_GetIntFromObj(interp, Tcl_GetObjResult(interp), &ret)875 ){876 Tcl_BackgroundError(interp);877 }878 Tcl_DecrRefCount(p);879 880 return ret;881}882 883#if defined(SQLITE_TEST) && defined(SQLITE_ENABLE_UNLOCK_NOTIFY)884static void setTestUnlockNotifyVars(Tcl_Interp *interp, int iArg, int nArg){885 char zBuf[64];886 sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", iArg);887 Tcl_SetVar(interp, "sqlite_unlock_notify_arg", zBuf, TCL_GLOBAL_ONLY);888 sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", nArg);889 Tcl_SetVar(interp, "sqlite_unlock_notify_argcount", zBuf, TCL_GLOBAL_ONLY);890}891#else892# define setTestUnlockNotifyVars(x,y,z)893#endif894 895#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY896static void DbUnlockNotify(void **apArg, int nArg){897 int i;898 for(i=0; i<nArg; i++){899 const int flags = (TCL_EVAL_GLOBAL|TCL_EVAL_DIRECT);900 SqliteDb *pDb = (SqliteDb *)apArg[i];901 setTestUnlockNotifyVars(pDb->interp, i, nArg);902 assert( pDb->pUnlockNotify);903 Tcl_EvalObjEx(pDb->interp, pDb->pUnlockNotify, flags);904 Tcl_DecrRefCount(pDb->pUnlockNotify);905 pDb->pUnlockNotify = 0;906 }907}908#endif909 910#ifdef SQLITE_ENABLE_PREUPDATE_HOOK911/*912** Pre-update hook callback.913*/914static void DbPreUpdateHandler(915 void *p,916 sqlite3 *db,917 int op,918 const char *zDb,919 const char *zTbl,920 sqlite_int64 iKey1,921 sqlite_int64 iKey2922){923 SqliteDb *pDb = (SqliteDb *)p;924 Tcl_Obj *pCmd;925 static const char *azStr[] = {"DELETE", "INSERT", "UPDATE"};926 927 assert( (SQLITE_DELETE-1)/9 == 0 );928 assert( (SQLITE_INSERT-1)/9 == 1 );929 assert( (SQLITE_UPDATE-1)/9 == 2 );930 assert( pDb->pPreUpdateHook );931 assert( db==pDb->db );932 assert( op==SQLITE_INSERT || op==SQLITE_UPDATE || op==SQLITE_DELETE );933 934 pCmd = Tcl_DuplicateObj(pDb->pPreUpdateHook);935 Tcl_IncrRefCount(pCmd);936 Tcl_ListObjAppendElement(0, pCmd, Tcl_NewStringObj(azStr[(op-1)/9], -1));937 Tcl_ListObjAppendElement(0, pCmd, Tcl_NewStringObj(zDb, -1));938 Tcl_ListObjAppendElement(0, pCmd, Tcl_NewStringObj(zTbl, -1));939 Tcl_ListObjAppendElement(0, pCmd, Tcl_NewWideIntObj(iKey1));940 Tcl_ListObjAppendElement(0, pCmd, Tcl_NewWideIntObj(iKey2));941 Tcl_EvalObjEx(pDb->interp, pCmd, TCL_EVAL_DIRECT);942 Tcl_DecrRefCount(pCmd);943}944#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */945 946static void DbUpdateHandler(947 void *p,948 int op,949 const char *zDb,950 const char *zTbl,951 sqlite_int64 rowid952){953 SqliteDb *pDb = (SqliteDb *)p;954 Tcl_Obj *pCmd;955 static const char *azStr[] = {"DELETE", "INSERT", "UPDATE"};956 957 assert( (SQLITE_DELETE-1)/9 == 0 );958 assert( (SQLITE_INSERT-1)/9 == 1 );959 assert( (SQLITE_UPDATE-1)/9 == 2 );960 961 assert( pDb->pUpdateHook );962 assert( op==SQLITE_INSERT || op==SQLITE_UPDATE || op==SQLITE_DELETE );963 964 pCmd = Tcl_DuplicateObj(pDb->pUpdateHook);965 Tcl_IncrRefCount(pCmd);966 Tcl_ListObjAppendElement(0, pCmd, Tcl_NewStringObj(azStr[(op-1)/9], -1));967 Tcl_ListObjAppendElement(0, pCmd, Tcl_NewStringObj(zDb, -1));968 Tcl_ListObjAppendElement(0, pCmd, Tcl_NewStringObj(zTbl, -1));969 Tcl_ListObjAppendElement(0, pCmd, Tcl_NewWideIntObj(rowid));970 Tcl_EvalObjEx(pDb->interp, pCmd, TCL_EVAL_DIRECT);971 Tcl_DecrRefCount(pCmd);972}973 974static void tclCollateNeeded(975 void *pCtx,976 sqlite3 *db,977 int enc,978 const char *zName979){980 SqliteDb *pDb = (SqliteDb *)pCtx;981 Tcl_Obj *pScript = Tcl_DuplicateObj(pDb->pCollateNeeded);982 Tcl_IncrRefCount(pScript);983 Tcl_ListObjAppendElement(0, pScript, Tcl_NewStringObj(zName, -1));984 Tcl_EvalObjEx(pDb->interp, pScript, 0);985 Tcl_DecrRefCount(pScript);986}987 988/*989** This routine is called to evaluate an SQL collation function implemented990** using TCL script.991*/992static int tclSqlCollate(993 void *pCtx,994 int nA,995 const void *zA,996 int nB,997 const void *zB998){999 SqlCollate *p = (SqlCollate *)pCtx;1000 Tcl_Obj *pCmd;1001 1002 pCmd = Tcl_NewStringObj(p->zScript, -1);1003 Tcl_IncrRefCount(pCmd);1004 Tcl_ListObjAppendElement(p->interp, pCmd, Tcl_NewStringObj(zA, nA));1005 Tcl_ListObjAppendElement(p->interp, pCmd, Tcl_NewStringObj(zB, nB));1006 Tcl_EvalObjEx(p->interp, pCmd, TCL_EVAL_DIRECT);1007 Tcl_DecrRefCount(pCmd);1008 return (atoi(Tcl_GetStringResult(p->interp)));1009}1010 1011/*1012** This routine is called to evaluate an SQL function implemented1013** using TCL script.1014*/1015static void tclSqlFunc(sqlite3_context *context, int argc, sqlite3_value**argv){1016 SqlFunc *p = sqlite3_user_data(context);1017 Tcl_Obj *pCmd;1018 int i;1019 int rc;1020 1021 if( argc==0 ){1022 /* If there are no arguments to the function, call Tcl_EvalObjEx on the1023 ** script object directly. This allows the TCL compiler to generate1024 ** bytecode for the command on the first invocation and thus make1025 ** subsequent invocations much faster. */1026 pCmd = p->pScript;1027 Tcl_IncrRefCount(pCmd);1028 rc = Tcl_EvalObjEx(p->interp, pCmd, 0);1029 Tcl_DecrRefCount(pCmd);1030 }else{1031 /* If there are arguments to the function, make a shallow copy of the1032 ** script object, lappend the arguments, then evaluate the copy.1033 **1034 ** By "shallow" copy, we mean only the outer list Tcl_Obj is duplicated.1035 ** The new Tcl_Obj contains pointers to the original list elements.1036 ** That way, when Tcl_EvalObjv() is run and shimmers the first element1037 ** of the list to tclCmdNameType, that alternate representation will1038 ** be preserved and reused on the next invocation.1039 */1040 Tcl_Obj **aArg;1041 Tcl_Size nArg;1042 if( Tcl_ListObjGetElements(p->interp, p->pScript, &nArg, &aArg) ){1043 sqlite3_result_error(context, Tcl_GetStringResult(p->interp), -1);1044 return;1045 }1046 pCmd = Tcl_NewListObj(nArg, aArg);1047 Tcl_IncrRefCount(pCmd);1048 for(i=0; i<argc; i++){1049 sqlite3_value *pIn = argv[i];1050 Tcl_Obj *pVal;1051 1052 /* Set pVal to contain the i'th column of this row. */1053 switch( sqlite3_value_type(pIn) ){1054 case SQLITE_BLOB: {1055 int bytes = sqlite3_value_bytes(pIn);1056 pVal = Tcl_NewByteArrayObj(sqlite3_value_blob(pIn), bytes);1057 break;1058 }1059 case SQLITE_INTEGER: {1060 sqlite_int64 v = sqlite3_value_int64(pIn);1061 if( v>=-2147483647 && v<=2147483647 ){1062 pVal = Tcl_NewIntObj((int)v);1063 }else{1064 pVal = Tcl_NewWideIntObj(v);1065 }1066 break;1067 }1068 case SQLITE_FLOAT: {1069 double r = sqlite3_value_double(pIn);1070 pVal = Tcl_NewDoubleObj(r);1071 break;1072 }1073 case SQLITE_NULL: {1074 pVal = Tcl_NewStringObj(p->pDb->zNull, -1);1075 break;1076 }1077 default: {1078 int bytes = sqlite3_value_bytes(pIn);1079 pVal = Tcl_NewStringObj((char *)sqlite3_value_text(pIn), bytes);1080 break;1081 }1082 }1083 rc = Tcl_ListObjAppendElement(p->interp, pCmd, pVal);1084 if( rc ){1085 Tcl_DecrRefCount(pCmd);1086 sqlite3_result_error(context, Tcl_GetStringResult(p->interp), -1);1087 return;1088 }1089 }1090 if( !p->useEvalObjv ){1091 /* Tcl_EvalObjEx() will automatically call Tcl_EvalObjv() if pCmd1092 ** is a list without a string representation. To prevent this from1093 ** happening, make sure pCmd has a valid string representation */1094 Tcl_GetString(pCmd);1095 }1096 rc = Tcl_EvalObjEx(p->interp, pCmd, TCL_EVAL_DIRECT);1097 Tcl_DecrRefCount(pCmd);1098 }1099 1100 if( TCL_BREAK==rc ){1101 sqlite3_result_null(context);1102 }else if( rc && rc!=TCL_RETURN ){1103 sqlite3_result_error(context, Tcl_GetStringResult(p->interp), -1);1104 }else{1105 Tcl_Obj *pVar = Tcl_GetObjResult(p->interp);1106 Tcl_Size n;1107 u8 *data;1108 const char *zType = (pVar->typePtr ? pVar->typePtr->name : "");1109 char c = zType[0];1110 int eType = p->eType;1111 1112 if( eType==SQLITE_NULL ){1113 if( c=='b' && strcmp(zType,"bytearray")==0 && pVar->bytes==0 ){1114 /* Only return a BLOB type if the Tcl variable is a bytearray and1115 ** has no string representation. */1116 eType = SQLITE_BLOB;1117 }else if( (c=='b' && pVar->bytes==0 && strcmp(zType,"boolean")==0 )1118 || (c=='b' && pVar->bytes==0 && strcmp(zType,"booleanString")==0 )1119 || (c=='w' && strcmp(zType,"wideInt")==0)1120 || (c=='i' && strcmp(zType,"int")==0)1121 ){1122 eType = SQLITE_INTEGER;1123 }else if( c=='d' && strcmp(zType,"double")==0 ){1124 eType = SQLITE_FLOAT;1125 }else{1126 eType = SQLITE_TEXT;1127 }1128 }1129 1130 switch( eType ){1131 case SQLITE_BLOB: {1132 data = Tcl_GetByteArrayFromObj(pVar, &n);1133 sqlite3_result_blob(context, data, n, SQLITE_TRANSIENT);1134 break;1135 }1136 case SQLITE_INTEGER: {1137 Tcl_WideInt v;1138 if( TCL_OK==Tcl_GetWideIntFromObj(0, pVar, &v) ){1139 sqlite3_result_int64(context, v);1140 break;1141 }1142 /* fall-through */1143 }1144 case SQLITE_FLOAT: {1145 double r;1146 if( TCL_OK==Tcl_GetDoubleFromObj(0, pVar, &r) ){1147 sqlite3_result_double(context, r);1148 break;1149 }1150 /* fall-through */1151 }1152 default: {1153 data = (unsigned char *)Tcl_GetStringFromObj(pVar, &n);1154 sqlite3_result_text64(context, (char *)data, n, SQLITE_TRANSIENT,1155 SQLITE_UTF8);1156 break;1157 }1158 }1159 1160 }1161}1162 1163#ifndef SQLITE_OMIT_AUTHORIZATION1164/*1165** This is the authentication function. It appends the authentication1166** type code and the two arguments to zCmd[] then invokes the result1167** on the interpreter. The reply is examined to determine if the1168** authentication fails or succeeds.1169*/1170static int auth_callback(1171 void *pArg,1172 int code,1173 const char *zArg1,1174 const char *zArg2,1175 const char *zArg3,1176 const char *zArg41177){1178 const char *zCode;1179 Tcl_DString str;1180 int rc;1181 const char *zReply;1182 /* EVIDENCE-OF: R-38590-62769 The first parameter to the authorizer1183 ** callback is a copy of the third parameter to the1184 ** sqlite3_set_authorizer() interface.1185 */1186 SqliteDb *pDb = (SqliteDb*)pArg;1187 if( pDb->disableAuth ) return SQLITE_OK;1188 1189 /* EVIDENCE-OF: R-56518-44310 The second parameter to the callback is an1190 ** integer action code that specifies the particular action to be1191 ** authorized. */1192 switch( code ){1193 case SQLITE_COPY : zCode="SQLITE_COPY"; break;1194 case SQLITE_CREATE_INDEX : zCode="SQLITE_CREATE_INDEX"; break;1195 case SQLITE_CREATE_TABLE : zCode="SQLITE_CREATE_TABLE"; break;1196 case SQLITE_CREATE_TEMP_INDEX : zCode="SQLITE_CREATE_TEMP_INDEX"; break;1197 case SQLITE_CREATE_TEMP_TABLE : zCode="SQLITE_CREATE_TEMP_TABLE"; break;1198 case SQLITE_CREATE_TEMP_TRIGGER: zCode="SQLITE_CREATE_TEMP_TRIGGER"; break;1199 case SQLITE_CREATE_TEMP_VIEW : zCode="SQLITE_CREATE_TEMP_VIEW"; break;1200 case SQLITE_CREATE_TRIGGER : zCode="SQLITE_CREATE_TRIGGER"; break;