| Index: third_party/sqlite/src/src/tclsqlite.c
|
| diff --git a/third_party/sqlite/src/src/tclsqlite.c b/third_party/sqlite/src/src/tclsqlite.c
|
| index f024317e9098399b31d96e723cab0719959a1cf1..5b52bf0c91ca14652974173a6e6d66d22bb2ee07 100644
|
| --- a/third_party/sqlite/src/src/tclsqlite.c
|
| +++ b/third_party/sqlite/src/src/tclsqlite.c
|
| @@ -30,10 +30,17 @@
|
| ** If requested, include the SQLite compiler options file for MSVC.
|
| */
|
| #if defined(INCLUDE_MSVC_H)
|
| -#include "msvc.h"
|
| +# include "msvc.h"
|
| #endif
|
|
|
| -#include "tcl.h"
|
| +#if defined(INCLUDE_SQLITE_TCL_H)
|
| +# include "sqlite_tcl.h"
|
| +#else
|
| +# include "tcl.h"
|
| +# ifndef SQLITE_TCLAPI
|
| +# define SQLITE_TCLAPI
|
| +# endif
|
| +#endif
|
| #include <errno.h>
|
|
|
| /*
|
| @@ -133,6 +140,7 @@ struct SqliteDb {
|
| char *zBusy; /* The busy callback routine */
|
| char *zCommit; /* The commit hook callback routine */
|
| char *zTrace; /* The trace callback routine */
|
| + char *zTraceV2; /* The trace_v2 callback routine */
|
| char *zProfile; /* The profile callback routine */
|
| char *zProgress; /* The progress callback routine */
|
| char *zAuth; /* The authorization callback routine */
|
| @@ -140,6 +148,7 @@ struct SqliteDb {
|
| char *zNull; /* Text to substitute for an SQL NULL value */
|
| SqlFunc *pFunc; /* List of SQL functions */
|
| Tcl_Obj *pUpdateHook; /* Update hook script (if any) */
|
| + Tcl_Obj *pPreUpdateHook; /* Pre-update hook script (if any) */
|
| Tcl_Obj *pRollbackHook; /* Rollback hook script (if any) */
|
| Tcl_Obj *pWalHook; /* WAL hook script (if any) */
|
| Tcl_Obj *pUnlockNotify; /* Unlock notify script (if any) */
|
| @@ -153,6 +162,7 @@ struct SqliteDb {
|
| IncrblobChannel *pIncrblob;/* Linked list of open incrblob channels */
|
| int nStep, nSort, nIndex; /* Statistics for most recent operation */
|
| int nTransaction; /* Number of nested [transaction] methods */
|
| + int openFlags; /* Flags used to open. (SQLITE_OPEN_URI) */
|
| #ifdef SQLITE_TEST
|
| int bLegacyPrepare; /* True to use sqlite3_prepare() */
|
| #endif
|
| @@ -190,7 +200,7 @@ static void closeIncrblobChannels(SqliteDb *pDb){
|
| for(p=pDb->pIncrblob; p; p=pNext){
|
| pNext = p->pNext;
|
|
|
| - /* Note: Calling unregister here call Tcl_Close on the incrblob channel,
|
| + /* Note: Calling unregister here call Tcl_Close on the incrblob channel,
|
| ** which deletes the IncrblobChannel structure at *p. So do not
|
| ** call Tcl_Free() here.
|
| */
|
| @@ -201,7 +211,10 @@ static void closeIncrblobChannels(SqliteDb *pDb){
|
| /*
|
| ** Close an incremental blob channel.
|
| */
|
| -static int incrblobClose(ClientData instanceData, Tcl_Interp *interp){
|
| +static int SQLITE_TCLAPI incrblobClose(
|
| + ClientData instanceData,
|
| + Tcl_Interp *interp
|
| +){
|
| IncrblobChannel *p = (IncrblobChannel *)instanceData;
|
| int rc = sqlite3_blob_close(p->pBlob);
|
| sqlite3 *db = p->pDb->db;
|
| @@ -230,9 +243,9 @@ static int incrblobClose(ClientData instanceData, Tcl_Interp *interp){
|
| /*
|
| ** Read data from an incremental blob channel.
|
| */
|
| -static int incrblobInput(
|
| - ClientData instanceData,
|
| - char *buf,
|
| +static int SQLITE_TCLAPI incrblobInput(
|
| + ClientData instanceData,
|
| + char *buf,
|
| int bufSize,
|
| int *errorCodePtr
|
| ){
|
| @@ -262,9 +275,9 @@ static int incrblobInput(
|
| /*
|
| ** Write data to an incremental blob channel.
|
| */
|
| -static int incrblobOutput(
|
| - ClientData instanceData,
|
| - CONST char *buf,
|
| +static int SQLITE_TCLAPI incrblobOutput(
|
| + ClientData instanceData,
|
| + CONST char *buf,
|
| int toWrite,
|
| int *errorCodePtr
|
| ){
|
| @@ -295,8 +308,8 @@ static int incrblobOutput(
|
| /*
|
| ** Seek an incremental blob channel.
|
| */
|
| -static int incrblobSeek(
|
| - ClientData instanceData,
|
| +static int SQLITE_TCLAPI incrblobSeek(
|
| + ClientData instanceData,
|
| long offset,
|
| int seekMode,
|
| int *errorCodePtr
|
| @@ -321,10 +334,17 @@ static int incrblobSeek(
|
| }
|
|
|
|
|
| -static void incrblobWatch(ClientData instanceData, int mode){
|
| - /* NO-OP */
|
| +static void SQLITE_TCLAPI incrblobWatch(
|
| + ClientData instanceData,
|
| + int mode
|
| +){
|
| + /* NO-OP */
|
| }
|
| -static int incrblobHandle(ClientData instanceData, int dir, ClientData *hPtr){
|
| +static int SQLITE_TCLAPI incrblobHandle(
|
| + ClientData instanceData,
|
| + int dir,
|
| + ClientData *hPtr
|
| +){
|
| return TCL_ERROR;
|
| }
|
|
|
| @@ -350,11 +370,11 @@ static Tcl_ChannelType IncrblobChannelType = {
|
| ** Create a new incrblob channel.
|
| */
|
| static int createIncrblobChannel(
|
| - Tcl_Interp *interp,
|
| - SqliteDb *pDb,
|
| + Tcl_Interp *interp,
|
| + SqliteDb *pDb,
|
| const char *zDb,
|
| - const char *zTable,
|
| - const char *zColumn,
|
| + const char *zTable,
|
| + const char *zColumn,
|
| sqlite_int64 iRow,
|
| int isReadonly
|
| ){
|
| @@ -436,7 +456,7 @@ static SqlFunc *findSqlFunc(SqliteDb *pDb, const char *zName){
|
| pNew = (SqlFunc*)Tcl_Alloc( sizeof(*pNew) + nName + 1 );
|
| pNew->zName = (char*)&pNew[1];
|
| memcpy(pNew->zName, zName, nName+1);
|
| - for(p=pDb->pFunc; p; p=p->pNext){
|
| + for(p=pDb->pFunc; p; p=p->pNext){
|
| if( sqlite3_stricmp(p->zName, pNew->zName)==0 ){
|
| Tcl_Free((char*)pNew);
|
| return p;
|
| @@ -483,7 +503,7 @@ static void flushStmtCache(SqliteDb *pDb){
|
| ** TCL calls this procedure when an sqlite3 database command is
|
| ** deleted.
|
| */
|
| -static void DbDeleteCmd(void *db){
|
| +static void SQLITE_TCLAPI DbDeleteCmd(void *db){
|
| SqliteDb *pDb = (SqliteDb*)db;
|
| flushStmtCache(pDb);
|
| closeIncrblobChannels(pDb);
|
| @@ -506,6 +526,9 @@ static void DbDeleteCmd(void *db){
|
| if( pDb->zTrace ){
|
| Tcl_Free(pDb->zTrace);
|
| }
|
| + if( pDb->zTraceV2 ){
|
| + Tcl_Free(pDb->zTraceV2);
|
| + }
|
| if( pDb->zProfile ){
|
| Tcl_Free(pDb->zProfile);
|
| }
|
| @@ -518,6 +541,9 @@ static void DbDeleteCmd(void *db){
|
| if( pDb->pUpdateHook ){
|
| Tcl_DecrRefCount(pDb->pUpdateHook);
|
| }
|
| + if( pDb->pPreUpdateHook ){
|
| + Tcl_DecrRefCount(pDb->pPreUpdateHook);
|
| + }
|
| if( pDb->pRollbackHook ){
|
| Tcl_DecrRefCount(pDb->pRollbackHook);
|
| }
|
| @@ -564,7 +590,8 @@ static int DbProgressHandler(void *cd){
|
| }
|
| #endif
|
|
|
| -#ifndef SQLITE_OMIT_TRACE
|
| +#if !defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_OMIT_FLOATING_POINT) && \
|
| + !defined(SQLITE_OMIT_DEPRECATED)
|
| /*
|
| ** This routine is called by the SQLite trace handler whenever a new
|
| ** block of SQL is executed. The TCL script in pDb->zTrace is executed.
|
| @@ -584,6 +611,83 @@ static void DbTraceHandler(void *cd, const char *zSql){
|
|
|
| #ifndef SQLITE_OMIT_TRACE
|
| /*
|
| +** This routine is called by the SQLite trace_v2 handler whenever a new
|
| +** supported event is generated. Unsupported event types are ignored.
|
| +** The TCL script in pDb->zTraceV2 is executed, with the arguments for
|
| +** the event appended to it (as list elements).
|
| +*/
|
| +static int DbTraceV2Handler(
|
| + unsigned type, /* One of the SQLITE_TRACE_* event types. */
|
| + void *cd, /* The original context data pointer. */
|
| + void *pd, /* Primary event data, depends on event type. */
|
| + void *xd /* Extra event data, depends on event type. */
|
| +){
|
| + SqliteDb *pDb = (SqliteDb*)cd;
|
| + Tcl_Obj *pCmd;
|
| +
|
| + switch( type ){
|
| + case SQLITE_TRACE_STMT: {
|
| + sqlite3_stmt *pStmt = (sqlite3_stmt *)pd;
|
| + char *zSql = (char *)xd;
|
| +
|
| + pCmd = Tcl_NewStringObj(pDb->zTraceV2, -1);
|
| + Tcl_IncrRefCount(pCmd);
|
| + Tcl_ListObjAppendElement(pDb->interp, pCmd,
|
| + Tcl_NewWideIntObj((Tcl_WideInt)pStmt));
|
| + Tcl_ListObjAppendElement(pDb->interp, pCmd,
|
| + Tcl_NewStringObj(zSql, -1));
|
| + Tcl_EvalObjEx(pDb->interp, pCmd, TCL_EVAL_DIRECT);
|
| + Tcl_DecrRefCount(pCmd);
|
| + Tcl_ResetResult(pDb->interp);
|
| + break;
|
| + }
|
| + case SQLITE_TRACE_PROFILE: {
|
| + sqlite3_stmt *pStmt = (sqlite3_stmt *)pd;
|
| + sqlite3_int64 ns = (sqlite3_int64)xd;
|
| +
|
| + pCmd = Tcl_NewStringObj(pDb->zTraceV2, -1);
|
| + Tcl_IncrRefCount(pCmd);
|
| + Tcl_ListObjAppendElement(pDb->interp, pCmd,
|
| + Tcl_NewWideIntObj((Tcl_WideInt)pStmt));
|
| + Tcl_ListObjAppendElement(pDb->interp, pCmd,
|
| + Tcl_NewWideIntObj((Tcl_WideInt)ns));
|
| + Tcl_EvalObjEx(pDb->interp, pCmd, TCL_EVAL_DIRECT);
|
| + Tcl_DecrRefCount(pCmd);
|
| + Tcl_ResetResult(pDb->interp);
|
| + break;
|
| + }
|
| + case SQLITE_TRACE_ROW: {
|
| + sqlite3_stmt *pStmt = (sqlite3_stmt *)pd;
|
| +
|
| + pCmd = Tcl_NewStringObj(pDb->zTraceV2, -1);
|
| + Tcl_IncrRefCount(pCmd);
|
| + Tcl_ListObjAppendElement(pDb->interp, pCmd,
|
| + Tcl_NewWideIntObj((Tcl_WideInt)pStmt));
|
| + Tcl_EvalObjEx(pDb->interp, pCmd, TCL_EVAL_DIRECT);
|
| + Tcl_DecrRefCount(pCmd);
|
| + Tcl_ResetResult(pDb->interp);
|
| + break;
|
| + }
|
| + case SQLITE_TRACE_CLOSE: {
|
| + sqlite3 *db = (sqlite3 *)pd;
|
| +
|
| + pCmd = Tcl_NewStringObj(pDb->zTraceV2, -1);
|
| + Tcl_IncrRefCount(pCmd);
|
| + Tcl_ListObjAppendElement(pDb->interp, pCmd,
|
| + Tcl_NewWideIntObj((Tcl_WideInt)db));
|
| + Tcl_EvalObjEx(pDb->interp, pCmd, TCL_EVAL_DIRECT);
|
| + Tcl_DecrRefCount(pCmd);
|
| + Tcl_ResetResult(pDb->interp);
|
| + break;
|
| + }
|
| + }
|
| + return SQLITE_OK;
|
| +}
|
| +#endif
|
| +
|
| +#if !defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_OMIT_FLOATING_POINT) && \
|
| + !defined(SQLITE_OMIT_DEPRECATED)
|
| +/*
|
| ** This routine is called by the SQLite profile handler after a statement
|
| ** SQL has executed. The TCL script in pDb->zProfile is evaluated.
|
| */
|
| @@ -632,9 +736,9 @@ static void DbRollbackHandler(void *clientData){
|
| ** This procedure handles wal_hook callbacks.
|
| */
|
| static int DbWalHandler(
|
| - void *clientData,
|
| - sqlite3 *db,
|
| - const char *zDb,
|
| + void *clientData,
|
| + sqlite3 *db,
|
| + const char *zDb,
|
| int nEntry
|
| ){
|
| int ret = SQLITE_OK;
|
| @@ -648,7 +752,7 @@ static int DbWalHandler(
|
| Tcl_IncrRefCount(p);
|
| Tcl_ListObjAppendElement(interp, p, Tcl_NewStringObj(zDb, -1));
|
| Tcl_ListObjAppendElement(interp, p, Tcl_NewIntObj(nEntry));
|
| - if( TCL_OK!=Tcl_EvalObjEx(interp, p, 0)
|
| + if( TCL_OK!=Tcl_EvalObjEx(interp, p, 0)
|
| || TCL_OK!=Tcl_GetIntFromObj(interp, Tcl_GetObjResult(interp), &ret)
|
| ){
|
| Tcl_BackgroundError(interp);
|
| @@ -685,23 +789,63 @@ static void DbUnlockNotify(void **apArg, int nArg){
|
| }
|
| #endif
|
|
|
| +#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
|
| +/*
|
| +** Pre-update hook callback.
|
| +*/
|
| +static void DbPreUpdateHandler(
|
| + void *p,
|
| + sqlite3 *db,
|
| + int op,
|
| + const char *zDb,
|
| + const char *zTbl,
|
| + sqlite_int64 iKey1,
|
| + sqlite_int64 iKey2
|
| +){
|
| + SqliteDb *pDb = (SqliteDb *)p;
|
| + Tcl_Obj *pCmd;
|
| + static const char *azStr[] = {"DELETE", "INSERT", "UPDATE"};
|
| +
|
| + assert( (SQLITE_DELETE-1)/9 == 0 );
|
| + assert( (SQLITE_INSERT-1)/9 == 1 );
|
| + assert( (SQLITE_UPDATE-1)/9 == 2 );
|
| + assert( pDb->pPreUpdateHook );
|
| + assert( db==pDb->db );
|
| + assert( op==SQLITE_INSERT || op==SQLITE_UPDATE || op==SQLITE_DELETE );
|
| +
|
| + pCmd = Tcl_DuplicateObj(pDb->pPreUpdateHook);
|
| + Tcl_IncrRefCount(pCmd);
|
| + Tcl_ListObjAppendElement(0, pCmd, Tcl_NewStringObj(azStr[(op-1)/9], -1));
|
| + Tcl_ListObjAppendElement(0, pCmd, Tcl_NewStringObj(zDb, -1));
|
| + Tcl_ListObjAppendElement(0, pCmd, Tcl_NewStringObj(zTbl, -1));
|
| + Tcl_ListObjAppendElement(0, pCmd, Tcl_NewWideIntObj(iKey1));
|
| + Tcl_ListObjAppendElement(0, pCmd, Tcl_NewWideIntObj(iKey2));
|
| + Tcl_EvalObjEx(pDb->interp, pCmd, TCL_EVAL_DIRECT);
|
| + Tcl_DecrRefCount(pCmd);
|
| +}
|
| +#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */
|
| +
|
| static void DbUpdateHandler(
|
| - void *p,
|
| + void *p,
|
| int op,
|
| - const char *zDb,
|
| - const char *zTbl,
|
| + const char *zDb,
|
| + const char *zTbl,
|
| sqlite_int64 rowid
|
| ){
|
| SqliteDb *pDb = (SqliteDb *)p;
|
| Tcl_Obj *pCmd;
|
| + static const char *azStr[] = {"DELETE", "INSERT", "UPDATE"};
|
| +
|
| + assert( (SQLITE_DELETE-1)/9 == 0 );
|
| + assert( (SQLITE_INSERT-1)/9 == 1 );
|
| + assert( (SQLITE_UPDATE-1)/9 == 2 );
|
|
|
| assert( pDb->pUpdateHook );
|
| assert( op==SQLITE_INSERT || op==SQLITE_UPDATE || op==SQLITE_DELETE );
|
|
|
| pCmd = Tcl_DuplicateObj(pDb->pUpdateHook);
|
| Tcl_IncrRefCount(pCmd);
|
| - Tcl_ListObjAppendElement(0, pCmd, Tcl_NewStringObj(
|
| - ( (op==SQLITE_INSERT)?"INSERT":(op==SQLITE_UPDATE)?"UPDATE":"DELETE"), -1));
|
| + Tcl_ListObjAppendElement(0, pCmd, Tcl_NewStringObj(azStr[(op-1)/9], -1));
|
| Tcl_ListObjAppendElement(0, pCmd, Tcl_NewStringObj(zDb, -1));
|
| Tcl_ListObjAppendElement(0, pCmd, Tcl_NewStringObj(zTbl, -1));
|
| Tcl_ListObjAppendElement(0, pCmd, Tcl_NewWideIntObj(rowid));
|
| @@ -770,7 +914,7 @@ static void tclSqlFunc(sqlite3_context *context, int argc, sqlite3_value**argv){
|
| ** script object, lappend the arguments, then evaluate the copy.
|
| **
|
| ** By "shallow" copy, we mean only the outer list Tcl_Obj is duplicated.
|
| - ** The new Tcl_Obj contains pointers to the original list elements.
|
| + ** The new Tcl_Obj contains pointers to the original list elements.
|
| ** That way, when Tcl_EvalObjv() is run and shimmers the first element
|
| ** of the list to tclCmdNameType, that alternate representation will
|
| ** be preserved and reused on the next invocation.
|
| @@ -778,15 +922,15 @@ static void tclSqlFunc(sqlite3_context *context, int argc, sqlite3_value**argv){
|
| Tcl_Obj **aArg;
|
| int nArg;
|
| if( Tcl_ListObjGetElements(p->interp, p->pScript, &nArg, &aArg) ){
|
| - sqlite3_result_error(context, Tcl_GetStringResult(p->interp), -1);
|
| + sqlite3_result_error(context, Tcl_GetStringResult(p->interp), -1);
|
| return;
|
| - }
|
| + }
|
| pCmd = Tcl_NewListObj(nArg, aArg);
|
| Tcl_IncrRefCount(pCmd);
|
| for(i=0; i<argc; i++){
|
| sqlite3_value *pIn = argv[i];
|
| Tcl_Obj *pVal;
|
| -
|
| +
|
| /* Set pVal to contain the i'th column of this row. */
|
| switch( sqlite3_value_type(pIn) ){
|
| case SQLITE_BLOB: {
|
| @@ -821,7 +965,7 @@ static void tclSqlFunc(sqlite3_context *context, int argc, sqlite3_value**argv){
|
| rc = Tcl_ListObjAppendElement(p->interp, pCmd, pVal);
|
| if( rc ){
|
| Tcl_DecrRefCount(pCmd);
|
| - sqlite3_result_error(context, Tcl_GetStringResult(p->interp), -1);
|
| + sqlite3_result_error(context, Tcl_GetStringResult(p->interp), -1);
|
| return;
|
| }
|
| }
|
| @@ -836,7 +980,7 @@ static void tclSqlFunc(sqlite3_context *context, int argc, sqlite3_value**argv){
|
| }
|
|
|
| if( rc && rc!=TCL_RETURN ){
|
| - sqlite3_result_error(context, Tcl_GetStringResult(p->interp), -1);
|
| + sqlite3_result_error(context, Tcl_GetStringResult(p->interp), -1);
|
| }else{
|
| Tcl_Obj *pVar = Tcl_GetObjResult(p->interp);
|
| int n;
|
| @@ -938,7 +1082,7 @@ static int auth_callback(
|
| Tcl_DStringAppendElement(&str, zArg4 ? zArg4 : "");
|
| #ifdef SQLITE_USER_AUTHENTICATION
|
| Tcl_DStringAppendElement(&str, zArg5 ? zArg5 : "");
|
| -#endif
|
| +#endif
|
| rc = Tcl_GlobalEval(pDb->interp, Tcl_DStringValue(&str));
|
| Tcl_DStringFree(&str);
|
| zReply = rc==TCL_OK ? Tcl_GetStringResult(pDb->interp) : "SQLITE_DENY";
|
| @@ -1009,7 +1153,7 @@ static char *local_getline(char *zPrompt, FILE *in){
|
| ** It is invoked after evaluating the script SCRIPT to commit or rollback
|
| ** the transaction or savepoint opened by the [transaction] command.
|
| */
|
| -static int DbTransPostCmd(
|
| +static int SQLITE_TCLAPI DbTransPostCmd(
|
| ClientData data[], /* data[0] is the Sqlite3Db* for $db */
|
| Tcl_Interp *interp, /* Tcl interpreter */
|
| int result /* Result of evaluating SCRIPT */
|
| @@ -1030,12 +1174,12 @@ static int DbTransPostCmd(
|
| pDb->disableAuth++;
|
| if( sqlite3_exec(pDb->db, zEnd, 0, 0, 0) ){
|
| /* This is a tricky scenario to handle. The most likely cause of an
|
| - ** error is that the exec() above was an attempt to commit the
|
| + ** error is that the exec() above was an attempt to commit the
|
| ** top-level transaction that returned SQLITE_BUSY. Or, less likely,
|
| ** that an IO-error has occurred. In either case, throw a Tcl exception
|
| ** and try to rollback the transaction.
|
| **
|
| - ** But it could also be that the user executed one or more BEGIN,
|
| + ** But it could also be that the user executed one or more BEGIN,
|
| ** COMMIT, SAVEPOINT, RELEASE or ROLLBACK commands that are confusing
|
| ** this method's logic. Not clear how this would be best handled.
|
| */
|
| @@ -1054,7 +1198,7 @@ static int DbTransPostCmd(
|
| ** Unless SQLITE_TEST is defined, this function is a simple wrapper around
|
| ** sqlite3_prepare_v2(). If SQLITE_TEST is defined, then it uses either
|
| ** sqlite3_prepare_v2() or legacy interface sqlite3_prepare(), depending
|
| -** on whether or not the [db_use_legacy_prepare] command has been used to
|
| +** on whether or not the [db_use_legacy_prepare] command has been used to
|
| ** configure the connection.
|
| */
|
| static int dbPrepare(
|
| @@ -1110,7 +1254,7 @@ static int dbPrepareAndBind(
|
|
|
| for(pPreStmt = pDb->stmtList; pPreStmt; pPreStmt=pPreStmt->pNext){
|
| int n = pPreStmt->nSql;
|
| - if( nSql>=n
|
| + if( nSql>=n
|
| && memcmp(pPreStmt->zSql, zSql, n)==0
|
| && (zSql[n]==0 || zSql[n-1]==';')
|
| ){
|
| @@ -1136,7 +1280,7 @@ static int dbPrepareAndBind(
|
| break;
|
| }
|
| }
|
| -
|
| +
|
| /* If no prepared statement was found. Compile the SQL text. Also allocate
|
| ** a new SqlPreparedStmt structure. */
|
| if( pPreStmt==0 ){
|
| @@ -1182,7 +1326,7 @@ static int dbPrepareAndBind(
|
| assert( strlen30(pPreStmt->zSql)==pPreStmt->nSql );
|
| assert( 0==memcmp(pPreStmt->zSql, zSql, pPreStmt->nSql) );
|
|
|
| - /* Bind values to parameters that begin with $ or : */
|
| + /* Bind values to parameters that begin with $ or : */
|
| for(i=1; i<=nVar; i++){
|
| const char *zVar = sqlite3_bind_parameter_name(pStmt, i);
|
| if( zVar!=0 && (zVar[0]=='$' || zVar[0]==':' || zVar[0]=='@') ){
|
| @@ -1270,8 +1414,8 @@ static void dbReleaseStmt(
|
| assert( pDb->nStmt>0 );
|
| }
|
| pDb->nStmt++;
|
| -
|
| - /* If we have too many statement in cache, remove the surplus from
|
| +
|
| + /* If we have too many statement in cache, remove the surplus from
|
| ** the end of the cache list. */
|
| while( pDb->nStmt>pDb->maxStmt ){
|
| SqlPreparedStmt *pLast = pDb->stmtLast;
|
| @@ -1325,8 +1469,8 @@ static void dbReleaseColumnNames(DbEvalContext *p){
|
| ** If pArray is not NULL, then it contains the name of a Tcl array
|
| ** variable. The "*" member of this array is set to a list containing
|
| ** the names of the columns returned by the statement as part of each
|
| -** call to dbEvalStep(), in order from left to right. e.g. if the names
|
| -** of the returned columns are a, b and c, it does the equivalent of the
|
| +** call to dbEvalStep(), in order from left to right. e.g. if the names
|
| +** of the returned columns are a, b and c, it does the equivalent of the
|
| ** tcl command:
|
| **
|
| ** set ${pArray}(*) {a b c}
|
| @@ -1447,7 +1591,7 @@ static int dbEvalStep(DbEvalContext *p){
|
| #if SQLITE_TEST
|
| if( p->pDb->bLegacyPrepare && rcs==SQLITE_SCHEMA && zPrevSql ){
|
| /* If the runtime error was an SQLITE_SCHEMA, and the database
|
| - ** handle is configured to use the legacy sqlite3_prepare()
|
| + ** handle is configured to use the legacy sqlite3_prepare()
|
| ** interface, retry prepare()/step() on the same SQL statement.
|
| ** This only happens once. If there is a second SQLITE_SCHEMA
|
| ** error, the error will be returned to the caller. */
|
| @@ -1535,11 +1679,11 @@ static int DbUseNre(void){
|
| return( (major==8 && minor>=6) || major>8 );
|
| }
|
| #else
|
| -/*
|
| +/*
|
| ** Compiling using headers earlier than 8.6. In this case NR cannot be
|
| ** used, so DbUseNre() to always return zero. Add #defines for the other
|
| ** Tcl_NRxxx() functions to prevent them from causing compilation errors,
|
| -** even though the only invocations of them are within conditional blocks
|
| +** even though the only invocations of them are within conditional blocks
|
| ** of the form:
|
| **
|
| ** if( DbUseNre() ) { ... }
|
| @@ -1556,7 +1700,7 @@ static int DbUseNre(void){
|
| **
|
| ** $db eval SQL ?ARRAYNAME? SCRIPT
|
| */
|
| -static int DbEvalNextCmd(
|
| +static int SQLITE_TCLAPI DbEvalNextCmd(
|
| ClientData data[], /* data[0] is the (DbEvalContext*) */
|
| Tcl_Interp *interp, /* Tcl interpreter */
|
| int result /* Result so far */
|
| @@ -1585,11 +1729,11 @@ static int DbEvalNextCmd(
|
| }
|
| }
|
|
|
| - /* The required interpreter variables are now populated with the data
|
| + /* The required interpreter variables are now populated with the data
|
| ** from the current row. If using NRE, schedule callbacks to evaluate
|
| ** script pScript, then to invoke this function again to fetch the next
|
| ** row (or clean up if there is no next row or the script throws an
|
| - ** exception). After scheduling the callbacks, return control to the
|
| + ** exception). After scheduling the callbacks, return control to the
|
| ** caller.
|
| **
|
| ** If not using NRE, evaluate pScript directly and continue with the
|
| @@ -1614,6 +1758,46 @@ static int DbEvalNextCmd(
|
| }
|
|
|
| /*
|
| +** This function is used by the implementations of the following database
|
| +** handle sub-commands:
|
| +**
|
| +** $db update_hook ?SCRIPT?
|
| +** $db wal_hook ?SCRIPT?
|
| +** $db commit_hook ?SCRIPT?
|
| +** $db preupdate hook ?SCRIPT?
|
| +*/
|
| +static void DbHookCmd(
|
| + Tcl_Interp *interp, /* Tcl interpreter */
|
| + SqliteDb *pDb, /* Database handle */
|
| + Tcl_Obj *pArg, /* SCRIPT argument (or NULL) */
|
| + Tcl_Obj **ppHook /* Pointer to member of SqliteDb */
|
| +){
|
| + sqlite3 *db = pDb->db;
|
| +
|
| + if( *ppHook ){
|
| + Tcl_SetObjResult(interp, *ppHook);
|
| + if( pArg ){
|
| + Tcl_DecrRefCount(*ppHook);
|
| + *ppHook = 0;
|
| + }
|
| + }
|
| + if( pArg ){
|
| + assert( !(*ppHook) );
|
| + if( Tcl_GetCharLength(pArg)>0 ){
|
| + *ppHook = pArg;
|
| + Tcl_IncrRefCount(*ppHook);
|
| + }
|
| + }
|
| +
|
| +#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
|
| + sqlite3_preupdate_hook(db, (pDb->pPreUpdateHook?DbPreUpdateHandler:0), pDb);
|
| +#endif
|
| + sqlite3_update_hook(db, (pDb->pUpdateHook?DbUpdateHandler:0), pDb);
|
| + sqlite3_rollback_hook(db, (pDb->pRollbackHook?DbRollbackHandler:0), pDb);
|
| + sqlite3_wal_hook(db, (pDb->pWalHook?DbWalHandler:0), pDb);
|
| +}
|
| +
|
| +/*
|
| ** The "sqlite" command below creates a new Tcl command for each
|
| ** connection it opens to an SQLite database. This routine is invoked
|
| ** whenever one of those connection-specific commands is executed
|
| @@ -1626,7 +1810,12 @@ static int DbEvalNextCmd(
|
| ** and calls that connection "db1". The second command causes this
|
| ** subroutine to be invoked.
|
| */
|
| -static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
| +static int SQLITE_TCLAPI DbObjCmd(
|
| + void *cd,
|
| + Tcl_Interp *interp,
|
| + int objc,
|
| + Tcl_Obj *const*objv
|
| +){
|
| SqliteDb *pDb = (SqliteDb*)cd;
|
| int choice;
|
| int rc = TCL_OK;
|
| @@ -1638,11 +1827,13 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
| "errorcode", "eval", "exists",
|
| "function", "incrblob", "interrupt",
|
| "last_insert_rowid", "nullvalue", "onecolumn",
|
| - "profile", "progress", "rekey",
|
| - "restore", "rollback_hook", "status",
|
| - "timeout", "total_changes", "trace",
|
| - "transaction", "unlock_notify", "update_hook",
|
| - "version", "wal_hook", 0
|
| + "preupdate", "profile", "progress",
|
| + "rekey", "restore", "rollback_hook",
|
| + "status", "timeout", "total_changes",
|
| + "trace", "trace_v2", "transaction",
|
| + "unlock_notify", "update_hook", "version",
|
| + "wal_hook",
|
| + 0
|
| };
|
| enum DB_enum {
|
| DB_AUTHORIZER, DB_BACKUP, DB_BUSY,
|
| @@ -1652,11 +1843,12 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
| DB_ERRORCODE, DB_EVAL, DB_EXISTS,
|
| DB_FUNCTION, DB_INCRBLOB, DB_INTERRUPT,
|
| DB_LAST_INSERT_ROWID, DB_NULLVALUE, DB_ONECOLUMN,
|
| - DB_PROFILE, DB_PROGRESS, DB_REKEY,
|
| - DB_RESTORE, DB_ROLLBACK_HOOK, DB_STATUS,
|
| - DB_TIMEOUT, DB_TOTAL_CHANGES, DB_TRACE,
|
| - DB_TRANSACTION, DB_UNLOCK_NOTIFY, DB_UPDATE_HOOK,
|
| - DB_VERSION, DB_WAL_HOOK
|
| + DB_PREUPDATE, DB_PROFILE, DB_PROGRESS,
|
| + DB_REKEY, DB_RESTORE, DB_ROLLBACK_HOOK,
|
| + DB_STATUS, DB_TIMEOUT, DB_TOTAL_CHANGES,
|
| + DB_TRACE, DB_TRACE_V2, DB_TRANSACTION,
|
| + DB_UNLOCK_NOTIFY, DB_UPDATE_HOOK, DB_VERSION,
|
| + DB_WAL_HOOK,
|
| };
|
| /* don't leave trailing commas on DB_enum, it confuses the AIX xlc compiler */
|
|
|
| @@ -1750,7 +1942,8 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
| Tcl_WrongNumArgs(interp, 2, objv, "?DATABASE? FILENAME");
|
| return TCL_ERROR;
|
| }
|
| - rc = sqlite3_open(zDestFile, &pDest);
|
| + rc = sqlite3_open_v2(zDestFile, &pDest,
|
| + SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE| pDb->openFlags, 0);
|
| if( rc!=SQLITE_OK ){
|
| Tcl_AppendResult(interp, "cannot open target database: ",
|
| sqlite3_errmsg(pDest), (char*)0);
|
| @@ -1841,7 +2034,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
| return TCL_ERROR;
|
| }else{
|
| if( TCL_ERROR==Tcl_GetIntFromObj(interp, objv[3], &n) ){
|
| - Tcl_AppendResult( interp, "cannot convert \"",
|
| + Tcl_AppendResult( interp, "cannot convert \"",
|
| Tcl_GetStringFromObj(objv[3],0), "\" to integer", (char*)0);
|
| return TCL_ERROR;
|
| }else{
|
| @@ -1855,7 +2048,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
| }
|
| }
|
| }else{
|
| - Tcl_AppendResult( interp, "bad option \"",
|
| + Tcl_AppendResult( interp, "bad option \"",
|
| Tcl_GetStringFromObj(objv[2],0), "\": must be flush or size",
|
| (char*)0);
|
| return TCL_ERROR;
|
| @@ -1866,7 +2059,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
| /* $db changes
|
| **
|
| ** Return the number of rows that were modified, inserted, or deleted by
|
| - ** the most recent INSERT, UPDATE or DELETE statement, not including
|
| + ** the most recent INSERT, UPDATE or DELETE statement, not including
|
| ** any changes made by trigger programs.
|
| */
|
| case DB_CHANGES: {
|
| @@ -1913,7 +2106,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
| pCollate->zScript = (char*)&pCollate[1];
|
| pDb->pCollate = pCollate;
|
| memcpy(pCollate->zScript, zScript, nScript+1);
|
| - if( sqlite3_create_collation(pDb->db, zName, SQLITE_UTF8,
|
| + if( sqlite3_create_collation(pDb->db, zName, SQLITE_UTF8,
|
| pCollate, tclSqlCollate) ){
|
| Tcl_SetResult(interp, (char *)sqlite3_errmsg(pDb->db), TCL_VOLATILE);
|
| return TCL_ERROR;
|
| @@ -2039,7 +2232,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
| const char *zSep;
|
| const char *zNull;
|
| if( objc<5 || objc>7 ){
|
| - Tcl_WrongNumArgs(interp, 2, objv,
|
| + Tcl_WrongNumArgs(interp, 2, objv,
|
| "CONFLICT-ALGORITHM TABLE FILENAME ?SEPARATOR? ?NULLINDICATOR?");
|
| return TCL_ERROR;
|
| }
|
| @@ -2068,7 +2261,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
| strcmp(zConflict, "fail" ) != 0 &&
|
| strcmp(zConflict, "ignore" ) != 0 &&
|
| strcmp(zConflict, "replace" ) != 0 ) {
|
| - Tcl_AppendResult(interp, "Error: \"", zConflict,
|
| + Tcl_AppendResult(interp, "Error: \"", zConflict,
|
| "\", conflict-algorithm must be one of: rollback, "
|
| "abort, fail, ignore, or replace", (char*)0);
|
| return TCL_ERROR;
|
| @@ -2114,7 +2307,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
| }
|
| in = fopen(zFile, "rb");
|
| if( in==0 ){
|
| - Tcl_AppendResult(interp, "Error: cannot open file: ", zFile, NULL);
|
| + Tcl_AppendResult(interp, "Error: cannot open file: ", zFile, (char*)0);
|
| sqlite3_finalize(pStmt);
|
| return TCL_ERROR;
|
| }
|
| @@ -2157,7 +2350,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
| for(i=0; i<nCol; i++){
|
| /* check for null data, if so, bind as null */
|
| if( (nNull>0 && strcmp(azCol[i], zNull)==0)
|
| - || strlen30(azCol[i])==0
|
| + || strlen30(azCol[i])==0
|
| ){
|
| sqlite3_bind_null(pStmt, i+1);
|
| }else{
|
| @@ -2236,8 +2429,9 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
| ** The onecolumn method is the equivalent of:
|
| ** lindex [$db eval $sql] 0
|
| */
|
| - case DB_EXISTS:
|
| + case DB_EXISTS:
|
| case DB_ONECOLUMN: {
|
| + Tcl_Obj *pResult = 0;
|
| DbEvalContext sEval;
|
| if( objc!=3 ){
|
| Tcl_WrongNumArgs(interp, 2, objv, "SQL");
|
| @@ -2248,21 +2442,22 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
| rc = dbEvalStep(&sEval);
|
| if( choice==DB_ONECOLUMN ){
|
| if( rc==TCL_OK ){
|
| - Tcl_SetObjResult(interp, dbEvalColumnValue(&sEval, 0));
|
| + pResult = dbEvalColumnValue(&sEval, 0);
|
| }else if( rc==TCL_BREAK ){
|
| Tcl_ResetResult(interp);
|
| }
|
| }else if( rc==TCL_BREAK || rc==TCL_OK ){
|
| - Tcl_SetObjResult(interp, Tcl_NewBooleanObj(rc==TCL_OK));
|
| + pResult = Tcl_NewBooleanObj(rc==TCL_OK);
|
| }
|
| dbEvalFinalize(&sEval);
|
| + if( pResult ) Tcl_SetObjResult(interp, pResult);
|
|
|
| if( rc==TCL_BREAK ){
|
| rc = TCL_OK;
|
| }
|
| break;
|
| }
|
| -
|
| +
|
| /*
|
| ** $db eval $sql ?array? ?{ ...code... }?
|
| **
|
| @@ -2308,7 +2503,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
| }
|
| pScript = objv[objc-1];
|
| Tcl_IncrRefCount(pScript);
|
| -
|
| +
|
| p = (DbEvalContext *)Tcl_Alloc(sizeof(DbEvalContext));
|
| dbEvalInit(p, pDb, objv[2], pArray);
|
|
|
| @@ -2341,7 +2536,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
| int n = strlen30(z);
|
| if( n>2 && strncmp(z, "-argcount",n)==0 ){
|
| if( i==(objc-2) ){
|
| - Tcl_AppendResult(interp, "option requires an argument: ", z, 0);
|
| + Tcl_AppendResult(interp, "option requires an argument: ", z,(char*)0);
|
| return TCL_ERROR;
|
| }
|
| if( Tcl_GetIntFromObj(interp, objv[i+1], &nArg) ) return TCL_ERROR;
|
| @@ -2355,8 +2550,8 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
| if( n>2 && strncmp(z, "-deterministic",n)==0 ){
|
| flags |= SQLITE_DETERMINISTIC;
|
| }else{
|
| - Tcl_AppendResult(interp, "bad option \"", z,
|
| - "\": must be -argcount or -deterministic", 0
|
| + Tcl_AppendResult(interp, "bad option \"", z,
|
| + "\": must be -argcount or -deterministic", (char*)0
|
| );
|
| return TCL_ERROR;
|
| }
|
| @@ -2464,7 +2659,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
| }
|
|
|
| /*
|
| - ** $db last_insert_rowid
|
| + ** $db last_insert_rowid
|
| **
|
| ** Return an integer which is the ROWID for the most recent insert.
|
| */
|
| @@ -2486,7 +2681,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
| */
|
|
|
| /* $db progress ?N CALLBACK?
|
| - **
|
| + **
|
| ** Invoke the given callback every N virtual machine opcodes while executing
|
| ** queries.
|
| */
|
| @@ -2554,7 +2749,8 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
| }else{
|
| pDb->zProfile = 0;
|
| }
|
| -#if !defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_OMIT_FLOATING_POINT)
|
| +#if !defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_OMIT_FLOATING_POINT) && \
|
| + !defined(SQLITE_OMIT_DEPRECATED)
|
| if( pDb->zProfile ){
|
| pDb->interp = interp;
|
| sqlite3_profile(pDb->db, DbProfileHandler, pDb);
|
| @@ -2572,7 +2768,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
| ** Change the encryption key on the currently open database.
|
| */
|
| case DB_REKEY: {
|
| -#ifdef SQLITE_HAS_CODEC
|
| +#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_CODEC_FROM_TCL)
|
| int nKey;
|
| void *pKey;
|
| #endif
|
| @@ -2580,7 +2776,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
| Tcl_WrongNumArgs(interp, 2, objv, "KEY");
|
| return TCL_ERROR;
|
| }
|
| -#ifdef SQLITE_HAS_CODEC
|
| +#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_CODEC_FROM_TCL)
|
| pKey = Tcl_GetByteArrayFromObj(objv[2], &nKey);
|
| rc = sqlite3_rekey(pDb->db, pKey, nKey);
|
| if( rc ){
|
| @@ -2593,7 +2789,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
|
|
| /* $db restore ?DATABASE? FILENAME
|
| **
|
| - ** Open a database file named FILENAME. Transfer the content
|
| + ** Open a database file named FILENAME. Transfer the content
|
| ** of FILENAME into the local database DATABASE (default: "main").
|
| */
|
| case DB_RESTORE: {
|
| @@ -2613,7 +2809,8 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
| Tcl_WrongNumArgs(interp, 2, objv, "?DATABASE? FILENAME");
|
| return TCL_ERROR;
|
| }
|
| - rc = sqlite3_open_v2(zSrcFile, &pSrc, SQLITE_OPEN_READONLY, 0);
|
| + rc = sqlite3_open_v2(zSrcFile, &pSrc,
|
| + SQLITE_OPEN_READONLY | pDb->openFlags, 0);
|
| if( rc!=SQLITE_OK ){
|
| Tcl_AppendResult(interp, "cannot open source database: ",
|
| sqlite3_errmsg(pSrc), (char*)0);
|
| @@ -2653,7 +2850,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
| /*
|
| ** $db status (step|sort|autoindex)
|
| **
|
| - ** Display SQLITE_STMTSTATUS_FULLSCAN_STEP or
|
| + ** Display SQLITE_STMTSTATUS_FULLSCAN_STEP or
|
| ** SQLITE_STMTSTATUS_SORT for the most recent eval.
|
| */
|
| case DB_STATUS: {
|
| @@ -2671,15 +2868,15 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
| }else if( strcmp(zOp, "autoindex")==0 ){
|
| v = pDb->nIndex;
|
| }else{
|
| - Tcl_AppendResult(interp,
|
| - "bad argument: should be autoindex, step, or sort",
|
| + Tcl_AppendResult(interp,
|
| + "bad argument: should be autoindex, step, or sort",
|
| (char*)0);
|
| return TCL_ERROR;
|
| }
|
| Tcl_SetObjResult(interp, Tcl_NewIntObj(v));
|
| break;
|
| }
|
| -
|
| +
|
| /*
|
| ** $db timeout MILLESECONDS
|
| **
|
| @@ -2695,11 +2892,11 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
| sqlite3_busy_timeout(pDb->db, ms);
|
| break;
|
| }
|
| -
|
| +
|
| /*
|
| ** $db total_changes
|
| **
|
| - ** Return the number of rows that were modified, inserted, or deleted
|
| + ** Return the number of rows that were modified, inserted, or deleted
|
| ** since the database handle was created.
|
| */
|
| case DB_TOTAL_CHANGES: {
|
| @@ -2740,7 +2937,8 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
| }else{
|
| pDb->zTrace = 0;
|
| }
|
| -#if !defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_OMIT_FLOATING_POINT)
|
| +#if !defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_OMIT_FLOATING_POINT) && \
|
| + !defined(SQLITE_OMIT_DEPRECATED)
|
| if( pDb->zTrace ){
|
| pDb->interp = interp;
|
| sqlite3_trace(pDb->db, DbTraceHandler, pDb);
|
| @@ -2752,6 +2950,88 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
| break;
|
| }
|
|
|
| + /* $db trace_v2 ?CALLBACK? ?MASK?
|
| + **
|
| + ** Make arrangements to invoke the CALLBACK routine for each trace event
|
| + ** matching the mask that is generated. The parameters are appended to
|
| + ** CALLBACK before it is executed.
|
| + */
|
| + case DB_TRACE_V2: {
|
| + if( objc>4 ){
|
| + Tcl_WrongNumArgs(interp, 2, objv, "?CALLBACK? ?MASK?");
|
| + return TCL_ERROR;
|
| + }else if( objc==2 ){
|
| + if( pDb->zTraceV2 ){
|
| + Tcl_AppendResult(interp, pDb->zTraceV2, (char*)0);
|
| + }
|
| + }else{
|
| + char *zTraceV2;
|
| + int len;
|
| + Tcl_WideInt wMask = 0;
|
| + if( objc==4 ){
|
| + static const char *TTYPE_strs[] = {
|
| + "statement", "profile", "row", "close", 0
|
| + };
|
| + enum TTYPE_enum {
|
| + TTYPE_STMT, TTYPE_PROFILE, TTYPE_ROW, TTYPE_CLOSE
|
| + };
|
| + int i;
|
| + if( TCL_OK!=Tcl_ListObjLength(interp, objv[3], &len) ){
|
| + return TCL_ERROR;
|
| + }
|
| + for(i=0; i<len; i++){
|
| + Tcl_Obj *pObj;
|
| + int ttype;
|
| + if( TCL_OK!=Tcl_ListObjIndex(interp, objv[3], i, &pObj) ){
|
| + return TCL_ERROR;
|
| + }
|
| + if( Tcl_GetIndexFromObj(interp, pObj, TTYPE_strs, "trace type",
|
| + 0, &ttype)!=TCL_OK ){
|
| + Tcl_WideInt wType;
|
| + Tcl_Obj *pError = Tcl_DuplicateObj(Tcl_GetObjResult(interp));
|
| + Tcl_IncrRefCount(pError);
|
| + if( TCL_OK==Tcl_GetWideIntFromObj(interp, pObj, &wType) ){
|
| + Tcl_DecrRefCount(pError);
|
| + wMask |= wType;
|
| + }else{
|
| + Tcl_SetObjResult(interp, pError);
|
| + Tcl_DecrRefCount(pError);
|
| + return TCL_ERROR;
|
| + }
|
| + }else{
|
| + switch( (enum TTYPE_enum)ttype ){
|
| + case TTYPE_STMT: wMask |= SQLITE_TRACE_STMT; break;
|
| + case TTYPE_PROFILE: wMask |= SQLITE_TRACE_PROFILE; break;
|
| + case TTYPE_ROW: wMask |= SQLITE_TRACE_ROW; break;
|
| + case TTYPE_CLOSE: wMask |= SQLITE_TRACE_CLOSE; break;
|
| + }
|
| + }
|
| + }
|
| + }else{
|
| + wMask = SQLITE_TRACE_STMT; /* use the "legacy" default */
|
| + }
|
| + if( pDb->zTraceV2 ){
|
| + Tcl_Free(pDb->zTraceV2);
|
| + }
|
| + zTraceV2 = Tcl_GetStringFromObj(objv[2], &len);
|
| + if( zTraceV2 && len>0 ){
|
| + pDb->zTraceV2 = Tcl_Alloc( len + 1 );
|
| + memcpy(pDb->zTraceV2, zTraceV2, len+1);
|
| + }else{
|
| + pDb->zTraceV2 = 0;
|
| + }
|
| +#if !defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_OMIT_FLOATING_POINT)
|
| + if( pDb->zTraceV2 ){
|
| + pDb->interp = interp;
|
| + sqlite3_trace_v2(pDb->db, (unsigned)wMask, DbTraceV2Handler, pDb);
|
| + }else{
|
| + sqlite3_trace_v2(pDb->db, 0, 0, 0);
|
| + }
|
| +#endif
|
| + }
|
| + break;
|
| + }
|
| +
|
| /* $db transaction [-deferred|-immediate|-exclusive] SCRIPT
|
| **
|
| ** Start a new transaction (if we are not already in the midst of a
|
| @@ -2804,7 +3084,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
| /* If using NRE, schedule a callback to invoke the script pScript, then
|
| ** a second callback to commit (or rollback) the transaction or savepoint
|
| ** opened above. If not using NRE, evaluate the script directly, then
|
| - ** call function DbTransPostCmd() to commit (or rollback) the transaction
|
| + ** call function DbTransPostCmd() to commit (or rollback) the transaction
|
| ** or savepoint. */
|
| if( DbUseNre() ){
|
| Tcl_NRAddCallback(interp, DbTransPostCmd, cd, 0, 0, 0);
|
| @@ -2835,14 +3115,14 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
| Tcl_DecrRefCount(pDb->pUnlockNotify);
|
| pDb->pUnlockNotify = 0;
|
| }
|
| -
|
| +
|
| if( objc==3 ){
|
| xNotify = DbUnlockNotify;
|
| pNotifyArg = (void *)pDb;
|
| pDb->pUnlockNotify = objv[2];
|
| Tcl_IncrRefCount(pDb->pUnlockNotify);
|
| }
|
| -
|
| +
|
| if( sqlite3_unlock_notify(pDb->db, xNotify, pNotifyArg) ){
|
| Tcl_AppendResult(interp, sqlite3_errmsg(pDb->db), (char*)0);
|
| rc = TCL_ERROR;
|
| @@ -2853,49 +3133,111 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
| }
|
|
|
| /*
|
| + ** $db preupdate_hook count
|
| + ** $db preupdate_hook hook ?SCRIPT?
|
| + ** $db preupdate_hook new INDEX
|
| + ** $db preupdate_hook old INDEX
|
| + */
|
| + case DB_PREUPDATE: {
|
| +#ifndef SQLITE_ENABLE_PREUPDATE_HOOK
|
| + Tcl_AppendResult(interp, "preupdate_hook was omitted at compile-time",
|
| + (char*)0);
|
| + rc = TCL_ERROR;
|
| +#else
|
| + static const char *azSub[] = {"count", "depth", "hook", "new", "old", 0};
|
| + enum DbPreupdateSubCmd {
|
| + PRE_COUNT, PRE_DEPTH, PRE_HOOK, PRE_NEW, PRE_OLD
|
| + };
|
| + int iSub;
|
| +
|
| + if( objc<3 ){
|
| + Tcl_WrongNumArgs(interp, 2, objv, "SUB-COMMAND ?ARGS?");
|
| + }
|
| + if( Tcl_GetIndexFromObj(interp, objv[2], azSub, "sub-command", 0, &iSub) ){
|
| + return TCL_ERROR;
|
| + }
|
| +
|
| + switch( (enum DbPreupdateSubCmd)iSub ){
|
| + case PRE_COUNT: {
|
| + int nCol = sqlite3_preupdate_count(pDb->db);
|
| + Tcl_SetObjResult(interp, Tcl_NewIntObj(nCol));
|
| + break;
|
| + }
|
| +
|
| + case PRE_HOOK: {
|
| + if( objc>4 ){
|
| + Tcl_WrongNumArgs(interp, 2, objv, "hook ?SCRIPT?");
|
| + return TCL_ERROR;
|
| + }
|
| + DbHookCmd(interp, pDb, (objc==4 ? objv[3] : 0), &pDb->pPreUpdateHook);
|
| + break;
|
| + }
|
| +
|
| + case PRE_DEPTH: {
|
| + Tcl_Obj *pRet;
|
| + if( objc!=3 ){
|
| + Tcl_WrongNumArgs(interp, 3, objv, "");
|
| + return TCL_ERROR;
|
| + }
|
| + pRet = Tcl_NewIntObj(sqlite3_preupdate_depth(pDb->db));
|
| + Tcl_SetObjResult(interp, pRet);
|
| + break;
|
| + }
|
| +
|
| + case PRE_NEW:
|
| + case PRE_OLD: {
|
| + int iIdx;
|
| + sqlite3_value *pValue;
|
| + if( objc!=4 ){
|
| + Tcl_WrongNumArgs(interp, 3, objv, "INDEX");
|
| + return TCL_ERROR;
|
| + }
|
| + if( Tcl_GetIntFromObj(interp, objv[3], &iIdx) ){
|
| + return TCL_ERROR;
|
| + }
|
| +
|
| + if( iSub==PRE_OLD ){
|
| + rc = sqlite3_preupdate_old(pDb->db, iIdx, &pValue);
|
| + }else{
|
| + assert( iSub==PRE_NEW );
|
| + rc = sqlite3_preupdate_new(pDb->db, iIdx, &pValue);
|
| + }
|
| +
|
| + if( rc==SQLITE_OK ){
|
| + Tcl_Obj *pObj;
|
| + pObj = Tcl_NewStringObj((char*)sqlite3_value_text(pValue), -1);
|
| + Tcl_SetObjResult(interp, pObj);
|
| + }else{
|
| + Tcl_AppendResult(interp, sqlite3_errmsg(pDb->db), (char*)0);
|
| + return TCL_ERROR;
|
| + }
|
| + }
|
| + }
|
| +#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */
|
| + break;
|
| + }
|
| +
|
| + /*
|
| ** $db wal_hook ?script?
|
| ** $db update_hook ?script?
|
| ** $db rollback_hook ?script?
|
| */
|
| - case DB_WAL_HOOK:
|
| - case DB_UPDATE_HOOK:
|
| + case DB_WAL_HOOK:
|
| + case DB_UPDATE_HOOK:
|
| case DB_ROLLBACK_HOOK: {
|
| -
|
| - /* set ppHook to point at pUpdateHook or pRollbackHook, depending on
|
| + /* set ppHook to point at pUpdateHook or pRollbackHook, depending on
|
| ** whether [$db update_hook] or [$db rollback_hook] was invoked.
|
| */
|
| - Tcl_Obj **ppHook;
|
| - if( choice==DB_UPDATE_HOOK ){
|
| - ppHook = &pDb->pUpdateHook;
|
| - }else if( choice==DB_WAL_HOOK ){
|
| - ppHook = &pDb->pWalHook;
|
| - }else{
|
| - ppHook = &pDb->pRollbackHook;
|
| - }
|
| -
|
| - if( objc!=2 && objc!=3 ){
|
| + Tcl_Obj **ppHook = 0;
|
| + if( choice==DB_WAL_HOOK ) ppHook = &pDb->pWalHook;
|
| + if( choice==DB_UPDATE_HOOK ) ppHook = &pDb->pUpdateHook;
|
| + if( choice==DB_ROLLBACK_HOOK ) ppHook = &pDb->pRollbackHook;
|
| + if( objc>3 ){
|
| Tcl_WrongNumArgs(interp, 2, objv, "?SCRIPT?");
|
| return TCL_ERROR;
|
| }
|
| - if( *ppHook ){
|
| - Tcl_SetObjResult(interp, *ppHook);
|
| - if( objc==3 ){
|
| - Tcl_DecrRefCount(*ppHook);
|
| - *ppHook = 0;
|
| - }
|
| - }
|
| - if( objc==3 ){
|
| - assert( !(*ppHook) );
|
| - if( Tcl_GetCharLength(objv[2])>0 ){
|
| - *ppHook = objv[2];
|
| - Tcl_IncrRefCount(*ppHook);
|
| - }
|
| - }
|
| -
|
| - sqlite3_update_hook(pDb->db, (pDb->pUpdateHook?DbUpdateHandler:0), pDb);
|
| - sqlite3_rollback_hook(pDb->db,(pDb->pRollbackHook?DbRollbackHandler:0),pDb);
|
| - sqlite3_wal_hook(pDb->db,(pDb->pWalHook?DbWalHandler:0),pDb);
|
|
|
| + DbHookCmd(interp, pDb, (objc==3 ? objv[2] : 0), ppHook);
|
| break;
|
| }
|
|
|
| @@ -2918,7 +3260,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
| ** Adaptor that provides an objCmd interface to the NRE-enabled
|
| ** interface implementation.
|
| */
|
| -static int DbObjCmdAdaptor(
|
| +static int SQLITE_TCLAPI DbObjCmdAdaptor(
|
| void *cd,
|
| Tcl_Interp *interp,
|
| int objc,
|
| @@ -2943,7 +3285,12 @@ static int DbObjCmdAdaptor(
|
| ** The second argument is the name of the database file.
|
| **
|
| */
|
| -static int DbMain(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
| +static int SQLITE_TCLAPI DbMain(
|
| + void *cd,
|
| + Tcl_Interp *interp,
|
| + int objc,
|
| + Tcl_Obj *const*objv
|
| +){
|
| SqliteDb *p;
|
| const char *zArg;
|
| char *zErrMsg;
|
| @@ -2952,7 +3299,7 @@ static int DbMain(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
| const char *zVfs = 0;
|
| int flags;
|
| Tcl_DString translatedFilename;
|
| -#ifdef SQLITE_HAS_CODEC
|
| +#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_CODEC_FROM_TCL)
|
| void *pKey = 0;
|
| int nKey = 0;
|
| #endif
|
| @@ -2976,8 +3323,12 @@ static int DbMain(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
| Tcl_AppendResult(interp,sqlite3_libversion(), (char*)0);
|
| return TCL_OK;
|
| }
|
| + if( strcmp(zArg,"-sourceid")==0 ){
|
| + Tcl_AppendResult(interp,sqlite3_sourceid(), (char*)0);
|
| + return TCL_OK;
|
| + }
|
| if( strcmp(zArg,"-has-codec")==0 ){
|
| -#ifdef SQLITE_HAS_CODEC
|
| +#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_CODEC_FROM_TCL)
|
| Tcl_AppendResult(interp,"1",(char*)0);
|
| #else
|
| Tcl_AppendResult(interp,"0",(char*)0);
|
| @@ -2988,7 +3339,7 @@ static int DbMain(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
| for(i=3; i+1<objc; i+=2){
|
| zArg = Tcl_GetString(objv[i]);
|
| if( strcmp(zArg,"-key")==0 ){
|
| -#ifdef SQLITE_HAS_CODEC
|
| +#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_CODEC_FROM_TCL)
|
| pKey = Tcl_GetByteArrayFromObj(objv[i+1], &nKey);
|
| #endif
|
| }else if( strcmp(zArg, "-vfs")==0 ){
|
| @@ -3043,10 +3394,10 @@ static int DbMain(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
| }
|
| }
|
| if( objc<3 || (objc&1)!=1 ){
|
| - Tcl_WrongNumArgs(interp, 1, objv,
|
| + Tcl_WrongNumArgs(interp, 1, objv,
|
| "HANDLE FILENAME ?-vfs VFSNAME? ?-readonly BOOLEAN? ?-create BOOLEAN?"
|
| " ?-nomutex BOOLEAN? ?-fullmutex BOOLEAN? ?-uri BOOLEAN?"
|
| -#ifdef SQLITE_HAS_CODEC
|
| +#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_CODEC_FROM_TCL)
|
| " ?-key CODECKEY?"
|
| #endif
|
| );
|
| @@ -3072,7 +3423,7 @@ static int DbMain(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
| }else{
|
| zErrMsg = sqlite3_mprintf("%s", sqlite3_errstr(rc));
|
| }
|
| -#ifdef SQLITE_HAS_CODEC
|
| +#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_CODEC_FROM_TCL)
|
| if( p->db ){
|
| sqlite3_key(p->db, pKey, nKey);
|
| }
|
| @@ -3084,6 +3435,7 @@ static int DbMain(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
| return TCL_ERROR;
|
| }
|
| p->maxStmt = NUM_PREPARED_STMTS;
|
| + p->openFlags = flags & SQLITE_OPEN_URI;
|
| p->interp = interp;
|
| zArg = Tcl_GetStringFromObj(objv[1], 0);
|
| if( DbUseNre() ){
|
| @@ -3143,9 +3495,13 @@ EXTERN int Sqlite3_Unload(Tcl_Interp *interp, int flags){ return TCL_OK; }
|
| EXTERN int Tclsqlite3_Unload(Tcl_Interp *interp, int flags){ return TCL_OK; }
|
|
|
| /* Because it accesses the file-system and uses persistent state, SQLite
|
| -** is not considered appropriate for safe interpreters. Hence, we deliberately
|
| -** omit the _SafeInit() interfaces.
|
| +** is not considered appropriate for safe interpreters. Hence, we cause
|
| +** the _SafeInit() interfaces return TCL_ERROR.
|
| */
|
| +EXTERN int Sqlite3_SafeInit(Tcl_Interp *interp){ return TCL_ERROR; }
|
| +EXTERN int Sqlite3_SafeUnload(Tcl_Interp *interp, int flags){return TCL_ERROR;}
|
| +
|
| +
|
|
|
| #ifndef SQLITE_3_SUFFIX_ONLY
|
| int Sqlite_Init(Tcl_Interp *interp){ return Sqlite3_Init(interp); }
|
| @@ -3330,7 +3686,7 @@ static void MD5Init(MD5Context *ctx){
|
| * Update context to reflect the concatenation of another buffer full
|
| * of bytes.
|
| */
|
| -static
|
| +static
|
| void MD5Update(MD5Context *ctx, const unsigned char *buf, unsigned int len){
|
| uint32 t;
|
|
|
| @@ -3376,7 +3732,7 @@ void MD5Update(MD5Context *ctx, const unsigned char *buf, unsigned int len){
|
| }
|
|
|
| /*
|
| - * Final wrapup - pad to 64-byte boundary with the bit pattern
|
| + * Final wrapup - pad to 64-byte boundary with the bit pattern
|
| * 1 0* (64-bit count of bits processed, MSB-first)
|
| */
|
| static void MD5Final(unsigned char digest[16], MD5Context *ctx){
|
| @@ -3452,16 +3808,21 @@ static void MD5DigestToBase10x8(unsigned char digest[16], char zDigest[50]){
|
|
|
| /*
|
| ** A TCL command for md5. The argument is the text to be hashed. The
|
| -** Result is the hash in base64.
|
| +** Result is the hash in base64.
|
| */
|
| -static int md5_cmd(void*cd, Tcl_Interp *interp, int argc, const char **argv){
|
| +static int SQLITE_TCLAPI md5_cmd(
|
| + void*cd,
|
| + Tcl_Interp *interp,
|
| + int argc,
|
| + const char **argv
|
| +){
|
| MD5Context ctx;
|
| unsigned char digest[16];
|
| char zBuf[50];
|
| void (*converter)(unsigned char*, char*);
|
|
|
| if( argc!=2 ){
|
| - Tcl_AppendResult(interp,"wrong # args: should be \"", argv[0],
|
| + Tcl_AppendResult(interp,"wrong # args: should be \"", argv[0],
|
| " TEXT\"", (char*)0);
|
| return TCL_ERROR;
|
| }
|
| @@ -3478,7 +3839,12 @@ static int md5_cmd(void*cd, Tcl_Interp *interp, int argc, const char **argv){
|
| ** A TCL command to take the md5 hash of a file. The argument is the
|
| ** name of the file.
|
| */
|
| -static int md5file_cmd(void*cd, Tcl_Interp*interp, int argc, const char **argv){
|
| +static int SQLITE_TCLAPI md5file_cmd(
|
| + void*cd,
|
| + Tcl_Interp *interp,
|
| + int argc,
|
| + const char **argv
|
| +){
|
| FILE *in;
|
| MD5Context ctx;
|
| void (*converter)(unsigned char*, char*);
|
| @@ -3486,13 +3852,13 @@ static int md5file_cmd(void*cd, Tcl_Interp*interp, int argc, const char **argv){
|
| char zBuf[10240];
|
|
|
| if( argc!=2 ){
|
| - Tcl_AppendResult(interp,"wrong # args: should be \"", argv[0],
|
| + Tcl_AppendResult(interp,"wrong # args: should be \"", argv[0],
|
| " FILENAME\"", (char*)0);
|
| return TCL_ERROR;
|
| }
|
| in = fopen(argv[1],"rb");
|
| if( in==0 ){
|
| - Tcl_AppendResult(interp,"unable to open file \"", argv[1],
|
| + Tcl_AppendResult(interp,"unable to open file \"", argv[1],
|
| "\" for reading", (char*)0);
|
| return TCL_ERROR;
|
| }
|
| @@ -3558,8 +3924,12 @@ static void md5finalize(sqlite3_context *context){
|
| MD5DigestToBase16(digest, zBuf);
|
| sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
|
| }
|
| -int Md5_Register(sqlite3 *db){
|
| - int rc = sqlite3_create_function(db, "md5sum", -1, SQLITE_UTF8, 0, 0,
|
| +int Md5_Register(
|
| + sqlite3 *db,
|
| + char **pzErrMsg,
|
| + const sqlite3_api_routines *pThunk
|
| +){
|
| + int rc = sqlite3_create_function(db, "md5sum", -1, SQLITE_UTF8, 0, 0,
|
| md5step, md5finalize);
|
| sqlite3_overload_function(db, "md5sum", -1); /* To exercise this API */
|
| return rc;
|
| @@ -3606,7 +3976,7 @@ static const char *tclsh_main_loop(void);
|
|
|
| #ifdef SQLITE_TEST
|
| static void init_all(Tcl_Interp *);
|
| -static int init_all_cmd(
|
| +static int SQLITE_TCLAPI init_all_cmd(
|
| ClientData cd,
|
| Tcl_Interp *interp,
|
| int objc,
|
| @@ -3636,7 +4006,7 @@ static int init_all_cmd(
|
| ** to use the sqlite3_prepare_v2() function to prepare statements. If it
|
| ** is false, sqlite3_prepare().
|
| */
|
| -static int db_use_legacy_prepare_cmd(
|
| +static int SQLITE_TCLAPI db_use_legacy_prepare_cmd(
|
| ClientData cd,
|
| Tcl_Interp *interp,
|
| int objc,
|
| @@ -3673,7 +4043,7 @@ static int db_use_legacy_prepare_cmd(
|
| ** return the text representation of the most recently used statement
|
| ** handle.
|
| */
|
| -static int db_last_stmt_ptr(
|
| +static int SQLITE_TCLAPI db_last_stmt_ptr(
|
| ClientData cd,
|
| Tcl_Interp *interp,
|
| int objc,
|
| @@ -3710,7 +4080,7 @@ static int db_last_stmt_ptr(
|
| ** Configure the interpreter passed as the first argument to have access
|
| ** to the commands and linked variables that make up:
|
| **
|
| -** * the [sqlite3] extension itself,
|
| +** * the [sqlite3] extension itself,
|
| **
|
| ** * If SQLITE_TCLMD5 or SQLITE_TEST is defined, the Md5 commands, and
|
| **
|
| @@ -3760,8 +4130,12 @@ static void init_all(Tcl_Interp *interp){
|
| extern int Sqlitemultiplex_Init(Tcl_Interp*);
|
| extern int SqliteSuperlock_Init(Tcl_Interp*);
|
| extern int SqlitetestSyscall_Init(Tcl_Interp*);
|
| +#if defined(SQLITE_ENABLE_SESSION) && defined(SQLITE_ENABLE_PREUPDATE_HOOK)
|
| + extern int TestSession_Init(Tcl_Interp*);
|
| +#endif
|
| extern int Fts5tcl_Init(Tcl_Interp *);
|
| extern int SqliteRbu_Init(Tcl_Interp*);
|
| + extern int Sqlitetesttcl_Init(Tcl_Interp*);
|
| #if defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4)
|
| extern int Sqlitetestfts3_Init(Tcl_Interp *interp);
|
| #endif
|
| @@ -3794,7 +4168,7 @@ static void init_all(Tcl_Interp *interp){
|
| Sqlitetesttclvar_Init(interp);
|
| Sqlitetestfs_Init(interp);
|
| SqlitetestThread_Init(interp);
|
| - SqlitetestOnefile_Init(interp);
|
| + SqlitetestOnefile_Init();
|
| SqlitetestOsinst_Init(interp);
|
| Sqlitetestbackup_Init(interp);
|
| Sqlitetestintarray_Init(interp);
|
| @@ -3804,8 +4178,12 @@ static void init_all(Tcl_Interp *interp){
|
| Sqlitemultiplex_Init(interp);
|
| SqliteSuperlock_Init(interp);
|
| SqlitetestSyscall_Init(interp);
|
| +#if defined(SQLITE_ENABLE_SESSION) && defined(SQLITE_ENABLE_PREUPDATE_HOOK)
|
| + TestSession_Init(interp);
|
| +#endif
|
| Fts5tcl_Init(interp);
|
| SqliteRbu_Init(interp);
|
| + Sqlitetesttcl_Init(interp);
|
|
|
| #if defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4)
|
| Sqlitetestfts3_Init(interp);
|
| @@ -3834,7 +4212,7 @@ static void init_all(Tcl_Interp *interp){
|
| #endif
|
|
|
| #define TCLSH_MAIN main /* Needed to fake out mktclapp */
|
| -int TCLSH_MAIN(int argc, char **argv){
|
| +int SQLITE_CDECL TCLSH_MAIN(int argc, char **argv){
|
| Tcl_Interp *interp;
|
|
|
| #if !defined(_WIN32_WCE)
|
|
|