| OLD | NEW | 
 | (Empty) | 
|     1 /* |  | 
|     2 ** 2001 September 15 |  | 
|     3 ** |  | 
|     4 ** The author disclaims copyright to this source code.  In place of |  | 
|     5 ** 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 and |  | 
|    13 ** compile the whole thing to build a TCL-enabled version of SQLite. |  | 
|    14 */ |  | 
|    15 #include "tcl.h" |  | 
|    16 #include <errno.h> |  | 
|    17  |  | 
|    18 /* |  | 
|    19 ** Some additional include files are needed if this file is not |  | 
|    20 ** appended to the amalgamation. |  | 
|    21 */ |  | 
|    22 #ifndef SQLITE_AMALGAMATION |  | 
|    23 # include "sqliteInt.h" |  | 
|    24 # include <stdlib.h> |  | 
|    25 # include <string.h> |  | 
|    26 # include <assert.h> |  | 
|    27 # include <ctype.h> |  | 
|    28 #endif |  | 
|    29  |  | 
|    30 /* |  | 
|    31  * Windows needs to know which symbols to export.  Unix does not. |  | 
|    32  * BUILD_sqlite should be undefined for Unix. |  | 
|    33  */ |  | 
|    34 #ifdef BUILD_sqlite |  | 
|    35 #undef TCL_STORAGE_CLASS |  | 
|    36 #define TCL_STORAGE_CLASS DLLEXPORT |  | 
|    37 #endif /* BUILD_sqlite */ |  | 
|    38  |  | 
|    39 #define NUM_PREPARED_STMTS 10 |  | 
|    40 #define MAX_PREPARED_STMTS 100 |  | 
|    41  |  | 
|    42 /* |  | 
|    43 ** If TCL uses UTF-8 and SQLite is configured to use iso8859, then we |  | 
|    44 ** have to do a translation when going between the two.  Set the  |  | 
|    45 ** UTF_TRANSLATION_NEEDED macro to indicate that we need to do |  | 
|    46 ** this translation.   |  | 
|    47 */ |  | 
|    48 #if defined(TCL_UTF_MAX) && !defined(SQLITE_UTF8) |  | 
|    49 # define UTF_TRANSLATION_NEEDED 1 |  | 
|    50 #endif |  | 
|    51  |  | 
|    52 /* |  | 
|    53 ** New SQL functions can be created as TCL scripts.  Each such function |  | 
|    54 ** is described by an instance of the following structure. |  | 
|    55 */ |  | 
|    56 typedef struct SqlFunc SqlFunc; |  | 
|    57 struct SqlFunc { |  | 
|    58   Tcl_Interp *interp;   /* The TCL interpret to execute the function */ |  | 
|    59   Tcl_Obj *pScript;     /* The Tcl_Obj representation of the script */ |  | 
|    60   int useEvalObjv;      /* True if it is safe to use Tcl_EvalObjv */ |  | 
|    61   char *zName;          /* Name of this function */ |  | 
|    62   SqlFunc *pNext;       /* Next function on the list of them all */ |  | 
|    63 }; |  | 
|    64  |  | 
|    65 /* |  | 
|    66 ** New collation sequences function can be created as TCL scripts.  Each such |  | 
|    67 ** function is described by an instance of the following structure. |  | 
|    68 */ |  | 
|    69 typedef struct SqlCollate SqlCollate; |  | 
|    70 struct SqlCollate { |  | 
|    71   Tcl_Interp *interp;   /* The TCL interpret to execute the function */ |  | 
|    72   char *zScript;        /* The script to be run */ |  | 
|    73   SqlCollate *pNext;    /* Next function on the list of them all */ |  | 
|    74 }; |  | 
|    75  |  | 
|    76 /* |  | 
|    77 ** Prepared statements are cached for faster execution.  Each prepared |  | 
|    78 ** statement is described by an instance of the following structure. |  | 
|    79 */ |  | 
|    80 typedef struct SqlPreparedStmt SqlPreparedStmt; |  | 
|    81 struct SqlPreparedStmt { |  | 
|    82   SqlPreparedStmt *pNext;  /* Next in linked list */ |  | 
|    83   SqlPreparedStmt *pPrev;  /* Previous on the list */ |  | 
|    84   sqlite3_stmt *pStmt;     /* The prepared statement */ |  | 
|    85   int nSql;                /* chars in zSql[] */ |  | 
|    86   const char *zSql;        /* Text of the SQL statement */ |  | 
|    87 }; |  | 
|    88  |  | 
|    89 typedef struct IncrblobChannel IncrblobChannel; |  | 
|    90  |  | 
|    91 /* |  | 
|    92 ** There is one instance of this structure for each SQLite database |  | 
|    93 ** that has been opened by the SQLite TCL interface. |  | 
|    94 */ |  | 
|    95 typedef struct SqliteDb SqliteDb; |  | 
|    96 struct SqliteDb { |  | 
|    97   sqlite3 *db;               /* The "real" database structure. MUST BE FIRST */ |  | 
|    98   Tcl_Interp *interp;        /* The interpreter used for this database */ |  | 
|    99   char *zBusy;               /* The busy callback routine */ |  | 
|   100   char *zCommit;             /* The commit hook callback routine */ |  | 
|   101   char *zTrace;              /* The trace callback routine */ |  | 
|   102   char *zProfile;            /* The profile callback routine */ |  | 
|   103   char *zProgress;           /* The progress callback routine */ |  | 
|   104   char *zAuth;               /* The authorization callback routine */ |  | 
|   105   int disableAuth;           /* Disable the authorizer if it exists */ |  | 
|   106   char *zNull;               /* Text to substitute for an SQL NULL value */ |  | 
|   107   SqlFunc *pFunc;            /* List of SQL functions */ |  | 
|   108   Tcl_Obj *pUpdateHook;      /* Update hook script (if any) */ |  | 
|   109   Tcl_Obj *pRollbackHook;    /* Rollback hook script (if any) */ |  | 
|   110   Tcl_Obj *pUnlockNotify;    /* Unlock notify script (if any) */ |  | 
|   111   SqlCollate *pCollate;      /* List of SQL collation functions */ |  | 
|   112   int rc;                    /* Return code of most recent sqlite3_exec() */ |  | 
|   113   Tcl_Obj *pCollateNeeded;   /* Collation needed script */ |  | 
|   114   SqlPreparedStmt *stmtList; /* List of prepared statements*/ |  | 
|   115   SqlPreparedStmt *stmtLast; /* Last statement in the list */ |  | 
|   116   int maxStmt;               /* The next maximum number of stmtList */ |  | 
|   117   int nStmt;                 /* Number of statements in stmtList */ |  | 
|   118   IncrblobChannel *pIncrblob;/* Linked list of open incrblob channels */ |  | 
|   119   int nStep, nSort;          /* Statistics for most recent operation */ |  | 
|   120   int nTransaction;          /* Number of nested [transaction] methods */ |  | 
|   121 }; |  | 
|   122  |  | 
|   123 struct IncrblobChannel { |  | 
|   124   sqlite3_blob *pBlob;      /* sqlite3 blob handle */ |  | 
|   125   SqliteDb *pDb;            /* Associated database connection */ |  | 
|   126   int iSeek;                /* Current seek offset */ |  | 
|   127   Tcl_Channel channel;      /* Channel identifier */ |  | 
|   128   IncrblobChannel *pNext;   /* Linked list of all open incrblob channels */ |  | 
|   129   IncrblobChannel *pPrev;   /* Linked list of all open incrblob channels */ |  | 
|   130 }; |  | 
|   131  |  | 
|   132 /* |  | 
|   133 ** Compute a string length that is limited to what can be stored in |  | 
|   134 ** lower 30 bits of a 32-bit signed integer. |  | 
|   135 */ |  | 
|   136 static int strlen30(const char *z){ |  | 
|   137   const char *z2 = z; |  | 
|   138   while( *z2 ){ z2++; } |  | 
|   139   return 0x3fffffff & (int)(z2 - z); |  | 
|   140 } |  | 
|   141  |  | 
|   142  |  | 
|   143 #ifndef SQLITE_OMIT_INCRBLOB |  | 
|   144 /* |  | 
|   145 ** Close all incrblob channels opened using database connection pDb. |  | 
|   146 ** This is called when shutting down the database connection. |  | 
|   147 */ |  | 
|   148 static void closeIncrblobChannels(SqliteDb *pDb){ |  | 
|   149   IncrblobChannel *p; |  | 
|   150   IncrblobChannel *pNext; |  | 
|   151  |  | 
|   152   for(p=pDb->pIncrblob; p; p=pNext){ |  | 
|   153     pNext = p->pNext; |  | 
|   154  |  | 
|   155     /* Note: Calling unregister here call Tcl_Close on the incrblob channel,  |  | 
|   156     ** which deletes the IncrblobChannel structure at *p. So do not |  | 
|   157     ** call Tcl_Free() here. |  | 
|   158     */ |  | 
|   159     Tcl_UnregisterChannel(pDb->interp, p->channel); |  | 
|   160   } |  | 
|   161 } |  | 
|   162  |  | 
|   163 /* |  | 
|   164 ** Close an incremental blob channel. |  | 
|   165 */ |  | 
|   166 static int incrblobClose(ClientData instanceData, Tcl_Interp *interp){ |  | 
|   167   IncrblobChannel *p = (IncrblobChannel *)instanceData; |  | 
|   168   int rc = sqlite3_blob_close(p->pBlob); |  | 
|   169   sqlite3 *db = p->pDb->db; |  | 
|   170  |  | 
|   171   /* Remove the channel from the SqliteDb.pIncrblob list. */ |  | 
|   172   if( p->pNext ){ |  | 
|   173     p->pNext->pPrev = p->pPrev; |  | 
|   174   } |  | 
|   175   if( p->pPrev ){ |  | 
|   176     p->pPrev->pNext = p->pNext; |  | 
|   177   } |  | 
|   178   if( p->pDb->pIncrblob==p ){ |  | 
|   179     p->pDb->pIncrblob = p->pNext; |  | 
|   180   } |  | 
|   181  |  | 
|   182   /* Free the IncrblobChannel structure */ |  | 
|   183   Tcl_Free((char *)p); |  | 
|   184  |  | 
|   185   if( rc!=SQLITE_OK ){ |  | 
|   186     Tcl_SetResult(interp, (char *)sqlite3_errmsg(db), TCL_VOLATILE); |  | 
|   187     return TCL_ERROR; |  | 
|   188   } |  | 
|   189   return TCL_OK; |  | 
|   190 } |  | 
|   191  |  | 
|   192 /* |  | 
|   193 ** Read data from an incremental blob channel. |  | 
|   194 */ |  | 
|   195 static int incrblobInput( |  | 
|   196   ClientData instanceData,  |  | 
|   197   char *buf,  |  | 
|   198   int bufSize, |  | 
|   199   int *errorCodePtr |  | 
|   200 ){ |  | 
|   201   IncrblobChannel *p = (IncrblobChannel *)instanceData; |  | 
|   202   int nRead = bufSize;         /* Number of bytes to read */ |  | 
|   203   int nBlob;                   /* Total size of the blob */ |  | 
|   204   int rc;                      /* sqlite error code */ |  | 
|   205  |  | 
|   206   nBlob = sqlite3_blob_bytes(p->pBlob); |  | 
|   207   if( (p->iSeek+nRead)>nBlob ){ |  | 
|   208     nRead = nBlob-p->iSeek; |  | 
|   209   } |  | 
|   210   if( nRead<=0 ){ |  | 
|   211     return 0; |  | 
|   212   } |  | 
|   213  |  | 
|   214   rc = sqlite3_blob_read(p->pBlob, (void *)buf, nRead, p->iSeek); |  | 
|   215   if( rc!=SQLITE_OK ){ |  | 
|   216     *errorCodePtr = rc; |  | 
|   217     return -1; |  | 
|   218   } |  | 
|   219  |  | 
|   220   p->iSeek += nRead; |  | 
|   221   return nRead; |  | 
|   222 } |  | 
|   223  |  | 
|   224 /* |  | 
|   225 ** Write data to an incremental blob channel. |  | 
|   226 */ |  | 
|   227 static int incrblobOutput( |  | 
|   228   ClientData instanceData,  |  | 
|   229   CONST char *buf,  |  | 
|   230   int toWrite, |  | 
|   231   int *errorCodePtr |  | 
|   232 ){ |  | 
|   233   IncrblobChannel *p = (IncrblobChannel *)instanceData; |  | 
|   234   int nWrite = toWrite;        /* Number of bytes to write */ |  | 
|   235   int nBlob;                   /* Total size of the blob */ |  | 
|   236   int rc;                      /* sqlite error code */ |  | 
|   237  |  | 
|   238   nBlob = sqlite3_blob_bytes(p->pBlob); |  | 
|   239   if( (p->iSeek+nWrite)>nBlob ){ |  | 
|   240     *errorCodePtr = EINVAL; |  | 
|   241     return -1; |  | 
|   242   } |  | 
|   243   if( nWrite<=0 ){ |  | 
|   244     return 0; |  | 
|   245   } |  | 
|   246  |  | 
|   247   rc = sqlite3_blob_write(p->pBlob, (void *)buf, nWrite, p->iSeek); |  | 
|   248   if( rc!=SQLITE_OK ){ |  | 
|   249     *errorCodePtr = EIO; |  | 
|   250     return -1; |  | 
|   251   } |  | 
|   252  |  | 
|   253   p->iSeek += nWrite; |  | 
|   254   return nWrite; |  | 
|   255 } |  | 
|   256  |  | 
|   257 /* |  | 
|   258 ** Seek an incremental blob channel. |  | 
|   259 */ |  | 
|   260 static int incrblobSeek( |  | 
|   261   ClientData instanceData,  |  | 
|   262   long offset, |  | 
|   263   int seekMode, |  | 
|   264   int *errorCodePtr |  | 
|   265 ){ |  | 
|   266   IncrblobChannel *p = (IncrblobChannel *)instanceData; |  | 
|   267  |  | 
|   268   switch( seekMode ){ |  | 
|   269     case SEEK_SET: |  | 
|   270       p->iSeek = offset; |  | 
|   271       break; |  | 
|   272     case SEEK_CUR: |  | 
|   273       p->iSeek += offset; |  | 
|   274       break; |  | 
|   275     case SEEK_END: |  | 
|   276       p->iSeek = sqlite3_blob_bytes(p->pBlob) + offset; |  | 
|   277       break; |  | 
|   278  |  | 
|   279     default: assert(!"Bad seekMode"); |  | 
|   280   } |  | 
|   281  |  | 
|   282   return p->iSeek; |  | 
|   283 } |  | 
|   284  |  | 
|   285  |  | 
|   286 static void incrblobWatch(ClientData instanceData, int mode){  |  | 
|   287   /* NO-OP */  |  | 
|   288 } |  | 
|   289 static int incrblobHandle(ClientData instanceData, int dir, ClientData *hPtr){ |  | 
|   290   return TCL_ERROR; |  | 
|   291 } |  | 
|   292  |  | 
|   293 static Tcl_ChannelType IncrblobChannelType = { |  | 
|   294   "incrblob",                        /* typeName                             */ |  | 
|   295   TCL_CHANNEL_VERSION_2,             /* version                              */ |  | 
|   296   incrblobClose,                     /* closeProc                            */ |  | 
|   297   incrblobInput,                     /* inputProc                            */ |  | 
|   298   incrblobOutput,                    /* outputProc                           */ |  | 
|   299   incrblobSeek,                      /* seekProc                             */ |  | 
|   300   0,                                 /* setOptionProc                        */ |  | 
|   301   0,                                 /* getOptionProc                        */ |  | 
|   302   incrblobWatch,                     /* watchProc (this is a no-op)          */ |  | 
|   303   incrblobHandle,                    /* getHandleProc (always returns error) */ |  | 
|   304   0,                                 /* close2Proc                           */ |  | 
|   305   0,                                 /* blockModeProc                        */ |  | 
|   306   0,                                 /* flushProc                            */ |  | 
|   307   0,                                 /* handlerProc                          */ |  | 
|   308   0,                                 /* wideSeekProc                         */ |  | 
|   309 }; |  | 
|   310  |  | 
|   311 /* |  | 
|   312 ** Create a new incrblob channel. |  | 
|   313 */ |  | 
|   314 static int createIncrblobChannel( |  | 
|   315   Tcl_Interp *interp,  |  | 
|   316   SqliteDb *pDb,  |  | 
|   317   const char *zDb, |  | 
|   318   const char *zTable,  |  | 
|   319   const char *zColumn,  |  | 
|   320   sqlite_int64 iRow, |  | 
|   321   int isReadonly |  | 
|   322 ){ |  | 
|   323   IncrblobChannel *p; |  | 
|   324   sqlite3 *db = pDb->db; |  | 
|   325   sqlite3_blob *pBlob; |  | 
|   326   int rc; |  | 
|   327   int flags = TCL_READABLE|(isReadonly ? 0 : TCL_WRITABLE); |  | 
|   328  |  | 
|   329   /* This variable is used to name the channels: "incrblob_[incr count]" */ |  | 
|   330   static int count = 0; |  | 
|   331   char zChannel[64]; |  | 
|   332  |  | 
|   333   rc = sqlite3_blob_open(db, zDb, zTable, zColumn, iRow, !isReadonly, &pBlob); |  | 
|   334   if( rc!=SQLITE_OK ){ |  | 
|   335     Tcl_SetResult(interp, (char *)sqlite3_errmsg(pDb->db), TCL_VOLATILE); |  | 
|   336     return TCL_ERROR; |  | 
|   337   } |  | 
|   338  |  | 
|   339   p = (IncrblobChannel *)Tcl_Alloc(sizeof(IncrblobChannel)); |  | 
|   340   p->iSeek = 0; |  | 
|   341   p->pBlob = pBlob; |  | 
|   342  |  | 
|   343   sqlite3_snprintf(sizeof(zChannel), zChannel, "incrblob_%d", ++count); |  | 
|   344   p->channel = Tcl_CreateChannel(&IncrblobChannelType, zChannel, p, flags); |  | 
|   345   Tcl_RegisterChannel(interp, p->channel); |  | 
|   346  |  | 
|   347   /* Link the new channel into the SqliteDb.pIncrblob list. */ |  | 
|   348   p->pNext = pDb->pIncrblob; |  | 
|   349   p->pPrev = 0; |  | 
|   350   if( p->pNext ){ |  | 
|   351     p->pNext->pPrev = p; |  | 
|   352   } |  | 
|   353   pDb->pIncrblob = p; |  | 
|   354   p->pDb = pDb; |  | 
|   355  |  | 
|   356   Tcl_SetResult(interp, (char *)Tcl_GetChannelName(p->channel), TCL_VOLATILE); |  | 
|   357   return TCL_OK; |  | 
|   358 } |  | 
|   359 #else  /* else clause for "#ifndef SQLITE_OMIT_INCRBLOB" */ |  | 
|   360   #define closeIncrblobChannels(pDb) |  | 
|   361 #endif |  | 
|   362  |  | 
|   363 /* |  | 
|   364 ** Look at the script prefix in pCmd.  We will be executing this script |  | 
|   365 ** after first appending one or more arguments.  This routine analyzes |  | 
|   366 ** the script to see if it is safe to use Tcl_EvalObjv() on the script |  | 
|   367 ** rather than the more general Tcl_EvalEx().  Tcl_EvalObjv() is much |  | 
|   368 ** faster. |  | 
|   369 ** |  | 
|   370 ** Scripts that are safe to use with Tcl_EvalObjv() consists of a |  | 
|   371 ** command name followed by zero or more arguments with no [...] or $ |  | 
|   372 ** or {...} or ; to be seen anywhere.  Most callback scripts consist |  | 
|   373 ** of just a single procedure name and they meet this requirement. |  | 
|   374 */ |  | 
|   375 static int safeToUseEvalObjv(Tcl_Interp *interp, Tcl_Obj *pCmd){ |  | 
|   376   /* We could try to do something with Tcl_Parse().  But we will instead |  | 
|   377   ** just do a search for forbidden characters.  If any of the forbidden |  | 
|   378   ** characters appear in pCmd, we will report the string as unsafe. |  | 
|   379   */ |  | 
|   380   const char *z; |  | 
|   381   int n; |  | 
|   382   z = Tcl_GetStringFromObj(pCmd, &n); |  | 
|   383   while( n-- > 0 ){ |  | 
|   384     int c = *(z++); |  | 
|   385     if( c=='$' || c=='[' || c==';' ) return 0; |  | 
|   386   } |  | 
|   387   return 1; |  | 
|   388 } |  | 
|   389  |  | 
|   390 /* |  | 
|   391 ** Find an SqlFunc structure with the given name.  Or create a new |  | 
|   392 ** one if an existing one cannot be found.  Return a pointer to the |  | 
|   393 ** structure. |  | 
|   394 */ |  | 
|   395 static SqlFunc *findSqlFunc(SqliteDb *pDb, const char *zName){ |  | 
|   396   SqlFunc *p, *pNew; |  | 
|   397   int i; |  | 
|   398   pNew = (SqlFunc*)Tcl_Alloc( sizeof(*pNew) + strlen30(zName) + 1 ); |  | 
|   399   pNew->zName = (char*)&pNew[1]; |  | 
|   400   for(i=0; zName[i]; i++){ pNew->zName[i] = tolower(zName[i]); } |  | 
|   401   pNew->zName[i] = 0; |  | 
|   402   for(p=pDb->pFunc; p; p=p->pNext){  |  | 
|   403     if( strcmp(p->zName, pNew->zName)==0 ){ |  | 
|   404       Tcl_Free((char*)pNew); |  | 
|   405       return p; |  | 
|   406     } |  | 
|   407   } |  | 
|   408   pNew->interp = pDb->interp; |  | 
|   409   pNew->pScript = 0; |  | 
|   410   pNew->pNext = pDb->pFunc; |  | 
|   411   pDb->pFunc = pNew; |  | 
|   412   return pNew; |  | 
|   413 } |  | 
|   414  |  | 
|   415 /* |  | 
|   416 ** Finalize and free a list of prepared statements |  | 
|   417 */ |  | 
|   418 static void flushStmtCache( SqliteDb *pDb ){ |  | 
|   419   SqlPreparedStmt *pPreStmt; |  | 
|   420  |  | 
|   421   while(  pDb->stmtList ){ |  | 
|   422     sqlite3_finalize( pDb->stmtList->pStmt ); |  | 
|   423     pPreStmt = pDb->stmtList; |  | 
|   424     pDb->stmtList = pDb->stmtList->pNext; |  | 
|   425     Tcl_Free( (char*)pPreStmt ); |  | 
|   426   } |  | 
|   427   pDb->nStmt = 0; |  | 
|   428   pDb->stmtLast = 0; |  | 
|   429 } |  | 
|   430  |  | 
|   431 /* |  | 
|   432 ** TCL calls this procedure when an sqlite3 database command is |  | 
|   433 ** deleted. |  | 
|   434 */ |  | 
|   435 static void DbDeleteCmd(void *db){ |  | 
|   436   SqliteDb *pDb = (SqliteDb*)db; |  | 
|   437   flushStmtCache(pDb); |  | 
|   438   closeIncrblobChannels(pDb); |  | 
|   439   sqlite3_close(pDb->db); |  | 
|   440   while( pDb->pFunc ){ |  | 
|   441     SqlFunc *pFunc = pDb->pFunc; |  | 
|   442     pDb->pFunc = pFunc->pNext; |  | 
|   443     Tcl_DecrRefCount(pFunc->pScript); |  | 
|   444     Tcl_Free((char*)pFunc); |  | 
|   445   } |  | 
|   446   while( pDb->pCollate ){ |  | 
|   447     SqlCollate *pCollate = pDb->pCollate; |  | 
|   448     pDb->pCollate = pCollate->pNext; |  | 
|   449     Tcl_Free((char*)pCollate); |  | 
|   450   } |  | 
|   451   if( pDb->zBusy ){ |  | 
|   452     Tcl_Free(pDb->zBusy); |  | 
|   453   } |  | 
|   454   if( pDb->zTrace ){ |  | 
|   455     Tcl_Free(pDb->zTrace); |  | 
|   456   } |  | 
|   457   if( pDb->zProfile ){ |  | 
|   458     Tcl_Free(pDb->zProfile); |  | 
|   459   } |  | 
|   460   if( pDb->zAuth ){ |  | 
|   461     Tcl_Free(pDb->zAuth); |  | 
|   462   } |  | 
|   463   if( pDb->zNull ){ |  | 
|   464     Tcl_Free(pDb->zNull); |  | 
|   465   } |  | 
|   466   if( pDb->pUpdateHook ){ |  | 
|   467     Tcl_DecrRefCount(pDb->pUpdateHook); |  | 
|   468   } |  | 
|   469   if( pDb->pRollbackHook ){ |  | 
|   470     Tcl_DecrRefCount(pDb->pRollbackHook); |  | 
|   471   } |  | 
|   472   if( pDb->pCollateNeeded ){ |  | 
|   473     Tcl_DecrRefCount(pDb->pCollateNeeded); |  | 
|   474   } |  | 
|   475   Tcl_Free((char*)pDb); |  | 
|   476 } |  | 
|   477  |  | 
|   478 /* |  | 
|   479 ** This routine is called when a database file is locked while trying |  | 
|   480 ** to execute SQL. |  | 
|   481 */ |  | 
|   482 static int DbBusyHandler(void *cd, int nTries){ |  | 
|   483   SqliteDb *pDb = (SqliteDb*)cd; |  | 
|   484   int rc; |  | 
|   485   char zVal[30]; |  | 
|   486  |  | 
|   487   sqlite3_snprintf(sizeof(zVal), zVal, "%d", nTries); |  | 
|   488   rc = Tcl_VarEval(pDb->interp, pDb->zBusy, " ", zVal, (char*)0); |  | 
|   489   if( rc!=TCL_OK || atoi(Tcl_GetStringResult(pDb->interp)) ){ |  | 
|   490     return 0; |  | 
|   491   } |  | 
|   492   return 1; |  | 
|   493 } |  | 
|   494  |  | 
|   495 #ifndef SQLITE_OMIT_PROGRESS_CALLBACK |  | 
|   496 /* |  | 
|   497 ** This routine is invoked as the 'progress callback' for the database. |  | 
|   498 */ |  | 
|   499 static int DbProgressHandler(void *cd){ |  | 
|   500   SqliteDb *pDb = (SqliteDb*)cd; |  | 
|   501   int rc; |  | 
|   502  |  | 
|   503   assert( pDb->zProgress ); |  | 
|   504   rc = Tcl_Eval(pDb->interp, pDb->zProgress); |  | 
|   505   if( rc!=TCL_OK || atoi(Tcl_GetStringResult(pDb->interp)) ){ |  | 
|   506     return 1; |  | 
|   507   } |  | 
|   508   return 0; |  | 
|   509 } |  | 
|   510 #endif |  | 
|   511  |  | 
|   512 #ifndef SQLITE_OMIT_TRACE |  | 
|   513 /* |  | 
|   514 ** This routine is called by the SQLite trace handler whenever a new |  | 
|   515 ** block of SQL is executed.  The TCL script in pDb->zTrace is executed. |  | 
|   516 */ |  | 
|   517 static void DbTraceHandler(void *cd, const char *zSql){ |  | 
|   518   SqliteDb *pDb = (SqliteDb*)cd; |  | 
|   519   Tcl_DString str; |  | 
|   520  |  | 
|   521   Tcl_DStringInit(&str); |  | 
|   522   Tcl_DStringAppend(&str, pDb->zTrace, -1); |  | 
|   523   Tcl_DStringAppendElement(&str, zSql); |  | 
|   524   Tcl_Eval(pDb->interp, Tcl_DStringValue(&str)); |  | 
|   525   Tcl_DStringFree(&str); |  | 
|   526   Tcl_ResetResult(pDb->interp); |  | 
|   527 } |  | 
|   528 #endif |  | 
|   529  |  | 
|   530 #ifndef SQLITE_OMIT_TRACE |  | 
|   531 /* |  | 
|   532 ** This routine is called by the SQLite profile handler after a statement |  | 
|   533 ** SQL has executed.  The TCL script in pDb->zProfile is evaluated. |  | 
|   534 */ |  | 
|   535 static void DbProfileHandler(void *cd, const char *zSql, sqlite_uint64 tm){ |  | 
|   536   SqliteDb *pDb = (SqliteDb*)cd; |  | 
|   537   Tcl_DString str; |  | 
|   538   char zTm[100]; |  | 
|   539  |  | 
|   540   sqlite3_snprintf(sizeof(zTm)-1, zTm, "%lld", tm); |  | 
|   541   Tcl_DStringInit(&str); |  | 
|   542   Tcl_DStringAppend(&str, pDb->zProfile, -1); |  | 
|   543   Tcl_DStringAppendElement(&str, zSql); |  | 
|   544   Tcl_DStringAppendElement(&str, zTm); |  | 
|   545   Tcl_Eval(pDb->interp, Tcl_DStringValue(&str)); |  | 
|   546   Tcl_DStringFree(&str); |  | 
|   547   Tcl_ResetResult(pDb->interp); |  | 
|   548 } |  | 
|   549 #endif |  | 
|   550  |  | 
|   551 /* |  | 
|   552 ** This routine is called when a transaction is committed.  The |  | 
|   553 ** TCL script in pDb->zCommit is executed.  If it returns non-zero or |  | 
|   554 ** if it throws an exception, the transaction is rolled back instead |  | 
|   555 ** of being committed. |  | 
|   556 */ |  | 
|   557 static int DbCommitHandler(void *cd){ |  | 
|   558   SqliteDb *pDb = (SqliteDb*)cd; |  | 
|   559   int rc; |  | 
|   560  |  | 
|   561   rc = Tcl_Eval(pDb->interp, pDb->zCommit); |  | 
|   562   if( rc!=TCL_OK || atoi(Tcl_GetStringResult(pDb->interp)) ){ |  | 
|   563     return 1; |  | 
|   564   } |  | 
|   565   return 0; |  | 
|   566 } |  | 
|   567  |  | 
|   568 static void DbRollbackHandler(void *clientData){ |  | 
|   569   SqliteDb *pDb = (SqliteDb*)clientData; |  | 
|   570   assert(pDb->pRollbackHook); |  | 
|   571   if( TCL_OK!=Tcl_EvalObjEx(pDb->interp, pDb->pRollbackHook, 0) ){ |  | 
|   572     Tcl_BackgroundError(pDb->interp); |  | 
|   573   } |  | 
|   574 } |  | 
|   575  |  | 
|   576 #if defined(SQLITE_TEST) && defined(SQLITE_ENABLE_UNLOCK_NOTIFY) |  | 
|   577 static void setTestUnlockNotifyVars(Tcl_Interp *interp, int iArg, int nArg){ |  | 
|   578   char zBuf[64]; |  | 
|   579   sprintf(zBuf, "%d", iArg); |  | 
|   580   Tcl_SetVar(interp, "sqlite_unlock_notify_arg", zBuf, TCL_GLOBAL_ONLY); |  | 
|   581   sprintf(zBuf, "%d", nArg); |  | 
|   582   Tcl_SetVar(interp, "sqlite_unlock_notify_argcount", zBuf, TCL_GLOBAL_ONLY); |  | 
|   583 } |  | 
|   584 #else |  | 
|   585 # define setTestUnlockNotifyVars(x,y,z) |  | 
|   586 #endif |  | 
|   587  |  | 
|   588 #ifdef SQLITE_ENABLE_UNLOCK_NOTIFY |  | 
|   589 static void DbUnlockNotify(void **apArg, int nArg){ |  | 
|   590   int i; |  | 
|   591   for(i=0; i<nArg; i++){ |  | 
|   592     const int flags = (TCL_EVAL_GLOBAL|TCL_EVAL_DIRECT); |  | 
|   593     SqliteDb *pDb = (SqliteDb *)apArg[i]; |  | 
|   594     setTestUnlockNotifyVars(pDb->interp, i, nArg); |  | 
|   595     assert( pDb->pUnlockNotify); |  | 
|   596     Tcl_EvalObjEx(pDb->interp, pDb->pUnlockNotify, flags); |  | 
|   597     Tcl_DecrRefCount(pDb->pUnlockNotify); |  | 
|   598     pDb->pUnlockNotify = 0; |  | 
|   599   } |  | 
|   600 } |  | 
|   601 #endif |  | 
|   602  |  | 
|   603 static void DbUpdateHandler( |  | 
|   604   void *p,  |  | 
|   605   int op, |  | 
|   606   const char *zDb,  |  | 
|   607   const char *zTbl,  |  | 
|   608   sqlite_int64 rowid |  | 
|   609 ){ |  | 
|   610   SqliteDb *pDb = (SqliteDb *)p; |  | 
|   611   Tcl_Obj *pCmd; |  | 
|   612  |  | 
|   613   assert( pDb->pUpdateHook ); |  | 
|   614   assert( op==SQLITE_INSERT || op==SQLITE_UPDATE || op==SQLITE_DELETE ); |  | 
|   615  |  | 
|   616   pCmd = Tcl_DuplicateObj(pDb->pUpdateHook); |  | 
|   617   Tcl_IncrRefCount(pCmd); |  | 
|   618   Tcl_ListObjAppendElement(0, pCmd, Tcl_NewStringObj( |  | 
|   619     ( (op==SQLITE_INSERT)?"INSERT":(op==SQLITE_UPDATE)?"UPDATE":"DELETE"), -1)); |  | 
|   620   Tcl_ListObjAppendElement(0, pCmd, Tcl_NewStringObj(zDb, -1)); |  | 
|   621   Tcl_ListObjAppendElement(0, pCmd, Tcl_NewStringObj(zTbl, -1)); |  | 
|   622   Tcl_ListObjAppendElement(0, pCmd, Tcl_NewWideIntObj(rowid)); |  | 
|   623   Tcl_EvalObjEx(pDb->interp, pCmd, TCL_EVAL_DIRECT); |  | 
|   624 } |  | 
|   625  |  | 
|   626 static void tclCollateNeeded( |  | 
|   627   void *pCtx, |  | 
|   628   sqlite3 *db, |  | 
|   629   int enc, |  | 
|   630   const char *zName |  | 
|   631 ){ |  | 
|   632   SqliteDb *pDb = (SqliteDb *)pCtx; |  | 
|   633   Tcl_Obj *pScript = Tcl_DuplicateObj(pDb->pCollateNeeded); |  | 
|   634   Tcl_IncrRefCount(pScript); |  | 
|   635   Tcl_ListObjAppendElement(0, pScript, Tcl_NewStringObj(zName, -1)); |  | 
|   636   Tcl_EvalObjEx(pDb->interp, pScript, 0); |  | 
|   637   Tcl_DecrRefCount(pScript); |  | 
|   638 } |  | 
|   639  |  | 
|   640 /* |  | 
|   641 ** This routine is called to evaluate an SQL collation function implemented |  | 
|   642 ** using TCL script. |  | 
|   643 */ |  | 
|   644 static int tclSqlCollate( |  | 
|   645   void *pCtx, |  | 
|   646   int nA, |  | 
|   647   const void *zA, |  | 
|   648   int nB, |  | 
|   649   const void *zB |  | 
|   650 ){ |  | 
|   651   SqlCollate *p = (SqlCollate *)pCtx; |  | 
|   652   Tcl_Obj *pCmd; |  | 
|   653  |  | 
|   654   pCmd = Tcl_NewStringObj(p->zScript, -1); |  | 
|   655   Tcl_IncrRefCount(pCmd); |  | 
|   656   Tcl_ListObjAppendElement(p->interp, pCmd, Tcl_NewStringObj(zA, nA)); |  | 
|   657   Tcl_ListObjAppendElement(p->interp, pCmd, Tcl_NewStringObj(zB, nB)); |  | 
|   658   Tcl_EvalObjEx(p->interp, pCmd, TCL_EVAL_DIRECT); |  | 
|   659   Tcl_DecrRefCount(pCmd); |  | 
|   660   return (atoi(Tcl_GetStringResult(p->interp))); |  | 
|   661 } |  | 
|   662  |  | 
|   663 /* |  | 
|   664 ** This routine is called to evaluate an SQL function implemented |  | 
|   665 ** using TCL script. |  | 
|   666 */ |  | 
|   667 static void tclSqlFunc(sqlite3_context *context, int argc, sqlite3_value**argv){ |  | 
|   668   SqlFunc *p = sqlite3_user_data(context); |  | 
|   669   Tcl_Obj *pCmd; |  | 
|   670   int i; |  | 
|   671   int rc; |  | 
|   672  |  | 
|   673   if( argc==0 ){ |  | 
|   674     /* If there are no arguments to the function, call Tcl_EvalObjEx on the |  | 
|   675     ** script object directly.  This allows the TCL compiler to generate |  | 
|   676     ** bytecode for the command on the first invocation and thus make |  | 
|   677     ** subsequent invocations much faster. */ |  | 
|   678     pCmd = p->pScript; |  | 
|   679     Tcl_IncrRefCount(pCmd); |  | 
|   680     rc = Tcl_EvalObjEx(p->interp, pCmd, 0); |  | 
|   681     Tcl_DecrRefCount(pCmd); |  | 
|   682   }else{ |  | 
|   683     /* If there are arguments to the function, make a shallow copy of the |  | 
|   684     ** script object, lappend the arguments, then evaluate the copy. |  | 
|   685     ** |  | 
|   686     ** By "shallow" copy, we mean a only the outer list Tcl_Obj is duplicated. |  | 
|   687     ** The new Tcl_Obj contains pointers to the original list elements.  |  | 
|   688     ** That way, when Tcl_EvalObjv() is run and shimmers the first element |  | 
|   689     ** of the list to tclCmdNameType, that alternate representation will |  | 
|   690     ** be preserved and reused on the next invocation. |  | 
|   691     */ |  | 
|   692     Tcl_Obj **aArg; |  | 
|   693     int nArg; |  | 
|   694     if( Tcl_ListObjGetElements(p->interp, p->pScript, &nArg, &aArg) ){ |  | 
|   695       sqlite3_result_error(context, Tcl_GetStringResult(p->interp), -1);  |  | 
|   696       return; |  | 
|   697     }      |  | 
|   698     pCmd = Tcl_NewListObj(nArg, aArg); |  | 
|   699     Tcl_IncrRefCount(pCmd); |  | 
|   700     for(i=0; i<argc; i++){ |  | 
|   701       sqlite3_value *pIn = argv[i]; |  | 
|   702       Tcl_Obj *pVal; |  | 
|   703              |  | 
|   704       /* Set pVal to contain the i'th column of this row. */ |  | 
|   705       switch( sqlite3_value_type(pIn) ){ |  | 
|   706         case SQLITE_BLOB: { |  | 
|   707           int bytes = sqlite3_value_bytes(pIn); |  | 
|   708           pVal = Tcl_NewByteArrayObj(sqlite3_value_blob(pIn), bytes); |  | 
|   709           break; |  | 
|   710         } |  | 
|   711         case SQLITE_INTEGER: { |  | 
|   712           sqlite_int64 v = sqlite3_value_int64(pIn); |  | 
|   713           if( v>=-2147483647 && v<=2147483647 ){ |  | 
|   714             pVal = Tcl_NewIntObj(v); |  | 
|   715           }else{ |  | 
|   716             pVal = Tcl_NewWideIntObj(v); |  | 
|   717           } |  | 
|   718           break; |  | 
|   719         } |  | 
|   720         case SQLITE_FLOAT: { |  | 
|   721           double r = sqlite3_value_double(pIn); |  | 
|   722           pVal = Tcl_NewDoubleObj(r); |  | 
|   723           break; |  | 
|   724         } |  | 
|   725         case SQLITE_NULL: { |  | 
|   726           pVal = Tcl_NewStringObj("", 0); |  | 
|   727           break; |  | 
|   728         } |  | 
|   729         default: { |  | 
|   730           int bytes = sqlite3_value_bytes(pIn); |  | 
|   731           pVal = Tcl_NewStringObj((char *)sqlite3_value_text(pIn), bytes); |  | 
|   732           break; |  | 
|   733         } |  | 
|   734       } |  | 
|   735       rc = Tcl_ListObjAppendElement(p->interp, pCmd, pVal); |  | 
|   736       if( rc ){ |  | 
|   737         Tcl_DecrRefCount(pCmd); |  | 
|   738         sqlite3_result_error(context, Tcl_GetStringResult(p->interp), -1);  |  | 
|   739         return; |  | 
|   740       } |  | 
|   741     } |  | 
|   742     if( !p->useEvalObjv ){ |  | 
|   743       /* Tcl_EvalObjEx() will automatically call Tcl_EvalObjv() if pCmd |  | 
|   744       ** is a list without a string representation.  To prevent this from |  | 
|   745       ** happening, make sure pCmd has a valid string representation */ |  | 
|   746       Tcl_GetString(pCmd); |  | 
|   747     } |  | 
|   748     rc = Tcl_EvalObjEx(p->interp, pCmd, TCL_EVAL_DIRECT); |  | 
|   749     Tcl_DecrRefCount(pCmd); |  | 
|   750   } |  | 
|   751  |  | 
|   752   if( rc && rc!=TCL_RETURN ){ |  | 
|   753     sqlite3_result_error(context, Tcl_GetStringResult(p->interp), -1);  |  | 
|   754   }else{ |  | 
|   755     Tcl_Obj *pVar = Tcl_GetObjResult(p->interp); |  | 
|   756     int n; |  | 
|   757     u8 *data; |  | 
|   758     char *zType = pVar->typePtr ? pVar->typePtr->name : ""; |  | 
|   759     char c = zType[0]; |  | 
|   760     if( c=='b' && strcmp(zType,"bytearray")==0 && pVar->bytes==0 ){ |  | 
|   761       /* Only return a BLOB type if the Tcl variable is a bytearray and |  | 
|   762       ** has no string representation. */ |  | 
|   763       data = Tcl_GetByteArrayFromObj(pVar, &n); |  | 
|   764       sqlite3_result_blob(context, data, n, SQLITE_TRANSIENT); |  | 
|   765     }else if( c=='b' && strcmp(zType,"boolean")==0 ){ |  | 
|   766       Tcl_GetIntFromObj(0, pVar, &n); |  | 
|   767       sqlite3_result_int(context, n); |  | 
|   768     }else if( c=='d' && strcmp(zType,"double")==0 ){ |  | 
|   769       double r; |  | 
|   770       Tcl_GetDoubleFromObj(0, pVar, &r); |  | 
|   771       sqlite3_result_double(context, r); |  | 
|   772     }else if( (c=='w' && strcmp(zType,"wideInt")==0) || |  | 
|   773           (c=='i' && strcmp(zType,"int")==0) ){ |  | 
|   774       Tcl_WideInt v; |  | 
|   775       Tcl_GetWideIntFromObj(0, pVar, &v); |  | 
|   776       sqlite3_result_int64(context, v); |  | 
|   777     }else{ |  | 
|   778       data = (unsigned char *)Tcl_GetStringFromObj(pVar, &n); |  | 
|   779       sqlite3_result_text(context, (char *)data, n, SQLITE_TRANSIENT); |  | 
|   780     } |  | 
|   781   } |  | 
|   782 } |  | 
|   783  |  | 
|   784 #ifndef SQLITE_OMIT_AUTHORIZATION |  | 
|   785 /* |  | 
|   786 ** This is the authentication function.  It appends the authentication |  | 
|   787 ** type code and the two arguments to zCmd[] then invokes the result |  | 
|   788 ** on the interpreter.  The reply is examined to determine if the |  | 
|   789 ** authentication fails or succeeds. |  | 
|   790 */ |  | 
|   791 static int auth_callback( |  | 
|   792   void *pArg, |  | 
|   793   int code, |  | 
|   794   const char *zArg1, |  | 
|   795   const char *zArg2, |  | 
|   796   const char *zArg3, |  | 
|   797   const char *zArg4 |  | 
|   798 ){ |  | 
|   799   char *zCode; |  | 
|   800   Tcl_DString str; |  | 
|   801   int rc; |  | 
|   802   const char *zReply; |  | 
|   803   SqliteDb *pDb = (SqliteDb*)pArg; |  | 
|   804   if( pDb->disableAuth ) return SQLITE_OK; |  | 
|   805  |  | 
|   806   switch( code ){ |  | 
|   807     case SQLITE_COPY              : zCode="SQLITE_COPY"; break; |  | 
|   808     case SQLITE_CREATE_INDEX      : zCode="SQLITE_CREATE_INDEX"; break; |  | 
|   809     case SQLITE_CREATE_TABLE      : zCode="SQLITE_CREATE_TABLE"; break; |  | 
|   810     case SQLITE_CREATE_TEMP_INDEX : zCode="SQLITE_CREATE_TEMP_INDEX"; break; |  | 
|   811     case SQLITE_CREATE_TEMP_TABLE : zCode="SQLITE_CREATE_TEMP_TABLE"; break; |  | 
|   812     case SQLITE_CREATE_TEMP_TRIGGER: zCode="SQLITE_CREATE_TEMP_TRIGGER"; break; |  | 
|   813     case SQLITE_CREATE_TEMP_VIEW  : zCode="SQLITE_CREATE_TEMP_VIEW"; break; |  | 
|   814     case SQLITE_CREATE_TRIGGER    : zCode="SQLITE_CREATE_TRIGGER"; break; |  | 
|   815     case SQLITE_CREATE_VIEW       : zCode="SQLITE_CREATE_VIEW"; break; |  | 
|   816     case SQLITE_DELETE            : zCode="SQLITE_DELETE"; break; |  | 
|   817     case SQLITE_DROP_INDEX        : zCode="SQLITE_DROP_INDEX"; break; |  | 
|   818     case SQLITE_DROP_TABLE        : zCode="SQLITE_DROP_TABLE"; break; |  | 
|   819     case SQLITE_DROP_TEMP_INDEX   : zCode="SQLITE_DROP_TEMP_INDEX"; break; |  | 
|   820     case SQLITE_DROP_TEMP_TABLE   : zCode="SQLITE_DROP_TEMP_TABLE"; break; |  | 
|   821     case SQLITE_DROP_TEMP_TRIGGER : zCode="SQLITE_DROP_TEMP_TRIGGER"; break; |  | 
|   822     case SQLITE_DROP_TEMP_VIEW    : zCode="SQLITE_DROP_TEMP_VIEW"; break; |  | 
|   823     case SQLITE_DROP_TRIGGER      : zCode="SQLITE_DROP_TRIGGER"; break; |  | 
|   824     case SQLITE_DROP_VIEW         : zCode="SQLITE_DROP_VIEW"; break; |  | 
|   825     case SQLITE_INSERT            : zCode="SQLITE_INSERT"; break; |  | 
|   826     case SQLITE_PRAGMA            : zCode="SQLITE_PRAGMA"; break; |  | 
|   827     case SQLITE_READ              : zCode="SQLITE_READ"; break; |  | 
|   828     case SQLITE_SELECT            : zCode="SQLITE_SELECT"; break; |  | 
|   829     case SQLITE_TRANSACTION       : zCode="SQLITE_TRANSACTION"; break; |  | 
|   830     case SQLITE_UPDATE            : zCode="SQLITE_UPDATE"; break; |  | 
|   831     case SQLITE_ATTACH            : zCode="SQLITE_ATTACH"; break; |  | 
|   832     case SQLITE_DETACH            : zCode="SQLITE_DETACH"; break; |  | 
|   833     case SQLITE_ALTER_TABLE       : zCode="SQLITE_ALTER_TABLE"; break; |  | 
|   834     case SQLITE_REINDEX           : zCode="SQLITE_REINDEX"; break; |  | 
|   835     case SQLITE_ANALYZE           : zCode="SQLITE_ANALYZE"; break; |  | 
|   836     case SQLITE_CREATE_VTABLE     : zCode="SQLITE_CREATE_VTABLE"; break; |  | 
|   837     case SQLITE_DROP_VTABLE       : zCode="SQLITE_DROP_VTABLE"; break; |  | 
|   838     case SQLITE_FUNCTION          : zCode="SQLITE_FUNCTION"; break; |  | 
|   839     case SQLITE_SAVEPOINT         : zCode="SQLITE_SAVEPOINT"; break; |  | 
|   840     default                       : zCode="????"; break; |  | 
|   841   } |  | 
|   842   Tcl_DStringInit(&str); |  | 
|   843   Tcl_DStringAppend(&str, pDb->zAuth, -1); |  | 
|   844   Tcl_DStringAppendElement(&str, zCode); |  | 
|   845   Tcl_DStringAppendElement(&str, zArg1 ? zArg1 : ""); |  | 
|   846   Tcl_DStringAppendElement(&str, zArg2 ? zArg2 : ""); |  | 
|   847   Tcl_DStringAppendElement(&str, zArg3 ? zArg3 : ""); |  | 
|   848   Tcl_DStringAppendElement(&str, zArg4 ? zArg4 : ""); |  | 
|   849   rc = Tcl_GlobalEval(pDb->interp, Tcl_DStringValue(&str)); |  | 
|   850   Tcl_DStringFree(&str); |  | 
|   851   zReply = Tcl_GetStringResult(pDb->interp); |  | 
|   852   if( strcmp(zReply,"SQLITE_OK")==0 ){ |  | 
|   853     rc = SQLITE_OK; |  | 
|   854   }else if( strcmp(zReply,"SQLITE_DENY")==0 ){ |  | 
|   855     rc = SQLITE_DENY; |  | 
|   856   }else if( strcmp(zReply,"SQLITE_IGNORE")==0 ){ |  | 
|   857     rc = SQLITE_IGNORE; |  | 
|   858   }else{ |  | 
|   859     rc = 999; |  | 
|   860   } |  | 
|   861   return rc; |  | 
|   862 } |  | 
|   863 #endif /* SQLITE_OMIT_AUTHORIZATION */ |  | 
|   864  |  | 
|   865 /* |  | 
|   866 ** zText is a pointer to text obtained via an sqlite3_result_text() |  | 
|   867 ** or similar interface. This routine returns a Tcl string object,  |  | 
|   868 ** reference count set to 0, containing the text. If a translation |  | 
|   869 ** between iso8859 and UTF-8 is required, it is preformed. |  | 
|   870 */ |  | 
|   871 static Tcl_Obj *dbTextToObj(char const *zText){ |  | 
|   872   Tcl_Obj *pVal; |  | 
|   873 #ifdef UTF_TRANSLATION_NEEDED |  | 
|   874   Tcl_DString dCol; |  | 
|   875   Tcl_DStringInit(&dCol); |  | 
|   876   Tcl_ExternalToUtfDString(NULL, zText, -1, &dCol); |  | 
|   877   pVal = Tcl_NewStringObj(Tcl_DStringValue(&dCol), -1); |  | 
|   878   Tcl_DStringFree(&dCol); |  | 
|   879 #else |  | 
|   880   pVal = Tcl_NewStringObj(zText, -1); |  | 
|   881 #endif |  | 
|   882   return pVal; |  | 
|   883 } |  | 
|   884  |  | 
|   885 /* |  | 
|   886 ** This routine reads a line of text from FILE in, stores |  | 
|   887 ** the text in memory obtained from malloc() and returns a pointer |  | 
|   888 ** to the text.  NULL is returned at end of file, or if malloc() |  | 
|   889 ** fails. |  | 
|   890 ** |  | 
|   891 ** The interface is like "readline" but no command-line editing |  | 
|   892 ** is done. |  | 
|   893 ** |  | 
|   894 ** copied from shell.c from '.import' command |  | 
|   895 */ |  | 
|   896 static char *local_getline(char *zPrompt, FILE *in){ |  | 
|   897   char *zLine; |  | 
|   898   int nLine; |  | 
|   899   int n; |  | 
|   900   int eol; |  | 
|   901  |  | 
|   902   nLine = 100; |  | 
|   903   zLine = malloc( nLine ); |  | 
|   904   if( zLine==0 ) return 0; |  | 
|   905   n = 0; |  | 
|   906   eol = 0; |  | 
|   907   while( !eol ){ |  | 
|   908     if( n+100>nLine ){ |  | 
|   909       nLine = nLine*2 + 100; |  | 
|   910       zLine = realloc(zLine, nLine); |  | 
|   911       if( zLine==0 ) return 0; |  | 
|   912     } |  | 
|   913     if( fgets(&zLine[n], nLine - n, in)==0 ){ |  | 
|   914       if( n==0 ){ |  | 
|   915         free(zLine); |  | 
|   916         return 0; |  | 
|   917       } |  | 
|   918       zLine[n] = 0; |  | 
|   919       eol = 1; |  | 
|   920       break; |  | 
|   921     } |  | 
|   922     while( zLine[n] ){ n++; } |  | 
|   923     if( n>0 && zLine[n-1]=='\n' ){ |  | 
|   924       n--; |  | 
|   925       zLine[n] = 0; |  | 
|   926       eol = 1; |  | 
|   927     } |  | 
|   928   } |  | 
|   929   zLine = realloc( zLine, n+1 ); |  | 
|   930   return zLine; |  | 
|   931 } |  | 
|   932  |  | 
|   933  |  | 
|   934 /* |  | 
|   935 ** Figure out the column names for the data returned by the statement |  | 
|   936 ** passed as the second argument. |  | 
|   937 ** |  | 
|   938 ** If parameter papColName is not NULL, then *papColName is set to point |  | 
|   939 ** at an array allocated using Tcl_Alloc(). It is the callers responsibility |  | 
|   940 ** to free this array using Tcl_Free(), and to decrement the reference |  | 
|   941 ** count of each Tcl_Obj* member of the array. |  | 
|   942 ** |  | 
|   943 ** The return value of this function is the number of columns of data |  | 
|   944 ** returned by pStmt (and hence the size of the *papColName array). |  | 
|   945 ** |  | 
|   946 ** If pArray is not NULL, then it contains the name of a Tcl array |  | 
|   947 ** variable. The "*" member of this array is set to a list containing |  | 
|   948 ** the names of the columns returned by the statement, in order from |  | 
|   949 ** left to right. e.g. if the names of the returned columns are a, b and |  | 
|   950 ** c, it does the equivalent of the tcl command: |  | 
|   951 ** |  | 
|   952 **     set ${pArray}(*) {a b c} |  | 
|   953 */ |  | 
|   954 static int |  | 
|   955 computeColumnNames( |  | 
|   956   Tcl_Interp *interp,  |  | 
|   957   sqlite3_stmt *pStmt,              /* SQL statement */ |  | 
|   958   Tcl_Obj ***papColName,            /* OUT: Array of column names */ |  | 
|   959   Tcl_Obj *pArray                   /* Name of array variable (may be null) */ |  | 
|   960 ){ |  | 
|   961   int nCol; |  | 
|   962  |  | 
|   963   /* Compute column names */ |  | 
|   964   nCol = sqlite3_column_count(pStmt); |  | 
|   965   if( papColName ){ |  | 
|   966     int i; |  | 
|   967     Tcl_Obj **apColName = (Tcl_Obj**)Tcl_Alloc( sizeof(Tcl_Obj*)*nCol ); |  | 
|   968     for(i=0; i<nCol; i++){ |  | 
|   969       apColName[i] = dbTextToObj(sqlite3_column_name(pStmt,i)); |  | 
|   970       Tcl_IncrRefCount(apColName[i]); |  | 
|   971     } |  | 
|   972  |  | 
|   973     /* If results are being stored in an array variable, then create |  | 
|   974     ** the array(*) entry for that array |  | 
|   975     */ |  | 
|   976     if( pArray ){ |  | 
|   977       Tcl_Obj *pColList = Tcl_NewObj(); |  | 
|   978       Tcl_Obj *pStar = Tcl_NewStringObj("*", -1); |  | 
|   979       Tcl_IncrRefCount(pColList); |  | 
|   980       for(i=0; i<nCol; i++){ |  | 
|   981         Tcl_ListObjAppendElement(interp, pColList, apColName[i]); |  | 
|   982       } |  | 
|   983       Tcl_IncrRefCount(pStar); |  | 
|   984       Tcl_ObjSetVar2(interp, pArray, pStar, pColList,0); |  | 
|   985       Tcl_DecrRefCount(pColList); |  | 
|   986       Tcl_DecrRefCount(pStar); |  | 
|   987     } |  | 
|   988     *papColName = apColName; |  | 
|   989   } |  | 
|   990  |  | 
|   991   return nCol; |  | 
|   992 } |  | 
|   993  |  | 
|   994 /* |  | 
|   995 ** The "sqlite" command below creates a new Tcl command for each |  | 
|   996 ** connection it opens to an SQLite database.  This routine is invoked |  | 
|   997 ** whenever one of those connection-specific commands is executed |  | 
|   998 ** in Tcl.  For example, if you run Tcl code like this: |  | 
|   999 ** |  | 
|  1000 **       sqlite3 db1  "my_database" |  | 
|  1001 **       db1 close |  | 
|  1002 ** |  | 
|  1003 ** The first command opens a connection to the "my_database" database |  | 
|  1004 ** and calls that connection "db1".  The second command causes this |  | 
|  1005 ** subroutine to be invoked. |  | 
|  1006 */ |  | 
|  1007 static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){ |  | 
|  1008   SqliteDb *pDb = (SqliteDb*)cd; |  | 
|  1009   int choice; |  | 
|  1010   int rc = TCL_OK; |  | 
|  1011   static const char *DB_strs[] = { |  | 
|  1012     "authorizer",         "backup",            "busy", |  | 
|  1013     "cache",              "changes",           "close", |  | 
|  1014     "collate",            "collation_needed",  "commit_hook", |  | 
|  1015     "complete",           "copy",              "enable_load_extension", |  | 
|  1016     "errorcode",          "eval",              "exists", |  | 
|  1017     "function",           "incrblob",          "interrupt", |  | 
|  1018     "last_insert_rowid",  "nullvalue",         "onecolumn", |  | 
|  1019     "profile",            "progress",          "rekey", |  | 
|  1020     "restore",            "rollback_hook",     "status", |  | 
|  1021     "timeout",            "total_changes",     "trace", |  | 
|  1022     "transaction",        "unlock_notify",     "update_hook", |  | 
|  1023     "version",            0                     |  | 
|  1024   }; |  | 
|  1025   enum DB_enum { |  | 
|  1026     DB_AUTHORIZER,        DB_BACKUP,           DB_BUSY, |  | 
|  1027     DB_CACHE,             DB_CHANGES,          DB_CLOSE, |  | 
|  1028     DB_COLLATE,           DB_COLLATION_NEEDED, DB_COMMIT_HOOK, |  | 
|  1029     DB_COMPLETE,          DB_COPY,             DB_ENABLE_LOAD_EXTENSION, |  | 
|  1030     DB_ERRORCODE,         DB_EVAL,             DB_EXISTS, |  | 
|  1031     DB_FUNCTION,          DB_INCRBLOB,         DB_INTERRUPT, |  | 
|  1032     DB_LAST_INSERT_ROWID, DB_NULLVALUE,        DB_ONECOLUMN, |  | 
|  1033     DB_PROFILE,           DB_PROGRESS,         DB_REKEY, |  | 
|  1034     DB_RESTORE,           DB_ROLLBACK_HOOK,    DB_STATUS, |  | 
|  1035     DB_TIMEOUT,           DB_TOTAL_CHANGES,    DB_TRACE, |  | 
|  1036     DB_TRANSACTION,       DB_UNLOCK_NOTIFY,    DB_UPDATE_HOOK, |  | 
|  1037     DB_VERSION, |  | 
|  1038   }; |  | 
|  1039   /* don't leave trailing commas on DB_enum, it confuses the AIX xlc compiler */ |  | 
|  1040  |  | 
|  1041   if( objc<2 ){ |  | 
|  1042     Tcl_WrongNumArgs(interp, 1, objv, "SUBCOMMAND ..."); |  | 
|  1043     return TCL_ERROR; |  | 
|  1044   } |  | 
|  1045   if( Tcl_GetIndexFromObj(interp, objv[1], DB_strs, "option", 0, &choice) ){ |  | 
|  1046     return TCL_ERROR; |  | 
|  1047   } |  | 
|  1048  |  | 
|  1049   switch( (enum DB_enum)choice ){ |  | 
|  1050  |  | 
|  1051   /*    $db authorizer ?CALLBACK? |  | 
|  1052   ** |  | 
|  1053   ** Invoke the given callback to authorize each SQL operation as it is |  | 
|  1054   ** compiled.  5 arguments are appended to the callback before it is |  | 
|  1055   ** invoked: |  | 
|  1056   ** |  | 
|  1057   **   (1) The authorization type (ex: SQLITE_CREATE_TABLE, SQLITE_INSERT, ...) |  | 
|  1058   **   (2) First descriptive name (depends on authorization type) |  | 
|  1059   **   (3) Second descriptive name |  | 
|  1060   **   (4) Name of the database (ex: "main", "temp") |  | 
|  1061   **   (5) Name of trigger that is doing the access |  | 
|  1062   ** |  | 
|  1063   ** The callback should return on of the following strings: SQLITE_OK, |  | 
|  1064   ** SQLITE_IGNORE, or SQLITE_DENY.  Any other return value is an error. |  | 
|  1065   ** |  | 
|  1066   ** If this method is invoked with no arguments, the current authorization |  | 
|  1067   ** callback string is returned. |  | 
|  1068   */ |  | 
|  1069   case DB_AUTHORIZER: { |  | 
|  1070 #ifdef SQLITE_OMIT_AUTHORIZATION |  | 
|  1071     Tcl_AppendResult(interp, "authorization not available in this build", 0); |  | 
|  1072     return TCL_ERROR; |  | 
|  1073 #else |  | 
|  1074     if( objc>3 ){ |  | 
|  1075       Tcl_WrongNumArgs(interp, 2, objv, "?CALLBACK?"); |  | 
|  1076       return TCL_ERROR; |  | 
|  1077     }else if( objc==2 ){ |  | 
|  1078       if( pDb->zAuth ){ |  | 
|  1079         Tcl_AppendResult(interp, pDb->zAuth, 0); |  | 
|  1080       } |  | 
|  1081     }else{ |  | 
|  1082       char *zAuth; |  | 
|  1083       int len; |  | 
|  1084       if( pDb->zAuth ){ |  | 
|  1085         Tcl_Free(pDb->zAuth); |  | 
|  1086       } |  | 
|  1087       zAuth = Tcl_GetStringFromObj(objv[2], &len); |  | 
|  1088       if( zAuth && len>0 ){ |  | 
|  1089         pDb->zAuth = Tcl_Alloc( len + 1 ); |  | 
|  1090         memcpy(pDb->zAuth, zAuth, len+1); |  | 
|  1091       }else{ |  | 
|  1092         pDb->zAuth = 0; |  | 
|  1093       } |  | 
|  1094       if( pDb->zAuth ){ |  | 
|  1095         pDb->interp = interp; |  | 
|  1096         sqlite3_set_authorizer(pDb->db, auth_callback, pDb); |  | 
|  1097       }else{ |  | 
|  1098         sqlite3_set_authorizer(pDb->db, 0, 0); |  | 
|  1099       } |  | 
|  1100     } |  | 
|  1101 #endif |  | 
|  1102     break; |  | 
|  1103   } |  | 
|  1104  |  | 
|  1105   /*    $db backup ?DATABASE? FILENAME |  | 
|  1106   ** |  | 
|  1107   ** Open or create a database file named FILENAME.  Transfer the |  | 
|  1108   ** content of local database DATABASE (default: "main") into the |  | 
|  1109   ** FILENAME database. |  | 
|  1110   */ |  | 
|  1111   case DB_BACKUP: { |  | 
|  1112     const char *zDestFile; |  | 
|  1113     const char *zSrcDb; |  | 
|  1114     sqlite3 *pDest; |  | 
|  1115     sqlite3_backup *pBackup; |  | 
|  1116  |  | 
|  1117     if( objc==3 ){ |  | 
|  1118       zSrcDb = "main"; |  | 
|  1119       zDestFile = Tcl_GetString(objv[2]); |  | 
|  1120     }else if( objc==4 ){ |  | 
|  1121       zSrcDb = Tcl_GetString(objv[2]); |  | 
|  1122       zDestFile = Tcl_GetString(objv[3]); |  | 
|  1123     }else{ |  | 
|  1124       Tcl_WrongNumArgs(interp, 2, objv, "?DATABASE? FILENAME"); |  | 
|  1125       return TCL_ERROR; |  | 
|  1126     } |  | 
|  1127     rc = sqlite3_open(zDestFile, &pDest); |  | 
|  1128     if( rc!=SQLITE_OK ){ |  | 
|  1129       Tcl_AppendResult(interp, "cannot open target database: ", |  | 
|  1130            sqlite3_errmsg(pDest), (char*)0); |  | 
|  1131       sqlite3_close(pDest); |  | 
|  1132       return TCL_ERROR; |  | 
|  1133     } |  | 
|  1134     pBackup = sqlite3_backup_init(pDest, "main", pDb->db, zSrcDb); |  | 
|  1135     if( pBackup==0 ){ |  | 
|  1136       Tcl_AppendResult(interp, "backup failed: ", |  | 
|  1137            sqlite3_errmsg(pDest), (char*)0); |  | 
|  1138       sqlite3_close(pDest); |  | 
|  1139       return TCL_ERROR; |  | 
|  1140     } |  | 
|  1141     while(  (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK ){} |  | 
|  1142     sqlite3_backup_finish(pBackup); |  | 
|  1143     if( rc==SQLITE_DONE ){ |  | 
|  1144       rc = TCL_OK; |  | 
|  1145     }else{ |  | 
|  1146       Tcl_AppendResult(interp, "backup failed: ", |  | 
|  1147            sqlite3_errmsg(pDest), (char*)0); |  | 
|  1148       rc = TCL_ERROR; |  | 
|  1149     } |  | 
|  1150     sqlite3_close(pDest); |  | 
|  1151     break; |  | 
|  1152   } |  | 
|  1153  |  | 
|  1154   /*    $db busy ?CALLBACK? |  | 
|  1155   ** |  | 
|  1156   ** Invoke the given callback if an SQL statement attempts to open |  | 
|  1157   ** a locked database file. |  | 
|  1158   */ |  | 
|  1159   case DB_BUSY: { |  | 
|  1160     if( objc>3 ){ |  | 
|  1161       Tcl_WrongNumArgs(interp, 2, objv, "CALLBACK"); |  | 
|  1162       return TCL_ERROR; |  | 
|  1163     }else if( objc==2 ){ |  | 
|  1164       if( pDb->zBusy ){ |  | 
|  1165         Tcl_AppendResult(interp, pDb->zBusy, 0); |  | 
|  1166       } |  | 
|  1167     }else{ |  | 
|  1168       char *zBusy; |  | 
|  1169       int len; |  | 
|  1170       if( pDb->zBusy ){ |  | 
|  1171         Tcl_Free(pDb->zBusy); |  | 
|  1172       } |  | 
|  1173       zBusy = Tcl_GetStringFromObj(objv[2], &len); |  | 
|  1174       if( zBusy && len>0 ){ |  | 
|  1175         pDb->zBusy = Tcl_Alloc( len + 1 ); |  | 
|  1176         memcpy(pDb->zBusy, zBusy, len+1); |  | 
|  1177       }else{ |  | 
|  1178         pDb->zBusy = 0; |  | 
|  1179       } |  | 
|  1180       if( pDb->zBusy ){ |  | 
|  1181         pDb->interp = interp; |  | 
|  1182         sqlite3_busy_handler(pDb->db, DbBusyHandler, pDb); |  | 
|  1183       }else{ |  | 
|  1184         sqlite3_busy_handler(pDb->db, 0, 0); |  | 
|  1185       } |  | 
|  1186     } |  | 
|  1187     break; |  | 
|  1188   } |  | 
|  1189  |  | 
|  1190   /*     $db cache flush |  | 
|  1191   **     $db cache size n |  | 
|  1192   ** |  | 
|  1193   ** Flush the prepared statement cache, or set the maximum number of |  | 
|  1194   ** cached statements. |  | 
|  1195   */ |  | 
|  1196   case DB_CACHE: { |  | 
|  1197     char *subCmd; |  | 
|  1198     int n; |  | 
|  1199  |  | 
|  1200     if( objc<=2 ){ |  | 
|  1201       Tcl_WrongNumArgs(interp, 1, objv, "cache option ?arg?"); |  | 
|  1202       return TCL_ERROR; |  | 
|  1203     } |  | 
|  1204     subCmd = Tcl_GetStringFromObj( objv[2], 0 ); |  | 
|  1205     if( *subCmd=='f' && strcmp(subCmd,"flush")==0 ){ |  | 
|  1206       if( objc!=3 ){ |  | 
|  1207         Tcl_WrongNumArgs(interp, 2, objv, "flush"); |  | 
|  1208         return TCL_ERROR; |  | 
|  1209       }else{ |  | 
|  1210         flushStmtCache( pDb ); |  | 
|  1211       } |  | 
|  1212     }else if( *subCmd=='s' && strcmp(subCmd,"size")==0 ){ |  | 
|  1213       if( objc!=4 ){ |  | 
|  1214         Tcl_WrongNumArgs(interp, 2, objv, "size n"); |  | 
|  1215         return TCL_ERROR; |  | 
|  1216       }else{ |  | 
|  1217         if( TCL_ERROR==Tcl_GetIntFromObj(interp, objv[3], &n) ){ |  | 
|  1218           Tcl_AppendResult( interp, "cannot convert \"",  |  | 
|  1219                Tcl_GetStringFromObj(objv[3],0), "\" to integer", 0); |  | 
|  1220           return TCL_ERROR; |  | 
|  1221         }else{ |  | 
|  1222           if( n<0 ){ |  | 
|  1223             flushStmtCache( pDb ); |  | 
|  1224             n = 0; |  | 
|  1225           }else if( n>MAX_PREPARED_STMTS ){ |  | 
|  1226             n = MAX_PREPARED_STMTS; |  | 
|  1227           } |  | 
|  1228           pDb->maxStmt = n; |  | 
|  1229         } |  | 
|  1230       } |  | 
|  1231     }else{ |  | 
|  1232       Tcl_AppendResult( interp, "bad option \"",  |  | 
|  1233           Tcl_GetStringFromObj(objv[2],0), "\": must be flush or size", 0); |  | 
|  1234       return TCL_ERROR; |  | 
|  1235     } |  | 
|  1236     break; |  | 
|  1237   } |  | 
|  1238  |  | 
|  1239   /*     $db changes |  | 
|  1240   ** |  | 
|  1241   ** Return the number of rows that were modified, inserted, or deleted by |  | 
|  1242   ** the most recent INSERT, UPDATE or DELETE statement, not including  |  | 
|  1243   ** any changes made by trigger programs. |  | 
|  1244   */ |  | 
|  1245   case DB_CHANGES: { |  | 
|  1246     Tcl_Obj *pResult; |  | 
|  1247     if( objc!=2 ){ |  | 
|  1248       Tcl_WrongNumArgs(interp, 2, objv, ""); |  | 
|  1249       return TCL_ERROR; |  | 
|  1250     } |  | 
|  1251     pResult = Tcl_GetObjResult(interp); |  | 
|  1252     Tcl_SetIntObj(pResult, sqlite3_changes(pDb->db)); |  | 
|  1253     break; |  | 
|  1254   } |  | 
|  1255  |  | 
|  1256   /*    $db close |  | 
|  1257   ** |  | 
|  1258   ** Shutdown the database |  | 
|  1259   */ |  | 
|  1260   case DB_CLOSE: { |  | 
|  1261     Tcl_DeleteCommand(interp, Tcl_GetStringFromObj(objv[0], 0)); |  | 
|  1262     break; |  | 
|  1263   } |  | 
|  1264  |  | 
|  1265   /* |  | 
|  1266   **     $db collate NAME SCRIPT |  | 
|  1267   ** |  | 
|  1268   ** Create a new SQL collation function called NAME.  Whenever |  | 
|  1269   ** that function is called, invoke SCRIPT to evaluate the function. |  | 
|  1270   */ |  | 
|  1271   case DB_COLLATE: { |  | 
|  1272     SqlCollate *pCollate; |  | 
|  1273     char *zName; |  | 
|  1274     char *zScript; |  | 
|  1275     int nScript; |  | 
|  1276     if( objc!=4 ){ |  | 
|  1277       Tcl_WrongNumArgs(interp, 2, objv, "NAME SCRIPT"); |  | 
|  1278       return TCL_ERROR; |  | 
|  1279     } |  | 
|  1280     zName = Tcl_GetStringFromObj(objv[2], 0); |  | 
|  1281     zScript = Tcl_GetStringFromObj(objv[3], &nScript); |  | 
|  1282     pCollate = (SqlCollate*)Tcl_Alloc( sizeof(*pCollate) + nScript + 1 ); |  | 
|  1283     if( pCollate==0 ) return TCL_ERROR; |  | 
|  1284     pCollate->interp = interp; |  | 
|  1285     pCollate->pNext = pDb->pCollate; |  | 
|  1286     pCollate->zScript = (char*)&pCollate[1]; |  | 
|  1287     pDb->pCollate = pCollate; |  | 
|  1288     memcpy(pCollate->zScript, zScript, nScript+1); |  | 
|  1289     if( sqlite3_create_collation(pDb->db, zName, SQLITE_UTF8,  |  | 
|  1290         pCollate, tclSqlCollate) ){ |  | 
|  1291       Tcl_SetResult(interp, (char *)sqlite3_errmsg(pDb->db), TCL_VOLATILE); |  | 
|  1292       return TCL_ERROR; |  | 
|  1293     } |  | 
|  1294     break; |  | 
|  1295   } |  | 
|  1296  |  | 
|  1297   /* |  | 
|  1298   **     $db collation_needed SCRIPT |  | 
|  1299   ** |  | 
|  1300   ** Create a new SQL collation function called NAME.  Whenever |  | 
|  1301   ** that function is called, invoke SCRIPT to evaluate the function. |  | 
|  1302   */ |  | 
|  1303   case DB_COLLATION_NEEDED: { |  | 
|  1304     if( objc!=3 ){ |  | 
|  1305       Tcl_WrongNumArgs(interp, 2, objv, "SCRIPT"); |  | 
|  1306       return TCL_ERROR; |  | 
|  1307     } |  | 
|  1308     if( pDb->pCollateNeeded ){ |  | 
|  1309       Tcl_DecrRefCount(pDb->pCollateNeeded); |  | 
|  1310     } |  | 
|  1311     pDb->pCollateNeeded = Tcl_DuplicateObj(objv[2]); |  | 
|  1312     Tcl_IncrRefCount(pDb->pCollateNeeded); |  | 
|  1313     sqlite3_collation_needed(pDb->db, pDb, tclCollateNeeded); |  | 
|  1314     break; |  | 
|  1315   } |  | 
|  1316  |  | 
|  1317   /*    $db commit_hook ?CALLBACK? |  | 
|  1318   ** |  | 
|  1319   ** Invoke the given callback just before committing every SQL transaction. |  | 
|  1320   ** If the callback throws an exception or returns non-zero, then the |  | 
|  1321   ** transaction is aborted.  If CALLBACK is an empty string, the callback |  | 
|  1322   ** is disabled. |  | 
|  1323   */ |  | 
|  1324   case DB_COMMIT_HOOK: { |  | 
|  1325     if( objc>3 ){ |  | 
|  1326       Tcl_WrongNumArgs(interp, 2, objv, "?CALLBACK?"); |  | 
|  1327       return TCL_ERROR; |  | 
|  1328     }else if( objc==2 ){ |  | 
|  1329       if( pDb->zCommit ){ |  | 
|  1330         Tcl_AppendResult(interp, pDb->zCommit, 0); |  | 
|  1331       } |  | 
|  1332     }else{ |  | 
|  1333       char *zCommit; |  | 
|  1334       int len; |  | 
|  1335       if( pDb->zCommit ){ |  | 
|  1336         Tcl_Free(pDb->zCommit); |  | 
|  1337       } |  | 
|  1338       zCommit = Tcl_GetStringFromObj(objv[2], &len); |  | 
|  1339       if( zCommit && len>0 ){ |  | 
|  1340         pDb->zCommit = Tcl_Alloc( len + 1 ); |  | 
|  1341         memcpy(pDb->zCommit, zCommit, len+1); |  | 
|  1342       }else{ |  | 
|  1343         pDb->zCommit = 0; |  | 
|  1344       } |  | 
|  1345       if( pDb->zCommit ){ |  | 
|  1346         pDb->interp = interp; |  | 
|  1347         sqlite3_commit_hook(pDb->db, DbCommitHandler, pDb); |  | 
|  1348       }else{ |  | 
|  1349         sqlite3_commit_hook(pDb->db, 0, 0); |  | 
|  1350       } |  | 
|  1351     } |  | 
|  1352     break; |  | 
|  1353   } |  | 
|  1354  |  | 
|  1355   /*    $db complete SQL |  | 
|  1356   ** |  | 
|  1357   ** Return TRUE if SQL is a complete SQL statement.  Return FALSE if |  | 
|  1358   ** additional lines of input are needed.  This is similar to the |  | 
|  1359   ** built-in "info complete" command of Tcl. |  | 
|  1360   */ |  | 
|  1361   case DB_COMPLETE: { |  | 
|  1362 #ifndef SQLITE_OMIT_COMPLETE |  | 
|  1363     Tcl_Obj *pResult; |  | 
|  1364     int isComplete; |  | 
|  1365     if( objc!=3 ){ |  | 
|  1366       Tcl_WrongNumArgs(interp, 2, objv, "SQL"); |  | 
|  1367       return TCL_ERROR; |  | 
|  1368     } |  | 
|  1369     isComplete = sqlite3_complete( Tcl_GetStringFromObj(objv[2], 0) ); |  | 
|  1370     pResult = Tcl_GetObjResult(interp); |  | 
|  1371     Tcl_SetBooleanObj(pResult, isComplete); |  | 
|  1372 #endif |  | 
|  1373     break; |  | 
|  1374   } |  | 
|  1375  |  | 
|  1376   /*    $db copy conflict-algorithm table filename ?SEPARATOR? ?NULLINDICATOR? |  | 
|  1377   ** |  | 
|  1378   ** Copy data into table from filename, optionally using SEPARATOR |  | 
|  1379   ** as column separators.  If a column contains a null string, or the |  | 
|  1380   ** value of NULLINDICATOR, a NULL is inserted for the column. |  | 
|  1381   ** conflict-algorithm is one of the sqlite conflict algorithms: |  | 
|  1382   **    rollback, abort, fail, ignore, replace |  | 
|  1383   ** On success, return the number of lines processed, not necessarily same |  | 
|  1384   ** as 'db changes' due to conflict-algorithm selected. |  | 
|  1385   ** |  | 
|  1386   ** This code is basically an implementation/enhancement of |  | 
|  1387   ** the sqlite3 shell.c ".import" command. |  | 
|  1388   ** |  | 
|  1389   ** This command usage is equivalent to the sqlite2.x COPY statement, |  | 
|  1390   ** which imports file data into a table using the PostgreSQL COPY file format: |  | 
|  1391   **   $db copy $conflit_algo $table_name $filename \t \\N |  | 
|  1392   */ |  | 
|  1393   case DB_COPY: { |  | 
|  1394     char *zTable;               /* Insert data into this table */ |  | 
|  1395     char *zFile;                /* The file from which to extract data */ |  | 
|  1396     char *zConflict;            /* The conflict algorithm to use */ |  | 
|  1397     sqlite3_stmt *pStmt;        /* A statement */ |  | 
|  1398     int nCol;                   /* Number of columns in the table */ |  | 
|  1399     int nByte;                  /* Number of bytes in an SQL string */ |  | 
|  1400     int i, j;                   /* Loop counters */ |  | 
|  1401     int nSep;                   /* Number of bytes in zSep[] */ |  | 
|  1402     int nNull;                  /* Number of bytes in zNull[] */ |  | 
|  1403     char *zSql;                 /* An SQL statement */ |  | 
|  1404     char *zLine;                /* A single line of input from the file */ |  | 
|  1405     char **azCol;               /* zLine[] broken up into columns */ |  | 
|  1406     char *zCommit;              /* How to commit changes */ |  | 
|  1407     FILE *in;                   /* The input file */ |  | 
|  1408     int lineno = 0;             /* Line number of input file */ |  | 
|  1409     char zLineNum[80];          /* Line number print buffer */ |  | 
|  1410     Tcl_Obj *pResult;           /* interp result */ |  | 
|  1411  |  | 
|  1412     char *zSep; |  | 
|  1413     char *zNull; |  | 
|  1414     if( objc<5 || objc>7 ){ |  | 
|  1415       Tcl_WrongNumArgs(interp, 2, objv,  |  | 
|  1416          "CONFLICT-ALGORITHM TABLE FILENAME ?SEPARATOR? ?NULLINDICATOR?"); |  | 
|  1417       return TCL_ERROR; |  | 
|  1418     } |  | 
|  1419     if( objc>=6 ){ |  | 
|  1420       zSep = Tcl_GetStringFromObj(objv[5], 0); |  | 
|  1421     }else{ |  | 
|  1422       zSep = "\t"; |  | 
|  1423     } |  | 
|  1424     if( objc>=7 ){ |  | 
|  1425       zNull = Tcl_GetStringFromObj(objv[6], 0); |  | 
|  1426     }else{ |  | 
|  1427       zNull = ""; |  | 
|  1428     } |  | 
|  1429     zConflict = Tcl_GetStringFromObj(objv[2], 0); |  | 
|  1430     zTable = Tcl_GetStringFromObj(objv[3], 0); |  | 
|  1431     zFile = Tcl_GetStringFromObj(objv[4], 0); |  | 
|  1432     nSep = strlen30(zSep); |  | 
|  1433     nNull = strlen30(zNull); |  | 
|  1434     if( nSep==0 ){ |  | 
|  1435       Tcl_AppendResult(interp,"Error: non-null separator required for copy",0); |  | 
|  1436       return TCL_ERROR; |  | 
|  1437     } |  | 
|  1438     if(strcmp(zConflict, "rollback") != 0 && |  | 
|  1439        strcmp(zConflict, "abort"   ) != 0 && |  | 
|  1440        strcmp(zConflict, "fail"    ) != 0 && |  | 
|  1441        strcmp(zConflict, "ignore"  ) != 0 && |  | 
|  1442        strcmp(zConflict, "replace" ) != 0 ) { |  | 
|  1443       Tcl_AppendResult(interp, "Error: \"", zConflict,  |  | 
|  1444             "\", conflict-algorithm must be one of: rollback, " |  | 
|  1445             "abort, fail, ignore, or replace", 0); |  | 
|  1446       return TCL_ERROR; |  | 
|  1447     } |  | 
|  1448     zSql = sqlite3_mprintf("SELECT * FROM '%q'", zTable); |  | 
|  1449     if( zSql==0 ){ |  | 
|  1450       Tcl_AppendResult(interp, "Error: no such table: ", zTable, 0); |  | 
|  1451       return TCL_ERROR; |  | 
|  1452     } |  | 
|  1453     nByte = strlen30(zSql); |  | 
|  1454     rc = sqlite3_prepare(pDb->db, zSql, -1, &pStmt, 0); |  | 
|  1455     sqlite3_free(zSql); |  | 
|  1456     if( rc ){ |  | 
|  1457       Tcl_AppendResult(interp, "Error: ", sqlite3_errmsg(pDb->db), 0); |  | 
|  1458       nCol = 0; |  | 
|  1459     }else{ |  | 
|  1460       nCol = sqlite3_column_count(pStmt); |  | 
|  1461     } |  | 
|  1462     sqlite3_finalize(pStmt); |  | 
|  1463     if( nCol==0 ) { |  | 
|  1464       return TCL_ERROR; |  | 
|  1465     } |  | 
|  1466     zSql = malloc( nByte + 50 + nCol*2 ); |  | 
|  1467     if( zSql==0 ) { |  | 
|  1468       Tcl_AppendResult(interp, "Error: can't malloc()", 0); |  | 
|  1469       return TCL_ERROR; |  | 
|  1470     } |  | 
|  1471     sqlite3_snprintf(nByte+50, zSql, "INSERT OR %q INTO '%q' VALUES(?", |  | 
|  1472          zConflict, zTable); |  | 
|  1473     j = strlen30(zSql); |  | 
|  1474     for(i=1; i<nCol; i++){ |  | 
|  1475       zSql[j++] = ','; |  | 
|  1476       zSql[j++] = '?'; |  | 
|  1477     } |  | 
|  1478     zSql[j++] = ')'; |  | 
|  1479     zSql[j] = 0; |  | 
|  1480     rc = sqlite3_prepare(pDb->db, zSql, -1, &pStmt, 0); |  | 
|  1481     free(zSql); |  | 
|  1482     if( rc ){ |  | 
|  1483       Tcl_AppendResult(interp, "Error: ", sqlite3_errmsg(pDb->db), 0); |  | 
|  1484       sqlite3_finalize(pStmt); |  | 
|  1485       return TCL_ERROR; |  | 
|  1486     } |  | 
|  1487     in = fopen(zFile, "rb"); |  | 
|  1488     if( in==0 ){ |  | 
|  1489       Tcl_AppendResult(interp, "Error: cannot open file: ", zFile, NULL); |  | 
|  1490       sqlite3_finalize(pStmt); |  | 
|  1491       return TCL_ERROR; |  | 
|  1492     } |  | 
|  1493     azCol = malloc( sizeof(azCol[0])*(nCol+1) ); |  | 
|  1494     if( azCol==0 ) { |  | 
|  1495       Tcl_AppendResult(interp, "Error: can't malloc()", 0); |  | 
|  1496       fclose(in); |  | 
|  1497       return TCL_ERROR; |  | 
|  1498     } |  | 
|  1499     (void)sqlite3_exec(pDb->db, "BEGIN", 0, 0, 0); |  | 
|  1500     zCommit = "COMMIT"; |  | 
|  1501     while( (zLine = local_getline(0, in))!=0 ){ |  | 
|  1502       char *z; |  | 
|  1503       i = 0; |  | 
|  1504       lineno++; |  | 
|  1505       azCol[0] = zLine; |  | 
|  1506       for(i=0, z=zLine; *z; z++){ |  | 
|  1507         if( *z==zSep[0] && strncmp(z, zSep, nSep)==0 ){ |  | 
|  1508           *z = 0; |  | 
|  1509           i++; |  | 
|  1510           if( i<nCol ){ |  | 
|  1511             azCol[i] = &z[nSep]; |  | 
|  1512             z += nSep-1; |  | 
|  1513           } |  | 
|  1514         } |  | 
|  1515       } |  | 
|  1516       if( i+1!=nCol ){ |  | 
|  1517         char *zErr; |  | 
|  1518         int nErr = strlen30(zFile) + 200; |  | 
|  1519         zErr = malloc(nErr); |  | 
|  1520         if( zErr ){ |  | 
|  1521           sqlite3_snprintf(nErr, zErr, |  | 
|  1522              "Error: %s line %d: expected %d columns of data but found %d", |  | 
|  1523              zFile, lineno, nCol, i+1); |  | 
|  1524           Tcl_AppendResult(interp, zErr, 0); |  | 
|  1525           free(zErr); |  | 
|  1526         } |  | 
|  1527         zCommit = "ROLLBACK"; |  | 
|  1528         break; |  | 
|  1529       } |  | 
|  1530       for(i=0; i<nCol; i++){ |  | 
|  1531         /* check for null data, if so, bind as null */ |  | 
|  1532         if( (nNull>0 && strcmp(azCol[i], zNull)==0) |  | 
|  1533           || strlen30(azCol[i])==0  |  | 
|  1534         ){ |  | 
|  1535           sqlite3_bind_null(pStmt, i+1); |  | 
|  1536         }else{ |  | 
|  1537           sqlite3_bind_text(pStmt, i+1, azCol[i], -1, SQLITE_STATIC); |  | 
|  1538         } |  | 
|  1539       } |  | 
|  1540       sqlite3_step(pStmt); |  | 
|  1541       rc = sqlite3_reset(pStmt); |  | 
|  1542       free(zLine); |  | 
|  1543       if( rc!=SQLITE_OK ){ |  | 
|  1544         Tcl_AppendResult(interp,"Error: ", sqlite3_errmsg(pDb->db), 0); |  | 
|  1545         zCommit = "ROLLBACK"; |  | 
|  1546         break; |  | 
|  1547       } |  | 
|  1548     } |  | 
|  1549     free(azCol); |  | 
|  1550     fclose(in); |  | 
|  1551     sqlite3_finalize(pStmt); |  | 
|  1552     (void)sqlite3_exec(pDb->db, zCommit, 0, 0, 0); |  | 
|  1553  |  | 
|  1554     if( zCommit[0] == 'C' ){ |  | 
|  1555       /* success, set result as number of lines processed */ |  | 
|  1556       pResult = Tcl_GetObjResult(interp); |  | 
|  1557       Tcl_SetIntObj(pResult, lineno); |  | 
|  1558       rc = TCL_OK; |  | 
|  1559     }else{ |  | 
|  1560       /* failure, append lineno where failed */ |  | 
|  1561       sqlite3_snprintf(sizeof(zLineNum), zLineNum,"%d",lineno); |  | 
|  1562       Tcl_AppendResult(interp,", failed while processing line: ",zLineNum,0); |  | 
|  1563       rc = TCL_ERROR; |  | 
|  1564     } |  | 
|  1565     break; |  | 
|  1566   } |  | 
|  1567  |  | 
|  1568   /* |  | 
|  1569   **    $db enable_load_extension BOOLEAN |  | 
|  1570   ** |  | 
|  1571   ** Turn the extension loading feature on or off.  It if off by |  | 
|  1572   ** default. |  | 
|  1573   */ |  | 
|  1574   case DB_ENABLE_LOAD_EXTENSION: { |  | 
|  1575 #ifndef SQLITE_OMIT_LOAD_EXTENSION |  | 
|  1576     int onoff; |  | 
|  1577     if( objc!=3 ){ |  | 
|  1578       Tcl_WrongNumArgs(interp, 2, objv, "BOOLEAN"); |  | 
|  1579       return TCL_ERROR; |  | 
|  1580     } |  | 
|  1581     if( Tcl_GetBooleanFromObj(interp, objv[2], &onoff) ){ |  | 
|  1582       return TCL_ERROR; |  | 
|  1583     } |  | 
|  1584     sqlite3_enable_load_extension(pDb->db, onoff); |  | 
|  1585     break; |  | 
|  1586 #else |  | 
|  1587     Tcl_AppendResult(interp, "extension loading is turned off at compile-time", |  | 
|  1588                      0); |  | 
|  1589     return TCL_ERROR; |  | 
|  1590 #endif |  | 
|  1591   } |  | 
|  1592  |  | 
|  1593   /* |  | 
|  1594   **    $db errorcode |  | 
|  1595   ** |  | 
|  1596   ** Return the numeric error code that was returned by the most recent |  | 
|  1597   ** call to sqlite3_exec(). |  | 
|  1598   */ |  | 
|  1599   case DB_ERRORCODE: { |  | 
|  1600     Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_errcode(pDb->db))); |  | 
|  1601     break; |  | 
|  1602   } |  | 
|  1603     |  | 
|  1604   /* |  | 
|  1605   **    $db eval $sql ?array? ?{  ...code... }? |  | 
|  1606   **    $db onecolumn $sql |  | 
|  1607   ** |  | 
|  1608   ** The SQL statement in $sql is evaluated.  For each row, the values are |  | 
|  1609   ** placed in elements of the array named "array" and ...code... is executed. |  | 
|  1610   ** If "array" and "code" are omitted, then no callback is every invoked. |  | 
|  1611   ** If "array" is an empty string, then the values are placed in variables |  | 
|  1612   ** that have the same name as the fields extracted by the query. |  | 
|  1613   ** |  | 
|  1614   ** The onecolumn method is the equivalent of: |  | 
|  1615   **     lindex [$db eval $sql] 0 |  | 
|  1616   */ |  | 
|  1617   case DB_ONECOLUMN: |  | 
|  1618   case DB_EVAL: |  | 
|  1619   case DB_EXISTS: { |  | 
|  1620     char const *zSql;      /* Next SQL statement to execute */ |  | 
|  1621     char const *zLeft;     /* What is left after first stmt in zSql */ |  | 
|  1622     sqlite3_stmt *pStmt;   /* Compiled SQL statment */ |  | 
|  1623     Tcl_Obj *pArray;       /* Name of array into which results are written */ |  | 
|  1624     Tcl_Obj *pScript;      /* Script to run for each result set */ |  | 
|  1625     Tcl_Obj **apParm;      /* Parameters that need a Tcl_DecrRefCount() */ |  | 
|  1626     int nParm;             /* Number of entries used in apParm[] */ |  | 
|  1627     Tcl_Obj *aParm[10];    /* Static space for apParm[] in the common case */ |  | 
|  1628     Tcl_Obj *pRet;         /* Value to be returned */ |  | 
|  1629     SqlPreparedStmt *pPreStmt;  /* Pointer to a prepared statement */ |  | 
|  1630     int rc2; |  | 
|  1631  |  | 
|  1632     if( choice==DB_EVAL ){ |  | 
|  1633       if( objc<3 || objc>5 ){ |  | 
|  1634         Tcl_WrongNumArgs(interp, 2, objv, "SQL ?ARRAY-NAME? ?SCRIPT?"); |  | 
|  1635         return TCL_ERROR; |  | 
|  1636       } |  | 
|  1637       pRet = Tcl_NewObj(); |  | 
|  1638       Tcl_IncrRefCount(pRet); |  | 
|  1639     }else{ |  | 
|  1640       if( objc!=3 ){ |  | 
|  1641         Tcl_WrongNumArgs(interp, 2, objv, "SQL"); |  | 
|  1642         return TCL_ERROR; |  | 
|  1643       } |  | 
|  1644       if( choice==DB_EXISTS ){ |  | 
|  1645         pRet = Tcl_NewBooleanObj(0); |  | 
|  1646         Tcl_IncrRefCount(pRet); |  | 
|  1647       }else{ |  | 
|  1648         pRet = 0; |  | 
|  1649       } |  | 
|  1650     } |  | 
|  1651     if( objc==3 ){ |  | 
|  1652       pArray = pScript = 0; |  | 
|  1653     }else if( objc==4 ){ |  | 
|  1654       pArray = 0; |  | 
|  1655       pScript = objv[3]; |  | 
|  1656     }else{ |  | 
|  1657       pArray = objv[3]; |  | 
|  1658       if( Tcl_GetString(pArray)[0]==0 ) pArray = 0; |  | 
|  1659       pScript = objv[4]; |  | 
|  1660     } |  | 
|  1661  |  | 
|  1662     Tcl_IncrRefCount(objv[2]); |  | 
|  1663     zSql = Tcl_GetStringFromObj(objv[2], 0); |  | 
|  1664     while( rc==TCL_OK && zSql[0] ){ |  | 
|  1665       int i;                     /* Loop counter */ |  | 
|  1666       int nVar;                  /* Number of bind parameters in the pStmt */ |  | 
|  1667       int nCol = -1;             /* Number of columns in the result set */ |  | 
|  1668       Tcl_Obj **apColName = 0;   /* Array of column names */ |  | 
|  1669       int len;                   /* String length of zSql */ |  | 
|  1670    |  | 
|  1671       /* Try to find a SQL statement that has already been compiled and |  | 
|  1672       ** which matches the next sequence of SQL. |  | 
|  1673       */ |  | 
|  1674       pStmt = 0; |  | 
|  1675       while( isspace(zSql[0]) ){ zSql++; } |  | 
|  1676       len = strlen30(zSql); |  | 
|  1677       for(pPreStmt = pDb->stmtList; pPreStmt; pPreStmt=pPreStmt->pNext){ |  | 
|  1678         int n = pPreStmt->nSql; |  | 
|  1679         if( len>=n  |  | 
|  1680             && memcmp(pPreStmt->zSql, zSql, n)==0 |  | 
|  1681             && (zSql[n]==0 || zSql[n-1]==';') |  | 
|  1682         ){ |  | 
|  1683           pStmt = pPreStmt->pStmt; |  | 
|  1684           zLeft = &zSql[pPreStmt->nSql]; |  | 
|  1685  |  | 
|  1686           /* When a prepared statement is found, unlink it from the |  | 
|  1687           ** cache list.  It will later be added back to the beginning |  | 
|  1688           ** of the cache list in order to implement LRU replacement. |  | 
|  1689           */ |  | 
|  1690           if( pPreStmt->pPrev ){ |  | 
|  1691             pPreStmt->pPrev->pNext = pPreStmt->pNext; |  | 
|  1692           }else{ |  | 
|  1693             pDb->stmtList = pPreStmt->pNext; |  | 
|  1694           } |  | 
|  1695           if( pPreStmt->pNext ){ |  | 
|  1696             pPreStmt->pNext->pPrev = pPreStmt->pPrev; |  | 
|  1697           }else{ |  | 
|  1698             pDb->stmtLast = pPreStmt->pPrev; |  | 
|  1699           } |  | 
|  1700           pDb->nStmt--; |  | 
|  1701           break; |  | 
|  1702         } |  | 
|  1703       } |  | 
|  1704    |  | 
|  1705       /* If no prepared statement was found.  Compile the SQL text |  | 
|  1706       */ |  | 
|  1707       if( pStmt==0 ){ |  | 
|  1708         if( SQLITE_OK!=sqlite3_prepare_v2(pDb->db, zSql, -1, &pStmt, &zLeft) ){ |  | 
|  1709           Tcl_SetObjResult(interp, dbTextToObj(sqlite3_errmsg(pDb->db))); |  | 
|  1710           rc = TCL_ERROR; |  | 
|  1711           break; |  | 
|  1712         } |  | 
|  1713         if( pStmt==0 ){ |  | 
|  1714           if( SQLITE_OK!=sqlite3_errcode(pDb->db) ){ |  | 
|  1715             /* A compile-time error in the statement |  | 
|  1716             */ |  | 
|  1717             Tcl_SetObjResult(interp, dbTextToObj(sqlite3_errmsg(pDb->db))); |  | 
|  1718             rc = TCL_ERROR; |  | 
|  1719             break; |  | 
|  1720           }else{ |  | 
|  1721             /* The statement was a no-op.  Continue to the next statement |  | 
|  1722             ** in the SQL string. |  | 
|  1723             */ |  | 
|  1724             zSql = zLeft; |  | 
|  1725             continue; |  | 
|  1726           } |  | 
|  1727         } |  | 
|  1728         assert( pPreStmt==0 ); |  | 
|  1729       } |  | 
|  1730  |  | 
|  1731       /* Bind values to parameters that begin with $ or : |  | 
|  1732       */   |  | 
|  1733       nVar = sqlite3_bind_parameter_count(pStmt); |  | 
|  1734       nParm = 0; |  | 
|  1735       if( nVar>sizeof(aParm)/sizeof(aParm[0]) ){ |  | 
|  1736         apParm = (Tcl_Obj**)Tcl_Alloc(nVar*sizeof(apParm[0])); |  | 
|  1737       }else{ |  | 
|  1738         apParm = aParm; |  | 
|  1739       } |  | 
|  1740       for(i=1; i<=nVar; i++){ |  | 
|  1741         const char *zVar = sqlite3_bind_parameter_name(pStmt, i); |  | 
|  1742         if( zVar!=0 && (zVar[0]=='$' || zVar[0]==':' || zVar[0]=='@') ){ |  | 
|  1743           Tcl_Obj *pVar = Tcl_GetVar2Ex(interp, &zVar[1], 0, 0); |  | 
|  1744           if( pVar ){ |  | 
|  1745             int n; |  | 
|  1746             u8 *data; |  | 
|  1747             char *zType = pVar->typePtr ? pVar->typePtr->name : ""; |  | 
|  1748             char c = zType[0]; |  | 
|  1749             if( zVar[0]=='@' || |  | 
|  1750                (c=='b' && strcmp(zType,"bytearray")==0 && pVar->bytes==0) ){ |  | 
|  1751               /* Load a BLOB type if the Tcl variable is a bytearray and |  | 
|  1752               ** it has no string representation or the host |  | 
|  1753               ** parameter name begins with "@". */ |  | 
|  1754               data = Tcl_GetByteArrayFromObj(pVar, &n); |  | 
|  1755               sqlite3_bind_blob(pStmt, i, data, n, SQLITE_STATIC); |  | 
|  1756               Tcl_IncrRefCount(pVar); |  | 
|  1757               apParm[nParm++] = pVar; |  | 
|  1758             }else if( c=='b' && strcmp(zType,"boolean")==0 ){ |  | 
|  1759               Tcl_GetIntFromObj(interp, pVar, &n); |  | 
|  1760               sqlite3_bind_int(pStmt, i, n); |  | 
|  1761             }else if( c=='d' && strcmp(zType,"double")==0 ){ |  | 
|  1762               double r; |  | 
|  1763               Tcl_GetDoubleFromObj(interp, pVar, &r); |  | 
|  1764               sqlite3_bind_double(pStmt, i, r); |  | 
|  1765             }else if( (c=='w' && strcmp(zType,"wideInt")==0) || |  | 
|  1766                   (c=='i' && strcmp(zType,"int")==0) ){ |  | 
|  1767               Tcl_WideInt v; |  | 
|  1768               Tcl_GetWideIntFromObj(interp, pVar, &v); |  | 
|  1769               sqlite3_bind_int64(pStmt, i, v); |  | 
|  1770             }else{ |  | 
|  1771               data = (unsigned char *)Tcl_GetStringFromObj(pVar, &n); |  | 
|  1772               sqlite3_bind_text(pStmt, i, (char *)data, n, SQLITE_STATIC); |  | 
|  1773               Tcl_IncrRefCount(pVar); |  | 
|  1774               apParm[nParm++] = pVar; |  | 
|  1775             } |  | 
|  1776           }else{ |  | 
|  1777             sqlite3_bind_null( pStmt, i ); |  | 
|  1778           } |  | 
|  1779         } |  | 
|  1780       } |  | 
|  1781  |  | 
|  1782       /* Execute the SQL |  | 
|  1783       */ |  | 
|  1784       while( rc==TCL_OK && pStmt && SQLITE_ROW==sqlite3_step(pStmt) ){ |  | 
|  1785  |  | 
|  1786         /* Compute column names. This must be done after the first successful |  | 
|  1787         ** call to sqlite3_step(), in case the query is recompiled and the |  | 
|  1788         ** number or names of the returned columns changes.  |  | 
|  1789         */ |  | 
|  1790         assert(!pArray||pScript); |  | 
|  1791         if (nCol < 0) { |  | 
|  1792           Tcl_Obj ***ap = (pScript?&apColName:0); |  | 
|  1793           nCol = computeColumnNames(interp, pStmt, ap, pArray); |  | 
|  1794         } |  | 
|  1795  |  | 
|  1796         for(i=0; i<nCol; i++){ |  | 
|  1797           Tcl_Obj *pVal; |  | 
|  1798            |  | 
|  1799           /* Set pVal to contain the i'th column of this row. */ |  | 
|  1800           switch( sqlite3_column_type(pStmt, i) ){ |  | 
|  1801             case SQLITE_BLOB: { |  | 
|  1802               int bytes = sqlite3_column_bytes(pStmt, i); |  | 
|  1803               const char *zBlob = sqlite3_column_blob(pStmt, i); |  | 
|  1804               if( !zBlob ) bytes = 0; |  | 
|  1805               pVal = Tcl_NewByteArrayObj((u8*)zBlob, bytes); |  | 
|  1806               break; |  | 
|  1807             } |  | 
|  1808             case SQLITE_INTEGER: { |  | 
|  1809               sqlite_int64 v = sqlite3_column_int64(pStmt, i); |  | 
|  1810               if( v>=-2147483647 && v<=2147483647 ){ |  | 
|  1811                 pVal = Tcl_NewIntObj(v); |  | 
|  1812               }else{ |  | 
|  1813                 pVal = Tcl_NewWideIntObj(v); |  | 
|  1814               } |  | 
|  1815               break; |  | 
|  1816             } |  | 
|  1817             case SQLITE_FLOAT: { |  | 
|  1818               double r = sqlite3_column_double(pStmt, i); |  | 
|  1819               pVal = Tcl_NewDoubleObj(r); |  | 
|  1820               break; |  | 
|  1821             } |  | 
|  1822             case SQLITE_NULL: { |  | 
|  1823               pVal = dbTextToObj(pDb->zNull); |  | 
|  1824               break; |  | 
|  1825             } |  | 
|  1826             default: { |  | 
|  1827               pVal = dbTextToObj((char *)sqlite3_column_text(pStmt, i)); |  | 
|  1828               break; |  | 
|  1829             } |  | 
|  1830           } |  | 
|  1831    |  | 
|  1832           if( pScript ){ |  | 
|  1833             if( pArray==0 ){ |  | 
|  1834               Tcl_ObjSetVar2(interp, apColName[i], 0, pVal, 0); |  | 
|  1835             }else{ |  | 
|  1836               Tcl_ObjSetVar2(interp, pArray, apColName[i], pVal, 0); |  | 
|  1837             } |  | 
|  1838           }else if( choice==DB_ONECOLUMN ){ |  | 
|  1839             assert( pRet==0 ); |  | 
|  1840             if( pRet==0 ){ |  | 
|  1841               pRet = pVal; |  | 
|  1842               Tcl_IncrRefCount(pRet); |  | 
|  1843             } |  | 
|  1844             rc = TCL_BREAK; |  | 
|  1845             i = nCol; |  | 
|  1846           }else if( choice==DB_EXISTS ){ |  | 
|  1847             Tcl_DecrRefCount(pRet); |  | 
|  1848             pRet = Tcl_NewBooleanObj(1); |  | 
|  1849             Tcl_IncrRefCount(pRet); |  | 
|  1850             rc = TCL_BREAK; |  | 
|  1851             i = nCol; |  | 
|  1852           }else{ |  | 
|  1853             Tcl_ListObjAppendElement(interp, pRet, pVal); |  | 
|  1854           } |  | 
|  1855         } |  | 
|  1856    |  | 
|  1857         if( pScript ){ |  | 
|  1858           pDb->nStep = sqlite3_stmt_status(pStmt,  |  | 
|  1859                                   SQLITE_STMTSTATUS_FULLSCAN_STEP, 0); |  | 
|  1860           pDb->nSort = sqlite3_stmt_status(pStmt, |  | 
|  1861                                   SQLITE_STMTSTATUS_SORT, 0); |  | 
|  1862           rc = Tcl_EvalObjEx(interp, pScript, 0); |  | 
|  1863           if( rc==TCL_CONTINUE ){ |  | 
|  1864             rc = TCL_OK; |  | 
|  1865           } |  | 
|  1866         } |  | 
|  1867       } |  | 
|  1868       if( rc==TCL_BREAK ){ |  | 
|  1869         rc = TCL_OK; |  | 
|  1870       } |  | 
|  1871  |  | 
|  1872       /* Free the column name objects */ |  | 
|  1873       if( pScript ){ |  | 
|  1874         /* If the query returned no rows, but an array variable was  |  | 
|  1875         ** specified, call computeColumnNames() now to populate the  |  | 
|  1876         ** arrayname(*) variable. |  | 
|  1877         */ |  | 
|  1878         if (pArray && nCol < 0) { |  | 
|  1879           Tcl_Obj ***ap = (pScript?&apColName:0); |  | 
|  1880           nCol = computeColumnNames(interp, pStmt, ap, pArray); |  | 
|  1881         } |  | 
|  1882         for(i=0; i<nCol; i++){ |  | 
|  1883           Tcl_DecrRefCount(apColName[i]); |  | 
|  1884         } |  | 
|  1885         Tcl_Free((char*)apColName); |  | 
|  1886       } |  | 
|  1887  |  | 
|  1888       /* Free the bound string and blob parameters */ |  | 
|  1889       for(i=0; i<nParm; i++){ |  | 
|  1890         Tcl_DecrRefCount(apParm[i]); |  | 
|  1891       } |  | 
|  1892       if( apParm!=aParm ){ |  | 
|  1893         Tcl_Free((char*)apParm); |  | 
|  1894       } |  | 
|  1895  |  | 
|  1896       /* Reset the statement.  If the result code is SQLITE_SCHEMA, then |  | 
|  1897       ** flush the statement cache and try the statement again. |  | 
|  1898       */ |  | 
|  1899       rc2 = sqlite3_reset(pStmt); |  | 
|  1900       pDb->nStep = sqlite3_stmt_status(pStmt,  |  | 
|  1901                                   SQLITE_STMTSTATUS_FULLSCAN_STEP, 1); |  | 
|  1902       pDb->nSort = sqlite3_stmt_status(pStmt, |  | 
|  1903                                   SQLITE_STMTSTATUS_SORT, 1); |  | 
|  1904       if( SQLITE_OK!=rc2 ){ |  | 
|  1905         /* If a run-time error occurs, report the error and stop reading |  | 
|  1906         ** the SQL |  | 
|  1907         */ |  | 
|  1908         Tcl_SetObjResult(interp, dbTextToObj(sqlite3_errmsg(pDb->db))); |  | 
|  1909         sqlite3_finalize(pStmt); |  | 
|  1910         rc = TCL_ERROR; |  | 
|  1911         if( pPreStmt ) Tcl_Free((char*)pPreStmt); |  | 
|  1912         break; |  | 
|  1913       }else if( pDb->maxStmt<=0 ){ |  | 
|  1914         /* If the cache is turned off, deallocated the statement */ |  | 
|  1915         if( pPreStmt ) Tcl_Free((char*)pPreStmt); |  | 
|  1916         sqlite3_finalize(pStmt); |  | 
|  1917       }else{ |  | 
|  1918         /* Everything worked and the cache is operational. |  | 
|  1919         ** Create a new SqlPreparedStmt structure if we need one. |  | 
|  1920         ** (If we already have one we can just reuse it.) |  | 
|  1921         */ |  | 
|  1922         if( pPreStmt==0 ){ |  | 
|  1923           len = zLeft - zSql; |  | 
|  1924           pPreStmt = (SqlPreparedStmt*)Tcl_Alloc( sizeof(*pPreStmt) ); |  | 
|  1925           if( pPreStmt==0 ) return TCL_ERROR; |  | 
|  1926           pPreStmt->pStmt = pStmt; |  | 
|  1927           pPreStmt->nSql = len; |  | 
|  1928           pPreStmt->zSql = sqlite3_sql(pStmt); |  | 
|  1929           assert( strlen30(pPreStmt->zSql)==len ); |  | 
|  1930           assert( 0==memcmp(pPreStmt->zSql, zSql, len) ); |  | 
|  1931         } |  | 
|  1932  |  | 
|  1933         /* Add the prepared statement to the beginning of the cache list |  | 
|  1934         */ |  | 
|  1935         pPreStmt->pNext = pDb->stmtList; |  | 
|  1936         pPreStmt->pPrev = 0; |  | 
|  1937         if( pDb->stmtList ){ |  | 
|  1938          pDb->stmtList->pPrev = pPreStmt; |  | 
|  1939         } |  | 
|  1940         pDb->stmtList = pPreStmt; |  | 
|  1941         if( pDb->stmtLast==0 ){ |  | 
|  1942           assert( pDb->nStmt==0 ); |  | 
|  1943           pDb->stmtLast = pPreStmt; |  | 
|  1944         }else{ |  | 
|  1945           assert( pDb->nStmt>0 ); |  | 
|  1946         } |  | 
|  1947         pDb->nStmt++; |  | 
|  1948     |  | 
|  1949         /* If we have too many statement in cache, remove the surplus from the |  | 
|  1950         ** end of the cache list. |  | 
|  1951         */ |  | 
|  1952         while( pDb->nStmt>pDb->maxStmt ){ |  | 
|  1953           sqlite3_finalize(pDb->stmtLast->pStmt); |  | 
|  1954           pDb->stmtLast = pDb->stmtLast->pPrev; |  | 
|  1955           Tcl_Free((char*)pDb->stmtLast->pNext); |  | 
|  1956           pDb->stmtLast->pNext = 0; |  | 
|  1957           pDb->nStmt--; |  | 
|  1958         } |  | 
|  1959       } |  | 
|  1960  |  | 
|  1961       /* Proceed to the next statement */ |  | 
|  1962       zSql = zLeft; |  | 
|  1963     } |  | 
|  1964     Tcl_DecrRefCount(objv[2]); |  | 
|  1965  |  | 
|  1966     if( pRet ){ |  | 
|  1967       if( rc==TCL_OK ){ |  | 
|  1968         Tcl_SetObjResult(interp, pRet); |  | 
|  1969       } |  | 
|  1970       Tcl_DecrRefCount(pRet); |  | 
|  1971     }else if( rc==TCL_OK ){ |  | 
|  1972       Tcl_ResetResult(interp); |  | 
|  1973     } |  | 
|  1974     break; |  | 
|  1975   } |  | 
|  1976  |  | 
|  1977   /* |  | 
|  1978   **     $db function NAME [-argcount N] SCRIPT |  | 
|  1979   ** |  | 
|  1980   ** Create a new SQL function called NAME.  Whenever that function is |  | 
|  1981   ** called, invoke SCRIPT to evaluate the function. |  | 
|  1982   */ |  | 
|  1983   case DB_FUNCTION: { |  | 
|  1984     SqlFunc *pFunc; |  | 
|  1985     Tcl_Obj *pScript; |  | 
|  1986     char *zName; |  | 
|  1987     int nArg = -1; |  | 
|  1988     if( objc==6 ){ |  | 
|  1989       const char *z = Tcl_GetString(objv[3]); |  | 
|  1990       int n = strlen30(z); |  | 
|  1991       if( n>2 && strncmp(z, "-argcount",n)==0 ){ |  | 
|  1992         if( Tcl_GetIntFromObj(interp, objv[4], &nArg) ) return TCL_ERROR; |  | 
|  1993         if( nArg<0 ){ |  | 
|  1994           Tcl_AppendResult(interp, "number of arguments must be non-negative", |  | 
|  1995                            (char*)0); |  | 
|  1996           return TCL_ERROR; |  | 
|  1997         } |  | 
|  1998       } |  | 
|  1999       pScript = objv[5]; |  | 
|  2000     }else if( objc!=4 ){ |  | 
|  2001       Tcl_WrongNumArgs(interp, 2, objv, "NAME [-argcount N] SCRIPT"); |  | 
|  2002       return TCL_ERROR; |  | 
|  2003     }else{ |  | 
|  2004       pScript = objv[3]; |  | 
|  2005     } |  | 
|  2006     zName = Tcl_GetStringFromObj(objv[2], 0); |  | 
|  2007     pFunc = findSqlFunc(pDb, zName); |  | 
|  2008     if( pFunc==0 ) return TCL_ERROR; |  | 
|  2009     if( pFunc->pScript ){ |  | 
|  2010       Tcl_DecrRefCount(pFunc->pScript); |  | 
|  2011     } |  | 
|  2012     pFunc->pScript = pScript; |  | 
|  2013     Tcl_IncrRefCount(pScript); |  | 
|  2014     pFunc->useEvalObjv = safeToUseEvalObjv(interp, pScript); |  | 
|  2015     rc = sqlite3_create_function(pDb->db, zName, nArg, SQLITE_UTF8, |  | 
|  2016         pFunc, tclSqlFunc, 0, 0); |  | 
|  2017     if( rc!=SQLITE_OK ){ |  | 
|  2018       rc = TCL_ERROR; |  | 
|  2019       Tcl_SetResult(interp, (char *)sqlite3_errmsg(pDb->db), TCL_VOLATILE); |  | 
|  2020     } |  | 
|  2021     break; |  | 
|  2022   } |  | 
|  2023  |  | 
|  2024   /* |  | 
|  2025   **     $db incrblob ?-readonly? ?DB? TABLE COLUMN ROWID |  | 
|  2026   */ |  | 
|  2027   case DB_INCRBLOB: { |  | 
|  2028 #ifdef SQLITE_OMIT_INCRBLOB |  | 
|  2029     Tcl_AppendResult(interp, "incrblob not available in this build", 0); |  | 
|  2030     return TCL_ERROR; |  | 
|  2031 #else |  | 
|  2032     int isReadonly = 0; |  | 
|  2033     const char *zDb = "main"; |  | 
|  2034     const char *zTable; |  | 
|  2035     const char *zColumn; |  | 
|  2036     sqlite_int64 iRow; |  | 
|  2037  |  | 
|  2038     /* Check for the -readonly option */ |  | 
|  2039     if( objc>3 && strcmp(Tcl_GetString(objv[2]), "-readonly")==0 ){ |  | 
|  2040       isReadonly = 1; |  | 
|  2041     } |  | 
|  2042  |  | 
|  2043     if( objc!=(5+isReadonly) && objc!=(6+isReadonly) ){ |  | 
|  2044       Tcl_WrongNumArgs(interp, 2, objv, "?-readonly? ?DB? TABLE COLUMN ROWID"); |  | 
|  2045       return TCL_ERROR; |  | 
|  2046     } |  | 
|  2047  |  | 
|  2048     if( objc==(6+isReadonly) ){ |  | 
|  2049       zDb = Tcl_GetString(objv[2]); |  | 
|  2050     } |  | 
|  2051     zTable = Tcl_GetString(objv[objc-3]); |  | 
|  2052     zColumn = Tcl_GetString(objv[objc-2]); |  | 
|  2053     rc = Tcl_GetWideIntFromObj(interp, objv[objc-1], &iRow); |  | 
|  2054  |  | 
|  2055     if( rc==TCL_OK ){ |  | 
|  2056       rc = createIncrblobChannel( |  | 
|  2057           interp, pDb, zDb, zTable, zColumn, iRow, isReadonly |  | 
|  2058       ); |  | 
|  2059     } |  | 
|  2060 #endif |  | 
|  2061     break; |  | 
|  2062   } |  | 
|  2063  |  | 
|  2064   /* |  | 
|  2065   **     $db interrupt |  | 
|  2066   ** |  | 
|  2067   ** Interrupt the execution of the inner-most SQL interpreter.  This |  | 
|  2068   ** causes the SQL statement to return an error of SQLITE_INTERRUPT. |  | 
|  2069   */ |  | 
|  2070   case DB_INTERRUPT: { |  | 
|  2071     sqlite3_interrupt(pDb->db); |  | 
|  2072     break; |  | 
|  2073   } |  | 
|  2074  |  | 
|  2075   /* |  | 
|  2076   **     $db nullvalue ?STRING? |  | 
|  2077   ** |  | 
|  2078   ** Change text used when a NULL comes back from the database. If ?STRING? |  | 
|  2079   ** is not present, then the current string used for NULL is returned. |  | 
|  2080   ** If STRING is present, then STRING is returned. |  | 
|  2081   ** |  | 
|  2082   */ |  | 
|  2083   case DB_NULLVALUE: { |  | 
|  2084     if( objc!=2 && objc!=3 ){ |  | 
|  2085       Tcl_WrongNumArgs(interp, 2, objv, "NULLVALUE"); |  | 
|  2086       return TCL_ERROR; |  | 
|  2087     } |  | 
|  2088     if( objc==3 ){ |  | 
|  2089       int len; |  | 
|  2090       char *zNull = Tcl_GetStringFromObj(objv[2], &len); |  | 
|  2091       if( pDb->zNull ){ |  | 
|  2092         Tcl_Free(pDb->zNull); |  | 
|  2093       } |  | 
|  2094       if( zNull && len>0 ){ |  | 
|  2095         pDb->zNull = Tcl_Alloc( len + 1 ); |  | 
|  2096         strncpy(pDb->zNull, zNull, len); |  | 
|  2097         pDb->zNull[len] = '\0'; |  | 
|  2098       }else{ |  | 
|  2099         pDb->zNull = 0; |  | 
|  2100       } |  | 
|  2101     } |  | 
|  2102     Tcl_SetObjResult(interp, dbTextToObj(pDb->zNull)); |  | 
|  2103     break; |  | 
|  2104   } |  | 
|  2105  |  | 
|  2106   /* |  | 
|  2107   **     $db last_insert_rowid  |  | 
|  2108   ** |  | 
|  2109   ** Return an integer which is the ROWID for the most recent insert. |  | 
|  2110   */ |  | 
|  2111   case DB_LAST_INSERT_ROWID: { |  | 
|  2112     Tcl_Obj *pResult; |  | 
|  2113     Tcl_WideInt rowid; |  | 
|  2114     if( objc!=2 ){ |  | 
|  2115       Tcl_WrongNumArgs(interp, 2, objv, ""); |  | 
|  2116       return TCL_ERROR; |  | 
|  2117     } |  | 
|  2118     rowid = sqlite3_last_insert_rowid(pDb->db); |  | 
|  2119     pResult = Tcl_GetObjResult(interp); |  | 
|  2120     Tcl_SetWideIntObj(pResult, rowid); |  | 
|  2121     break; |  | 
|  2122   } |  | 
|  2123  |  | 
|  2124   /* |  | 
|  2125   ** The DB_ONECOLUMN method is implemented together with DB_EVAL. |  | 
|  2126   */ |  | 
|  2127  |  | 
|  2128   /*    $db progress ?N CALLBACK? |  | 
|  2129   **  |  | 
|  2130   ** Invoke the given callback every N virtual machine opcodes while executing |  | 
|  2131   ** queries. |  | 
|  2132   */ |  | 
|  2133   case DB_PROGRESS: { |  | 
|  2134     if( objc==2 ){ |  | 
|  2135       if( pDb->zProgress ){ |  | 
|  2136         Tcl_AppendResult(interp, pDb->zProgress, 0); |  | 
|  2137       } |  | 
|  2138     }else if( objc==4 ){ |  | 
|  2139       char *zProgress; |  | 
|  2140       int len; |  | 
|  2141       int N; |  | 
|  2142       if( TCL_OK!=Tcl_GetIntFromObj(interp, objv[2], &N) ){ |  | 
|  2143         return TCL_ERROR; |  | 
|  2144       }; |  | 
|  2145       if( pDb->zProgress ){ |  | 
|  2146         Tcl_Free(pDb->zProgress); |  | 
|  2147       } |  | 
|  2148       zProgress = Tcl_GetStringFromObj(objv[3], &len); |  | 
|  2149       if( zProgress && len>0 ){ |  | 
|  2150         pDb->zProgress = Tcl_Alloc( len + 1 ); |  | 
|  2151         memcpy(pDb->zProgress, zProgress, len+1); |  | 
|  2152       }else{ |  | 
|  2153         pDb->zProgress = 0; |  | 
|  2154       } |  | 
|  2155 #ifndef SQLITE_OMIT_PROGRESS_CALLBACK |  | 
|  2156       if( pDb->zProgress ){ |  | 
|  2157         pDb->interp = interp; |  | 
|  2158         sqlite3_progress_handler(pDb->db, N, DbProgressHandler, pDb); |  | 
|  2159       }else{ |  | 
|  2160         sqlite3_progress_handler(pDb->db, 0, 0, 0); |  | 
|  2161       } |  | 
|  2162 #endif |  | 
|  2163     }else{ |  | 
|  2164       Tcl_WrongNumArgs(interp, 2, objv, "N CALLBACK"); |  | 
|  2165       return TCL_ERROR; |  | 
|  2166     } |  | 
|  2167     break; |  | 
|  2168   } |  | 
|  2169  |  | 
|  2170   /*    $db profile ?CALLBACK? |  | 
|  2171   ** |  | 
|  2172   ** Make arrangements to invoke the CALLBACK routine after each SQL statement |  | 
|  2173   ** that has run.  The text of the SQL and the amount of elapse time are |  | 
|  2174   ** appended to CALLBACK before the script is run. |  | 
|  2175   */ |  | 
|  2176   case DB_PROFILE: { |  | 
|  2177     if( objc>3 ){ |  | 
|  2178       Tcl_WrongNumArgs(interp, 2, objv, "?CALLBACK?"); |  | 
|  2179       return TCL_ERROR; |  | 
|  2180     }else if( objc==2 ){ |  | 
|  2181       if( pDb->zProfile ){ |  | 
|  2182         Tcl_AppendResult(interp, pDb->zProfile, 0); |  | 
|  2183       } |  | 
|  2184     }else{ |  | 
|  2185       char *zProfile; |  | 
|  2186       int len; |  | 
|  2187       if( pDb->zProfile ){ |  | 
|  2188         Tcl_Free(pDb->zProfile); |  | 
|  2189       } |  | 
|  2190       zProfile = Tcl_GetStringFromObj(objv[2], &len); |  | 
|  2191       if( zProfile && len>0 ){ |  | 
|  2192         pDb->zProfile = Tcl_Alloc( len + 1 ); |  | 
|  2193         memcpy(pDb->zProfile, zProfile, len+1); |  | 
|  2194       }else{ |  | 
|  2195         pDb->zProfile = 0; |  | 
|  2196       } |  | 
|  2197 #ifndef SQLITE_OMIT_TRACE |  | 
|  2198       if( pDb->zProfile ){ |  | 
|  2199         pDb->interp = interp; |  | 
|  2200         sqlite3_profile(pDb->db, DbProfileHandler, pDb); |  | 
|  2201       }else{ |  | 
|  2202         sqlite3_profile(pDb->db, 0, 0); |  | 
|  2203       } |  | 
|  2204 #endif |  | 
|  2205     } |  | 
|  2206     break; |  | 
|  2207   } |  | 
|  2208  |  | 
|  2209   /* |  | 
|  2210   **     $db rekey KEY |  | 
|  2211   ** |  | 
|  2212   ** Change the encryption key on the currently open database. |  | 
|  2213   */ |  | 
|  2214   case DB_REKEY: { |  | 
|  2215     int nKey; |  | 
|  2216     void *pKey; |  | 
|  2217     if( objc!=3 ){ |  | 
|  2218       Tcl_WrongNumArgs(interp, 2, objv, "KEY"); |  | 
|  2219       return TCL_ERROR; |  | 
|  2220     } |  | 
|  2221     pKey = Tcl_GetByteArrayFromObj(objv[2], &nKey); |  | 
|  2222 #ifdef SQLITE_HAS_CODEC |  | 
|  2223     rc = sqlite3_rekey(pDb->db, pKey, nKey); |  | 
|  2224     if( rc ){ |  | 
|  2225       Tcl_AppendResult(interp, sqlite3ErrStr(rc), 0); |  | 
|  2226       rc = TCL_ERROR; |  | 
|  2227     } |  | 
|  2228 #endif |  | 
|  2229     break; |  | 
|  2230   } |  | 
|  2231  |  | 
|  2232   /*    $db restore ?DATABASE? FILENAME |  | 
|  2233   ** |  | 
|  2234   ** Open a database file named FILENAME.  Transfer the content  |  | 
|  2235   ** of FILENAME into the local database DATABASE (default: "main"). |  | 
|  2236   */ |  | 
|  2237   case DB_RESTORE: { |  | 
|  2238     const char *zSrcFile; |  | 
|  2239     const char *zDestDb; |  | 
|  2240     sqlite3 *pSrc; |  | 
|  2241     sqlite3_backup *pBackup; |  | 
|  2242     int nTimeout = 0; |  | 
|  2243  |  | 
|  2244     if( objc==3 ){ |  | 
|  2245       zDestDb = "main"; |  | 
|  2246       zSrcFile = Tcl_GetString(objv[2]); |  | 
|  2247     }else if( objc==4 ){ |  | 
|  2248       zDestDb = Tcl_GetString(objv[2]); |  | 
|  2249       zSrcFile = Tcl_GetString(objv[3]); |  | 
|  2250     }else{ |  | 
|  2251       Tcl_WrongNumArgs(interp, 2, objv, "?DATABASE? FILENAME"); |  | 
|  2252       return TCL_ERROR; |  | 
|  2253     } |  | 
|  2254     rc = sqlite3_open_v2(zSrcFile, &pSrc, SQLITE_OPEN_READONLY, 0); |  | 
|  2255     if( rc!=SQLITE_OK ){ |  | 
|  2256       Tcl_AppendResult(interp, "cannot open source database: ", |  | 
|  2257            sqlite3_errmsg(pSrc), (char*)0); |  | 
|  2258       sqlite3_close(pSrc); |  | 
|  2259       return TCL_ERROR; |  | 
|  2260     } |  | 
|  2261     pBackup = sqlite3_backup_init(pDb->db, zDestDb, pSrc, "main"); |  | 
|  2262     if( pBackup==0 ){ |  | 
|  2263       Tcl_AppendResult(interp, "restore failed: ", |  | 
|  2264            sqlite3_errmsg(pDb->db), (char*)0); |  | 
|  2265       sqlite3_close(pSrc); |  | 
|  2266       return TCL_ERROR; |  | 
|  2267     } |  | 
|  2268     while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK |  | 
|  2269               || rc==SQLITE_BUSY ){ |  | 
|  2270       if( rc==SQLITE_BUSY ){ |  | 
|  2271         if( nTimeout++ >= 3 ) break; |  | 
|  2272         sqlite3_sleep(100); |  | 
|  2273       } |  | 
|  2274     } |  | 
|  2275     sqlite3_backup_finish(pBackup); |  | 
|  2276     if( rc==SQLITE_DONE ){ |  | 
|  2277       rc = TCL_OK; |  | 
|  2278     }else if( rc==SQLITE_BUSY || rc==SQLITE_LOCKED ){ |  | 
|  2279       Tcl_AppendResult(interp, "restore failed: source database busy", |  | 
|  2280                        (char*)0); |  | 
|  2281       rc = TCL_ERROR; |  | 
|  2282     }else{ |  | 
|  2283       Tcl_AppendResult(interp, "restore failed: ", |  | 
|  2284            sqlite3_errmsg(pDb->db), (char*)0); |  | 
|  2285       rc = TCL_ERROR; |  | 
|  2286     } |  | 
|  2287     sqlite3_close(pSrc); |  | 
|  2288     break; |  | 
|  2289   } |  | 
|  2290  |  | 
|  2291   /* |  | 
|  2292   **     $db status (step|sort) |  | 
|  2293   ** |  | 
|  2294   ** Display SQLITE_STMTSTATUS_FULLSCAN_STEP or  |  | 
|  2295   ** SQLITE_STMTSTATUS_SORT for the most recent eval. |  | 
|  2296   */ |  | 
|  2297   case DB_STATUS: { |  | 
|  2298     int v; |  | 
|  2299     const char *zOp; |  | 
|  2300     if( objc!=3 ){ |  | 
|  2301       Tcl_WrongNumArgs(interp, 2, objv, "(step|sort)"); |  | 
|  2302       return TCL_ERROR; |  | 
|  2303     } |  | 
|  2304     zOp = Tcl_GetString(objv[2]); |  | 
|  2305     if( strcmp(zOp, "step")==0 ){ |  | 
|  2306       v = pDb->nStep; |  | 
|  2307     }else if( strcmp(zOp, "sort")==0 ){ |  | 
|  2308       v = pDb->nSort; |  | 
|  2309     }else{ |  | 
|  2310       Tcl_AppendResult(interp, "bad argument: should be step or sort",  |  | 
|  2311             (char*)0); |  | 
|  2312       return TCL_ERROR; |  | 
|  2313     } |  | 
|  2314     Tcl_SetObjResult(interp, Tcl_NewIntObj(v)); |  | 
|  2315     break; |  | 
|  2316   } |  | 
|  2317    |  | 
|  2318   /* |  | 
|  2319   **     $db timeout MILLESECONDS |  | 
|  2320   ** |  | 
|  2321   ** Delay for the number of milliseconds specified when a file is locked. |  | 
|  2322   */ |  | 
|  2323   case DB_TIMEOUT: { |  | 
|  2324     int ms; |  | 
|  2325     if( objc!=3 ){ |  | 
|  2326       Tcl_WrongNumArgs(interp, 2, objv, "MILLISECONDS"); |  | 
|  2327       return TCL_ERROR; |  | 
|  2328     } |  | 
|  2329     if( Tcl_GetIntFromObj(interp, objv[2], &ms) ) return TCL_ERROR; |  | 
|  2330     sqlite3_busy_timeout(pDb->db, ms); |  | 
|  2331     break; |  | 
|  2332   } |  | 
|  2333    |  | 
|  2334   /* |  | 
|  2335   **     $db total_changes |  | 
|  2336   ** |  | 
|  2337   ** Return the number of rows that were modified, inserted, or deleted  |  | 
|  2338   ** since the database handle was created. |  | 
|  2339   */ |  | 
|  2340   case DB_TOTAL_CHANGES: { |  | 
|  2341     Tcl_Obj *pResult; |  | 
|  2342     if( objc!=2 ){ |  | 
|  2343       Tcl_WrongNumArgs(interp, 2, objv, ""); |  | 
|  2344       return TCL_ERROR; |  | 
|  2345     } |  | 
|  2346     pResult = Tcl_GetObjResult(interp); |  | 
|  2347     Tcl_SetIntObj(pResult, sqlite3_total_changes(pDb->db)); |  | 
|  2348     break; |  | 
|  2349   } |  | 
|  2350  |  | 
|  2351   /*    $db trace ?CALLBACK? |  | 
|  2352   ** |  | 
|  2353   ** Make arrangements to invoke the CALLBACK routine for each SQL statement |  | 
|  2354   ** that is executed.  The text of the SQL is appended to CALLBACK before |  | 
|  2355   ** it is executed. |  | 
|  2356   */ |  | 
|  2357   case DB_TRACE: { |  | 
|  2358     if( objc>3 ){ |  | 
|  2359       Tcl_WrongNumArgs(interp, 2, objv, "?CALLBACK?"); |  | 
|  2360       return TCL_ERROR; |  | 
|  2361     }else if( objc==2 ){ |  | 
|  2362       if( pDb->zTrace ){ |  | 
|  2363         Tcl_AppendResult(interp, pDb->zTrace, 0); |  | 
|  2364       } |  | 
|  2365     }else{ |  | 
|  2366       char *zTrace; |  | 
|  2367       int len; |  | 
|  2368       if( pDb->zTrace ){ |  | 
|  2369         Tcl_Free(pDb->zTrace); |  | 
|  2370       } |  | 
|  2371       zTrace = Tcl_GetStringFromObj(objv[2], &len); |  | 
|  2372       if( zTrace && len>0 ){ |  | 
|  2373         pDb->zTrace = Tcl_Alloc( len + 1 ); |  | 
|  2374         memcpy(pDb->zTrace, zTrace, len+1); |  | 
|  2375       }else{ |  | 
|  2376         pDb->zTrace = 0; |  | 
|  2377       } |  | 
|  2378 #ifndef SQLITE_OMIT_TRACE |  | 
|  2379       if( pDb->zTrace ){ |  | 
|  2380         pDb->interp = interp; |  | 
|  2381         sqlite3_trace(pDb->db, DbTraceHandler, pDb); |  | 
|  2382       }else{ |  | 
|  2383         sqlite3_trace(pDb->db, 0, 0); |  | 
|  2384       } |  | 
|  2385 #endif |  | 
|  2386     } |  | 
|  2387     break; |  | 
|  2388   } |  | 
|  2389  |  | 
|  2390   /*    $db transaction [-deferred|-immediate|-exclusive] SCRIPT |  | 
|  2391   ** |  | 
|  2392   ** Start a new transaction (if we are not already in the midst of a |  | 
|  2393   ** transaction) and execute the TCL script SCRIPT.  After SCRIPT |  | 
|  2394   ** completes, either commit the transaction or roll it back if SCRIPT |  | 
|  2395   ** throws an exception.  Or if no new transation was started, do nothing. |  | 
|  2396   ** pass the exception on up the stack. |  | 
|  2397   ** |  | 
|  2398   ** This command was inspired by Dave Thomas's talk on Ruby at the |  | 
|  2399   ** 2005 O'Reilly Open Source Convention (OSCON). |  | 
|  2400   */ |  | 
|  2401   case DB_TRANSACTION: { |  | 
|  2402     Tcl_Obj *pScript; |  | 
|  2403     const char *zBegin = "SAVEPOINT _tcl_transaction"; |  | 
|  2404     const char *zEnd; |  | 
|  2405     if( objc!=3 && objc!=4 ){ |  | 
|  2406       Tcl_WrongNumArgs(interp, 2, objv, "[TYPE] SCRIPT"); |  | 
|  2407       return TCL_ERROR; |  | 
|  2408     } |  | 
|  2409  |  | 
|  2410     if( pDb->nTransaction ){ |  | 
|  2411       zBegin = "SAVEPOINT _tcl_transaction"; |  | 
|  2412     }else if( pDb->nTransaction==0 && objc==4 ){ |  | 
|  2413       static const char *TTYPE_strs[] = { |  | 
|  2414         "deferred",   "exclusive",  "immediate", 0 |  | 
|  2415       }; |  | 
|  2416       enum TTYPE_enum { |  | 
|  2417         TTYPE_DEFERRED, TTYPE_EXCLUSIVE, TTYPE_IMMEDIATE |  | 
|  2418       }; |  | 
|  2419       int ttype; |  | 
|  2420       if( Tcl_GetIndexFromObj(interp, objv[2], TTYPE_strs, "transaction type", |  | 
|  2421                               0, &ttype) ){ |  | 
|  2422         return TCL_ERROR; |  | 
|  2423       } |  | 
|  2424       switch( (enum TTYPE_enum)ttype ){ |  | 
|  2425         case TTYPE_DEFERRED:    /* no-op */;                 break; |  | 
|  2426         case TTYPE_EXCLUSIVE:   zBegin = "BEGIN EXCLUSIVE";  break; |  | 
|  2427         case TTYPE_IMMEDIATE:   zBegin = "BEGIN IMMEDIATE";  break; |  | 
|  2428       } |  | 
|  2429     } |  | 
|  2430     pScript = objv[objc-1]; |  | 
|  2431  |  | 
|  2432     pDb->disableAuth++; |  | 
|  2433     rc = sqlite3_exec(pDb->db, zBegin, 0, 0, 0); |  | 
|  2434     pDb->disableAuth--; |  | 
|  2435     if( rc!=SQLITE_OK ){ |  | 
|  2436       Tcl_AppendResult(interp, sqlite3_errmsg(pDb->db), 0); |  | 
|  2437       return TCL_ERROR; |  | 
|  2438     } |  | 
|  2439  |  | 
|  2440     pDb->nTransaction++; |  | 
|  2441     rc = Tcl_EvalObjEx(interp, pScript, 0); |  | 
|  2442     pDb->nTransaction--; |  | 
|  2443  |  | 
|  2444     if( rc!=TCL_ERROR ){ |  | 
|  2445       if( pDb->nTransaction ){ |  | 
|  2446         zEnd = "RELEASE _tcl_transaction"; |  | 
|  2447       }else{ |  | 
|  2448         zEnd = "COMMIT"; |  | 
|  2449       } |  | 
|  2450     }else{ |  | 
|  2451       if( pDb->nTransaction ){ |  | 
|  2452         zEnd = "ROLLBACK TO _tcl_transaction ; RELEASE _tcl_transaction"; |  | 
|  2453       }else{ |  | 
|  2454         zEnd = "ROLLBACK"; |  | 
|  2455       } |  | 
|  2456     } |  | 
|  2457  |  | 
|  2458     pDb->disableAuth++; |  | 
|  2459     if( sqlite3_exec(pDb->db, zEnd, 0, 0, 0) ){ |  | 
|  2460       /* This is a tricky scenario to handle. The most likely cause of an |  | 
|  2461       ** error is that the exec() above was an attempt to commit the  |  | 
|  2462       ** top-level transaction that returned SQLITE_BUSY. Or, less likely, |  | 
|  2463       ** that an IO-error has occured. In either case, throw a Tcl exception |  | 
|  2464       ** and try to rollback the transaction. |  | 
|  2465       ** |  | 
|  2466       ** But it could also be that the user executed one or more BEGIN,  |  | 
|  2467       ** COMMIT, SAVEPOINT, RELEASE or ROLLBACK commands that are confusing |  | 
|  2468       ** this method's logic. Not clear how this would be best handled. |  | 
|  2469       */ |  | 
|  2470       if( rc!=TCL_ERROR ){ |  | 
|  2471         Tcl_AppendResult(interp, sqlite3_errmsg(pDb->db), 0); |  | 
|  2472         rc = TCL_ERROR; |  | 
|  2473       } |  | 
|  2474       sqlite3_exec(pDb->db, "ROLLBACK", 0, 0, 0); |  | 
|  2475     } |  | 
|  2476     pDb->disableAuth--; |  | 
|  2477  |  | 
|  2478     break; |  | 
|  2479   } |  | 
|  2480  |  | 
|  2481   /* |  | 
|  2482   **    $db unlock_notify ?script? |  | 
|  2483   */ |  | 
|  2484   case DB_UNLOCK_NOTIFY: { |  | 
|  2485 #ifndef SQLITE_ENABLE_UNLOCK_NOTIFY |  | 
|  2486     Tcl_AppendResult(interp, "unlock_notify not available in this build", 0); |  | 
|  2487     rc = TCL_ERROR; |  | 
|  2488 #else |  | 
|  2489     if( objc!=2 && objc!=3 ){ |  | 
|  2490       Tcl_WrongNumArgs(interp, 2, objv, "?SCRIPT?"); |  | 
|  2491       rc = TCL_ERROR; |  | 
|  2492     }else{ |  | 
|  2493       void (*xNotify)(void **, int) = 0; |  | 
|  2494       void *pNotifyArg = 0; |  | 
|  2495  |  | 
|  2496       if( pDb->pUnlockNotify ){ |  | 
|  2497         Tcl_DecrRefCount(pDb->pUnlockNotify); |  | 
|  2498         pDb->pUnlockNotify = 0; |  | 
|  2499       } |  | 
|  2500    |  | 
|  2501       if( objc==3 ){ |  | 
|  2502         xNotify = DbUnlockNotify; |  | 
|  2503         pNotifyArg = (void *)pDb; |  | 
|  2504         pDb->pUnlockNotify = objv[2]; |  | 
|  2505         Tcl_IncrRefCount(pDb->pUnlockNotify); |  | 
|  2506       } |  | 
|  2507    |  | 
|  2508       if( sqlite3_unlock_notify(pDb->db, xNotify, pNotifyArg) ){ |  | 
|  2509         Tcl_AppendResult(interp, sqlite3_errmsg(pDb->db), 0); |  | 
|  2510         rc = TCL_ERROR; |  | 
|  2511       } |  | 
|  2512     } |  | 
|  2513 #endif |  | 
|  2514     break; |  | 
|  2515   } |  | 
|  2516  |  | 
|  2517   /* |  | 
|  2518   **    $db update_hook ?script? |  | 
|  2519   **    $db rollback_hook ?script? |  | 
|  2520   */ |  | 
|  2521   case DB_UPDATE_HOOK:  |  | 
|  2522   case DB_ROLLBACK_HOOK: { |  | 
|  2523  |  | 
|  2524     /* set ppHook to point at pUpdateHook or pRollbackHook, depending on  |  | 
|  2525     ** whether [$db update_hook] or [$db rollback_hook] was invoked. |  | 
|  2526     */ |  | 
|  2527     Tcl_Obj **ppHook;  |  | 
|  2528     if( choice==DB_UPDATE_HOOK ){ |  | 
|  2529       ppHook = &pDb->pUpdateHook; |  | 
|  2530     }else{ |  | 
|  2531       ppHook = &pDb->pRollbackHook; |  | 
|  2532     } |  | 
|  2533  |  | 
|  2534     if( objc!=2 && objc!=3 ){ |  | 
|  2535        Tcl_WrongNumArgs(interp, 2, objv, "?SCRIPT?"); |  | 
|  2536        return TCL_ERROR; |  | 
|  2537     } |  | 
|  2538     if( *ppHook ){ |  | 
|  2539       Tcl_SetObjResult(interp, *ppHook); |  | 
|  2540       if( objc==3 ){ |  | 
|  2541         Tcl_DecrRefCount(*ppHook); |  | 
|  2542         *ppHook = 0; |  | 
|  2543       } |  | 
|  2544     } |  | 
|  2545     if( objc==3 ){ |  | 
|  2546       assert( !(*ppHook) ); |  | 
|  2547       if( Tcl_GetCharLength(objv[2])>0 ){ |  | 
|  2548         *ppHook = objv[2]; |  | 
|  2549         Tcl_IncrRefCount(*ppHook); |  | 
|  2550       } |  | 
|  2551     } |  | 
|  2552  |  | 
|  2553     sqlite3_update_hook(pDb->db, (pDb->pUpdateHook?DbUpdateHandler:0), pDb); |  | 
|  2554     sqlite3_rollback_hook(pDb->db,(pDb->pRollbackHook?DbRollbackHandler:0),pDb); |  | 
|  2555  |  | 
|  2556     break; |  | 
|  2557   } |  | 
|  2558  |  | 
|  2559   /*    $db version |  | 
|  2560   ** |  | 
|  2561   ** Return the version string for this database. |  | 
|  2562   */ |  | 
|  2563   case DB_VERSION: { |  | 
|  2564     Tcl_SetResult(interp, (char *)sqlite3_libversion(), TCL_STATIC); |  | 
|  2565     break; |  | 
|  2566   } |  | 
|  2567  |  | 
|  2568  |  | 
|  2569   } /* End of the SWITCH statement */ |  | 
|  2570   return rc; |  | 
|  2571 } |  | 
|  2572  |  | 
|  2573 /* |  | 
|  2574 **   sqlite3 DBNAME FILENAME ?-vfs VFSNAME? ?-key KEY? ?-readonly BOOLEAN? |  | 
|  2575 **                           ?-create BOOLEAN? ?-nomutex BOOLEAN? |  | 
|  2576 ** |  | 
|  2577 ** This is the main Tcl command.  When the "sqlite" Tcl command is |  | 
|  2578 ** invoked, this routine runs to process that command. |  | 
|  2579 ** |  | 
|  2580 ** The first argument, DBNAME, is an arbitrary name for a new |  | 
|  2581 ** database connection.  This command creates a new command named |  | 
|  2582 ** DBNAME that is used to control that connection.  The database |  | 
|  2583 ** connection is deleted when the DBNAME command is deleted. |  | 
|  2584 ** |  | 
|  2585 ** The second argument is the name of the database file. |  | 
|  2586 ** |  | 
|  2587 */ |  | 
|  2588 static int DbMain(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){ |  | 
|  2589   SqliteDb *p; |  | 
|  2590   void *pKey = 0; |  | 
|  2591   int nKey = 0; |  | 
|  2592   const char *zArg; |  | 
|  2593   char *zErrMsg; |  | 
|  2594   int i; |  | 
|  2595   const char *zFile; |  | 
|  2596   const char *zVfs = 0; |  | 
|  2597   int flags; |  | 
|  2598   Tcl_DString translatedFilename; |  | 
|  2599  |  | 
|  2600   /* In normal use, each TCL interpreter runs in a single thread.  So |  | 
|  2601   ** by default, we can turn of mutexing on SQLite database connections. |  | 
|  2602   ** However, for testing purposes it is useful to have mutexes turned |  | 
|  2603   ** on.  So, by default, mutexes default off.  But if compiled with |  | 
|  2604   ** SQLITE_TCL_DEFAULT_FULLMUTEX then mutexes default on. |  | 
|  2605   */ |  | 
|  2606 #ifdef SQLITE_TCL_DEFAULT_FULLMUTEX |  | 
|  2607   flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_FULLMUTEX; |  | 
|  2608 #else |  | 
|  2609   flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_NOMUTEX; |  | 
|  2610 #endif |  | 
|  2611  |  | 
|  2612   if( objc==2 ){ |  | 
|  2613     zArg = Tcl_GetStringFromObj(objv[1], 0); |  | 
|  2614     if( strcmp(zArg,"-version")==0 ){ |  | 
|  2615       Tcl_AppendResult(interp,sqlite3_version,0); |  | 
|  2616       return TCL_OK; |  | 
|  2617     } |  | 
|  2618     if( strcmp(zArg,"-has-codec")==0 ){ |  | 
|  2619 #ifdef SQLITE_HAS_CODEC |  | 
|  2620       Tcl_AppendResult(interp,"1",0); |  | 
|  2621 #else |  | 
|  2622       Tcl_AppendResult(interp,"0",0); |  | 
|  2623 #endif |  | 
|  2624       return TCL_OK; |  | 
|  2625     } |  | 
|  2626   } |  | 
|  2627   for(i=3; i+1<objc; i+=2){ |  | 
|  2628     zArg = Tcl_GetString(objv[i]); |  | 
|  2629     if( strcmp(zArg,"-key")==0 ){ |  | 
|  2630       pKey = Tcl_GetByteArrayFromObj(objv[i+1], &nKey); |  | 
|  2631     }else if( strcmp(zArg, "-vfs")==0 ){ |  | 
|  2632       i++; |  | 
|  2633       zVfs = Tcl_GetString(objv[i]); |  | 
|  2634     }else if( strcmp(zArg, "-readonly")==0 ){ |  | 
|  2635       int b; |  | 
|  2636       if( Tcl_GetBooleanFromObj(interp, objv[i+1], &b) ) return TCL_ERROR; |  | 
|  2637       if( b ){ |  | 
|  2638         flags &= ~(SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE); |  | 
|  2639         flags |= SQLITE_OPEN_READONLY; |  | 
|  2640       }else{ |  | 
|  2641         flags &= ~SQLITE_OPEN_READONLY; |  | 
|  2642         flags |= SQLITE_OPEN_READWRITE; |  | 
|  2643       } |  | 
|  2644     }else if( strcmp(zArg, "-create")==0 ){ |  | 
|  2645       int b; |  | 
|  2646       if( Tcl_GetBooleanFromObj(interp, objv[i+1], &b) ) return TCL_ERROR; |  | 
|  2647       if( b && (flags & SQLITE_OPEN_READONLY)==0 ){ |  | 
|  2648         flags |= SQLITE_OPEN_CREATE; |  | 
|  2649       }else{ |  | 
|  2650         flags &= ~SQLITE_OPEN_CREATE; |  | 
|  2651       } |  | 
|  2652     }else if( strcmp(zArg, "-nomutex")==0 ){ |  | 
|  2653       int b; |  | 
|  2654       if( Tcl_GetBooleanFromObj(interp, objv[i+1], &b) ) return TCL_ERROR; |  | 
|  2655       if( b ){ |  | 
|  2656         flags |= SQLITE_OPEN_NOMUTEX; |  | 
|  2657         flags &= ~SQLITE_OPEN_FULLMUTEX; |  | 
|  2658       }else{ |  | 
|  2659         flags &= ~SQLITE_OPEN_NOMUTEX; |  | 
|  2660       } |  | 
|  2661    }else if( strcmp(zArg, "-fullmutex")==0 ){ |  | 
|  2662       int b; |  | 
|  2663       if( Tcl_GetBooleanFromObj(interp, objv[i+1], &b) ) return TCL_ERROR; |  | 
|  2664       if( b ){ |  | 
|  2665         flags |= SQLITE_OPEN_FULLMUTEX; |  | 
|  2666         flags &= ~SQLITE_OPEN_NOMUTEX; |  | 
|  2667       }else{ |  | 
|  2668         flags &= ~SQLITE_OPEN_FULLMUTEX; |  | 
|  2669       } |  | 
|  2670     }else{ |  | 
|  2671       Tcl_AppendResult(interp, "unknown option: ", zArg, (char*)0); |  | 
|  2672       return TCL_ERROR; |  | 
|  2673     } |  | 
|  2674   } |  | 
|  2675   if( objc<3 || (objc&1)!=1 ){ |  | 
|  2676     Tcl_WrongNumArgs(interp, 1, objv,  |  | 
|  2677       "HANDLE FILENAME ?-vfs VFSNAME? ?-readonly BOOLEAN? ?-create BOOLEAN?" |  | 
|  2678       " ?-nomutex BOOLEAN? ?-fullmutex BOOLEAN?" |  | 
|  2679 #ifdef SQLITE_HAS_CODEC |  | 
|  2680       " ?-key CODECKEY?" |  | 
|  2681 #endif |  | 
|  2682     ); |  | 
|  2683     return TCL_ERROR; |  | 
|  2684   } |  | 
|  2685   zErrMsg = 0; |  | 
|  2686   p = (SqliteDb*)Tcl_Alloc( sizeof(*p) ); |  | 
|  2687   if( p==0 ){ |  | 
|  2688     Tcl_SetResult(interp, "malloc failed", TCL_STATIC); |  | 
|  2689     return TCL_ERROR; |  | 
|  2690   } |  | 
|  2691   memset(p, 0, sizeof(*p)); |  | 
|  2692   zFile = Tcl_GetStringFromObj(objv[2], 0); |  | 
|  2693   zFile = Tcl_TranslateFileName(interp, zFile, &translatedFilename); |  | 
|  2694   sqlite3_open_v2(zFile, &p->db, flags, zVfs); |  | 
|  2695   Tcl_DStringFree(&translatedFilename); |  | 
|  2696   if( SQLITE_OK!=sqlite3_errcode(p->db) ){ |  | 
|  2697     zErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(p->db)); |  | 
|  2698     sqlite3_close(p->db); |  | 
|  2699     p->db = 0; |  | 
|  2700   } |  | 
|  2701 #ifdef SQLITE_HAS_CODEC |  | 
|  2702   if( p->db ){ |  | 
|  2703     sqlite3_key(p->db, pKey, nKey); |  | 
|  2704   } |  | 
|  2705 #endif |  | 
|  2706   if( p->db==0 ){ |  | 
|  2707     Tcl_SetResult(interp, zErrMsg, TCL_VOLATILE); |  | 
|  2708     Tcl_Free((char*)p); |  | 
|  2709     sqlite3_free(zErrMsg); |  | 
|  2710     return TCL_ERROR; |  | 
|  2711   } |  | 
|  2712   p->maxStmt = NUM_PREPARED_STMTS; |  | 
|  2713   p->interp = interp; |  | 
|  2714   zArg = Tcl_GetStringFromObj(objv[1], 0); |  | 
|  2715   Tcl_CreateObjCommand(interp, zArg, DbObjCmd, (char*)p, DbDeleteCmd); |  | 
|  2716   return TCL_OK; |  | 
|  2717 } |  | 
|  2718  |  | 
|  2719 /* |  | 
|  2720 ** Provide a dummy Tcl_InitStubs if we are using this as a static |  | 
|  2721 ** library. |  | 
|  2722 */ |  | 
|  2723 #ifndef USE_TCL_STUBS |  | 
|  2724 # undef  Tcl_InitStubs |  | 
|  2725 # define Tcl_InitStubs(a,b,c) |  | 
|  2726 #endif |  | 
|  2727  |  | 
|  2728 /* |  | 
|  2729 ** Make sure we have a PACKAGE_VERSION macro defined.  This will be |  | 
|  2730 ** defined automatically by the TEA makefile.  But other makefiles |  | 
|  2731 ** do not define it. |  | 
|  2732 */ |  | 
|  2733 #ifndef PACKAGE_VERSION |  | 
|  2734 # define PACKAGE_VERSION SQLITE_VERSION |  | 
|  2735 #endif |  | 
|  2736  |  | 
|  2737 /* |  | 
|  2738 ** Initialize this module. |  | 
|  2739 ** |  | 
|  2740 ** This Tcl module contains only a single new Tcl command named "sqlite". |  | 
|  2741 ** (Hence there is no namespace.  There is no point in using a namespace |  | 
|  2742 ** if the extension only supplies one new name!)  The "sqlite" command is |  | 
|  2743 ** used to open a new SQLite database.  See the DbMain() routine above |  | 
|  2744 ** for additional information. |  | 
|  2745 */ |  | 
|  2746 EXTERN int Sqlite3_Init(Tcl_Interp *interp){ |  | 
|  2747   Tcl_InitStubs(interp, "8.4", 0); |  | 
|  2748   Tcl_CreateObjCommand(interp, "sqlite3", (Tcl_ObjCmdProc*)DbMain, 0, 0); |  | 
|  2749   Tcl_PkgProvide(interp, "sqlite3", PACKAGE_VERSION); |  | 
|  2750   Tcl_CreateObjCommand(interp, "sqlite", (Tcl_ObjCmdProc*)DbMain, 0, 0); |  | 
|  2751   Tcl_PkgProvide(interp, "sqlite", PACKAGE_VERSION); |  | 
|  2752   return TCL_OK; |  | 
|  2753 } |  | 
|  2754 EXTERN int Tclsqlite3_Init(Tcl_Interp *interp){ return Sqlite3_Init(interp); } |  | 
|  2755 EXTERN int Sqlite3_SafeInit(Tcl_Interp *interp){ return TCL_OK; } |  | 
|  2756 EXTERN int Tclsqlite3_SafeInit(Tcl_Interp *interp){ return TCL_OK; } |  | 
|  2757 EXTERN int Sqlite3_Unload(Tcl_Interp *interp, int flags){ return TCL_OK; } |  | 
|  2758 EXTERN int Tclsqlite3_Unload(Tcl_Interp *interp, int flags){ return TCL_OK; } |  | 
|  2759 EXTERN int Sqlite3_SafeUnload(Tcl_Interp *interp, int flags){ return TCL_OK; } |  | 
|  2760 EXTERN int Tclsqlite3_SafeUnload(Tcl_Interp *interp, int flags){ return TCL_OK;} |  | 
|  2761  |  | 
|  2762  |  | 
|  2763 #ifndef SQLITE_3_SUFFIX_ONLY |  | 
|  2764 EXTERN int Sqlite_Init(Tcl_Interp *interp){ return Sqlite3_Init(interp); } |  | 
|  2765 EXTERN int Tclsqlite_Init(Tcl_Interp *interp){ return Sqlite3_Init(interp); } |  | 
|  2766 EXTERN int Sqlite_SafeInit(Tcl_Interp *interp){ return TCL_OK; } |  | 
|  2767 EXTERN int Tclsqlite_SafeInit(Tcl_Interp *interp){ return TCL_OK; } |  | 
|  2768 EXTERN int Sqlite_Unload(Tcl_Interp *interp, int flags){ return TCL_OK; } |  | 
|  2769 EXTERN int Tclsqlite_Unload(Tcl_Interp *interp, int flags){ return TCL_OK; } |  | 
|  2770 EXTERN int Sqlite_SafeUnload(Tcl_Interp *interp, int flags){ return TCL_OK; } |  | 
|  2771 EXTERN int Tclsqlite_SafeUnload(Tcl_Interp *interp, int flags){ return TCL_OK;} |  | 
|  2772 #endif |  | 
|  2773  |  | 
|  2774 #ifdef TCLSH |  | 
|  2775 /***************************************************************************** |  | 
|  2776 ** The code that follows is used to build standalone TCL interpreters |  | 
|  2777 ** that are statically linked with SQLite.   |  | 
|  2778 */ |  | 
|  2779  |  | 
|  2780 /* |  | 
|  2781 ** If the macro TCLSH is one, then put in code this for the |  | 
|  2782 ** "main" routine that will initialize Tcl and take input from |  | 
|  2783 ** standard input, or if a file is named on the command line |  | 
|  2784 ** the TCL interpreter reads and evaluates that file. |  | 
|  2785 */ |  | 
|  2786 #if TCLSH==1 |  | 
|  2787 static char zMainloop[] = |  | 
|  2788   "set line {}\n" |  | 
|  2789   "while {![eof stdin]} {\n" |  | 
|  2790     "if {$line!=\"\"} {\n" |  | 
|  2791       "puts -nonewline \"> \"\n" |  | 
|  2792     "} else {\n" |  | 
|  2793       "puts -nonewline \"% \"\n" |  | 
|  2794     "}\n" |  | 
|  2795     "flush stdout\n" |  | 
|  2796     "append line [gets stdin]\n" |  | 
|  2797     "if {[info complete $line]} {\n" |  | 
|  2798       "if {[catch {uplevel #0 $line} result]} {\n" |  | 
|  2799         "puts stderr \"Error: $result\"\n" |  | 
|  2800       "} elseif {$result!=\"\"} {\n" |  | 
|  2801         "puts $result\n" |  | 
|  2802       "}\n" |  | 
|  2803       "set line {}\n" |  | 
|  2804     "} else {\n" |  | 
|  2805       "append line \\n\n" |  | 
|  2806     "}\n" |  | 
|  2807   "}\n" |  | 
|  2808 ; |  | 
|  2809 #endif |  | 
|  2810  |  | 
|  2811 /* |  | 
|  2812 ** If the macro TCLSH is two, then get the main loop code out of |  | 
|  2813 ** the separate file "spaceanal_tcl.h". |  | 
|  2814 */ |  | 
|  2815 #if TCLSH==2 |  | 
|  2816 static char zMainloop[] =  |  | 
|  2817 #include "spaceanal_tcl.h" |  | 
|  2818 ; |  | 
|  2819 #endif |  | 
|  2820  |  | 
|  2821 #define TCLSH_MAIN main   /* Needed to fake out mktclapp */ |  | 
|  2822 int TCLSH_MAIN(int argc, char **argv){ |  | 
|  2823   Tcl_Interp *interp; |  | 
|  2824    |  | 
|  2825   /* Call sqlite3_shutdown() once before doing anything else. This is to |  | 
|  2826   ** test that sqlite3_shutdown() can be safely called by a process before |  | 
|  2827   ** sqlite3_initialize() is. */ |  | 
|  2828   sqlite3_shutdown(); |  | 
|  2829  |  | 
|  2830   Tcl_FindExecutable(argv[0]); |  | 
|  2831   interp = Tcl_CreateInterp(); |  | 
|  2832   Sqlite3_Init(interp); |  | 
|  2833 #ifdef SQLITE_TEST |  | 
|  2834   { |  | 
|  2835     extern int Md5_Init(Tcl_Interp*); |  | 
|  2836     extern int Sqliteconfig_Init(Tcl_Interp*); |  | 
|  2837     extern int Sqlitetest1_Init(Tcl_Interp*); |  | 
|  2838     extern int Sqlitetest2_Init(Tcl_Interp*); |  | 
|  2839     extern int Sqlitetest3_Init(Tcl_Interp*); |  | 
|  2840     extern int Sqlitetest4_Init(Tcl_Interp*); |  | 
|  2841     extern int Sqlitetest5_Init(Tcl_Interp*); |  | 
|  2842     extern int Sqlitetest6_Init(Tcl_Interp*); |  | 
|  2843     extern int Sqlitetest7_Init(Tcl_Interp*); |  | 
|  2844     extern int Sqlitetest8_Init(Tcl_Interp*); |  | 
|  2845     extern int Sqlitetest9_Init(Tcl_Interp*); |  | 
|  2846     extern int Sqlitetestasync_Init(Tcl_Interp*); |  | 
|  2847     extern int Sqlitetest_autoext_Init(Tcl_Interp*); |  | 
|  2848     extern int Sqlitetest_func_Init(Tcl_Interp*); |  | 
|  2849     extern int Sqlitetest_hexio_Init(Tcl_Interp*); |  | 
|  2850     extern int Sqlitetest_init_Init(Tcl_Interp*); |  | 
|  2851     extern int Sqlitetest_malloc_Init(Tcl_Interp*); |  | 
|  2852     extern int Sqlitetest_mutex_Init(Tcl_Interp*); |  | 
|  2853     extern int Sqlitetestschema_Init(Tcl_Interp*); |  | 
|  2854     extern int Sqlitetestsse_Init(Tcl_Interp*); |  | 
|  2855     extern int Sqlitetesttclvar_Init(Tcl_Interp*); |  | 
|  2856     extern int SqlitetestThread_Init(Tcl_Interp*); |  | 
|  2857     extern int SqlitetestOnefile_Init(); |  | 
|  2858     extern int SqlitetestOsinst_Init(Tcl_Interp*); |  | 
|  2859     extern int Sqlitetestbackup_Init(Tcl_Interp*); |  | 
|  2860  |  | 
|  2861     Md5_Init(interp); |  | 
|  2862     Sqliteconfig_Init(interp); |  | 
|  2863     Sqlitetest1_Init(interp); |  | 
|  2864     Sqlitetest2_Init(interp); |  | 
|  2865     Sqlitetest3_Init(interp); |  | 
|  2866     Sqlitetest4_Init(interp); |  | 
|  2867     Sqlitetest5_Init(interp); |  | 
|  2868     Sqlitetest6_Init(interp); |  | 
|  2869     Sqlitetest7_Init(interp); |  | 
|  2870     Sqlitetest8_Init(interp); |  | 
|  2871     Sqlitetest9_Init(interp); |  | 
|  2872     Sqlitetestasync_Init(interp); |  | 
|  2873     Sqlitetest_autoext_Init(interp); |  | 
|  2874     Sqlitetest_func_Init(interp); |  | 
|  2875     Sqlitetest_hexio_Init(interp); |  | 
|  2876     Sqlitetest_init_Init(interp); |  | 
|  2877     Sqlitetest_malloc_Init(interp); |  | 
|  2878     Sqlitetest_mutex_Init(interp); |  | 
|  2879     Sqlitetestschema_Init(interp); |  | 
|  2880     Sqlitetesttclvar_Init(interp); |  | 
|  2881     SqlitetestThread_Init(interp); |  | 
|  2882     SqlitetestOnefile_Init(interp); |  | 
|  2883     SqlitetestOsinst_Init(interp); |  | 
|  2884     Sqlitetestbackup_Init(interp); |  | 
|  2885  |  | 
|  2886 #ifdef SQLITE_SSE |  | 
|  2887     Sqlitetestsse_Init(interp); |  | 
|  2888 #endif |  | 
|  2889   } |  | 
|  2890 #endif |  | 
|  2891   if( argc>=2 || TCLSH==2 ){ |  | 
|  2892     int i; |  | 
|  2893     char zArgc[32]; |  | 
|  2894     sqlite3_snprintf(sizeof(zArgc), zArgc, "%d", argc-(3-TCLSH)); |  | 
|  2895     Tcl_SetVar(interp,"argc", zArgc, TCL_GLOBAL_ONLY); |  | 
|  2896     Tcl_SetVar(interp,"argv0",argv[1],TCL_GLOBAL_ONLY); |  | 
|  2897     Tcl_SetVar(interp,"argv", "", TCL_GLOBAL_ONLY); |  | 
|  2898     for(i=3-TCLSH; i<argc; i++){ |  | 
|  2899       Tcl_SetVar(interp, "argv", argv[i], |  | 
|  2900           TCL_GLOBAL_ONLY | TCL_LIST_ELEMENT | TCL_APPEND_VALUE); |  | 
|  2901     } |  | 
|  2902     if( TCLSH==1 && Tcl_EvalFile(interp, argv[1])!=TCL_OK ){ |  | 
|  2903       const char *zInfo = Tcl_GetVar(interp, "errorInfo", TCL_GLOBAL_ONLY); |  | 
|  2904       if( zInfo==0 ) zInfo = Tcl_GetStringResult(interp); |  | 
|  2905       fprintf(stderr,"%s: %s\n", *argv, zInfo); |  | 
|  2906       return 1; |  | 
|  2907     } |  | 
|  2908   } |  | 
|  2909   if( argc<=1 || TCLSH==2 ){ |  | 
|  2910     Tcl_GlobalEval(interp, zMainloop); |  | 
|  2911   } |  | 
|  2912   return 0; |  | 
|  2913 } |  | 
|  2914 #endif /* TCLSH */ |  | 
| OLD | NEW |