| 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 ** Code for testing all sorts of SQLite interfaces.  This code |  | 
|    13 ** is not included in the SQLite library.  It is used for automated |  | 
|    14 ** testing of the SQLite library. |  | 
|    15 ** |  | 
|    16 ** $Id: test1.c,v 1.354 2009/08/10 04:37:50 danielk1977 Exp $ |  | 
|    17 */ |  | 
|    18 #include "sqliteInt.h" |  | 
|    19 #include "tcl.h" |  | 
|    20 #include <stdlib.h> |  | 
|    21 #include <string.h> |  | 
|    22  |  | 
|    23 /* |  | 
|    24 ** This is a copy of the first part of the SqliteDb structure in  |  | 
|    25 ** tclsqlite.c.  We need it here so that the get_sqlite_pointer routine |  | 
|    26 ** can extract the sqlite3* pointer from an existing Tcl SQLite |  | 
|    27 ** connection. |  | 
|    28 */ |  | 
|    29 struct SqliteDb { |  | 
|    30   sqlite3 *db; |  | 
|    31 }; |  | 
|    32  |  | 
|    33 /* |  | 
|    34 ** Convert text generated by the "%p" conversion format back into |  | 
|    35 ** a pointer. |  | 
|    36 */ |  | 
|    37 static int testHexToInt(int h){ |  | 
|    38   if( h>='0' && h<='9' ){ |  | 
|    39     return h - '0'; |  | 
|    40   }else if( h>='a' && h<='f' ){ |  | 
|    41     return h - 'a' + 10; |  | 
|    42   }else{ |  | 
|    43     assert( h>='A' && h<='F' ); |  | 
|    44     return h - 'A' + 10; |  | 
|    45   } |  | 
|    46 } |  | 
|    47 void *sqlite3TestTextToPtr(const char *z){ |  | 
|    48   void *p; |  | 
|    49   u64 v; |  | 
|    50   u32 v2; |  | 
|    51   if( z[0]=='0' && z[1]=='x' ){ |  | 
|    52     z += 2; |  | 
|    53   } |  | 
|    54   v = 0; |  | 
|    55   while( *z ){ |  | 
|    56     v = (v<<4) + testHexToInt(*z); |  | 
|    57     z++; |  | 
|    58   } |  | 
|    59   if( sizeof(p)==sizeof(v) ){ |  | 
|    60     memcpy(&p, &v, sizeof(p)); |  | 
|    61   }else{ |  | 
|    62     assert( sizeof(p)==sizeof(v2) ); |  | 
|    63     v2 = (u32)v; |  | 
|    64     memcpy(&p, &v2, sizeof(p)); |  | 
|    65   } |  | 
|    66   return p; |  | 
|    67 } |  | 
|    68  |  | 
|    69  |  | 
|    70 /* |  | 
|    71 ** A TCL command that returns the address of the sqlite* pointer |  | 
|    72 ** for an sqlite connection instance.  Bad things happen if the |  | 
|    73 ** input is not an sqlite connection. |  | 
|    74 */ |  | 
|    75 static int get_sqlite_pointer( |  | 
|    76   void * clientData, |  | 
|    77   Tcl_Interp *interp, |  | 
|    78   int objc, |  | 
|    79   Tcl_Obj *CONST objv[] |  | 
|    80 ){ |  | 
|    81   struct SqliteDb *p; |  | 
|    82   Tcl_CmdInfo cmdInfo; |  | 
|    83   char zBuf[100]; |  | 
|    84   if( objc!=2 ){ |  | 
|    85     Tcl_WrongNumArgs(interp, 1, objv, "SQLITE-CONNECTION"); |  | 
|    86     return TCL_ERROR; |  | 
|    87   } |  | 
|    88   if( !Tcl_GetCommandInfo(interp, Tcl_GetString(objv[1]), &cmdInfo) ){ |  | 
|    89     Tcl_AppendResult(interp, "command not found: ", |  | 
|    90            Tcl_GetString(objv[1]), (char*)0); |  | 
|    91     return TCL_ERROR; |  | 
|    92   } |  | 
|    93   p = (struct SqliteDb*)cmdInfo.objClientData; |  | 
|    94   sprintf(zBuf, "%p", p->db); |  | 
|    95   if( strncmp(zBuf,"0x",2) ){ |  | 
|    96     sprintf(zBuf, "0x%p", p->db); |  | 
|    97   } |  | 
|    98   Tcl_AppendResult(interp, zBuf, 0); |  | 
|    99   return TCL_OK; |  | 
|   100 } |  | 
|   101  |  | 
|   102 /* |  | 
|   103 ** Decode a pointer to an sqlite3 object. |  | 
|   104 */ |  | 
|   105 int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb){ |  | 
|   106   struct SqliteDb *p; |  | 
|   107   Tcl_CmdInfo cmdInfo; |  | 
|   108   if( Tcl_GetCommandInfo(interp, zA, &cmdInfo) ){ |  | 
|   109     p = (struct SqliteDb*)cmdInfo.objClientData; |  | 
|   110     *ppDb = p->db; |  | 
|   111   }else{ |  | 
|   112     *ppDb = (sqlite3*)sqlite3TestTextToPtr(zA); |  | 
|   113   } |  | 
|   114   return TCL_OK; |  | 
|   115 } |  | 
|   116  |  | 
|   117  |  | 
|   118 const char *sqlite3TestErrorName(int rc){ |  | 
|   119   const char *zName = 0; |  | 
|   120   switch( rc ){ |  | 
|   121     case SQLITE_OK:                  zName = "SQLITE_OK";                break; |  | 
|   122     case SQLITE_ERROR:               zName = "SQLITE_ERROR";             break; |  | 
|   123     case SQLITE_INTERNAL:            zName = "SQLITE_INTERNAL";          break; |  | 
|   124     case SQLITE_PERM:                zName = "SQLITE_PERM";              break; |  | 
|   125     case SQLITE_ABORT:               zName = "SQLITE_ABORT";             break; |  | 
|   126     case SQLITE_BUSY:                zName = "SQLITE_BUSY";              break; |  | 
|   127     case SQLITE_LOCKED:              zName = "SQLITE_LOCKED";            break; |  | 
|   128     case SQLITE_LOCKED_SHAREDCACHE:  zName = "SQLITE_LOCKED_SHAREDCACHE";break; |  | 
|   129     case SQLITE_NOMEM:               zName = "SQLITE_NOMEM";             break; |  | 
|   130     case SQLITE_READONLY:            zName = "SQLITE_READONLY";          break; |  | 
|   131     case SQLITE_INTERRUPT:           zName = "SQLITE_INTERRUPT";         break; |  | 
|   132     case SQLITE_IOERR:               zName = "SQLITE_IOERR";             break; |  | 
|   133     case SQLITE_CORRUPT:             zName = "SQLITE_CORRUPT";           break; |  | 
|   134     case SQLITE_NOTFOUND:            zName = "SQLITE_NOTFOUND";          break; |  | 
|   135     case SQLITE_FULL:                zName = "SQLITE_FULL";              break; |  | 
|   136     case SQLITE_CANTOPEN:            zName = "SQLITE_CANTOPEN";          break; |  | 
|   137     case SQLITE_PROTOCOL:            zName = "SQLITE_PROTOCOL";          break; |  | 
|   138     case SQLITE_EMPTY:               zName = "SQLITE_EMPTY";             break; |  | 
|   139     case SQLITE_SCHEMA:              zName = "SQLITE_SCHEMA";            break; |  | 
|   140     case SQLITE_TOOBIG:              zName = "SQLITE_TOOBIG";            break; |  | 
|   141     case SQLITE_CONSTRAINT:          zName = "SQLITE_CONSTRAINT";        break; |  | 
|   142     case SQLITE_MISMATCH:            zName = "SQLITE_MISMATCH";          break; |  | 
|   143     case SQLITE_MISUSE:              zName = "SQLITE_MISUSE";            break; |  | 
|   144     case SQLITE_NOLFS:               zName = "SQLITE_NOLFS";             break; |  | 
|   145     case SQLITE_AUTH:                zName = "SQLITE_AUTH";              break; |  | 
|   146     case SQLITE_FORMAT:              zName = "SQLITE_FORMAT";            break; |  | 
|   147     case SQLITE_RANGE:               zName = "SQLITE_RANGE";             break; |  | 
|   148     case SQLITE_NOTADB:              zName = "SQLITE_NOTADB";            break; |  | 
|   149     case SQLITE_ROW:                 zName = "SQLITE_ROW";               break; |  | 
|   150     case SQLITE_DONE:                zName = "SQLITE_DONE";              break; |  | 
|   151     case SQLITE_IOERR_READ:          zName = "SQLITE_IOERR_READ";        break; |  | 
|   152     case SQLITE_IOERR_SHORT_READ:    zName = "SQLITE_IOERR_SHORT_READ";  break; |  | 
|   153     case SQLITE_IOERR_WRITE:         zName = "SQLITE_IOERR_WRITE";       break; |  | 
|   154     case SQLITE_IOERR_FSYNC:         zName = "SQLITE_IOERR_FSYNC";       break; |  | 
|   155     case SQLITE_IOERR_DIR_FSYNC:     zName = "SQLITE_IOERR_DIR_FSYNC";   break; |  | 
|   156     case SQLITE_IOERR_TRUNCATE:      zName = "SQLITE_IOERR_TRUNCATE";    break; |  | 
|   157     case SQLITE_IOERR_FSTAT:         zName = "SQLITE_IOERR_FSTAT";       break; |  | 
|   158     case SQLITE_IOERR_UNLOCK:        zName = "SQLITE_IOERR_UNLOCK";      break; |  | 
|   159     case SQLITE_IOERR_RDLOCK:        zName = "SQLITE_IOERR_RDLOCK";      break; |  | 
|   160     case SQLITE_IOERR_DELETE:        zName = "SQLITE_IOERR_DELETE";      break; |  | 
|   161     case SQLITE_IOERR_BLOCKED:       zName = "SQLITE_IOERR_BLOCKED";     break; |  | 
|   162     case SQLITE_IOERR_NOMEM:         zName = "SQLITE_IOERR_NOMEM";       break; |  | 
|   163     case SQLITE_IOERR_ACCESS:        zName = "SQLITE_IOERR_ACCESS";      break; |  | 
|   164     case SQLITE_IOERR_CHECKRESERVEDLOCK: |  | 
|   165                                zName = "SQLITE_IOERR_CHECKRESERVEDLOCK"; break; |  | 
|   166     case SQLITE_IOERR_LOCK:          zName = "SQLITE_IOERR_LOCK";        break; |  | 
|   167     default:                         zName = "SQLITE_Unknown";           break; |  | 
|   168   } |  | 
|   169   return zName; |  | 
|   170 } |  | 
|   171 #define t1ErrorName sqlite3TestErrorName |  | 
|   172  |  | 
|   173 /* |  | 
|   174 ** Convert an sqlite3_stmt* into an sqlite3*.  This depends on the |  | 
|   175 ** fact that the sqlite3* is the first field in the Vdbe structure. |  | 
|   176 */ |  | 
|   177 #define StmtToDb(X)   sqlite3_db_handle(X) |  | 
|   178  |  | 
|   179 /* |  | 
|   180 ** Check a return value to make sure it agrees with the results |  | 
|   181 ** from sqlite3_errcode. |  | 
|   182 */ |  | 
|   183 int sqlite3TestErrCode(Tcl_Interp *interp, sqlite3 *db, int rc){ |  | 
|   184   if( sqlite3_threadsafe()==0 && rc!=SQLITE_MISUSE && rc!=SQLITE_OK |  | 
|   185    && sqlite3_errcode(db)!=rc ){ |  | 
|   186     char zBuf[200]; |  | 
|   187     int r2 = sqlite3_errcode(db); |  | 
|   188     sprintf(zBuf, "error code %s (%d) does not match sqlite3_errcode %s (%d)", |  | 
|   189        t1ErrorName(rc), rc, t1ErrorName(r2), r2); |  | 
|   190     Tcl_ResetResult(interp); |  | 
|   191     Tcl_AppendResult(interp, zBuf, 0); |  | 
|   192     return 1; |  | 
|   193   } |  | 
|   194   return 0; |  | 
|   195 } |  | 
|   196  |  | 
|   197 /* |  | 
|   198 ** Decode a pointer to an sqlite3_stmt object. |  | 
|   199 */ |  | 
|   200 static int getStmtPointer( |  | 
|   201   Tcl_Interp *interp,  |  | 
|   202   const char *zArg,   |  | 
|   203   sqlite3_stmt **ppStmt |  | 
|   204 ){ |  | 
|   205   *ppStmt = (sqlite3_stmt*)sqlite3TestTextToPtr(zArg); |  | 
|   206   return TCL_OK; |  | 
|   207 } |  | 
|   208  |  | 
|   209 /* |  | 
|   210 ** Generate a text representation of a pointer that can be understood |  | 
|   211 ** by the getDbPointer and getVmPointer routines above. |  | 
|   212 ** |  | 
|   213 ** The problem is, on some machines (Solaris) if you do a printf with |  | 
|   214 ** "%p" you cannot turn around and do a scanf with the same "%p" and |  | 
|   215 ** get your pointer back.  You have to prepend a "0x" before it will |  | 
|   216 ** work.  Or at least that is what is reported to me (drh).  But this |  | 
|   217 ** behavior varies from machine to machine.  The solution used her is |  | 
|   218 ** to test the string right after it is generated to see if it can be |  | 
|   219 ** understood by scanf, and if not, try prepending an "0x" to see if |  | 
|   220 ** that helps.  If nothing works, a fatal error is generated. |  | 
|   221 */ |  | 
|   222 int sqlite3TestMakePointerStr(Tcl_Interp *interp, char *zPtr, void *p){ |  | 
|   223   sqlite3_snprintf(100, zPtr, "%p", p); |  | 
|   224   return TCL_OK; |  | 
|   225 } |  | 
|   226  |  | 
|   227 /* |  | 
|   228 ** The callback routine for sqlite3_exec_printf(). |  | 
|   229 */ |  | 
|   230 static int exec_printf_cb(void *pArg, int argc, char **argv, char **name){ |  | 
|   231   Tcl_DString *str = (Tcl_DString*)pArg; |  | 
|   232   int i; |  | 
|   233  |  | 
|   234   if( Tcl_DStringLength(str)==0 ){ |  | 
|   235     for(i=0; i<argc; i++){ |  | 
|   236       Tcl_DStringAppendElement(str, name[i] ? name[i] : "NULL"); |  | 
|   237     } |  | 
|   238   } |  | 
|   239   for(i=0; i<argc; i++){ |  | 
|   240     Tcl_DStringAppendElement(str, argv[i] ? argv[i] : "NULL"); |  | 
|   241   } |  | 
|   242   return 0; |  | 
|   243 } |  | 
|   244  |  | 
|   245 /* |  | 
|   246 ** The I/O tracing callback. |  | 
|   247 */ |  | 
|   248 #if !defined(SQLITE_OMIT_TRACE) && defined(SQLITE_ENABLE_IOTRACE) |  | 
|   249 static FILE *iotrace_file = 0; |  | 
|   250 static void io_trace_callback(const char *zFormat, ...){ |  | 
|   251   va_list ap; |  | 
|   252   va_start(ap, zFormat); |  | 
|   253   vfprintf(iotrace_file, zFormat, ap); |  | 
|   254   va_end(ap); |  | 
|   255   fflush(iotrace_file); |  | 
|   256 } |  | 
|   257 #endif |  | 
|   258  |  | 
|   259 /* |  | 
|   260 ** Usage:  io_trace FILENAME |  | 
|   261 ** |  | 
|   262 ** Turn I/O tracing on or off.  If FILENAME is not an empty string, |  | 
|   263 ** I/O tracing begins going into FILENAME. If FILENAME is an empty |  | 
|   264 ** string, I/O tracing is turned off. |  | 
|   265 */ |  | 
|   266 static int test_io_trace( |  | 
|   267   void *NotUsed, |  | 
|   268   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ |  | 
|   269   int argc,              /* Number of arguments */ |  | 
|   270   char **argv            /* Text of each argument */ |  | 
|   271 ){ |  | 
|   272 #if !defined(SQLITE_OMIT_TRACE) && defined(SQLITE_ENABLE_IOTRACE) |  | 
|   273   if( argc!=2 ){ |  | 
|   274     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], |  | 
|   275           " FILENAME\"", 0); |  | 
|   276     return TCL_ERROR; |  | 
|   277   } |  | 
|   278   if( iotrace_file ){ |  | 
|   279     if( iotrace_file!=stdout && iotrace_file!=stderr ){ |  | 
|   280       fclose(iotrace_file); |  | 
|   281     } |  | 
|   282     iotrace_file = 0; |  | 
|   283     sqlite3IoTrace = 0; |  | 
|   284   } |  | 
|   285   if( argv[1][0] ){ |  | 
|   286     if( strcmp(argv[1],"stdout")==0 ){ |  | 
|   287       iotrace_file = stdout; |  | 
|   288     }else if( strcmp(argv[1],"stderr")==0 ){ |  | 
|   289       iotrace_file = stderr; |  | 
|   290     }else{ |  | 
|   291       iotrace_file = fopen(argv[1], "w"); |  | 
|   292     } |  | 
|   293     sqlite3IoTrace = io_trace_callback; |  | 
|   294   } |  | 
|   295 #endif |  | 
|   296   return TCL_OK; |  | 
|   297 } |  | 
|   298  |  | 
|   299  |  | 
|   300 /* |  | 
|   301 ** Usage:  sqlite3_exec_printf  DB  FORMAT  STRING |  | 
|   302 ** |  | 
|   303 ** Invoke the sqlite3_exec_printf() interface using the open database |  | 
|   304 ** DB.  The SQL is the string FORMAT.  The format string should contain |  | 
|   305 ** one %s or %q.  STRING is the value inserted into %s or %q. |  | 
|   306 */ |  | 
|   307 static int test_exec_printf( |  | 
|   308   void *NotUsed, |  | 
|   309   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ |  | 
|   310   int argc,              /* Number of arguments */ |  | 
|   311   char **argv            /* Text of each argument */ |  | 
|   312 ){ |  | 
|   313   sqlite3 *db; |  | 
|   314   Tcl_DString str; |  | 
|   315   int rc; |  | 
|   316   char *zErr = 0; |  | 
|   317   char *zSql; |  | 
|   318   char zBuf[30]; |  | 
|   319   if( argc!=4 ){ |  | 
|   320     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],  |  | 
|   321        " DB FORMAT STRING", 0); |  | 
|   322     return TCL_ERROR; |  | 
|   323   } |  | 
|   324   if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; |  | 
|   325   Tcl_DStringInit(&str); |  | 
|   326   zSql = sqlite3_mprintf(argv[2], argv[3]); |  | 
|   327   rc = sqlite3_exec(db, zSql, exec_printf_cb, &str, &zErr); |  | 
|   328   sqlite3_free(zSql); |  | 
|   329   sprintf(zBuf, "%d", rc); |  | 
|   330   Tcl_AppendElement(interp, zBuf); |  | 
|   331   Tcl_AppendElement(interp, rc==SQLITE_OK ? Tcl_DStringValue(&str) : zErr); |  | 
|   332   Tcl_DStringFree(&str); |  | 
|   333   if( zErr ) sqlite3_free(zErr); |  | 
|   334   if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; |  | 
|   335   return TCL_OK; |  | 
|   336 } |  | 
|   337  |  | 
|   338 /* |  | 
|   339 ** Usage:  sqlite3_exec_hex  DB  HEX |  | 
|   340 ** |  | 
|   341 ** Invoke the sqlite3_exec() on a string that is obtained by translating |  | 
|   342 ** HEX into ASCII.  Most characters are translated as is.  %HH becomes |  | 
|   343 ** a hex character. |  | 
|   344 */ |  | 
|   345 static int test_exec_hex( |  | 
|   346   void *NotUsed, |  | 
|   347   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ |  | 
|   348   int argc,              /* Number of arguments */ |  | 
|   349   char **argv            /* Text of each argument */ |  | 
|   350 ){ |  | 
|   351   sqlite3 *db; |  | 
|   352   Tcl_DString str; |  | 
|   353   int rc, i, j; |  | 
|   354   char *zErr = 0; |  | 
|   355   char *zHex; |  | 
|   356   char zSql[500]; |  | 
|   357   char zBuf[30]; |  | 
|   358   if( argc!=3 ){ |  | 
|   359     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],  |  | 
|   360        " DB HEX", 0); |  | 
|   361     return TCL_ERROR; |  | 
|   362   } |  | 
|   363   if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; |  | 
|   364   zHex = argv[2]; |  | 
|   365   for(i=j=0; i<sizeof(zSql) && zHex[j]; i++, j++){ |  | 
|   366     if( zHex[j]=='%' && zHex[j+2] && zHex[j+2] ){ |  | 
|   367       zSql[i] = (testHexToInt(zHex[j+1])<<4) + testHexToInt(zHex[j+2]); |  | 
|   368       j += 2; |  | 
|   369     }else{ |  | 
|   370       zSql[i] = zHex[j]; |  | 
|   371     } |  | 
|   372   } |  | 
|   373   zSql[i] = 0; |  | 
|   374   Tcl_DStringInit(&str); |  | 
|   375   rc = sqlite3_exec(db, zSql, exec_printf_cb, &str, &zErr); |  | 
|   376   sprintf(zBuf, "%d", rc); |  | 
|   377   Tcl_AppendElement(interp, zBuf); |  | 
|   378   Tcl_AppendElement(interp, rc==SQLITE_OK ? Tcl_DStringValue(&str) : zErr); |  | 
|   379   Tcl_DStringFree(&str); |  | 
|   380   if( zErr ) sqlite3_free(zErr); |  | 
|   381   if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; |  | 
|   382   return TCL_OK; |  | 
|   383 } |  | 
|   384  |  | 
|   385 /* |  | 
|   386 ** Usage:  db_enter DB |  | 
|   387 **         db_leave DB |  | 
|   388 ** |  | 
|   389 ** Enter or leave the mutex on a database connection. |  | 
|   390 */ |  | 
|   391 static int db_enter( |  | 
|   392   void *NotUsed, |  | 
|   393   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ |  | 
|   394   int argc,              /* Number of arguments */ |  | 
|   395   char **argv            /* Text of each argument */ |  | 
|   396 ){ |  | 
|   397   sqlite3 *db; |  | 
|   398   if( argc!=2 ){ |  | 
|   399     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],  |  | 
|   400        " DB", 0); |  | 
|   401     return TCL_ERROR; |  | 
|   402   } |  | 
|   403   if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; |  | 
|   404   sqlite3_mutex_enter(db->mutex); |  | 
|   405   return TCL_OK; |  | 
|   406 } |  | 
|   407 static int db_leave( |  | 
|   408   void *NotUsed, |  | 
|   409   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ |  | 
|   410   int argc,              /* Number of arguments */ |  | 
|   411   char **argv            /* Text of each argument */ |  | 
|   412 ){ |  | 
|   413   sqlite3 *db; |  | 
|   414   if( argc!=2 ){ |  | 
|   415     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],  |  | 
|   416        " DB", 0); |  | 
|   417     return TCL_ERROR; |  | 
|   418   } |  | 
|   419   if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; |  | 
|   420   sqlite3_mutex_leave(db->mutex); |  | 
|   421   return TCL_OK; |  | 
|   422 } |  | 
|   423  |  | 
|   424 /* |  | 
|   425 ** Usage:  sqlite3_exec  DB  SQL |  | 
|   426 ** |  | 
|   427 ** Invoke the sqlite3_exec interface using the open database DB |  | 
|   428 */ |  | 
|   429 static int test_exec( |  | 
|   430   void *NotUsed, |  | 
|   431   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ |  | 
|   432   int argc,              /* Number of arguments */ |  | 
|   433   char **argv            /* Text of each argument */ |  | 
|   434 ){ |  | 
|   435   sqlite3 *db; |  | 
|   436   Tcl_DString str; |  | 
|   437   int rc; |  | 
|   438   char *zErr = 0; |  | 
|   439   char *zSql; |  | 
|   440   int i, j; |  | 
|   441   char zBuf[30]; |  | 
|   442   if( argc!=3 ){ |  | 
|   443     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],  |  | 
|   444        " DB SQL", 0); |  | 
|   445     return TCL_ERROR; |  | 
|   446   } |  | 
|   447   if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; |  | 
|   448   Tcl_DStringInit(&str); |  | 
|   449   zSql = sqlite3_mprintf("%s", argv[2]); |  | 
|   450   for(i=j=0; zSql[i];){ |  | 
|   451     if( zSql[i]=='%' ){ |  | 
|   452       zSql[j++] = (testHexToInt(zSql[i+1])<<4) + testHexToInt(zSql[i+2]); |  | 
|   453       i += 3; |  | 
|   454     }else{ |  | 
|   455       zSql[j++] = zSql[i++]; |  | 
|   456     } |  | 
|   457   } |  | 
|   458   zSql[j] = 0; |  | 
|   459   rc = sqlite3_exec(db, zSql, exec_printf_cb, &str, &zErr); |  | 
|   460   sqlite3_free(zSql); |  | 
|   461   sprintf(zBuf, "%d", rc); |  | 
|   462   Tcl_AppendElement(interp, zBuf); |  | 
|   463   Tcl_AppendElement(interp, rc==SQLITE_OK ? Tcl_DStringValue(&str) : zErr); |  | 
|   464   Tcl_DStringFree(&str); |  | 
|   465   if( zErr ) sqlite3_free(zErr); |  | 
|   466   if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; |  | 
|   467   return TCL_OK; |  | 
|   468 } |  | 
|   469  |  | 
|   470 /* |  | 
|   471 ** Usage:  sqlite3_exec_nr  DB  SQL |  | 
|   472 ** |  | 
|   473 ** Invoke the sqlite3_exec interface using the open database DB.  Discard |  | 
|   474 ** all results |  | 
|   475 */ |  | 
|   476 static int test_exec_nr( |  | 
|   477   void *NotUsed, |  | 
|   478   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ |  | 
|   479   int argc,              /* Number of arguments */ |  | 
|   480   char **argv            /* Text of each argument */ |  | 
|   481 ){ |  | 
|   482   sqlite3 *db; |  | 
|   483   int rc; |  | 
|   484   char *zErr = 0; |  | 
|   485   if( argc!=3 ){ |  | 
|   486     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],  |  | 
|   487        " DB SQL", 0); |  | 
|   488     return TCL_ERROR; |  | 
|   489   } |  | 
|   490   if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; |  | 
|   491   rc = sqlite3_exec(db, argv[2], 0, 0, &zErr); |  | 
|   492   if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; |  | 
|   493   return TCL_OK; |  | 
|   494 } |  | 
|   495  |  | 
|   496 /* |  | 
|   497 ** Usage:  sqlite3_mprintf_z_test  SEPARATOR  ARG0  ARG1 ... |  | 
|   498 ** |  | 
|   499 ** Test the %z format of sqlite_mprintf().  Use multiple mprintf() calls to  |  | 
|   500 ** concatenate arg0 through argn using separator as the separator. |  | 
|   501 ** Return the result. |  | 
|   502 */ |  | 
|   503 static int test_mprintf_z( |  | 
|   504   void *NotUsed, |  | 
|   505   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ |  | 
|   506   int argc,              /* Number of arguments */ |  | 
|   507   char **argv            /* Text of each argument */ |  | 
|   508 ){ |  | 
|   509   char *zResult = 0; |  | 
|   510   int i; |  | 
|   511  |  | 
|   512   for(i=2; i<argc && (i==2 || zResult); i++){ |  | 
|   513     zResult = sqlite3_mprintf("%z%s%s", zResult, argv[1], argv[i]); |  | 
|   514   } |  | 
|   515   Tcl_AppendResult(interp, zResult, 0); |  | 
|   516   sqlite3_free(zResult); |  | 
|   517   return TCL_OK; |  | 
|   518 } |  | 
|   519  |  | 
|   520 /* |  | 
|   521 ** Usage:  sqlite3_mprintf_n_test  STRING |  | 
|   522 ** |  | 
|   523 ** Test the %n format of sqlite_mprintf().  Return the length of the |  | 
|   524 ** input string. |  | 
|   525 */ |  | 
|   526 static int test_mprintf_n( |  | 
|   527   void *NotUsed, |  | 
|   528   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ |  | 
|   529   int argc,              /* Number of arguments */ |  | 
|   530   char **argv            /* Text of each argument */ |  | 
|   531 ){ |  | 
|   532   char *zStr; |  | 
|   533   int n = 0; |  | 
|   534   zStr = sqlite3_mprintf("%s%n", argv[1], &n); |  | 
|   535   sqlite3_free(zStr); |  | 
|   536   Tcl_SetObjResult(interp, Tcl_NewIntObj(n)); |  | 
|   537   return TCL_OK; |  | 
|   538 } |  | 
|   539  |  | 
|   540 /* |  | 
|   541 ** Usage:  sqlite3_snprintf_int  SIZE FORMAT  INT |  | 
|   542 ** |  | 
|   543 ** Test the of sqlite3_snprintf() routine.  SIZE is the size of the |  | 
|   544 ** output buffer in bytes.  The maximum size is 100.  FORMAT is the |  | 
|   545 ** format string.  INT is a single integer argument.  The FORMAT |  | 
|   546 ** string must require no more than this one integer argument.  If |  | 
|   547 ** You pass in a format string that requires more than one argument, |  | 
|   548 ** bad things will happen. |  | 
|   549 */ |  | 
|   550 static int test_snprintf_int( |  | 
|   551   void *NotUsed, |  | 
|   552   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ |  | 
|   553   int argc,              /* Number of arguments */ |  | 
|   554   char **argv            /* Text of each argument */ |  | 
|   555 ){ |  | 
|   556   char zStr[100]; |  | 
|   557   int n = atoi(argv[1]); |  | 
|   558   const char *zFormat = argv[2]; |  | 
|   559   int a1 = atoi(argv[3]); |  | 
|   560   if( n>sizeof(zStr) ) n = sizeof(zStr); |  | 
|   561   sqlite3_snprintf(sizeof(zStr), zStr, "abcdefghijklmnopqrstuvwxyz"); |  | 
|   562   sqlite3_snprintf(n, zStr, zFormat, a1); |  | 
|   563   Tcl_AppendResult(interp, zStr, 0); |  | 
|   564   return TCL_OK; |  | 
|   565 } |  | 
|   566  |  | 
|   567 #ifndef SQLITE_OMIT_GET_TABLE |  | 
|   568  |  | 
|   569 /* |  | 
|   570 ** Usage:  sqlite3_get_table_printf  DB  FORMAT  STRING  ?--no-counts? |  | 
|   571 ** |  | 
|   572 ** Invoke the sqlite3_get_table_printf() interface using the open database |  | 
|   573 ** DB.  The SQL is the string FORMAT.  The format string should contain |  | 
|   574 ** one %s or %q.  STRING is the value inserted into %s or %q. |  | 
|   575 */ |  | 
|   576 static int test_get_table_printf( |  | 
|   577   void *NotUsed, |  | 
|   578   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ |  | 
|   579   int argc,              /* Number of arguments */ |  | 
|   580   char **argv            /* Text of each argument */ |  | 
|   581 ){ |  | 
|   582   sqlite3 *db; |  | 
|   583   Tcl_DString str; |  | 
|   584   int rc; |  | 
|   585   char *zErr = 0; |  | 
|   586   int nRow, nCol; |  | 
|   587   char **aResult; |  | 
|   588   int i; |  | 
|   589   char zBuf[30]; |  | 
|   590   char *zSql; |  | 
|   591   int resCount = -1; |  | 
|   592   if( argc==5 ){ |  | 
|   593     if( Tcl_GetInt(interp, argv[4], &resCount) ) return TCL_ERROR; |  | 
|   594   } |  | 
|   595   if( argc!=4 && argc!=5 ){ |  | 
|   596     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],  |  | 
|   597        " DB FORMAT STRING ?COUNT?", 0); |  | 
|   598     return TCL_ERROR; |  | 
|   599   } |  | 
|   600   if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; |  | 
|   601   Tcl_DStringInit(&str); |  | 
|   602   zSql = sqlite3_mprintf(argv[2],argv[3]); |  | 
|   603   if( argc==5 ){ |  | 
|   604     rc = sqlite3_get_table(db, zSql, &aResult, 0, 0, &zErr); |  | 
|   605   }else{ |  | 
|   606     rc = sqlite3_get_table(db, zSql, &aResult, &nRow, &nCol, &zErr); |  | 
|   607     resCount = (nRow+1)*nCol; |  | 
|   608   } |  | 
|   609   sqlite3_free(zSql); |  | 
|   610   sprintf(zBuf, "%d", rc); |  | 
|   611   Tcl_AppendElement(interp, zBuf); |  | 
|   612   if( rc==SQLITE_OK ){ |  | 
|   613     if( argc==4 ){ |  | 
|   614       sprintf(zBuf, "%d", nRow); |  | 
|   615       Tcl_AppendElement(interp, zBuf); |  | 
|   616       sprintf(zBuf, "%d", nCol); |  | 
|   617       Tcl_AppendElement(interp, zBuf); |  | 
|   618     } |  | 
|   619     for(i=0; i<resCount; i++){ |  | 
|   620       Tcl_AppendElement(interp, aResult[i] ? aResult[i] : "NULL"); |  | 
|   621     } |  | 
|   622   }else{ |  | 
|   623     Tcl_AppendElement(interp, zErr); |  | 
|   624   } |  | 
|   625   sqlite3_free_table(aResult); |  | 
|   626   if( zErr ) sqlite3_free(zErr); |  | 
|   627   if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; |  | 
|   628   return TCL_OK; |  | 
|   629 } |  | 
|   630  |  | 
|   631 #endif /* SQLITE_OMIT_GET_TABLE */ |  | 
|   632  |  | 
|   633  |  | 
|   634 /* |  | 
|   635 ** Usage:  sqlite3_last_insert_rowid DB |  | 
|   636 ** |  | 
|   637 ** Returns the integer ROWID of the most recent insert. |  | 
|   638 */ |  | 
|   639 static int test_last_rowid( |  | 
|   640   void *NotUsed, |  | 
|   641   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ |  | 
|   642   int argc,              /* Number of arguments */ |  | 
|   643   char **argv            /* Text of each argument */ |  | 
|   644 ){ |  | 
|   645   sqlite3 *db; |  | 
|   646   char zBuf[30]; |  | 
|   647  |  | 
|   648   if( argc!=2 ){ |  | 
|   649     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " DB\"", 0); |  | 
|   650     return TCL_ERROR; |  | 
|   651   } |  | 
|   652   if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; |  | 
|   653   sprintf(zBuf, "%lld", sqlite3_last_insert_rowid(db)); |  | 
|   654   Tcl_AppendResult(interp, zBuf, 0); |  | 
|   655   return SQLITE_OK; |  | 
|   656 } |  | 
|   657  |  | 
|   658 /* |  | 
|   659 ** Usage:  sqlite3_key DB KEY |  | 
|   660 ** |  | 
|   661 ** Set the codec key. |  | 
|   662 */ |  | 
|   663 static int test_key( |  | 
|   664   void *NotUsed, |  | 
|   665   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ |  | 
|   666   int argc,              /* Number of arguments */ |  | 
|   667   char **argv            /* Text of each argument */ |  | 
|   668 ){ |  | 
|   669   sqlite3 *db; |  | 
|   670   const char *zKey; |  | 
|   671   int nKey; |  | 
|   672   if( argc!=3 ){ |  | 
|   673     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], |  | 
|   674        " FILENAME\"", 0); |  | 
|   675     return TCL_ERROR; |  | 
|   676   } |  | 
|   677   if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; |  | 
|   678   zKey = argv[2]; |  | 
|   679   nKey = strlen(zKey); |  | 
|   680 #ifdef SQLITE_HAS_CODEC |  | 
|   681   sqlite3_key(db, zKey, nKey); |  | 
|   682 #endif |  | 
|   683   return TCL_OK; |  | 
|   684 } |  | 
|   685  |  | 
|   686 /* |  | 
|   687 ** Usage:  sqlite3_rekey DB KEY |  | 
|   688 ** |  | 
|   689 ** Change the codec key. |  | 
|   690 */ |  | 
|   691 static int test_rekey( |  | 
|   692   void *NotUsed, |  | 
|   693   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ |  | 
|   694   int argc,              /* Number of arguments */ |  | 
|   695   char **argv            /* Text of each argument */ |  | 
|   696 ){ |  | 
|   697   sqlite3 *db; |  | 
|   698   const char *zKey; |  | 
|   699   int nKey; |  | 
|   700   if( argc!=3 ){ |  | 
|   701     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], |  | 
|   702        " FILENAME\"", 0); |  | 
|   703     return TCL_ERROR; |  | 
|   704   } |  | 
|   705   if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; |  | 
|   706   zKey = argv[2]; |  | 
|   707   nKey = strlen(zKey); |  | 
|   708 #ifdef SQLITE_HAS_CODEC |  | 
|   709   sqlite3_rekey(db, zKey, nKey); |  | 
|   710 #endif |  | 
|   711   return TCL_OK; |  | 
|   712 } |  | 
|   713  |  | 
|   714 /* |  | 
|   715 ** Usage:  sqlite3_close DB |  | 
|   716 ** |  | 
|   717 ** Closes the database opened by sqlite3_open. |  | 
|   718 */ |  | 
|   719 static int sqlite_test_close( |  | 
|   720   void *NotUsed, |  | 
|   721   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ |  | 
|   722   int argc,              /* Number of arguments */ |  | 
|   723   char **argv            /* Text of each argument */ |  | 
|   724 ){ |  | 
|   725   sqlite3 *db; |  | 
|   726   int rc; |  | 
|   727   if( argc!=2 ){ |  | 
|   728     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], |  | 
|   729        " FILENAME\"", 0); |  | 
|   730     return TCL_ERROR; |  | 
|   731   } |  | 
|   732   if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; |  | 
|   733   rc = sqlite3_close(db); |  | 
|   734   Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC); |  | 
|   735   return TCL_OK; |  | 
|   736 } |  | 
|   737  |  | 
|   738 /* |  | 
|   739 ** Implementation of the x_coalesce() function. |  | 
|   740 ** Return the first argument non-NULL argument. |  | 
|   741 */ |  | 
|   742 static void t1_ifnullFunc( |  | 
|   743   sqlite3_context *context, |  | 
|   744   int argc, |  | 
|   745   sqlite3_value **argv |  | 
|   746 ){ |  | 
|   747   int i; |  | 
|   748   for(i=0; i<argc; i++){ |  | 
|   749     if( SQLITE_NULL!=sqlite3_value_type(argv[i]) ){ |  | 
|   750       int n = sqlite3_value_bytes(argv[i]); |  | 
|   751       sqlite3_result_text(context, (char*)sqlite3_value_text(argv[i]), |  | 
|   752           n, SQLITE_TRANSIENT); |  | 
|   753       break; |  | 
|   754     } |  | 
|   755   } |  | 
|   756 } |  | 
|   757  |  | 
|   758 /* |  | 
|   759 ** These are test functions.    hex8() interprets its argument as |  | 
|   760 ** UTF8 and returns a hex encoding.  hex16le() interprets its argument |  | 
|   761 ** as UTF16le and returns a hex encoding. |  | 
|   762 */ |  | 
|   763 static void hex8Func(sqlite3_context *p, int argc, sqlite3_value **argv){ |  | 
|   764   const unsigned char *z; |  | 
|   765   int i; |  | 
|   766   char zBuf[200]; |  | 
|   767   z = sqlite3_value_text(argv[0]); |  | 
|   768   for(i=0; i<sizeof(zBuf)/2 - 2 && z[i]; i++){ |  | 
|   769     sprintf(&zBuf[i*2], "%02x", z[i]&0xff); |  | 
|   770   } |  | 
|   771   zBuf[i*2] = 0; |  | 
|   772   sqlite3_result_text(p, (char*)zBuf, -1, SQLITE_TRANSIENT); |  | 
|   773 } |  | 
|   774 #ifndef SQLITE_OMIT_UTF16 |  | 
|   775 static void hex16Func(sqlite3_context *p, int argc, sqlite3_value **argv){ |  | 
|   776   const unsigned short int *z; |  | 
|   777   int i; |  | 
|   778   char zBuf[400]; |  | 
|   779   z = sqlite3_value_text16(argv[0]); |  | 
|   780   for(i=0; i<sizeof(zBuf)/4 - 4 && z[i]; i++){ |  | 
|   781     sprintf(&zBuf[i*4], "%04x", z[i]&0xff); |  | 
|   782   } |  | 
|   783   zBuf[i*4] = 0; |  | 
|   784   sqlite3_result_text(p, (char*)zBuf, -1, SQLITE_TRANSIENT); |  | 
|   785 } |  | 
|   786 #endif |  | 
|   787  |  | 
|   788 /* |  | 
|   789 ** A structure into which to accumulate text. |  | 
|   790 */ |  | 
|   791 struct dstr { |  | 
|   792   int nAlloc;  /* Space allocated */ |  | 
|   793   int nUsed;   /* Space used */ |  | 
|   794   char *z;     /* The space */ |  | 
|   795 }; |  | 
|   796  |  | 
|   797 /* |  | 
|   798 ** Append text to a dstr |  | 
|   799 */ |  | 
|   800 static void dstrAppend(struct dstr *p, const char *z, int divider){ |  | 
|   801   int n = strlen(z); |  | 
|   802   if( p->nUsed + n + 2 > p->nAlloc ){ |  | 
|   803     char *zNew; |  | 
|   804     p->nAlloc = p->nAlloc*2 + n + 200; |  | 
|   805     zNew = sqlite3_realloc(p->z, p->nAlloc); |  | 
|   806     if( zNew==0 ){ |  | 
|   807       sqlite3_free(p->z); |  | 
|   808       memset(p, 0, sizeof(*p)); |  | 
|   809       return; |  | 
|   810     } |  | 
|   811     p->z = zNew; |  | 
|   812   } |  | 
|   813   if( divider && p->nUsed>0 ){ |  | 
|   814     p->z[p->nUsed++] = divider; |  | 
|   815   } |  | 
|   816   memcpy(&p->z[p->nUsed], z, n+1); |  | 
|   817   p->nUsed += n; |  | 
|   818 } |  | 
|   819  |  | 
|   820 /* |  | 
|   821 ** Invoked for each callback from sqlite3ExecFunc |  | 
|   822 */ |  | 
|   823 static int execFuncCallback(void *pData, int argc, char **argv, char **NotUsed){ |  | 
|   824   struct dstr *p = (struct dstr*)pData; |  | 
|   825   int i; |  | 
|   826   for(i=0; i<argc; i++){ |  | 
|   827     if( argv[i]==0 ){ |  | 
|   828       dstrAppend(p, "NULL", ' '); |  | 
|   829     }else{ |  | 
|   830       dstrAppend(p, argv[i], ' '); |  | 
|   831     } |  | 
|   832   } |  | 
|   833   return 0; |  | 
|   834 } |  | 
|   835  |  | 
|   836 /* |  | 
|   837 ** Implementation of the x_sqlite_exec() function.  This function takes |  | 
|   838 ** a single argument and attempts to execute that argument as SQL code. |  | 
|   839 ** This is illegal and should set the SQLITE_MISUSE flag on the database. |  | 
|   840 ** |  | 
|   841 ** 2004-Jan-07:  We have changed this to make it legal to call sqlite3_exec() |  | 
|   842 ** from within a function call.   |  | 
|   843 **  |  | 
|   844 ** This routine simulates the effect of having two threads attempt to |  | 
|   845 ** use the same database at the same time. |  | 
|   846 */ |  | 
|   847 static void sqlite3ExecFunc( |  | 
|   848   sqlite3_context *context,  |  | 
|   849   int argc,   |  | 
|   850   sqlite3_value **argv |  | 
|   851 ){ |  | 
|   852   struct dstr x; |  | 
|   853   memset(&x, 0, sizeof(x)); |  | 
|   854   (void)sqlite3_exec((sqlite3*)sqlite3_user_data(context), |  | 
|   855       (char*)sqlite3_value_text(argv[0]), |  | 
|   856       execFuncCallback, &x, 0); |  | 
|   857   sqlite3_result_text(context, x.z, x.nUsed, SQLITE_TRANSIENT); |  | 
|   858   sqlite3_free(x.z); |  | 
|   859 } |  | 
|   860  |  | 
|   861 /* |  | 
|   862 ** Implementation of tkt2213func(), a scalar function that takes exactly |  | 
|   863 ** one argument. It has two interesting features: |  | 
|   864 ** |  | 
|   865 ** * It calls sqlite3_value_text() 3 times on the argument sqlite3_value*. |  | 
|   866 **   If the three pointers returned are not the same an SQL error is raised. |  | 
|   867 ** |  | 
|   868 ** * Otherwise it returns a copy of the text representation of its  |  | 
|   869 **   argument in such a way as the VDBE representation is a Mem* cell  |  | 
|   870 **   with the MEM_Term flag clear.  |  | 
|   871 ** |  | 
|   872 ** Ticket #2213 can therefore be tested by evaluating the following |  | 
|   873 ** SQL expression: |  | 
|   874 ** |  | 
|   875 **   tkt2213func(tkt2213func('a string')); |  | 
|   876 */ |  | 
|   877 static void tkt2213Function( |  | 
|   878   sqlite3_context *context,  |  | 
|   879   int argc,   |  | 
|   880   sqlite3_value **argv |  | 
|   881 ){ |  | 
|   882   int nText; |  | 
|   883   unsigned char const *zText1; |  | 
|   884   unsigned char const *zText2; |  | 
|   885   unsigned char const *zText3; |  | 
|   886  |  | 
|   887   nText = sqlite3_value_bytes(argv[0]); |  | 
|   888   zText1 = sqlite3_value_text(argv[0]); |  | 
|   889   zText2 = sqlite3_value_text(argv[0]); |  | 
|   890   zText3 = sqlite3_value_text(argv[0]); |  | 
|   891  |  | 
|   892   if( zText1!=zText2 || zText2!=zText3 ){ |  | 
|   893     sqlite3_result_error(context, "tkt2213 is not fixed", -1); |  | 
|   894   }else{ |  | 
|   895     char *zCopy = (char *)sqlite3_malloc(nText); |  | 
|   896     memcpy(zCopy, zText1, nText); |  | 
|   897     sqlite3_result_text(context, zCopy, nText, sqlite3_free); |  | 
|   898   } |  | 
|   899 } |  | 
|   900  |  | 
|   901 /* |  | 
|   902 ** The following SQL function takes 4 arguments.  The 2nd and |  | 
|   903 ** 4th argument must be one of these strings:  'text', 'text16', |  | 
|   904 ** or 'blob' corresponding to API functions |  | 
|   905 ** |  | 
|   906 **      sqlite3_value_text() |  | 
|   907 **      sqlite3_value_text16() |  | 
|   908 **      sqlite3_value_blob() |  | 
|   909 ** |  | 
|   910 ** The third argument is a string, either 'bytes' or 'bytes16' or 'noop', |  | 
|   911 ** corresponding to APIs: |  | 
|   912 ** |  | 
|   913 **      sqlite3_value_bytes() |  | 
|   914 **      sqlite3_value_bytes16() |  | 
|   915 **      noop |  | 
|   916 ** |  | 
|   917 ** The APIs designated by the 2nd through 4th arguments are applied |  | 
|   918 ** to the first argument in order.  If the pointers returned by the |  | 
|   919 ** second and fourth are different, this routine returns 1.  Otherwise, |  | 
|   920 ** this routine returns 0. |  | 
|   921 ** |  | 
|   922 ** This function is used to test to see when returned pointers from |  | 
|   923 ** the _text(), _text16() and _blob() APIs become invalidated. |  | 
|   924 */ |  | 
|   925 static void ptrChngFunction( |  | 
|   926   sqlite3_context *context,  |  | 
|   927   int argc,   |  | 
|   928   sqlite3_value **argv |  | 
|   929 ){ |  | 
|   930   const void *p1, *p2; |  | 
|   931   const char *zCmd; |  | 
|   932   if( argc!=4 ) return; |  | 
|   933   zCmd = (const char*)sqlite3_value_text(argv[1]); |  | 
|   934   if( zCmd==0 ) return; |  | 
|   935   if( strcmp(zCmd,"text")==0 ){ |  | 
|   936     p1 = (const void*)sqlite3_value_text(argv[0]); |  | 
|   937 #ifndef SQLITE_OMIT_UTF16 |  | 
|   938   }else if( strcmp(zCmd, "text16")==0 ){ |  | 
|   939     p1 = (const void*)sqlite3_value_text16(argv[0]); |  | 
|   940 #endif |  | 
|   941   }else if( strcmp(zCmd, "blob")==0 ){ |  | 
|   942     p1 = (const void*)sqlite3_value_blob(argv[0]); |  | 
|   943   }else{ |  | 
|   944     return; |  | 
|   945   } |  | 
|   946   zCmd = (const char*)sqlite3_value_text(argv[2]); |  | 
|   947   if( zCmd==0 ) return; |  | 
|   948   if( strcmp(zCmd,"bytes")==0 ){ |  | 
|   949     sqlite3_value_bytes(argv[0]); |  | 
|   950 #ifndef SQLITE_OMIT_UTF16 |  | 
|   951   }else if( strcmp(zCmd, "bytes16")==0 ){ |  | 
|   952     sqlite3_value_bytes16(argv[0]); |  | 
|   953 #endif |  | 
|   954   }else if( strcmp(zCmd, "noop")==0 ){ |  | 
|   955     /* do nothing */ |  | 
|   956   }else{ |  | 
|   957     return; |  | 
|   958   } |  | 
|   959   zCmd = (const char*)sqlite3_value_text(argv[3]); |  | 
|   960   if( zCmd==0 ) return; |  | 
|   961   if( strcmp(zCmd,"text")==0 ){ |  | 
|   962     p2 = (const void*)sqlite3_value_text(argv[0]); |  | 
|   963 #ifndef SQLITE_OMIT_UTF16 |  | 
|   964   }else if( strcmp(zCmd, "text16")==0 ){ |  | 
|   965     p2 = (const void*)sqlite3_value_text16(argv[0]); |  | 
|   966 #endif |  | 
|   967   }else if( strcmp(zCmd, "blob")==0 ){ |  | 
|   968     p2 = (const void*)sqlite3_value_blob(argv[0]); |  | 
|   969   }else{ |  | 
|   970     return; |  | 
|   971   } |  | 
|   972   sqlite3_result_int(context, p1!=p2); |  | 
|   973 } |  | 
|   974  |  | 
|   975  |  | 
|   976 /* |  | 
|   977 ** Usage:  sqlite_test_create_function DB |  | 
|   978 ** |  | 
|   979 ** Call the sqlite3_create_function API on the given database in order |  | 
|   980 ** to create a function named "x_coalesce".  This function does the same thing |  | 
|   981 ** as the "coalesce" function.  This function also registers an SQL function |  | 
|   982 ** named "x_sqlite_exec" that invokes sqlite3_exec().  Invoking sqlite3_exec() |  | 
|   983 ** in this way is illegal recursion and should raise an SQLITE_MISUSE error. |  | 
|   984 ** The effect is similar to trying to use the same database connection from |  | 
|   985 ** two threads at the same time. |  | 
|   986 ** |  | 
|   987 ** The original motivation for this routine was to be able to call the |  | 
|   988 ** sqlite3_create_function function while a query is in progress in order |  | 
|   989 ** to test the SQLITE_MISUSE detection logic. |  | 
|   990 */ |  | 
|   991 static int test_create_function( |  | 
|   992   void *NotUsed, |  | 
|   993   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ |  | 
|   994   int argc,              /* Number of arguments */ |  | 
|   995   char **argv            /* Text of each argument */ |  | 
|   996 ){ |  | 
|   997   int rc; |  | 
|   998   sqlite3 *db; |  | 
|   999  |  | 
|  1000   if( argc!=2 ){ |  | 
|  1001     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], |  | 
|  1002        " DB\"", 0); |  | 
|  1003     return TCL_ERROR; |  | 
|  1004   } |  | 
|  1005   if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; |  | 
|  1006   rc = sqlite3_create_function(db, "x_coalesce", -1, SQLITE_ANY, 0,  |  | 
|  1007         t1_ifnullFunc, 0, 0); |  | 
|  1008   if( rc==SQLITE_OK ){ |  | 
|  1009     rc = sqlite3_create_function(db, "hex8", 1, SQLITE_ANY, 0,  |  | 
|  1010           hex8Func, 0, 0); |  | 
|  1011   } |  | 
|  1012 #ifndef SQLITE_OMIT_UTF16 |  | 
|  1013   if( rc==SQLITE_OK ){ |  | 
|  1014     rc = sqlite3_create_function(db, "hex16", 1, SQLITE_ANY, 0,  |  | 
|  1015           hex16Func, 0, 0); |  | 
|  1016   } |  | 
|  1017 #endif |  | 
|  1018   if( rc==SQLITE_OK ){ |  | 
|  1019     rc = sqlite3_create_function(db, "tkt2213func", 1, SQLITE_ANY, 0,  |  | 
|  1020           tkt2213Function, 0, 0); |  | 
|  1021   } |  | 
|  1022   if( rc==SQLITE_OK ){ |  | 
|  1023     rc = sqlite3_create_function(db, "pointer_change", 4, SQLITE_ANY, 0,  |  | 
|  1024           ptrChngFunction, 0, 0); |  | 
|  1025   } |  | 
|  1026  |  | 
|  1027 #ifndef SQLITE_OMIT_UTF16 |  | 
|  1028   /* Use the sqlite3_create_function16() API here. Mainly for fun, but also  |  | 
|  1029   ** because it is not tested anywhere else. */ |  | 
|  1030   if( rc==SQLITE_OK ){ |  | 
|  1031     const void *zUtf16; |  | 
|  1032     sqlite3_value *pVal; |  | 
|  1033     sqlite3_mutex_enter(db->mutex); |  | 
|  1034     pVal = sqlite3ValueNew(db); |  | 
|  1035     sqlite3ValueSetStr(pVal, -1, "x_sqlite_exec", SQLITE_UTF8, SQLITE_STATIC); |  | 
|  1036     zUtf16 = sqlite3ValueText(pVal, SQLITE_UTF16NATIVE); |  | 
|  1037     if( db->mallocFailed ){ |  | 
|  1038       rc = SQLITE_NOMEM; |  | 
|  1039     }else{ |  | 
|  1040       rc = sqlite3_create_function16(db, zUtf16,  |  | 
|  1041                 1, SQLITE_UTF16, db, sqlite3ExecFunc, 0, 0); |  | 
|  1042     } |  | 
|  1043     sqlite3ValueFree(pVal); |  | 
|  1044     sqlite3_mutex_leave(db->mutex); |  | 
|  1045   } |  | 
|  1046 #endif |  | 
|  1047  |  | 
|  1048   if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; |  | 
|  1049   Tcl_SetResult(interp, (char *)t1ErrorName(rc), 0); |  | 
|  1050   return TCL_OK; |  | 
|  1051 } |  | 
|  1052  |  | 
|  1053 /* |  | 
|  1054 ** Routines to implement the x_count() aggregate function. |  | 
|  1055 ** |  | 
|  1056 ** x_count() counts the number of non-null arguments.  But there are |  | 
|  1057 ** some twists for testing purposes. |  | 
|  1058 ** |  | 
|  1059 ** If the argument to x_count() is 40 then a UTF-8 error is reported |  | 
|  1060 ** on the step function.  If x_count(41) is seen, then a UTF-16 error |  | 
|  1061 ** is reported on the step function.  If the total count is 42, then |  | 
|  1062 ** a UTF-8 error is reported on the finalize function. |  | 
|  1063 */ |  | 
|  1064 typedef struct t1CountCtx t1CountCtx; |  | 
|  1065 struct t1CountCtx { |  | 
|  1066   int n; |  | 
|  1067 }; |  | 
|  1068 static void t1CountStep( |  | 
|  1069   sqlite3_context *context, |  | 
|  1070   int argc, |  | 
|  1071   sqlite3_value **argv |  | 
|  1072 ){ |  | 
|  1073   t1CountCtx *p; |  | 
|  1074   p = sqlite3_aggregate_context(context, sizeof(*p)); |  | 
|  1075   if( (argc==0 || SQLITE_NULL!=sqlite3_value_type(argv[0]) ) && p ){ |  | 
|  1076     p->n++; |  | 
|  1077   } |  | 
|  1078   if( argc>0 ){ |  | 
|  1079     int v = sqlite3_value_int(argv[0]); |  | 
|  1080     if( v==40 ){ |  | 
|  1081       sqlite3_result_error(context, "value of 40 handed to x_count", -1); |  | 
|  1082 #ifndef SQLITE_OMIT_UTF16 |  | 
|  1083     }else if( v==41 ){ |  | 
|  1084       const char zUtf16ErrMsg[] = { 0, 0x61, 0, 0x62, 0, 0x63, 0, 0, 0}; |  | 
|  1085       sqlite3_result_error16(context, &zUtf16ErrMsg[1-SQLITE_BIGENDIAN], -1); |  | 
|  1086 #endif |  | 
|  1087     } |  | 
|  1088   } |  | 
|  1089 }    |  | 
|  1090 static void t1CountFinalize(sqlite3_context *context){ |  | 
|  1091   t1CountCtx *p; |  | 
|  1092   p = sqlite3_aggregate_context(context, sizeof(*p)); |  | 
|  1093   if( p ){ |  | 
|  1094     if( p->n==42 ){ |  | 
|  1095       sqlite3_result_error(context, "x_count totals to 42", -1); |  | 
|  1096     }else{ |  | 
|  1097       sqlite3_result_int(context, p ? p->n : 0); |  | 
|  1098     } |  | 
|  1099   } |  | 
|  1100 } |  | 
|  1101  |  | 
|  1102 #ifndef SQLITE_OMIT_DEPRECATED |  | 
|  1103 static void legacyCountStep( |  | 
|  1104   sqlite3_context *context, |  | 
|  1105   int argc, |  | 
|  1106   sqlite3_value **argv |  | 
|  1107 ){ |  | 
|  1108   /* no-op */ |  | 
|  1109 } |  | 
|  1110  |  | 
|  1111 static void legacyCountFinalize(sqlite3_context *context){ |  | 
|  1112   sqlite3_result_int(context, sqlite3_aggregate_count(context)); |  | 
|  1113 } |  | 
|  1114 #endif |  | 
|  1115  |  | 
|  1116 /* |  | 
|  1117 ** Usage:  sqlite3_create_aggregate DB |  | 
|  1118 ** |  | 
|  1119 ** Call the sqlite3_create_function API on the given database in order |  | 
|  1120 ** to create a function named "x_count".  This function is similar |  | 
|  1121 ** to the built-in count() function, with a few special quirks |  | 
|  1122 ** for testing the sqlite3_result_error() APIs. |  | 
|  1123 ** |  | 
|  1124 ** The original motivation for this routine was to be able to call the |  | 
|  1125 ** sqlite3_create_aggregate function while a query is in progress in order |  | 
|  1126 ** to test the SQLITE_MISUSE detection logic.  See misuse.test. |  | 
|  1127 ** |  | 
|  1128 ** This routine was later extended to test the use of sqlite3_result_error() |  | 
|  1129 ** within aggregate functions. |  | 
|  1130 ** |  | 
|  1131 ** Later: It is now also extended to register the aggregate function |  | 
|  1132 ** "legacy_count()" with the supplied database handle. This is used |  | 
|  1133 ** to test the deprecated sqlite3_aggregate_count() API. |  | 
|  1134 */ |  | 
|  1135 static int test_create_aggregate( |  | 
|  1136   void *NotUsed, |  | 
|  1137   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ |  | 
|  1138   int argc,              /* Number of arguments */ |  | 
|  1139   char **argv            /* Text of each argument */ |  | 
|  1140 ){ |  | 
|  1141   sqlite3 *db; |  | 
|  1142   int rc; |  | 
|  1143   if( argc!=2 ){ |  | 
|  1144     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], |  | 
|  1145        " FILENAME\"", 0); |  | 
|  1146     return TCL_ERROR; |  | 
|  1147   } |  | 
|  1148   if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; |  | 
|  1149   rc = sqlite3_create_function(db, "x_count", 0, SQLITE_UTF8, 0, 0, |  | 
|  1150       t1CountStep,t1CountFinalize); |  | 
|  1151   if( rc==SQLITE_OK ){ |  | 
|  1152     rc = sqlite3_create_function(db, "x_count", 1, SQLITE_UTF8, 0, 0, |  | 
|  1153         t1CountStep,t1CountFinalize); |  | 
|  1154   } |  | 
|  1155 #ifndef SQLITE_OMIT_DEPRECATED |  | 
|  1156   if( rc==SQLITE_OK ){ |  | 
|  1157     rc = sqlite3_create_function(db, "legacy_count", 0, SQLITE_ANY, 0, 0, |  | 
|  1158         legacyCountStep, legacyCountFinalize |  | 
|  1159     ); |  | 
|  1160   } |  | 
|  1161 #endif |  | 
|  1162   if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; |  | 
|  1163   Tcl_SetResult(interp, (char *)t1ErrorName(rc), 0); |  | 
|  1164   return TCL_OK; |  | 
|  1165 } |  | 
|  1166  |  | 
|  1167  |  | 
|  1168 /* |  | 
|  1169 ** Usage:  printf TEXT |  | 
|  1170 ** |  | 
|  1171 ** Send output to printf.  Use this rather than puts to merge the output |  | 
|  1172 ** in the correct sequence with debugging printfs inserted into C code. |  | 
|  1173 ** Puts uses a separate buffer and debugging statements will be out of |  | 
|  1174 ** sequence if it is used. |  | 
|  1175 */ |  | 
|  1176 static int test_printf( |  | 
|  1177   void *NotUsed, |  | 
|  1178   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ |  | 
|  1179   int argc,              /* Number of arguments */ |  | 
|  1180   char **argv            /* Text of each argument */ |  | 
|  1181 ){ |  | 
|  1182   if( argc!=2 ){ |  | 
|  1183     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], |  | 
|  1184        " TEXT\"", 0); |  | 
|  1185     return TCL_ERROR; |  | 
|  1186   } |  | 
|  1187   printf("%s\n", argv[1]); |  | 
|  1188   return TCL_OK; |  | 
|  1189 } |  | 
|  1190  |  | 
|  1191  |  | 
|  1192  |  | 
|  1193 /* |  | 
|  1194 ** Usage:  sqlite3_mprintf_int FORMAT INTEGER INTEGER INTEGER |  | 
|  1195 ** |  | 
|  1196 ** Call mprintf with three integer arguments |  | 
|  1197 */ |  | 
|  1198 static int sqlite3_mprintf_int( |  | 
|  1199   void *NotUsed, |  | 
|  1200   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ |  | 
|  1201   int argc,              /* Number of arguments */ |  | 
|  1202   char **argv            /* Text of each argument */ |  | 
|  1203 ){ |  | 
|  1204   int a[3], i; |  | 
|  1205   char *z; |  | 
|  1206   if( argc!=5 ){ |  | 
|  1207     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], |  | 
|  1208        " FORMAT INT INT INT\"", 0); |  | 
|  1209     return TCL_ERROR; |  | 
|  1210   } |  | 
|  1211   for(i=2; i<5; i++){ |  | 
|  1212     if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR; |  | 
|  1213   } |  | 
|  1214   z = sqlite3_mprintf(argv[1], a[0], a[1], a[2]); |  | 
|  1215   Tcl_AppendResult(interp, z, 0); |  | 
|  1216   sqlite3_free(z); |  | 
|  1217   return TCL_OK; |  | 
|  1218 } |  | 
|  1219  |  | 
|  1220 /* |  | 
|  1221 ** Usage:  sqlite3_mprintf_int64 FORMAT INTEGER INTEGER INTEGER |  | 
|  1222 ** |  | 
|  1223 ** Call mprintf with three 64-bit integer arguments |  | 
|  1224 */ |  | 
|  1225 static int sqlite3_mprintf_int64( |  | 
|  1226   void *NotUsed, |  | 
|  1227   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ |  | 
|  1228   int argc,              /* Number of arguments */ |  | 
|  1229   char **argv            /* Text of each argument */ |  | 
|  1230 ){ |  | 
|  1231   int i; |  | 
|  1232   sqlite_int64 a[3]; |  | 
|  1233   char *z; |  | 
|  1234   if( argc!=5 ){ |  | 
|  1235     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], |  | 
|  1236        " FORMAT INT INT INT\"", 0); |  | 
|  1237     return TCL_ERROR; |  | 
|  1238   } |  | 
|  1239   for(i=2; i<5; i++){ |  | 
|  1240     if( !sqlite3Atoi64(argv[i], &a[i-2]) ){ |  | 
|  1241       Tcl_AppendResult(interp, "argument is not a valid 64-bit integer", 0); |  | 
|  1242       return TCL_ERROR; |  | 
|  1243     } |  | 
|  1244   } |  | 
|  1245   z = sqlite3_mprintf(argv[1], a[0], a[1], a[2]); |  | 
|  1246   Tcl_AppendResult(interp, z, 0); |  | 
|  1247   sqlite3_free(z); |  | 
|  1248   return TCL_OK; |  | 
|  1249 } |  | 
|  1250  |  | 
|  1251 /* |  | 
|  1252 ** Usage:  sqlite3_mprintf_long FORMAT INTEGER INTEGER INTEGER |  | 
|  1253 ** |  | 
|  1254 ** Call mprintf with three long integer arguments.   This might be the |  | 
|  1255 ** same as sqlite3_mprintf_int or sqlite3_mprintf_int64, depending on |  | 
|  1256 ** platform. |  | 
|  1257 */ |  | 
|  1258 static int sqlite3_mprintf_long( |  | 
|  1259   void *NotUsed, |  | 
|  1260   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ |  | 
|  1261   int argc,              /* Number of arguments */ |  | 
|  1262   char **argv            /* Text of each argument */ |  | 
|  1263 ){ |  | 
|  1264   int i; |  | 
|  1265   long int a[3]; |  | 
|  1266   int b[3]; |  | 
|  1267   char *z; |  | 
|  1268   if( argc!=5 ){ |  | 
|  1269     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], |  | 
|  1270        " FORMAT INT INT INT\"", 0); |  | 
|  1271     return TCL_ERROR; |  | 
|  1272   } |  | 
|  1273   for(i=2; i<5; i++){ |  | 
|  1274     if( Tcl_GetInt(interp, argv[i], &b[i-2]) ) return TCL_ERROR; |  | 
|  1275     a[i-2] = (long int)b[i-2]; |  | 
|  1276     a[i-2] &= (((u64)1)<<(sizeof(int)*8))-1; |  | 
|  1277   } |  | 
|  1278   z = sqlite3_mprintf(argv[1], a[0], a[1], a[2]); |  | 
|  1279   Tcl_AppendResult(interp, z, 0); |  | 
|  1280   sqlite3_free(z); |  | 
|  1281   return TCL_OK; |  | 
|  1282 } |  | 
|  1283  |  | 
|  1284 /* |  | 
|  1285 ** Usage:  sqlite3_mprintf_str FORMAT INTEGER INTEGER STRING |  | 
|  1286 ** |  | 
|  1287 ** Call mprintf with two integer arguments and one string argument |  | 
|  1288 */ |  | 
|  1289 static int sqlite3_mprintf_str( |  | 
|  1290   void *NotUsed, |  | 
|  1291   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ |  | 
|  1292   int argc,              /* Number of arguments */ |  | 
|  1293   char **argv            /* Text of each argument */ |  | 
|  1294 ){ |  | 
|  1295   int a[3], i; |  | 
|  1296   char *z; |  | 
|  1297   if( argc<4 || argc>5 ){ |  | 
|  1298     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], |  | 
|  1299        " FORMAT INT INT ?STRING?\"", 0); |  | 
|  1300     return TCL_ERROR; |  | 
|  1301   } |  | 
|  1302   for(i=2; i<4; i++){ |  | 
|  1303     if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR; |  | 
|  1304   } |  | 
|  1305   z = sqlite3_mprintf(argv[1], a[0], a[1], argc>4 ? argv[4] : NULL); |  | 
|  1306   Tcl_AppendResult(interp, z, 0); |  | 
|  1307   sqlite3_free(z); |  | 
|  1308   return TCL_OK; |  | 
|  1309 } |  | 
|  1310  |  | 
|  1311 /* |  | 
|  1312 ** Usage:  sqlite3_snprintf_str INTEGER FORMAT INTEGER INTEGER STRING |  | 
|  1313 ** |  | 
|  1314 ** Call mprintf with two integer arguments and one string argument |  | 
|  1315 */ |  | 
|  1316 static int sqlite3_snprintf_str( |  | 
|  1317   void *NotUsed, |  | 
|  1318   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ |  | 
|  1319   int argc,              /* Number of arguments */ |  | 
|  1320   char **argv            /* Text of each argument */ |  | 
|  1321 ){ |  | 
|  1322   int a[3], i; |  | 
|  1323   int n; |  | 
|  1324   char *z; |  | 
|  1325   if( argc<5 || argc>6 ){ |  | 
|  1326     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], |  | 
|  1327        " INT FORMAT INT INT ?STRING?\"", 0); |  | 
|  1328     return TCL_ERROR; |  | 
|  1329   } |  | 
|  1330   if( Tcl_GetInt(interp, argv[1], &n) ) return TCL_ERROR; |  | 
|  1331   if( n<0 ){ |  | 
|  1332     Tcl_AppendResult(interp, "N must be non-negative", 0); |  | 
|  1333     return TCL_ERROR; |  | 
|  1334   } |  | 
|  1335   for(i=3; i<5; i++){ |  | 
|  1336     if( Tcl_GetInt(interp, argv[i], &a[i-3]) ) return TCL_ERROR; |  | 
|  1337   } |  | 
|  1338   z = sqlite3_malloc( n+1 ); |  | 
|  1339   sqlite3_snprintf(n, z, argv[2], a[0], a[1], argc>4 ? argv[5] : NULL); |  | 
|  1340   Tcl_AppendResult(interp, z, 0); |  | 
|  1341   sqlite3_free(z); |  | 
|  1342   return TCL_OK; |  | 
|  1343 } |  | 
|  1344  |  | 
|  1345 /* |  | 
|  1346 ** Usage:  sqlite3_mprintf_double FORMAT INTEGER INTEGER DOUBLE |  | 
|  1347 ** |  | 
|  1348 ** Call mprintf with two integer arguments and one double argument |  | 
|  1349 */ |  | 
|  1350 static int sqlite3_mprintf_double( |  | 
|  1351   void *NotUsed, |  | 
|  1352   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ |  | 
|  1353   int argc,              /* Number of arguments */ |  | 
|  1354   char **argv            /* Text of each argument */ |  | 
|  1355 ){ |  | 
|  1356   int a[3], i; |  | 
|  1357   double r; |  | 
|  1358   char *z; |  | 
|  1359   if( argc!=5 ){ |  | 
|  1360     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], |  | 
|  1361        " FORMAT INT INT DOUBLE\"", 0); |  | 
|  1362     return TCL_ERROR; |  | 
|  1363   } |  | 
|  1364   for(i=2; i<4; i++){ |  | 
|  1365     if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR; |  | 
|  1366   } |  | 
|  1367   if( Tcl_GetDouble(interp, argv[4], &r) ) return TCL_ERROR; |  | 
|  1368   z = sqlite3_mprintf(argv[1], a[0], a[1], r); |  | 
|  1369   Tcl_AppendResult(interp, z, 0); |  | 
|  1370   sqlite3_free(z); |  | 
|  1371   return TCL_OK; |  | 
|  1372 } |  | 
|  1373  |  | 
|  1374 /* |  | 
|  1375 ** Usage:  sqlite3_mprintf_scaled FORMAT DOUBLE DOUBLE |  | 
|  1376 ** |  | 
|  1377 ** Call mprintf with a single double argument which is the product of the |  | 
|  1378 ** two arguments given above.  This is used to generate overflow and underflow |  | 
|  1379 ** doubles to test that they are converted properly. |  | 
|  1380 */ |  | 
|  1381 static int sqlite3_mprintf_scaled( |  | 
|  1382   void *NotUsed, |  | 
|  1383   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ |  | 
|  1384   int argc,              /* Number of arguments */ |  | 
|  1385   char **argv            /* Text of each argument */ |  | 
|  1386 ){ |  | 
|  1387   int i; |  | 
|  1388   double r[2]; |  | 
|  1389   char *z; |  | 
|  1390   if( argc!=4 ){ |  | 
|  1391     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], |  | 
|  1392        " FORMAT DOUBLE DOUBLE\"", 0); |  | 
|  1393     return TCL_ERROR; |  | 
|  1394   } |  | 
|  1395   for(i=2; i<4; i++){ |  | 
|  1396     if( Tcl_GetDouble(interp, argv[i], &r[i-2]) ) return TCL_ERROR; |  | 
|  1397   } |  | 
|  1398   z = sqlite3_mprintf(argv[1], r[0]*r[1]); |  | 
|  1399   Tcl_AppendResult(interp, z, 0); |  | 
|  1400   sqlite3_free(z); |  | 
|  1401   return TCL_OK; |  | 
|  1402 } |  | 
|  1403  |  | 
|  1404 /* |  | 
|  1405 ** Usage:  sqlite3_mprintf_stronly FORMAT STRING |  | 
|  1406 ** |  | 
|  1407 ** Call mprintf with a single double argument which is the product of the |  | 
|  1408 ** two arguments given above.  This is used to generate overflow and underflow |  | 
|  1409 ** doubles to test that they are converted properly. |  | 
|  1410 */ |  | 
|  1411 static int sqlite3_mprintf_stronly( |  | 
|  1412   void *NotUsed, |  | 
|  1413   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ |  | 
|  1414   int argc,              /* Number of arguments */ |  | 
|  1415   char **argv            /* Text of each argument */ |  | 
|  1416 ){ |  | 
|  1417   char *z; |  | 
|  1418   if( argc!=3 ){ |  | 
|  1419     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], |  | 
|  1420        " FORMAT STRING\"", 0); |  | 
|  1421     return TCL_ERROR; |  | 
|  1422   } |  | 
|  1423   z = sqlite3_mprintf(argv[1], argv[2]); |  | 
|  1424   Tcl_AppendResult(interp, z, 0); |  | 
|  1425   sqlite3_free(z); |  | 
|  1426   return TCL_OK; |  | 
|  1427 } |  | 
|  1428  |  | 
|  1429 /* |  | 
|  1430 ** Usage:  sqlite3_mprintf_hexdouble FORMAT HEX |  | 
|  1431 ** |  | 
|  1432 ** Call mprintf with a single double argument which is derived from the |  | 
|  1433 ** hexadecimal encoding of an IEEE double. |  | 
|  1434 */ |  | 
|  1435 static int sqlite3_mprintf_hexdouble( |  | 
|  1436   void *NotUsed, |  | 
|  1437   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ |  | 
|  1438   int argc,              /* Number of arguments */ |  | 
|  1439   char **argv            /* Text of each argument */ |  | 
|  1440 ){ |  | 
|  1441   char *z; |  | 
|  1442   double r; |  | 
|  1443   unsigned int x1, x2; |  | 
|  1444   sqlite_uint64 d; |  | 
|  1445   if( argc!=3 ){ |  | 
|  1446     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], |  | 
|  1447        " FORMAT STRING\"", 0); |  | 
|  1448     return TCL_ERROR; |  | 
|  1449   } |  | 
|  1450   if( sscanf(argv[2], "%08x%08x", &x2, &x1)!=2 ){ |  | 
|  1451     Tcl_AppendResult(interp, "2nd argument should be 16-characters of hex", 0); |  | 
|  1452     return TCL_ERROR; |  | 
|  1453   } |  | 
|  1454   d = x2; |  | 
|  1455   d = (d<<32) + x1; |  | 
|  1456   memcpy(&r, &d, sizeof(r)); |  | 
|  1457   z = sqlite3_mprintf(argv[1], r); |  | 
|  1458   Tcl_AppendResult(interp, z, 0); |  | 
|  1459   sqlite3_free(z); |  | 
|  1460   return TCL_OK; |  | 
|  1461 } |  | 
|  1462  |  | 
|  1463 /* |  | 
|  1464 ** Usage: sqlite3_enable_shared_cache ?BOOLEAN? |  | 
|  1465 ** |  | 
|  1466 */ |  | 
|  1467 #if !defined(SQLITE_OMIT_SHARED_CACHE) |  | 
|  1468 static int test_enable_shared( |  | 
|  1469   ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ |  | 
|  1470   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ |  | 
|  1471   int objc,              /* Number of arguments */ |  | 
|  1472   Tcl_Obj *CONST objv[]  /* Command arguments */ |  | 
|  1473 ){ |  | 
|  1474   int rc; |  | 
|  1475   int enable; |  | 
|  1476   int ret = 0; |  | 
|  1477  |  | 
|  1478   if( objc!=2 && objc!=1 ){ |  | 
|  1479     Tcl_WrongNumArgs(interp, 1, objv, "?BOOLEAN?"); |  | 
|  1480     return TCL_ERROR; |  | 
|  1481   } |  | 
|  1482   ret = sqlite3GlobalConfig.sharedCacheEnabled; |  | 
|  1483  |  | 
|  1484   if( objc==2 ){ |  | 
|  1485     if( Tcl_GetBooleanFromObj(interp, objv[1], &enable) ){ |  | 
|  1486       return TCL_ERROR; |  | 
|  1487     } |  | 
|  1488     rc = sqlite3_enable_shared_cache(enable); |  | 
|  1489     if( rc!=SQLITE_OK ){ |  | 
|  1490       Tcl_SetResult(interp, (char *)sqlite3ErrStr(rc), TCL_STATIC); |  | 
|  1491       return TCL_ERROR; |  | 
|  1492     } |  | 
|  1493   } |  | 
|  1494   Tcl_SetObjResult(interp, Tcl_NewBooleanObj(ret)); |  | 
|  1495   return TCL_OK; |  | 
|  1496 } |  | 
|  1497 #endif |  | 
|  1498  |  | 
|  1499  |  | 
|  1500  |  | 
|  1501 /* |  | 
|  1502 ** Usage: sqlite3_extended_result_codes   DB    BOOLEAN |  | 
|  1503 ** |  | 
|  1504 */ |  | 
|  1505 static int test_extended_result_codes( |  | 
|  1506   ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ |  | 
|  1507   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ |  | 
|  1508   int objc,              /* Number of arguments */ |  | 
|  1509   Tcl_Obj *CONST objv[]  /* Command arguments */ |  | 
|  1510 ){ |  | 
|  1511   int enable; |  | 
|  1512   sqlite3 *db; |  | 
|  1513  |  | 
|  1514   if( objc!=3 ){ |  | 
|  1515     Tcl_WrongNumArgs(interp, 1, objv, "DB BOOLEAN"); |  | 
|  1516     return TCL_ERROR; |  | 
|  1517   } |  | 
|  1518   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; |  | 
|  1519   if( Tcl_GetBooleanFromObj(interp, objv[2], &enable) ) return TCL_ERROR; |  | 
|  1520   sqlite3_extended_result_codes(db, enable); |  | 
|  1521   return TCL_OK; |  | 
|  1522 } |  | 
|  1523  |  | 
|  1524 /* |  | 
|  1525 ** Usage: sqlite3_libversion_number |  | 
|  1526 ** |  | 
|  1527 */ |  | 
|  1528 static int test_libversion_number( |  | 
|  1529   ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ |  | 
|  1530   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ |  | 
|  1531   int objc,              /* Number of arguments */ |  | 
|  1532   Tcl_Obj *CONST objv[]  /* Command arguments */ |  | 
|  1533 ){ |  | 
|  1534   Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_libversion_number())); |  | 
|  1535   return TCL_OK; |  | 
|  1536 } |  | 
|  1537  |  | 
|  1538 /* |  | 
|  1539 ** Usage: sqlite3_table_column_metadata DB dbname tblname colname |  | 
|  1540 ** |  | 
|  1541 */ |  | 
|  1542 #ifdef SQLITE_ENABLE_COLUMN_METADATA |  | 
|  1543 static int test_table_column_metadata( |  | 
|  1544   ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ |  | 
|  1545   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ |  | 
|  1546   int objc,              /* Number of arguments */ |  | 
|  1547   Tcl_Obj *CONST objv[]  /* Command arguments */ |  | 
|  1548 ){ |  | 
|  1549   sqlite3 *db; |  | 
|  1550   const char *zDb; |  | 
|  1551   const char *zTbl; |  | 
|  1552   const char *zCol; |  | 
|  1553   int rc; |  | 
|  1554   Tcl_Obj *pRet; |  | 
|  1555  |  | 
|  1556   const char *zDatatype; |  | 
|  1557   const char *zCollseq; |  | 
|  1558   int notnull; |  | 
|  1559   int primarykey; |  | 
|  1560   int autoincrement; |  | 
|  1561  |  | 
|  1562   if( objc!=5 ){ |  | 
|  1563     Tcl_WrongNumArgs(interp, 1, objv, "DB dbname tblname colname"); |  | 
|  1564     return TCL_ERROR; |  | 
|  1565   } |  | 
|  1566   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; |  | 
|  1567   zDb = Tcl_GetString(objv[2]); |  | 
|  1568   zTbl = Tcl_GetString(objv[3]); |  | 
|  1569   zCol = Tcl_GetString(objv[4]); |  | 
|  1570  |  | 
|  1571   if( strlen(zDb)==0 ) zDb = 0; |  | 
|  1572  |  | 
|  1573   rc = sqlite3_table_column_metadata(db, zDb, zTbl, zCol,  |  | 
|  1574       &zDatatype, &zCollseq, ¬null, &primarykey, &autoincrement); |  | 
|  1575  |  | 
|  1576   if( rc!=SQLITE_OK ){ |  | 
|  1577     Tcl_AppendResult(interp, sqlite3_errmsg(db), 0); |  | 
|  1578     return TCL_ERROR; |  | 
|  1579   } |  | 
|  1580  |  | 
|  1581   pRet = Tcl_NewObj(); |  | 
|  1582   Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zDatatype, -1)); |  | 
|  1583   Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zCollseq, -1)); |  | 
|  1584   Tcl_ListObjAppendElement(0, pRet, Tcl_NewIntObj(notnull)); |  | 
|  1585   Tcl_ListObjAppendElement(0, pRet, Tcl_NewIntObj(primarykey)); |  | 
|  1586   Tcl_ListObjAppendElement(0, pRet, Tcl_NewIntObj(autoincrement)); |  | 
|  1587   Tcl_SetObjResult(interp, pRet); |  | 
|  1588  |  | 
|  1589   return TCL_OK; |  | 
|  1590 } |  | 
|  1591 #endif |  | 
|  1592  |  | 
|  1593 #ifndef SQLITE_OMIT_INCRBLOB |  | 
|  1594  |  | 
|  1595 /* |  | 
|  1596 ** sqlite3_blob_read  CHANNEL OFFSET N |  | 
|  1597 ** |  | 
|  1598 **   This command is used to test the sqlite3_blob_read() in ways that |  | 
|  1599 **   the Tcl channel interface does not. The first argument should |  | 
|  1600 **   be the name of a valid channel created by the [incrblob] method |  | 
|  1601 **   of a database handle. This function calls sqlite3_blob_read() |  | 
|  1602 **   to read N bytes from offset OFFSET from the underlying SQLite |  | 
|  1603 **   blob handle. |  | 
|  1604 ** |  | 
|  1605 **   On success, a byte-array object containing the read data is  |  | 
|  1606 **   returned. On failure, the interpreter result is set to the |  | 
|  1607 **   text representation of the returned error code (i.e. "SQLITE_NOMEM") |  | 
|  1608 **   and a Tcl exception is thrown. |  | 
|  1609 */ |  | 
|  1610 static int test_blob_read( |  | 
|  1611   ClientData clientData, /* Not used */ |  | 
|  1612   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ |  | 
|  1613   int objc,              /* Number of arguments */ |  | 
|  1614   Tcl_Obj *CONST objv[]  /* Command arguments */ |  | 
|  1615 ){ |  | 
|  1616   Tcl_Channel channel; |  | 
|  1617   ClientData instanceData; |  | 
|  1618   sqlite3_blob *pBlob; |  | 
|  1619   int notUsed; |  | 
|  1620   int nByte; |  | 
|  1621   int iOffset; |  | 
|  1622   unsigned char *zBuf; |  | 
|  1623   int rc; |  | 
|  1624    |  | 
|  1625   if( objc!=4 ){ |  | 
|  1626     Tcl_WrongNumArgs(interp, 1, objv, "CHANNEL OFFSET N"); |  | 
|  1627     return TCL_ERROR; |  | 
|  1628   } |  | 
|  1629  |  | 
|  1630   channel = Tcl_GetChannel(interp, Tcl_GetString(objv[1]), ¬Used); |  | 
|  1631   if( !channel |  | 
|  1632    || TCL_OK!=Tcl_GetIntFromObj(interp, objv[2], &iOffset) |  | 
|  1633    || TCL_OK!=Tcl_GetIntFromObj(interp, objv[3], &nByte) |  | 
|  1634    || nByte<0 || iOffset<0 |  | 
|  1635   ){  |  | 
|  1636     return TCL_ERROR; |  | 
|  1637   } |  | 
|  1638  |  | 
|  1639   instanceData = Tcl_GetChannelInstanceData(channel); |  | 
|  1640   pBlob = *((sqlite3_blob **)instanceData); |  | 
|  1641  |  | 
|  1642   zBuf = (unsigned char *)Tcl_Alloc(nByte); |  | 
|  1643   rc = sqlite3_blob_read(pBlob, zBuf, nByte, iOffset); |  | 
|  1644   if( rc==SQLITE_OK ){ |  | 
|  1645     Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(zBuf, nByte)); |  | 
|  1646   }else{ |  | 
|  1647     Tcl_SetResult(interp, (char *)sqlite3TestErrorName(rc), TCL_VOLATILE); |  | 
|  1648   } |  | 
|  1649   Tcl_Free((char *)zBuf); |  | 
|  1650  |  | 
|  1651   return (rc==SQLITE_OK ? TCL_OK : TCL_ERROR); |  | 
|  1652 } |  | 
|  1653  |  | 
|  1654 /* |  | 
|  1655 ** sqlite3_blob_write CHANNEL OFFSET DATA ?NDATA? |  | 
|  1656 ** |  | 
|  1657 **   This command is used to test the sqlite3_blob_write() in ways that |  | 
|  1658 **   the Tcl channel interface does not. The first argument should |  | 
|  1659 **   be the name of a valid channel created by the [incrblob] method |  | 
|  1660 **   of a database handle. This function calls sqlite3_blob_write() |  | 
|  1661 **   to write the DATA byte-array to the underlying SQLite blob handle. |  | 
|  1662 **   at offset OFFSET. |  | 
|  1663 ** |  | 
|  1664 **   On success, an empty string is returned. On failure, the interpreter |  | 
|  1665 **   result is set to the text representation of the returned error code  |  | 
|  1666 **   (i.e. "SQLITE_NOMEM") and a Tcl exception is thrown. |  | 
|  1667 */ |  | 
|  1668 static int test_blob_write( |  | 
|  1669   ClientData clientData, /* Not used */ |  | 
|  1670   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ |  | 
|  1671   int objc,              /* Number of arguments */ |  | 
|  1672   Tcl_Obj *CONST objv[]  /* Command arguments */ |  | 
|  1673 ){ |  | 
|  1674   Tcl_Channel channel; |  | 
|  1675   ClientData instanceData; |  | 
|  1676   sqlite3_blob *pBlob; |  | 
|  1677   int notUsed; |  | 
|  1678   int iOffset; |  | 
|  1679   int rc; |  | 
|  1680  |  | 
|  1681   unsigned char *zBuf; |  | 
|  1682   int nBuf; |  | 
|  1683    |  | 
|  1684   if( objc!=4 && objc!=5 ){ |  | 
|  1685     Tcl_WrongNumArgs(interp, 1, objv, "CHANNEL OFFSET DATA ?NDATA?"); |  | 
|  1686     return TCL_ERROR; |  | 
|  1687   } |  | 
|  1688  |  | 
|  1689   channel = Tcl_GetChannel(interp, Tcl_GetString(objv[1]), ¬Used); |  | 
|  1690   if( !channel || TCL_OK!=Tcl_GetIntFromObj(interp, objv[2], &iOffset) ){  |  | 
|  1691     return TCL_ERROR; |  | 
|  1692   } |  | 
|  1693  |  | 
|  1694   instanceData = Tcl_GetChannelInstanceData(channel); |  | 
|  1695   pBlob = *((sqlite3_blob **)instanceData); |  | 
|  1696  |  | 
|  1697   zBuf = Tcl_GetByteArrayFromObj(objv[3], &nBuf); |  | 
|  1698   if( objc==5 && Tcl_GetIntFromObj(interp, objv[4], &nBuf) ){ |  | 
|  1699     return TCL_ERROR; |  | 
|  1700   } |  | 
|  1701   rc = sqlite3_blob_write(pBlob, zBuf, nBuf, iOffset); |  | 
|  1702   if( rc!=SQLITE_OK ){ |  | 
|  1703     Tcl_SetResult(interp, (char *)sqlite3TestErrorName(rc), TCL_VOLATILE); |  | 
|  1704   } |  | 
|  1705  |  | 
|  1706   return (rc==SQLITE_OK ? TCL_OK : TCL_ERROR); |  | 
|  1707 } |  | 
|  1708 #endif |  | 
|  1709  |  | 
|  1710 /* |  | 
|  1711 ** Usage: sqlite3_create_collation_v2 DB-HANDLE NAME CMP-PROC DEL-PROC |  | 
|  1712 ** |  | 
|  1713 **   This Tcl proc is used for testing the experimental |  | 
|  1714 **   sqlite3_create_collation_v2() interface. |  | 
|  1715 */ |  | 
|  1716 struct TestCollationX { |  | 
|  1717   Tcl_Interp *interp; |  | 
|  1718   Tcl_Obj *pCmp; |  | 
|  1719   Tcl_Obj *pDel; |  | 
|  1720 }; |  | 
|  1721 typedef struct TestCollationX TestCollationX; |  | 
|  1722 static void testCreateCollationDel(void *pCtx){ |  | 
|  1723   TestCollationX *p = (TestCollationX *)pCtx; |  | 
|  1724  |  | 
|  1725   int rc = Tcl_EvalObjEx(p->interp, p->pDel, TCL_EVAL_DIRECT|TCL_EVAL_GLOBAL); |  | 
|  1726   if( rc!=TCL_OK ){ |  | 
|  1727     Tcl_BackgroundError(p->interp); |  | 
|  1728   } |  | 
|  1729  |  | 
|  1730   Tcl_DecrRefCount(p->pCmp); |  | 
|  1731   Tcl_DecrRefCount(p->pDel); |  | 
|  1732   sqlite3_free((void *)p); |  | 
|  1733 } |  | 
|  1734 static int testCreateCollationCmp( |  | 
|  1735   void *pCtx, |  | 
|  1736   int nLeft, |  | 
|  1737   const void *zLeft, |  | 
|  1738   int nRight, |  | 
|  1739   const void *zRight |  | 
|  1740 ){ |  | 
|  1741   TestCollationX *p = (TestCollationX *)pCtx; |  | 
|  1742   Tcl_Obj *pScript = Tcl_DuplicateObj(p->pCmp); |  | 
|  1743   int iRes = 0; |  | 
|  1744  |  | 
|  1745   Tcl_IncrRefCount(pScript); |  | 
|  1746   Tcl_ListObjAppendElement(0, pScript, Tcl_NewStringObj((char *)zLeft, nLeft)); |  | 
|  1747   Tcl_ListObjAppendElement(0, pScript, Tcl_NewStringObj((char *)zRight,nRight)); |  | 
|  1748  |  | 
|  1749   if( TCL_OK!=Tcl_EvalObjEx(p->interp, pScript, TCL_EVAL_DIRECT|TCL_EVAL_GLOBAL) |  | 
|  1750    || TCL_OK!=Tcl_GetIntFromObj(p->interp, Tcl_GetObjResult(p->interp), &iRes) |  | 
|  1751   ){ |  | 
|  1752     Tcl_BackgroundError(p->interp); |  | 
|  1753   } |  | 
|  1754   Tcl_DecrRefCount(pScript); |  | 
|  1755  |  | 
|  1756   return iRes; |  | 
|  1757 } |  | 
|  1758 static int test_create_collation_v2( |  | 
|  1759   ClientData clientData, /* Not used */ |  | 
|  1760   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ |  | 
|  1761   int objc,              /* Number of arguments */ |  | 
|  1762   Tcl_Obj *CONST objv[]  /* Command arguments */ |  | 
|  1763 ){ |  | 
|  1764   TestCollationX *p; |  | 
|  1765   sqlite3 *db; |  | 
|  1766   int rc; |  | 
|  1767  |  | 
|  1768   if( objc!=5 ){ |  | 
|  1769     Tcl_WrongNumArgs(interp, 1, objv, "DB-HANDLE NAME CMP-PROC DEL-PROC"); |  | 
|  1770     return TCL_ERROR; |  | 
|  1771   } |  | 
|  1772   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; |  | 
|  1773  |  | 
|  1774   p = (TestCollationX *)sqlite3_malloc(sizeof(TestCollationX)); |  | 
|  1775   p->pCmp = objv[3]; |  | 
|  1776   p->pDel = objv[4]; |  | 
|  1777   p->interp = interp; |  | 
|  1778   Tcl_IncrRefCount(p->pCmp); |  | 
|  1779   Tcl_IncrRefCount(p->pDel); |  | 
|  1780  |  | 
|  1781   rc = sqlite3_create_collation_v2(db, Tcl_GetString(objv[2]), 16,  |  | 
|  1782       (void *)p, testCreateCollationCmp, testCreateCollationDel |  | 
|  1783   ); |  | 
|  1784   if( rc!=SQLITE_MISUSE ){ |  | 
|  1785     Tcl_AppendResult(interp, "sqlite3_create_collate_v2() failed to detect " |  | 
|  1786       "an invalid encoding", (char*)0); |  | 
|  1787     return TCL_ERROR; |  | 
|  1788   } |  | 
|  1789   rc = sqlite3_create_collation_v2(db, Tcl_GetString(objv[2]), SQLITE_UTF8,  |  | 
|  1790       (void *)p, testCreateCollationCmp, testCreateCollationDel |  | 
|  1791   ); |  | 
|  1792   return TCL_OK; |  | 
|  1793 } |  | 
|  1794  |  | 
|  1795 /* |  | 
|  1796 ** Usage: sqlite3_load_extension DB-HANDLE FILE ?PROC? |  | 
|  1797 */ |  | 
|  1798 static int test_load_extension( |  | 
|  1799   ClientData clientData, /* Not used */ |  | 
|  1800   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ |  | 
|  1801   int objc,              /* Number of arguments */ |  | 
|  1802   Tcl_Obj *CONST objv[]  /* Command arguments */ |  | 
|  1803 ){ |  | 
|  1804   Tcl_CmdInfo cmdInfo; |  | 
|  1805   sqlite3 *db; |  | 
|  1806   int rc; |  | 
|  1807   char *zDb; |  | 
|  1808   char *zFile; |  | 
|  1809   char *zProc = 0; |  | 
|  1810   char *zErr = 0; |  | 
|  1811  |  | 
|  1812   if( objc!=4 && objc!=3 ){ |  | 
|  1813     Tcl_WrongNumArgs(interp, 1, objv, "DB-HANDLE FILE ?PROC?"); |  | 
|  1814     return TCL_ERROR; |  | 
|  1815   } |  | 
|  1816   zDb = Tcl_GetString(objv[1]); |  | 
|  1817   zFile = Tcl_GetString(objv[2]); |  | 
|  1818   if( objc==4 ){ |  | 
|  1819     zProc = Tcl_GetString(objv[3]); |  | 
|  1820   } |  | 
|  1821  |  | 
|  1822   /* Extract the C database handle from the Tcl command name */ |  | 
|  1823   if( !Tcl_GetCommandInfo(interp, zDb, &cmdInfo) ){ |  | 
|  1824     Tcl_AppendResult(interp, "command not found: ", zDb, (char*)0); |  | 
|  1825     return TCL_ERROR; |  | 
|  1826   } |  | 
|  1827   db = ((struct SqliteDb*)cmdInfo.objClientData)->db; |  | 
|  1828   assert(db); |  | 
|  1829  |  | 
|  1830   /* Call the underlying C function. If an error occurs, set rc to  |  | 
|  1831   ** TCL_ERROR and load any error string into the interpreter. If no  |  | 
|  1832   ** error occurs, set rc to TCL_OK. |  | 
|  1833   */ |  | 
|  1834 #ifdef SQLITE_OMIT_LOAD_EXTENSION |  | 
|  1835   rc = SQLITE_ERROR; |  | 
|  1836   zErr = sqlite3_mprintf("this build omits sqlite3_load_extension()"); |  | 
|  1837 #else |  | 
|  1838   rc = sqlite3_load_extension(db, zFile, zProc, &zErr); |  | 
|  1839 #endif |  | 
|  1840   if( rc!=SQLITE_OK ){ |  | 
|  1841     Tcl_SetResult(interp, zErr ? zErr : "", TCL_VOLATILE); |  | 
|  1842     rc = TCL_ERROR; |  | 
|  1843   }else{ |  | 
|  1844     rc = TCL_OK; |  | 
|  1845   } |  | 
|  1846   sqlite3_free(zErr); |  | 
|  1847  |  | 
|  1848   return rc; |  | 
|  1849 } |  | 
|  1850  |  | 
|  1851 /* |  | 
|  1852 ** Usage: sqlite3_enable_load_extension DB-HANDLE ONOFF |  | 
|  1853 */ |  | 
|  1854 static int test_enable_load( |  | 
|  1855   ClientData clientData, /* Not used */ |  | 
|  1856   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ |  | 
|  1857   int objc,              /* Number of arguments */ |  | 
|  1858   Tcl_Obj *CONST objv[]  /* Command arguments */ |  | 
|  1859 ){ |  | 
|  1860   Tcl_CmdInfo cmdInfo; |  | 
|  1861   sqlite3 *db; |  | 
|  1862   char *zDb; |  | 
|  1863   int onoff; |  | 
|  1864  |  | 
|  1865   if( objc!=3 ){ |  | 
|  1866     Tcl_WrongNumArgs(interp, 1, objv, "DB-HANDLE ONOFF"); |  | 
|  1867     return TCL_ERROR; |  | 
|  1868   } |  | 
|  1869   zDb = Tcl_GetString(objv[1]); |  | 
|  1870  |  | 
|  1871   /* Extract the C database handle from the Tcl command name */ |  | 
|  1872   if( !Tcl_GetCommandInfo(interp, zDb, &cmdInfo) ){ |  | 
|  1873     Tcl_AppendResult(interp, "command not found: ", zDb, (char*)0); |  | 
|  1874     return TCL_ERROR; |  | 
|  1875   } |  | 
|  1876   db = ((struct SqliteDb*)cmdInfo.objClientData)->db; |  | 
|  1877   assert(db); |  | 
|  1878  |  | 
|  1879   /* Get the onoff parameter */ |  | 
|  1880   if( Tcl_GetBooleanFromObj(interp, objv[2], &onoff) ){ |  | 
|  1881     return TCL_ERROR; |  | 
|  1882   } |  | 
|  1883  |  | 
|  1884 #ifdef SQLITE_OMIT_LOAD_EXTENSION |  | 
|  1885   Tcl_AppendResult(interp, "this build omits sqlite3_load_extension()"); |  | 
|  1886   return TCL_ERROR; |  | 
|  1887 #else |  | 
|  1888   sqlite3_enable_load_extension(db, onoff); |  | 
|  1889   return TCL_OK; |  | 
|  1890 #endif |  | 
|  1891 } |  | 
|  1892  |  | 
|  1893 /* |  | 
|  1894 ** Usage:  sqlite_abort |  | 
|  1895 ** |  | 
|  1896 ** Shutdown the process immediately.  This is not a clean shutdown. |  | 
|  1897 ** This command is used to test the recoverability of a database in |  | 
|  1898 ** the event of a program crash. |  | 
|  1899 */ |  | 
|  1900 static int sqlite_abort( |  | 
|  1901   void *NotUsed, |  | 
|  1902   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ |  | 
|  1903   int argc,              /* Number of arguments */ |  | 
|  1904   char **argv            /* Text of each argument */ |  | 
|  1905 ){ |  | 
|  1906   assert( interp==0 );   /* This will always fail */ |  | 
|  1907   return TCL_OK; |  | 
|  1908 } |  | 
|  1909  |  | 
|  1910 /* |  | 
|  1911 ** The following routine is a user-defined SQL function whose purpose |  | 
|  1912 ** is to test the sqlite_set_result() API. |  | 
|  1913 */ |  | 
|  1914 static void testFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ |  | 
|  1915   while( argc>=2 ){ |  | 
|  1916     const char *zArg0 = (char*)sqlite3_value_text(argv[0]); |  | 
|  1917     if( zArg0 ){ |  | 
|  1918       if( 0==sqlite3StrICmp(zArg0, "int") ){ |  | 
|  1919         sqlite3_result_int(context, sqlite3_value_int(argv[1])); |  | 
|  1920       }else if( sqlite3StrICmp(zArg0,"int64")==0 ){ |  | 
|  1921         sqlite3_result_int64(context, sqlite3_value_int64(argv[1])); |  | 
|  1922       }else if( sqlite3StrICmp(zArg0,"string")==0 ){ |  | 
|  1923         sqlite3_result_text(context, (char*)sqlite3_value_text(argv[1]), -1, |  | 
|  1924             SQLITE_TRANSIENT); |  | 
|  1925       }else if( sqlite3StrICmp(zArg0,"double")==0 ){ |  | 
|  1926         sqlite3_result_double(context, sqlite3_value_double(argv[1])); |  | 
|  1927       }else if( sqlite3StrICmp(zArg0,"null")==0 ){ |  | 
|  1928         sqlite3_result_null(context); |  | 
|  1929       }else if( sqlite3StrICmp(zArg0,"value")==0 ){ |  | 
|  1930         sqlite3_result_value(context, argv[sqlite3_value_int(argv[1])]); |  | 
|  1931       }else{ |  | 
|  1932         goto error_out; |  | 
|  1933       } |  | 
|  1934     }else{ |  | 
|  1935       goto error_out; |  | 
|  1936     } |  | 
|  1937     argc -= 2; |  | 
|  1938     argv += 2; |  | 
|  1939   } |  | 
|  1940   return; |  | 
|  1941  |  | 
|  1942 error_out: |  | 
|  1943   sqlite3_result_error(context,"first argument should be one of: " |  | 
|  1944       "int int64 string double null value", -1); |  | 
|  1945 } |  | 
|  1946  |  | 
|  1947 /* |  | 
|  1948 ** Usage:   sqlite_register_test_function  DB  NAME |  | 
|  1949 ** |  | 
|  1950 ** Register the test SQL function on the database DB under the name NAME. |  | 
|  1951 */ |  | 
|  1952 static int test_register_func( |  | 
|  1953   void *NotUsed, |  | 
|  1954   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ |  | 
|  1955   int argc,              /* Number of arguments */ |  | 
|  1956   char **argv            /* Text of each argument */ |  | 
|  1957 ){ |  | 
|  1958   sqlite3 *db; |  | 
|  1959   int rc; |  | 
|  1960   if( argc!=3 ){ |  | 
|  1961     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],  |  | 
|  1962        " DB FUNCTION-NAME", 0); |  | 
|  1963     return TCL_ERROR; |  | 
|  1964   } |  | 
|  1965   if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; |  | 
|  1966   rc = sqlite3_create_function(db, argv[2], -1, SQLITE_UTF8, 0,  |  | 
|  1967       testFunc, 0, 0); |  | 
|  1968   if( rc!=0 ){ |  | 
|  1969     Tcl_AppendResult(interp, sqlite3ErrStr(rc), 0); |  | 
|  1970     return TCL_ERROR; |  | 
|  1971   } |  | 
|  1972   if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; |  | 
|  1973   return TCL_OK; |  | 
|  1974 } |  | 
|  1975  |  | 
|  1976 /* |  | 
|  1977 ** Usage:  sqlite3_finalize  STMT  |  | 
|  1978 ** |  | 
|  1979 ** Finalize a statement handle. |  | 
|  1980 */ |  | 
|  1981 static int test_finalize( |  | 
|  1982   void * clientData, |  | 
|  1983   Tcl_Interp *interp, |  | 
|  1984   int objc, |  | 
|  1985   Tcl_Obj *CONST objv[] |  | 
|  1986 ){ |  | 
|  1987   sqlite3_stmt *pStmt; |  | 
|  1988   int rc; |  | 
|  1989   sqlite3 *db = 0; |  | 
|  1990  |  | 
|  1991   if( objc!=2 ){ |  | 
|  1992     Tcl_AppendResult(interp, "wrong # args: should be \"", |  | 
|  1993         Tcl_GetStringFromObj(objv[0], 0), " <STMT>", 0); |  | 
|  1994     return TCL_ERROR; |  | 
|  1995   } |  | 
|  1996  |  | 
|  1997   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; |  | 
|  1998  |  | 
|  1999   if( pStmt ){ |  | 
|  2000     db = StmtToDb(pStmt); |  | 
|  2001   } |  | 
|  2002   rc = sqlite3_finalize(pStmt); |  | 
|  2003   Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC); |  | 
|  2004   if( db && sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; |  | 
|  2005   return TCL_OK; |  | 
|  2006 } |  | 
|  2007  |  | 
|  2008 /* |  | 
|  2009 ** Usage:  sqlite3_stmt_status  STMT  CODE  RESETFLAG |  | 
|  2010 ** |  | 
|  2011 ** Get the value of a status counter from a statement. |  | 
|  2012 */ |  | 
|  2013 static int test_stmt_status( |  | 
|  2014   void * clientData, |  | 
|  2015   Tcl_Interp *interp, |  | 
|  2016   int objc, |  | 
|  2017   Tcl_Obj *CONST objv[] |  | 
|  2018 ){ |  | 
|  2019   int iValue; |  | 
|  2020   int i, op, resetFlag; |  | 
|  2021   const char *zOpName; |  | 
|  2022   sqlite3_stmt *pStmt; |  | 
|  2023  |  | 
|  2024   static const struct { |  | 
|  2025     const char *zName; |  | 
|  2026     int op; |  | 
|  2027   } aOp[] = { |  | 
|  2028     { "SQLITE_STMTSTATUS_FULLSCAN_STEP",   SQLITE_STMTSTATUS_FULLSCAN_STEP   }, |  | 
|  2029     { "SQLITE_STMTSTATUS_SORT",            SQLITE_STMTSTATUS_SORT            }, |  | 
|  2030   }; |  | 
|  2031   if( objc!=4 ){ |  | 
|  2032     Tcl_WrongNumArgs(interp, 1, objv, "STMT PARAMETER RESETFLAG"); |  | 
|  2033     return TCL_ERROR; |  | 
|  2034   } |  | 
|  2035   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; |  | 
|  2036   zOpName = Tcl_GetString(objv[2]); |  | 
|  2037   for(i=0; i<ArraySize(aOp); i++){ |  | 
|  2038     if( strcmp(aOp[i].zName, zOpName)==0 ){ |  | 
|  2039       op = aOp[i].op; |  | 
|  2040       break; |  | 
|  2041     } |  | 
|  2042   } |  | 
|  2043   if( i>=ArraySize(aOp) ){ |  | 
|  2044     if( Tcl_GetIntFromObj(interp, objv[2], &op) ) return TCL_ERROR; |  | 
|  2045   } |  | 
|  2046   if( Tcl_GetBooleanFromObj(interp, objv[3], &resetFlag) ) return TCL_ERROR; |  | 
|  2047   iValue = sqlite3_stmt_status(pStmt, op, resetFlag); |  | 
|  2048   Tcl_SetObjResult(interp, Tcl_NewIntObj(iValue)); |  | 
|  2049   return TCL_OK; |  | 
|  2050 } |  | 
|  2051  |  | 
|  2052 /* |  | 
|  2053 ** Usage:  sqlite3_next_stmt  DB  STMT |  | 
|  2054 ** |  | 
|  2055 ** Return the next statment in sequence after STMT. |  | 
|  2056 */ |  | 
|  2057 static int test_next_stmt( |  | 
|  2058   void * clientData, |  | 
|  2059   Tcl_Interp *interp, |  | 
|  2060   int objc, |  | 
|  2061   Tcl_Obj *CONST objv[] |  | 
|  2062 ){ |  | 
|  2063   sqlite3_stmt *pStmt; |  | 
|  2064   sqlite3 *db = 0; |  | 
|  2065   char zBuf[50]; |  | 
|  2066  |  | 
|  2067   if( objc!=3 ){ |  | 
|  2068     Tcl_AppendResult(interp, "wrong # args: should be \"", |  | 
|  2069         Tcl_GetStringFromObj(objv[0], 0), " DB STMT", 0); |  | 
|  2070     return TCL_ERROR; |  | 
|  2071   } |  | 
|  2072  |  | 
|  2073   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; |  | 
|  2074   if( getStmtPointer(interp, Tcl_GetString(objv[2]), &pStmt) ) return TCL_ERROR; |  | 
|  2075   pStmt = sqlite3_next_stmt(db, pStmt); |  | 
|  2076   if( pStmt ){ |  | 
|  2077     if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR; |  | 
|  2078     Tcl_AppendResult(interp, zBuf, 0); |  | 
|  2079   } |  | 
|  2080   return TCL_OK; |  | 
|  2081 } |  | 
|  2082  |  | 
|  2083  |  | 
|  2084 /* |  | 
|  2085 ** Usage:  sqlite3_reset  STMT  |  | 
|  2086 ** |  | 
|  2087 ** Reset a statement handle. |  | 
|  2088 */ |  | 
|  2089 static int test_reset( |  | 
|  2090   void * clientData, |  | 
|  2091   Tcl_Interp *interp, |  | 
|  2092   int objc, |  | 
|  2093   Tcl_Obj *CONST objv[] |  | 
|  2094 ){ |  | 
|  2095   sqlite3_stmt *pStmt; |  | 
|  2096   int rc; |  | 
|  2097  |  | 
|  2098   if( objc!=2 ){ |  | 
|  2099     Tcl_AppendResult(interp, "wrong # args: should be \"", |  | 
|  2100         Tcl_GetStringFromObj(objv[0], 0), " <STMT>", 0); |  | 
|  2101     return TCL_ERROR; |  | 
|  2102   } |  | 
|  2103  |  | 
|  2104   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; |  | 
|  2105  |  | 
|  2106   rc = sqlite3_reset(pStmt); |  | 
|  2107   if( pStmt && sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ){ |  | 
|  2108     return TCL_ERROR; |  | 
|  2109   } |  | 
|  2110   Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC); |  | 
|  2111 /* |  | 
|  2112   if( rc ){ |  | 
|  2113     return TCL_ERROR; |  | 
|  2114   } |  | 
|  2115 */ |  | 
|  2116   return TCL_OK; |  | 
|  2117 } |  | 
|  2118  |  | 
|  2119 /* |  | 
|  2120 ** Usage:  sqlite3_expired STMT  |  | 
|  2121 ** |  | 
|  2122 ** Return TRUE if a recompilation of the statement is recommended. |  | 
|  2123 */ |  | 
|  2124 static int test_expired( |  | 
|  2125   void * clientData, |  | 
|  2126   Tcl_Interp *interp, |  | 
|  2127   int objc, |  | 
|  2128   Tcl_Obj *CONST objv[] |  | 
|  2129 ){ |  | 
|  2130 #ifndef SQLITE_OMIT_DEPRECATED |  | 
|  2131   sqlite3_stmt *pStmt; |  | 
|  2132   if( objc!=2 ){ |  | 
|  2133     Tcl_AppendResult(interp, "wrong # args: should be \"", |  | 
|  2134         Tcl_GetStringFromObj(objv[0], 0), " <STMT>", 0); |  | 
|  2135     return TCL_ERROR; |  | 
|  2136   } |  | 
|  2137   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; |  | 
|  2138   Tcl_SetObjResult(interp, Tcl_NewBooleanObj(sqlite3_expired(pStmt))); |  | 
|  2139 #endif |  | 
|  2140   return TCL_OK; |  | 
|  2141 } |  | 
|  2142  |  | 
|  2143 /* |  | 
|  2144 ** Usage:  sqlite3_transfer_bindings FROMSTMT TOSTMT |  | 
|  2145 ** |  | 
|  2146 ** Transfer all bindings from FROMSTMT over to TOSTMT |  | 
|  2147 */ |  | 
|  2148 static int test_transfer_bind( |  | 
|  2149   void * clientData, |  | 
|  2150   Tcl_Interp *interp, |  | 
|  2151   int objc, |  | 
|  2152   Tcl_Obj *CONST objv[] |  | 
|  2153 ){ |  | 
|  2154 #ifndef SQLITE_OMIT_DEPRECATED |  | 
|  2155   sqlite3_stmt *pStmt1, *pStmt2; |  | 
|  2156   if( objc!=3 ){ |  | 
|  2157     Tcl_AppendResult(interp, "wrong # args: should be \"", |  | 
|  2158         Tcl_GetStringFromObj(objv[0], 0), " FROM-STMT TO-STMT", 0); |  | 
|  2159     return TCL_ERROR; |  | 
|  2160   } |  | 
|  2161   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt1)) return TCL_ERROR; |  | 
|  2162   if( getStmtPointer(interp, Tcl_GetString(objv[2]), &pStmt2)) return TCL_ERROR; |  | 
|  2163   Tcl_SetObjResult(interp,  |  | 
|  2164      Tcl_NewIntObj(sqlite3_transfer_bindings(pStmt1,pStmt2))); |  | 
|  2165 #endif |  | 
|  2166   return TCL_OK; |  | 
|  2167 } |  | 
|  2168  |  | 
|  2169 /* |  | 
|  2170 ** Usage:  sqlite3_changes DB |  | 
|  2171 ** |  | 
|  2172 ** Return the number of changes made to the database by the last SQL |  | 
|  2173 ** execution. |  | 
|  2174 */ |  | 
|  2175 static int test_changes( |  | 
|  2176   void * clientData, |  | 
|  2177   Tcl_Interp *interp, |  | 
|  2178   int objc, |  | 
|  2179   Tcl_Obj *CONST objv[] |  | 
|  2180 ){ |  | 
|  2181   sqlite3 *db; |  | 
|  2182   if( objc!=2 ){ |  | 
|  2183     Tcl_AppendResult(interp, "wrong # args: should be \"", |  | 
|  2184        Tcl_GetString(objv[0]), " DB", 0); |  | 
|  2185     return TCL_ERROR; |  | 
|  2186   } |  | 
|  2187   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; |  | 
|  2188   Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_changes(db))); |  | 
|  2189   return TCL_OK; |  | 
|  2190 } |  | 
|  2191  |  | 
|  2192 /* |  | 
|  2193 ** This is the "static_bind_value" that variables are bound to when |  | 
|  2194 ** the FLAG option of sqlite3_bind is "static" |  | 
|  2195 */ |  | 
|  2196 static char *sqlite_static_bind_value = 0; |  | 
|  2197 static int sqlite_static_bind_nbyte = 0; |  | 
|  2198  |  | 
|  2199 /* |  | 
|  2200 ** Usage:  sqlite3_bind  VM  IDX  VALUE  FLAGS |  | 
|  2201 ** |  | 
|  2202 ** Sets the value of the IDX-th occurance of "?" in the original SQL |  | 
|  2203 ** string.  VALUE is the new value.  If FLAGS=="null" then VALUE is |  | 
|  2204 ** ignored and the value is set to NULL.  If FLAGS=="static" then |  | 
|  2205 ** the value is set to the value of a static variable named |  | 
|  2206 ** "sqlite_static_bind_value".  If FLAGS=="normal" then a copy |  | 
|  2207 ** of the VALUE is made.  If FLAGS=="blob10" then a VALUE is ignored |  | 
|  2208 ** an a 10-byte blob "abc\000xyz\000pq" is inserted. |  | 
|  2209 */ |  | 
|  2210 static int test_bind( |  | 
|  2211   void *NotUsed, |  | 
|  2212   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ |  | 
|  2213   int argc,              /* Number of arguments */ |  | 
|  2214   char **argv            /* Text of each argument */ |  | 
|  2215 ){ |  | 
|  2216   sqlite3_stmt *pStmt; |  | 
|  2217   int rc; |  | 
|  2218   int idx; |  | 
|  2219   if( argc!=5 ){ |  | 
|  2220     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],  |  | 
|  2221        " VM IDX VALUE (null|static|normal)\"", 0); |  | 
|  2222     return TCL_ERROR; |  | 
|  2223   } |  | 
|  2224   if( getStmtPointer(interp, argv[1], &pStmt) ) return TCL_ERROR; |  | 
|  2225   if( Tcl_GetInt(interp, argv[2], &idx) ) return TCL_ERROR; |  | 
|  2226   if( strcmp(argv[4],"null")==0 ){ |  | 
|  2227     rc = sqlite3_bind_null(pStmt, idx); |  | 
|  2228   }else if( strcmp(argv[4],"static")==0 ){ |  | 
|  2229     rc = sqlite3_bind_text(pStmt, idx, sqlite_static_bind_value, -1, 0); |  | 
|  2230   }else if( strcmp(argv[4],"static-nbytes")==0 ){ |  | 
|  2231     rc = sqlite3_bind_text(pStmt, idx, sqlite_static_bind_value, |  | 
|  2232                                        sqlite_static_bind_nbyte, 0); |  | 
|  2233   }else if( strcmp(argv[4],"normal")==0 ){ |  | 
|  2234     rc = sqlite3_bind_text(pStmt, idx, argv[3], -1, SQLITE_TRANSIENT); |  | 
|  2235   }else if( strcmp(argv[4],"blob10")==0 ){ |  | 
|  2236     rc = sqlite3_bind_text(pStmt, idx, "abc\000xyz\000pq", 10, SQLITE_STATIC); |  | 
|  2237   }else{ |  | 
|  2238     Tcl_AppendResult(interp, "4th argument should be " |  | 
|  2239         "\"null\" or \"static\" or \"normal\"", 0); |  | 
|  2240     return TCL_ERROR; |  | 
|  2241   } |  | 
|  2242   if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR; |  | 
|  2243   if( rc ){ |  | 
|  2244     char zBuf[50]; |  | 
|  2245     sprintf(zBuf, "(%d) ", rc); |  | 
|  2246     Tcl_AppendResult(interp, zBuf, sqlite3ErrStr(rc), 0); |  | 
|  2247     return TCL_ERROR; |  | 
|  2248   } |  | 
|  2249   return TCL_OK; |  | 
|  2250 } |  | 
|  2251  |  | 
|  2252 #ifndef SQLITE_OMIT_UTF16 |  | 
|  2253 /* |  | 
|  2254 ** Usage: add_test_collate <db ptr> <utf8> <utf16le> <utf16be> |  | 
|  2255 ** |  | 
|  2256 ** This function is used to test that SQLite selects the correct collation |  | 
|  2257 ** sequence callback when multiple versions (for different text encodings) |  | 
|  2258 ** are available. |  | 
|  2259 ** |  | 
|  2260 ** Calling this routine registers the collation sequence "test_collate" |  | 
|  2261 ** with database handle <db>. The second argument must be a list of three |  | 
|  2262 ** boolean values. If the first is true, then a version of test_collate is |  | 
|  2263 ** registered for UTF-8, if the second is true, a version is registered for |  | 
|  2264 ** UTF-16le, if the third is true, a UTF-16be version is available. |  | 
|  2265 ** Previous versions of test_collate are deleted. |  | 
|  2266 ** |  | 
|  2267 ** The collation sequence test_collate is implemented by calling the |  | 
|  2268 ** following TCL script: |  | 
|  2269 ** |  | 
|  2270 **   "test_collate <enc> <lhs> <rhs>" |  | 
|  2271 ** |  | 
|  2272 ** The <lhs> and <rhs> are the two values being compared, encoded in UTF-8. |  | 
|  2273 ** The <enc> parameter is the encoding of the collation function that |  | 
|  2274 ** SQLite selected to call. The TCL test script implements the |  | 
|  2275 ** "test_collate" proc. |  | 
|  2276 ** |  | 
|  2277 ** Note that this will only work with one intepreter at a time, as the |  | 
|  2278 ** interp pointer to use when evaluating the TCL script is stored in |  | 
|  2279 ** pTestCollateInterp. |  | 
|  2280 */ |  | 
|  2281 static Tcl_Interp* pTestCollateInterp; |  | 
|  2282 static int test_collate_func( |  | 
|  2283   void *pCtx,  |  | 
|  2284   int nA, const void *zA, |  | 
|  2285   int nB, const void *zB |  | 
|  2286 ){ |  | 
|  2287   Tcl_Interp *i = pTestCollateInterp; |  | 
|  2288   int encin = (int)pCtx; |  | 
|  2289   int res; |  | 
|  2290   int n; |  | 
|  2291  |  | 
|  2292   sqlite3_value *pVal; |  | 
|  2293   Tcl_Obj *pX; |  | 
|  2294  |  | 
|  2295   pX = Tcl_NewStringObj("test_collate", -1); |  | 
|  2296   Tcl_IncrRefCount(pX); |  | 
|  2297  |  | 
|  2298   switch( encin ){ |  | 
|  2299     case SQLITE_UTF8: |  | 
|  2300       Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-8",-1)); |  | 
|  2301       break; |  | 
|  2302     case SQLITE_UTF16LE: |  | 
|  2303       Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-16LE",-1)); |  | 
|  2304       break; |  | 
|  2305     case SQLITE_UTF16BE: |  | 
|  2306       Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-16BE",-1)); |  | 
|  2307       break; |  | 
|  2308     default: |  | 
|  2309       assert(0); |  | 
|  2310   } |  | 
|  2311  |  | 
|  2312   sqlite3BeginBenignMalloc(); |  | 
|  2313   pVal = sqlite3ValueNew(0); |  | 
|  2314   if( pVal ){ |  | 
|  2315     sqlite3ValueSetStr(pVal, nA, zA, encin, SQLITE_STATIC); |  | 
|  2316     n = sqlite3_value_bytes(pVal); |  | 
|  2317     Tcl_ListObjAppendElement(i,pX, |  | 
|  2318         Tcl_NewStringObj((char*)sqlite3_value_text(pVal),n)); |  | 
|  2319     sqlite3ValueSetStr(pVal, nB, zB, encin, SQLITE_STATIC); |  | 
|  2320     n = sqlite3_value_bytes(pVal); |  | 
|  2321     Tcl_ListObjAppendElement(i,pX, |  | 
|  2322         Tcl_NewStringObj((char*)sqlite3_value_text(pVal),n)); |  | 
|  2323     sqlite3ValueFree(pVal); |  | 
|  2324   } |  | 
|  2325   sqlite3EndBenignMalloc(); |  | 
|  2326  |  | 
|  2327   Tcl_EvalObjEx(i, pX, 0); |  | 
|  2328   Tcl_DecrRefCount(pX); |  | 
|  2329   Tcl_GetIntFromObj(i, Tcl_GetObjResult(i), &res); |  | 
|  2330   return res; |  | 
|  2331 } |  | 
|  2332 static int test_collate( |  | 
|  2333   void * clientData, |  | 
|  2334   Tcl_Interp *interp, |  | 
|  2335   int objc, |  | 
|  2336   Tcl_Obj *CONST objv[] |  | 
|  2337 ){ |  | 
|  2338   sqlite3 *db; |  | 
|  2339   int val; |  | 
|  2340   sqlite3_value *pVal; |  | 
|  2341   int rc; |  | 
|  2342  |  | 
|  2343   if( objc!=5 ) goto bad_args; |  | 
|  2344   pTestCollateInterp = interp; |  | 
|  2345   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; |  | 
|  2346  |  | 
|  2347   if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[2], &val) ) return TCL_ERROR; |  | 
|  2348   rc = sqlite3_create_collation(db, "test_collate", SQLITE_UTF8,  |  | 
|  2349           (void *)SQLITE_UTF8, val?test_collate_func:0); |  | 
|  2350   if( rc==SQLITE_OK ){ |  | 
|  2351     const void *zUtf16; |  | 
|  2352     if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[3], &val) ) return TCL_ERROR; |  | 
|  2353     rc = sqlite3_create_collation(db, "test_collate", SQLITE_UTF16LE,  |  | 
|  2354             (void *)SQLITE_UTF16LE, val?test_collate_func:0); |  | 
|  2355     if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[4], &val) ) return TCL_ERROR; |  | 
|  2356  |  | 
|  2357 #if 0 |  | 
|  2358     if( sqlite3_iMallocFail>0 ){ |  | 
|  2359       sqlite3_iMallocFail++; |  | 
|  2360     } |  | 
|  2361 #endif |  | 
|  2362     sqlite3_mutex_enter(db->mutex); |  | 
|  2363     pVal = sqlite3ValueNew(db); |  | 
|  2364     sqlite3ValueSetStr(pVal, -1, "test_collate", SQLITE_UTF8, SQLITE_STATIC); |  | 
|  2365     zUtf16 = sqlite3ValueText(pVal, SQLITE_UTF16NATIVE); |  | 
|  2366     if( db->mallocFailed ){ |  | 
|  2367       rc = SQLITE_NOMEM; |  | 
|  2368     }else{ |  | 
|  2369       rc = sqlite3_create_collation16(db, zUtf16, SQLITE_UTF16BE,  |  | 
|  2370           (void *)SQLITE_UTF16BE, val?test_collate_func:0); |  | 
|  2371     } |  | 
|  2372     sqlite3ValueFree(pVal); |  | 
|  2373     sqlite3_mutex_leave(db->mutex); |  | 
|  2374   } |  | 
|  2375   if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; |  | 
|  2376    |  | 
|  2377   if( rc!=SQLITE_OK ){ |  | 
|  2378     Tcl_AppendResult(interp, sqlite3TestErrorName(rc), 0); |  | 
|  2379     return TCL_ERROR; |  | 
|  2380   } |  | 
|  2381   return TCL_OK; |  | 
|  2382  |  | 
|  2383 bad_args: |  | 
|  2384   Tcl_AppendResult(interp, "wrong # args: should be \"", |  | 
|  2385       Tcl_GetStringFromObj(objv[0], 0), " <DB> <utf8> <utf16le> <utf16be>", 0); |  | 
|  2386   return TCL_ERROR; |  | 
|  2387 } |  | 
|  2388  |  | 
|  2389 /* |  | 
|  2390 ** When the collation needed callback is invoked, record the name of  |  | 
|  2391 ** the requested collating function here.  The recorded name is linked |  | 
|  2392 ** to a TCL variable and used to make sure that the requested collation |  | 
|  2393 ** name is correct. |  | 
|  2394 */ |  | 
|  2395 static char zNeededCollation[200]; |  | 
|  2396 static char *pzNeededCollation = zNeededCollation; |  | 
|  2397  |  | 
|  2398  |  | 
|  2399 /* |  | 
|  2400 ** Called when a collating sequence is needed.  Registered using |  | 
|  2401 ** sqlite3_collation_needed16(). |  | 
|  2402 */ |  | 
|  2403 static void test_collate_needed_cb( |  | 
|  2404   void *pCtx,  |  | 
|  2405   sqlite3 *db, |  | 
|  2406   int eTextRep, |  | 
|  2407   const void *pName |  | 
|  2408 ){ |  | 
|  2409   int enc = ENC(db); |  | 
|  2410   int i; |  | 
|  2411   char *z; |  | 
|  2412   for(z = (char*)pName, i=0; *z || z[1]; z++){ |  | 
|  2413     if( *z ) zNeededCollation[i++] = *z; |  | 
|  2414   } |  | 
|  2415   zNeededCollation[i] = 0; |  | 
|  2416   sqlite3_create_collation( |  | 
|  2417       db, "test_collate", ENC(db), (void *)enc, test_collate_func); |  | 
|  2418 } |  | 
|  2419  |  | 
|  2420 /* |  | 
|  2421 ** Usage: add_test_collate_needed DB |  | 
|  2422 */ |  | 
|  2423 static int test_collate_needed( |  | 
|  2424   void * clientData, |  | 
|  2425   Tcl_Interp *interp, |  | 
|  2426   int objc, |  | 
|  2427   Tcl_Obj *CONST objv[] |  | 
|  2428 ){ |  | 
|  2429   sqlite3 *db; |  | 
|  2430   int rc; |  | 
|  2431  |  | 
|  2432   if( objc!=2 ) goto bad_args; |  | 
|  2433   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; |  | 
|  2434   rc = sqlite3_collation_needed16(db, 0, test_collate_needed_cb); |  | 
|  2435   zNeededCollation[0] = 0; |  | 
|  2436   if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; |  | 
|  2437   return TCL_OK; |  | 
|  2438  |  | 
|  2439 bad_args: |  | 
|  2440   Tcl_WrongNumArgs(interp, 1, objv, "DB"); |  | 
|  2441   return TCL_ERROR; |  | 
|  2442 } |  | 
|  2443  |  | 
|  2444 /* |  | 
|  2445 ** tclcmd:   add_alignment_test_collations  DB |  | 
|  2446 ** |  | 
|  2447 ** Add two new collating sequences to the database DB |  | 
|  2448 ** |  | 
|  2449 **     utf16_aligned |  | 
|  2450 **     utf16_unaligned |  | 
|  2451 ** |  | 
|  2452 ** Both collating sequences use the same sort order as BINARY. |  | 
|  2453 ** The only difference is that the utf16_aligned collating |  | 
|  2454 ** sequence is declared with the SQLITE_UTF16_ALIGNED flag. |  | 
|  2455 ** Both collating functions increment the unaligned utf16 counter |  | 
|  2456 ** whenever they see a string that begins on an odd byte boundary. |  | 
|  2457 */ |  | 
|  2458 static int unaligned_string_counter = 0; |  | 
|  2459 static int alignmentCollFunc( |  | 
|  2460   void *NotUsed, |  | 
|  2461   int nKey1, const void *pKey1, |  | 
|  2462   int nKey2, const void *pKey2 |  | 
|  2463 ){ |  | 
|  2464   int rc, n; |  | 
|  2465   n = nKey1<nKey2 ? nKey1 : nKey2; |  | 
|  2466   if( nKey1>0 && 1==(1&(int)pKey1) ) unaligned_string_counter++; |  | 
|  2467   if( nKey2>0 && 1==(1&(int)pKey2) ) unaligned_string_counter++; |  | 
|  2468   rc = memcmp(pKey1, pKey2, n); |  | 
|  2469   if( rc==0 ){ |  | 
|  2470     rc = nKey1 - nKey2; |  | 
|  2471   } |  | 
|  2472   return rc; |  | 
|  2473 } |  | 
|  2474 static int add_alignment_test_collations( |  | 
|  2475   void * clientData, |  | 
|  2476   Tcl_Interp *interp, |  | 
|  2477   int objc, |  | 
|  2478   Tcl_Obj *CONST objv[] |  | 
|  2479 ){ |  | 
|  2480   sqlite3 *db; |  | 
|  2481   if( objc>=2 ){ |  | 
|  2482     if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; |  | 
|  2483     sqlite3_create_collation(db, "utf16_unaligned", SQLITE_UTF16,  |  | 
|  2484         0, alignmentCollFunc); |  | 
|  2485     sqlite3_create_collation(db, "utf16_aligned", SQLITE_UTF16_ALIGNED,  |  | 
|  2486         0, alignmentCollFunc); |  | 
|  2487   } |  | 
|  2488   return SQLITE_OK; |  | 
|  2489 } |  | 
|  2490 #endif /* !defined(SQLITE_OMIT_UTF16) */ |  | 
|  2491  |  | 
|  2492 /* |  | 
|  2493 ** Usage: add_test_function <db ptr> <utf8> <utf16le> <utf16be> |  | 
|  2494 ** |  | 
|  2495 ** This function is used to test that SQLite selects the correct user |  | 
|  2496 ** function callback when multiple versions (for different text encodings) |  | 
|  2497 ** are available. |  | 
|  2498 ** |  | 
|  2499 ** Calling this routine registers up to three versions of the user function |  | 
|  2500 ** "test_function" with database handle <db>.  If the second argument is |  | 
|  2501 ** true, then a version of test_function is registered for UTF-8, if the |  | 
|  2502 ** third is true, a version is registered for UTF-16le, if the fourth is |  | 
|  2503 ** true, a UTF-16be version is available.  Previous versions of |  | 
|  2504 ** test_function are deleted. |  | 
|  2505 ** |  | 
|  2506 ** The user function is implemented by calling the following TCL script: |  | 
|  2507 ** |  | 
|  2508 **   "test_function <enc> <arg>" |  | 
|  2509 ** |  | 
|  2510 ** Where <enc> is one of UTF-8, UTF-16LE or UTF16BE, and <arg> is the |  | 
|  2511 ** single argument passed to the SQL function. The value returned by |  | 
|  2512 ** the TCL script is used as the return value of the SQL function. It |  | 
|  2513 ** is passed to SQLite using UTF-16BE for a UTF-8 test_function(), UTF-8 |  | 
|  2514 ** for a UTF-16LE test_function(), and UTF-16LE for an implementation that |  | 
|  2515 ** prefers UTF-16BE. |  | 
|  2516 */ |  | 
|  2517 #ifndef SQLITE_OMIT_UTF16 |  | 
|  2518 static void test_function_utf8( |  | 
|  2519   sqlite3_context *pCtx,  |  | 
|  2520   int nArg, |  | 
|  2521   sqlite3_value **argv |  | 
|  2522 ){ |  | 
|  2523   Tcl_Interp *interp; |  | 
|  2524   Tcl_Obj *pX; |  | 
|  2525   sqlite3_value *pVal; |  | 
|  2526   interp = (Tcl_Interp *)sqlite3_user_data(pCtx); |  | 
|  2527   pX = Tcl_NewStringObj("test_function", -1); |  | 
|  2528   Tcl_IncrRefCount(pX); |  | 
|  2529   Tcl_ListObjAppendElement(interp, pX, Tcl_NewStringObj("UTF-8", -1)); |  | 
|  2530   Tcl_ListObjAppendElement(interp, pX,  |  | 
|  2531       Tcl_NewStringObj((char*)sqlite3_value_text(argv[0]), -1)); |  | 
|  2532   Tcl_EvalObjEx(interp, pX, 0); |  | 
|  2533   Tcl_DecrRefCount(pX); |  | 
|  2534   sqlite3_result_text(pCtx, Tcl_GetStringResult(interp), -1, SQLITE_TRANSIENT); |  | 
|  2535   pVal = sqlite3ValueNew(0); |  | 
|  2536   sqlite3ValueSetStr(pVal, -1, Tcl_GetStringResult(interp),  |  | 
|  2537       SQLITE_UTF8, SQLITE_STATIC); |  | 
|  2538   sqlite3_result_text16be(pCtx, sqlite3_value_text16be(pVal), |  | 
|  2539       -1, SQLITE_TRANSIENT); |  | 
|  2540   sqlite3ValueFree(pVal); |  | 
|  2541 } |  | 
|  2542 static void test_function_utf16le( |  | 
|  2543   sqlite3_context *pCtx,  |  | 
|  2544   int nArg, |  | 
|  2545   sqlite3_value **argv |  | 
|  2546 ){ |  | 
|  2547   Tcl_Interp *interp; |  | 
|  2548   Tcl_Obj *pX; |  | 
|  2549   sqlite3_value *pVal; |  | 
|  2550   interp = (Tcl_Interp *)sqlite3_user_data(pCtx); |  | 
|  2551   pX = Tcl_NewStringObj("test_function", -1); |  | 
|  2552   Tcl_IncrRefCount(pX); |  | 
|  2553   Tcl_ListObjAppendElement(interp, pX, Tcl_NewStringObj("UTF-16LE", -1)); |  | 
|  2554   Tcl_ListObjAppendElement(interp, pX,  |  | 
|  2555       Tcl_NewStringObj((char*)sqlite3_value_text(argv[0]), -1)); |  | 
|  2556   Tcl_EvalObjEx(interp, pX, 0); |  | 
|  2557   Tcl_DecrRefCount(pX); |  | 
|  2558   pVal = sqlite3ValueNew(0); |  | 
|  2559   sqlite3ValueSetStr(pVal, -1, Tcl_GetStringResult(interp),  |  | 
|  2560       SQLITE_UTF8, SQLITE_STATIC); |  | 
|  2561   sqlite3_result_text(pCtx,(char*)sqlite3_value_text(pVal),-1,SQLITE_TRANSIENT); |  | 
|  2562   sqlite3ValueFree(pVal); |  | 
|  2563 } |  | 
|  2564 static void test_function_utf16be( |  | 
|  2565   sqlite3_context *pCtx,  |  | 
|  2566   int nArg, |  | 
|  2567   sqlite3_value **argv |  | 
|  2568 ){ |  | 
|  2569   Tcl_Interp *interp; |  | 
|  2570   Tcl_Obj *pX; |  | 
|  2571   sqlite3_value *pVal; |  | 
|  2572   interp = (Tcl_Interp *)sqlite3_user_data(pCtx); |  | 
|  2573   pX = Tcl_NewStringObj("test_function", -1); |  | 
|  2574   Tcl_IncrRefCount(pX); |  | 
|  2575   Tcl_ListObjAppendElement(interp, pX, Tcl_NewStringObj("UTF-16BE", -1)); |  | 
|  2576   Tcl_ListObjAppendElement(interp, pX,  |  | 
|  2577       Tcl_NewStringObj((char*)sqlite3_value_text(argv[0]), -1)); |  | 
|  2578   Tcl_EvalObjEx(interp, pX, 0); |  | 
|  2579   Tcl_DecrRefCount(pX); |  | 
|  2580   pVal = sqlite3ValueNew(0); |  | 
|  2581   sqlite3ValueSetStr(pVal, -1, Tcl_GetStringResult(interp),  |  | 
|  2582       SQLITE_UTF8, SQLITE_STATIC); |  | 
|  2583   sqlite3_result_text16(pCtx, sqlite3_value_text16le(pVal), |  | 
|  2584       -1, SQLITE_TRANSIENT); |  | 
|  2585   sqlite3_result_text16be(pCtx, sqlite3_value_text16le(pVal), |  | 
|  2586       -1, SQLITE_TRANSIENT); |  | 
|  2587   sqlite3_result_text16le(pCtx, sqlite3_value_text16le(pVal), |  | 
|  2588       -1, SQLITE_TRANSIENT); |  | 
|  2589   sqlite3ValueFree(pVal); |  | 
|  2590 } |  | 
|  2591 #endif /* SQLITE_OMIT_UTF16 */ |  | 
|  2592 static int test_function( |  | 
|  2593   void * clientData, |  | 
|  2594   Tcl_Interp *interp, |  | 
|  2595   int objc, |  | 
|  2596   Tcl_Obj *CONST objv[] |  | 
|  2597 ){ |  | 
|  2598 #ifndef SQLITE_OMIT_UTF16 |  | 
|  2599   sqlite3 *db; |  | 
|  2600   int val; |  | 
|  2601  |  | 
|  2602   if( objc!=5 ) goto bad_args; |  | 
|  2603   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; |  | 
|  2604  |  | 
|  2605   if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[2], &val) ) return TCL_ERROR; |  | 
|  2606   if( val ){ |  | 
|  2607     sqlite3_create_function(db, "test_function", 1, SQLITE_UTF8,  |  | 
|  2608         interp, test_function_utf8, 0, 0); |  | 
|  2609   } |  | 
|  2610   if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[3], &val) ) return TCL_ERROR; |  | 
|  2611   if( val ){ |  | 
|  2612     sqlite3_create_function(db, "test_function", 1, SQLITE_UTF16LE,  |  | 
|  2613         interp, test_function_utf16le, 0, 0); |  | 
|  2614   } |  | 
|  2615   if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[4], &val) ) return TCL_ERROR; |  | 
|  2616   if( val ){ |  | 
|  2617     sqlite3_create_function(db, "test_function", 1, SQLITE_UTF16BE,  |  | 
|  2618         interp, test_function_utf16be, 0, 0); |  | 
|  2619   } |  | 
|  2620  |  | 
|  2621   return TCL_OK; |  | 
|  2622 bad_args: |  | 
|  2623   Tcl_AppendResult(interp, "wrong # args: should be \"", |  | 
|  2624       Tcl_GetStringFromObj(objv[0], 0), " <DB> <utf8> <utf16le> <utf16be>", 0); |  | 
|  2625 #endif /* SQLITE_OMIT_UTF16 */ |  | 
|  2626   return TCL_ERROR; |  | 
|  2627 } |  | 
|  2628  |  | 
|  2629 /* |  | 
|  2630 ** Usage:         test_errstr <err code> |  | 
|  2631 ** |  | 
|  2632 ** Test that the english language string equivalents for sqlite error codes |  | 
|  2633 ** are sane. The parameter is an integer representing an sqlite error code. |  | 
|  2634 ** The result is a list of two elements, the string representation of the |  | 
|  2635 ** error code and the english language explanation. |  | 
|  2636 */ |  | 
|  2637 static int test_errstr( |  | 
|  2638   void * clientData, |  | 
|  2639   Tcl_Interp *interp, |  | 
|  2640   int objc, |  | 
|  2641   Tcl_Obj *CONST objv[] |  | 
|  2642 ){ |  | 
|  2643   char *zCode; |  | 
|  2644   int i; |  | 
|  2645   if( objc!=1 ){ |  | 
|  2646     Tcl_WrongNumArgs(interp, 1, objv, "<error code>"); |  | 
|  2647   } |  | 
|  2648  |  | 
|  2649   zCode = Tcl_GetString(objv[1]); |  | 
|  2650   for(i=0; i<200; i++){ |  | 
|  2651     if( 0==strcmp(t1ErrorName(i), zCode) ) break; |  | 
|  2652   } |  | 
|  2653   Tcl_SetResult(interp, (char *)sqlite3ErrStr(i), 0); |  | 
|  2654   return TCL_OK; |  | 
|  2655 } |  | 
|  2656  |  | 
|  2657 /* |  | 
|  2658 ** Usage:    breakpoint |  | 
|  2659 ** |  | 
|  2660 ** This routine exists for one purpose - to provide a place to put a |  | 
|  2661 ** breakpoint with GDB that can be triggered using TCL code.  The use |  | 
|  2662 ** for this is when a particular test fails on (say) the 1485th iteration. |  | 
|  2663 ** In the TCL test script, we can add code like this: |  | 
|  2664 ** |  | 
|  2665 **     if {$i==1485} breakpoint |  | 
|  2666 ** |  | 
|  2667 ** Then run testfixture in the debugger and wait for the breakpoint to |  | 
|  2668 ** fire.  Then additional breakpoints can be set to trace down the bug. |  | 
|  2669 */ |  | 
|  2670 static int test_breakpoint( |  | 
|  2671   void *NotUsed, |  | 
|  2672   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ |  | 
|  2673   int argc,              /* Number of arguments */ |  | 
|  2674   char **argv            /* Text of each argument */ |  | 
|  2675 ){ |  | 
|  2676   return TCL_OK;         /* Do nothing */ |  | 
|  2677 } |  | 
|  2678  |  | 
|  2679 /* |  | 
|  2680 ** Usage:   sqlite3_bind_zeroblob  STMT IDX N |  | 
|  2681 ** |  | 
|  2682 ** Test the sqlite3_bind_zeroblob interface.  STMT is a prepared statement. |  | 
|  2683 ** IDX is the index of a wildcard in the prepared statement.  This command |  | 
|  2684 ** binds a N-byte zero-filled BLOB to the wildcard. |  | 
|  2685 */ |  | 
|  2686 static int test_bind_zeroblob( |  | 
|  2687   void * clientData, |  | 
|  2688   Tcl_Interp *interp, |  | 
|  2689   int objc, |  | 
|  2690   Tcl_Obj *CONST objv[] |  | 
|  2691 ){ |  | 
|  2692   sqlite3_stmt *pStmt; |  | 
|  2693   int idx; |  | 
|  2694   int n; |  | 
|  2695   int rc; |  | 
|  2696  |  | 
|  2697   if( objc!=4 ){ |  | 
|  2698     Tcl_WrongNumArgs(interp, 1, objv, "STMT IDX N"); |  | 
|  2699     return TCL_ERROR; |  | 
|  2700   } |  | 
|  2701  |  | 
|  2702   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; |  | 
|  2703   if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; |  | 
|  2704   if( Tcl_GetIntFromObj(interp, objv[3], &n) ) return TCL_ERROR; |  | 
|  2705  |  | 
|  2706   rc = sqlite3_bind_zeroblob(pStmt, idx, n); |  | 
|  2707   if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR; |  | 
|  2708   if( rc!=SQLITE_OK ){ |  | 
|  2709     return TCL_ERROR; |  | 
|  2710   } |  | 
|  2711  |  | 
|  2712   return TCL_OK; |  | 
|  2713 } |  | 
|  2714  |  | 
|  2715 /* |  | 
|  2716 ** Usage:   sqlite3_bind_int  STMT N VALUE |  | 
|  2717 ** |  | 
|  2718 ** Test the sqlite3_bind_int interface.  STMT is a prepared statement. |  | 
|  2719 ** N is the index of a wildcard in the prepared statement.  This command |  | 
|  2720 ** binds a 32-bit integer VALUE to that wildcard. |  | 
|  2721 */ |  | 
|  2722 static int test_bind_int( |  | 
|  2723   void * clientData, |  | 
|  2724   Tcl_Interp *interp, |  | 
|  2725   int objc, |  | 
|  2726   Tcl_Obj *CONST objv[] |  | 
|  2727 ){ |  | 
|  2728   sqlite3_stmt *pStmt; |  | 
|  2729   int idx; |  | 
|  2730   int value; |  | 
|  2731   int rc; |  | 
|  2732  |  | 
|  2733   if( objc!=4 ){ |  | 
|  2734     Tcl_AppendResult(interp, "wrong # args: should be \"", |  | 
|  2735         Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE", 0); |  | 
|  2736     return TCL_ERROR; |  | 
|  2737   } |  | 
|  2738  |  | 
|  2739   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; |  | 
|  2740   if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; |  | 
|  2741   if( Tcl_GetIntFromObj(interp, objv[3], &value) ) return TCL_ERROR; |  | 
|  2742  |  | 
|  2743   rc = sqlite3_bind_int(pStmt, idx, value); |  | 
|  2744   if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR; |  | 
|  2745   if( rc!=SQLITE_OK ){ |  | 
|  2746     return TCL_ERROR; |  | 
|  2747   } |  | 
|  2748  |  | 
|  2749   return TCL_OK; |  | 
|  2750 } |  | 
|  2751  |  | 
|  2752  |  | 
|  2753 /* |  | 
|  2754 ** Usage:   sqlite3_bind_int64  STMT N VALUE |  | 
|  2755 ** |  | 
|  2756 ** Test the sqlite3_bind_int64 interface.  STMT is a prepared statement. |  | 
|  2757 ** N is the index of a wildcard in the prepared statement.  This command |  | 
|  2758 ** binds a 64-bit integer VALUE to that wildcard. |  | 
|  2759 */ |  | 
|  2760 static int test_bind_int64( |  | 
|  2761   void * clientData, |  | 
|  2762   Tcl_Interp *interp, |  | 
|  2763   int objc, |  | 
|  2764   Tcl_Obj *CONST objv[] |  | 
|  2765 ){ |  | 
|  2766   sqlite3_stmt *pStmt; |  | 
|  2767   int idx; |  | 
|  2768   i64 value; |  | 
|  2769   int rc; |  | 
|  2770  |  | 
|  2771   if( objc!=4 ){ |  | 
|  2772     Tcl_AppendResult(interp, "wrong # args: should be \"", |  | 
|  2773         Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE", 0); |  | 
|  2774     return TCL_ERROR; |  | 
|  2775   } |  | 
|  2776  |  | 
|  2777   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; |  | 
|  2778   if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; |  | 
|  2779   if( Tcl_GetWideIntFromObj(interp, objv[3], &value) ) return TCL_ERROR; |  | 
|  2780  |  | 
|  2781   rc = sqlite3_bind_int64(pStmt, idx, value); |  | 
|  2782   if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR; |  | 
|  2783   if( rc!=SQLITE_OK ){ |  | 
|  2784     return TCL_ERROR; |  | 
|  2785   } |  | 
|  2786  |  | 
|  2787   return TCL_OK; |  | 
|  2788 } |  | 
|  2789  |  | 
|  2790  |  | 
|  2791 /* |  | 
|  2792 ** Usage:   sqlite3_bind_double  STMT N VALUE |  | 
|  2793 ** |  | 
|  2794 ** Test the sqlite3_bind_double interface.  STMT is a prepared statement. |  | 
|  2795 ** N is the index of a wildcard in the prepared statement.  This command |  | 
|  2796 ** binds a 64-bit integer VALUE to that wildcard. |  | 
|  2797 */ |  | 
|  2798 static int test_bind_double( |  | 
|  2799   void * clientData, |  | 
|  2800   Tcl_Interp *interp, |  | 
|  2801   int objc, |  | 
|  2802   Tcl_Obj *CONST objv[] |  | 
|  2803 ){ |  | 
|  2804   sqlite3_stmt *pStmt; |  | 
|  2805   int idx; |  | 
|  2806   double value; |  | 
|  2807   int rc; |  | 
|  2808   const char *zVal; |  | 
|  2809   int i; |  | 
|  2810   static const struct { |  | 
|  2811     const char *zName;     /* Name of the special floating point value */ |  | 
|  2812     unsigned int iUpper;   /* Upper 32 bits */ |  | 
|  2813     unsigned int iLower;   /* Lower 32 bits */ |  | 
|  2814   } aSpecialFp[] = { |  | 
|  2815     {  "NaN",      0x7fffffff, 0xffffffff }, |  | 
|  2816     {  "SNaN",     0x7ff7ffff, 0xffffffff }, |  | 
|  2817     {  "-NaN",     0xffffffff, 0xffffffff }, |  | 
|  2818     {  "-SNaN",    0xfff7ffff, 0xffffffff }, |  | 
|  2819     {  "+Inf",     0x7ff00000, 0x00000000 }, |  | 
|  2820     {  "-Inf",     0xfff00000, 0x00000000 }, |  | 
|  2821     {  "Epsilon",  0x00000000, 0x00000001 }, |  | 
|  2822     {  "-Epsilon", 0x80000000, 0x00000001 }, |  | 
|  2823     {  "NaN0",     0x7ff80000, 0x00000000 }, |  | 
|  2824     {  "-NaN0",    0xfff80000, 0x00000000 }, |  | 
|  2825   }; |  | 
|  2826  |  | 
|  2827   if( objc!=4 ){ |  | 
|  2828     Tcl_AppendResult(interp, "wrong # args: should be \"", |  | 
|  2829         Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE", 0); |  | 
|  2830     return TCL_ERROR; |  | 
|  2831   } |  | 
|  2832  |  | 
|  2833   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; |  | 
|  2834   if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; |  | 
|  2835  |  | 
|  2836   /* Intercept the string "NaN" and generate a NaN value for it. |  | 
|  2837   ** All other strings are passed through to Tcl_GetDoubleFromObj(). |  | 
|  2838   ** Tcl_GetDoubleFromObj() should understand "NaN" but some versions |  | 
|  2839   ** contain a bug. |  | 
|  2840   */ |  | 
|  2841   zVal = Tcl_GetString(objv[3]); |  | 
|  2842   for(i=0; i<sizeof(aSpecialFp)/sizeof(aSpecialFp[0]); i++){ |  | 
|  2843     if( strcmp(aSpecialFp[i].zName, zVal)==0 ){ |  | 
|  2844       sqlite3_uint64 x; |  | 
|  2845       x = aSpecialFp[i].iUpper; |  | 
|  2846       x <<= 32; |  | 
|  2847       x |= aSpecialFp[i].iLower; |  | 
|  2848       assert( sizeof(value)==8 ); |  | 
|  2849       assert( sizeof(x)==8 ); |  | 
|  2850       memcpy(&value, &x, 8); |  | 
|  2851       break; |  | 
|  2852     } |  | 
|  2853   } |  | 
|  2854   if( i>=sizeof(aSpecialFp)/sizeof(aSpecialFp[0]) && |  | 
|  2855          Tcl_GetDoubleFromObj(interp, objv[3], &value) ){ |  | 
|  2856     return TCL_ERROR; |  | 
|  2857   } |  | 
|  2858   rc = sqlite3_bind_double(pStmt, idx, value); |  | 
|  2859   if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR; |  | 
|  2860   if( rc!=SQLITE_OK ){ |  | 
|  2861     return TCL_ERROR; |  | 
|  2862   } |  | 
|  2863  |  | 
|  2864   return TCL_OK; |  | 
|  2865 } |  | 
|  2866  |  | 
|  2867 /* |  | 
|  2868 ** Usage:   sqlite3_bind_null  STMT N |  | 
|  2869 ** |  | 
|  2870 ** Test the sqlite3_bind_null interface.  STMT is a prepared statement. |  | 
|  2871 ** N is the index of a wildcard in the prepared statement.  This command |  | 
|  2872 ** binds a NULL to the wildcard. |  | 
|  2873 */ |  | 
|  2874 static int test_bind_null( |  | 
|  2875   void * clientData, |  | 
|  2876   Tcl_Interp *interp, |  | 
|  2877   int objc, |  | 
|  2878   Tcl_Obj *CONST objv[] |  | 
|  2879 ){ |  | 
|  2880   sqlite3_stmt *pStmt; |  | 
|  2881   int idx; |  | 
|  2882   int rc; |  | 
|  2883  |  | 
|  2884   if( objc!=3 ){ |  | 
|  2885     Tcl_AppendResult(interp, "wrong # args: should be \"", |  | 
|  2886         Tcl_GetStringFromObj(objv[0], 0), " STMT N", 0); |  | 
|  2887     return TCL_ERROR; |  | 
|  2888   } |  | 
|  2889  |  | 
|  2890   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; |  | 
|  2891   if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; |  | 
|  2892  |  | 
|  2893   rc = sqlite3_bind_null(pStmt, idx); |  | 
|  2894   if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR; |  | 
|  2895   if( rc!=SQLITE_OK ){ |  | 
|  2896     return TCL_ERROR; |  | 
|  2897   } |  | 
|  2898  |  | 
|  2899   return TCL_OK; |  | 
|  2900 } |  | 
|  2901  |  | 
|  2902 /* |  | 
|  2903 ** Usage:   sqlite3_bind_text  STMT N STRING BYTES |  | 
|  2904 ** |  | 
|  2905 ** Test the sqlite3_bind_text interface.  STMT is a prepared statement. |  | 
|  2906 ** N is the index of a wildcard in the prepared statement.  This command |  | 
|  2907 ** binds a UTF-8 string STRING to the wildcard.  The string is BYTES bytes |  | 
|  2908 ** long. |  | 
|  2909 */ |  | 
|  2910 static int test_bind_text( |  | 
|  2911   void * clientData, |  | 
|  2912   Tcl_Interp *interp, |  | 
|  2913   int objc, |  | 
|  2914   Tcl_Obj *CONST objv[] |  | 
|  2915 ){ |  | 
|  2916   sqlite3_stmt *pStmt; |  | 
|  2917   int idx; |  | 
|  2918   int bytes; |  | 
|  2919   char *value; |  | 
|  2920   int rc; |  | 
|  2921  |  | 
|  2922   if( objc!=5 ){ |  | 
|  2923     Tcl_AppendResult(interp, "wrong # args: should be \"", |  | 
|  2924         Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE BYTES", 0); |  | 
|  2925     return TCL_ERROR; |  | 
|  2926   } |  | 
|  2927  |  | 
|  2928   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; |  | 
|  2929   if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; |  | 
|  2930   value = (char*)Tcl_GetByteArrayFromObj(objv[3], &bytes); |  | 
|  2931   if( Tcl_GetIntFromObj(interp, objv[4], &bytes) ) return TCL_ERROR; |  | 
|  2932  |  | 
|  2933   rc = sqlite3_bind_text(pStmt, idx, value, bytes, SQLITE_TRANSIENT); |  | 
|  2934   if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR; |  | 
|  2935   if( rc!=SQLITE_OK ){ |  | 
|  2936     Tcl_AppendResult(interp, sqlite3TestErrorName(rc), 0); |  | 
|  2937     return TCL_ERROR; |  | 
|  2938   } |  | 
|  2939  |  | 
|  2940   return TCL_OK; |  | 
|  2941 } |  | 
|  2942  |  | 
|  2943 /* |  | 
|  2944 ** Usage:   sqlite3_bind_text16 ?-static? STMT N STRING BYTES |  | 
|  2945 ** |  | 
|  2946 ** Test the sqlite3_bind_text16 interface.  STMT is a prepared statement. |  | 
|  2947 ** N is the index of a wildcard in the prepared statement.  This command |  | 
|  2948 ** binds a UTF-16 string STRING to the wildcard.  The string is BYTES bytes |  | 
|  2949 ** long. |  | 
|  2950 */ |  | 
|  2951 static int test_bind_text16( |  | 
|  2952   void * clientData, |  | 
|  2953   Tcl_Interp *interp, |  | 
|  2954   int objc, |  | 
|  2955   Tcl_Obj *CONST objv[] |  | 
|  2956 ){ |  | 
|  2957 #ifndef SQLITE_OMIT_UTF16 |  | 
|  2958   sqlite3_stmt *pStmt; |  | 
|  2959   int idx; |  | 
|  2960   int bytes; |  | 
|  2961   char *value; |  | 
|  2962   int rc; |  | 
|  2963  |  | 
|  2964   void (*xDel)() = (objc==6?SQLITE_STATIC:SQLITE_TRANSIENT); |  | 
|  2965   Tcl_Obj *oStmt    = objv[objc-4]; |  | 
|  2966   Tcl_Obj *oN       = objv[objc-3]; |  | 
|  2967   Tcl_Obj *oString  = objv[objc-2]; |  | 
|  2968   Tcl_Obj *oBytes   = objv[objc-1]; |  | 
|  2969  |  | 
|  2970   if( objc!=5 && objc!=6){ |  | 
|  2971     Tcl_AppendResult(interp, "wrong # args: should be \"", |  | 
|  2972         Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE BYTES", 0); |  | 
|  2973     return TCL_ERROR; |  | 
|  2974   } |  | 
|  2975  |  | 
|  2976   if( getStmtPointer(interp, Tcl_GetString(oStmt), &pStmt) ) return TCL_ERROR; |  | 
|  2977   if( Tcl_GetIntFromObj(interp, oN, &idx) ) return TCL_ERROR; |  | 
|  2978   value = (char*)Tcl_GetByteArrayFromObj(oString, 0); |  | 
|  2979   if( Tcl_GetIntFromObj(interp, oBytes, &bytes) ) return TCL_ERROR; |  | 
|  2980  |  | 
|  2981   rc = sqlite3_bind_text16(pStmt, idx, (void *)value, bytes, xDel); |  | 
|  2982   if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR; |  | 
|  2983   if( rc!=SQLITE_OK ){ |  | 
|  2984     Tcl_AppendResult(interp, sqlite3TestErrorName(rc), 0); |  | 
|  2985     return TCL_ERROR; |  | 
|  2986   } |  | 
|  2987  |  | 
|  2988 #endif /* SQLITE_OMIT_UTF16 */ |  | 
|  2989   return TCL_OK; |  | 
|  2990 } |  | 
|  2991  |  | 
|  2992 /* |  | 
|  2993 ** Usage:   sqlite3_bind_blob ?-static? STMT N DATA BYTES |  | 
|  2994 ** |  | 
|  2995 ** Test the sqlite3_bind_blob interface.  STMT is a prepared statement. |  | 
|  2996 ** N is the index of a wildcard in the prepared statement.  This command |  | 
|  2997 ** binds a BLOB to the wildcard.  The BLOB is BYTES bytes in size. |  | 
|  2998 */ |  | 
|  2999 static int test_bind_blob( |  | 
|  3000   void * clientData, |  | 
|  3001   Tcl_Interp *interp, |  | 
|  3002   int objc, |  | 
|  3003   Tcl_Obj *CONST objv[] |  | 
|  3004 ){ |  | 
|  3005   sqlite3_stmt *pStmt; |  | 
|  3006   int idx; |  | 
|  3007   int bytes; |  | 
|  3008   char *value; |  | 
|  3009   int rc; |  | 
|  3010   sqlite3_destructor_type xDestructor = SQLITE_TRANSIENT; |  | 
|  3011  |  | 
|  3012   if( objc!=5 && objc!=6 ){ |  | 
|  3013     Tcl_AppendResult(interp, "wrong # args: should be \"", |  | 
|  3014         Tcl_GetStringFromObj(objv[0], 0), " STMT N DATA BYTES", 0); |  | 
|  3015     return TCL_ERROR; |  | 
|  3016   } |  | 
|  3017  |  | 
|  3018   if( objc==6 ){ |  | 
|  3019     xDestructor = SQLITE_STATIC; |  | 
|  3020     objv++; |  | 
|  3021   } |  | 
|  3022  |  | 
|  3023   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; |  | 
|  3024   if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; |  | 
|  3025   value = Tcl_GetString(objv[3]); |  | 
|  3026   if( Tcl_GetIntFromObj(interp, objv[4], &bytes) ) return TCL_ERROR; |  | 
|  3027  |  | 
|  3028   rc = sqlite3_bind_blob(pStmt, idx, value, bytes, xDestructor); |  | 
|  3029   if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR; |  | 
|  3030   if( rc!=SQLITE_OK ){ |  | 
|  3031     return TCL_ERROR; |  | 
|  3032   } |  | 
|  3033  |  | 
|  3034   return TCL_OK; |  | 
|  3035 } |  | 
|  3036  |  | 
|  3037 /* |  | 
|  3038 ** Usage:   sqlite3_bind_parameter_count  STMT |  | 
|  3039 ** |  | 
|  3040 ** Return the number of wildcards in the given statement. |  | 
|  3041 */ |  | 
|  3042 static int test_bind_parameter_count( |  | 
|  3043   void * clientData, |  | 
|  3044   Tcl_Interp *interp, |  | 
|  3045   int objc, |  | 
|  3046   Tcl_Obj *CONST objv[] |  | 
|  3047 ){ |  | 
|  3048   sqlite3_stmt *pStmt; |  | 
|  3049  |  | 
|  3050   if( objc!=2 ){ |  | 
|  3051     Tcl_WrongNumArgs(interp, 1, objv, "STMT"); |  | 
|  3052     return TCL_ERROR; |  | 
|  3053   } |  | 
|  3054   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; |  | 
|  3055   Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_bind_parameter_count(pStmt))); |  | 
|  3056   return TCL_OK; |  | 
|  3057 } |  | 
|  3058  |  | 
|  3059 /* |  | 
|  3060 ** Usage:   sqlite3_bind_parameter_name  STMT  N |  | 
|  3061 ** |  | 
|  3062 ** Return the name of the Nth wildcard.  The first wildcard is 1. |  | 
|  3063 ** An empty string is returned if N is out of range or if the wildcard |  | 
|  3064 ** is nameless. |  | 
|  3065 */ |  | 
|  3066 static int test_bind_parameter_name( |  | 
|  3067   void * clientData, |  | 
|  3068   Tcl_Interp *interp, |  | 
|  3069   int objc, |  | 
|  3070   Tcl_Obj *CONST objv[] |  | 
|  3071 ){ |  | 
|  3072   sqlite3_stmt *pStmt; |  | 
|  3073   int i; |  | 
|  3074  |  | 
|  3075   if( objc!=3 ){ |  | 
|  3076     Tcl_WrongNumArgs(interp, 1, objv, "STMT N"); |  | 
|  3077     return TCL_ERROR; |  | 
|  3078   } |  | 
|  3079   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; |  | 
|  3080   if( Tcl_GetIntFromObj(interp, objv[2], &i) ) return TCL_ERROR; |  | 
|  3081   Tcl_SetObjResult(interp,  |  | 
|  3082      Tcl_NewStringObj(sqlite3_bind_parameter_name(pStmt,i),-1) |  | 
|  3083   ); |  | 
|  3084   return TCL_OK; |  | 
|  3085 } |  | 
|  3086  |  | 
|  3087 /* |  | 
|  3088 ** Usage:   sqlite3_bind_parameter_index  STMT  NAME |  | 
|  3089 ** |  | 
|  3090 ** Return the index of the wildcard called NAME.  Return 0 if there is |  | 
|  3091 ** no such wildcard. |  | 
|  3092 */ |  | 
|  3093 static int test_bind_parameter_index( |  | 
|  3094   void * clientData, |  | 
|  3095   Tcl_Interp *interp, |  | 
|  3096   int objc, |  | 
|  3097   Tcl_Obj *CONST objv[] |  | 
|  3098 ){ |  | 
|  3099   sqlite3_stmt *pStmt; |  | 
|  3100  |  | 
|  3101   if( objc!=3 ){ |  | 
|  3102     Tcl_WrongNumArgs(interp, 1, objv, "STMT NAME"); |  | 
|  3103     return TCL_ERROR; |  | 
|  3104   } |  | 
|  3105   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; |  | 
|  3106   Tcl_SetObjResult(interp,  |  | 
|  3107      Tcl_NewIntObj( |  | 
|  3108        sqlite3_bind_parameter_index(pStmt,Tcl_GetString(objv[2])) |  | 
|  3109      ) |  | 
|  3110   ); |  | 
|  3111   return TCL_OK; |  | 
|  3112 } |  | 
|  3113  |  | 
|  3114 /* |  | 
|  3115 ** Usage:   sqlite3_clear_bindings STMT |  | 
|  3116 ** |  | 
|  3117 */ |  | 
|  3118 static int test_clear_bindings( |  | 
|  3119   void * clientData, |  | 
|  3120   Tcl_Interp *interp, |  | 
|  3121   int objc, |  | 
|  3122   Tcl_Obj *CONST objv[] |  | 
|  3123 ){ |  | 
|  3124   sqlite3_stmt *pStmt; |  | 
|  3125  |  | 
|  3126   if( objc!=2 ){ |  | 
|  3127     Tcl_WrongNumArgs(interp, 1, objv, "STMT"); |  | 
|  3128     return TCL_ERROR; |  | 
|  3129   } |  | 
|  3130   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; |  | 
|  3131   Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_clear_bindings(pStmt))); |  | 
|  3132   return TCL_OK; |  | 
|  3133 } |  | 
|  3134  |  | 
|  3135 /* |  | 
|  3136 ** Usage:   sqlite3_sleep MILLISECONDS |  | 
|  3137 */ |  | 
|  3138 static int test_sleep( |  | 
|  3139   void * clientData, |  | 
|  3140   Tcl_Interp *interp, |  | 
|  3141   int objc, |  | 
|  3142   Tcl_Obj *CONST objv[] |  | 
|  3143 ){ |  | 
|  3144   int ms; |  | 
|  3145  |  | 
|  3146   if( objc!=2 ){ |  | 
|  3147     Tcl_WrongNumArgs(interp, 1, objv, "MILLISECONDS"); |  | 
|  3148     return TCL_ERROR; |  | 
|  3149   } |  | 
|  3150   if( Tcl_GetIntFromObj(interp, objv[1], &ms) ){ |  | 
|  3151     return TCL_ERROR; |  | 
|  3152   } |  | 
|  3153   Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_sleep(ms))); |  | 
|  3154   return TCL_OK; |  | 
|  3155 } |  | 
|  3156  |  | 
|  3157 /* |  | 
|  3158 ** Usage: sqlite3_extended_errcode DB |  | 
|  3159 ** |  | 
|  3160 ** Return the string representation of the most recent sqlite3_* API |  | 
|  3161 ** error code. e.g. "SQLITE_ERROR". |  | 
|  3162 */ |  | 
|  3163 static int test_ex_errcode( |  | 
|  3164   void * clientData, |  | 
|  3165   Tcl_Interp *interp, |  | 
|  3166   int objc, |  | 
|  3167   Tcl_Obj *CONST objv[] |  | 
|  3168 ){ |  | 
|  3169   sqlite3 *db; |  | 
|  3170   int rc; |  | 
|  3171  |  | 
|  3172   if( objc!=2 ){ |  | 
|  3173     Tcl_AppendResult(interp, "wrong # args: should be \"",  |  | 
|  3174        Tcl_GetString(objv[0]), " DB", 0); |  | 
|  3175     return TCL_ERROR; |  | 
|  3176   } |  | 
|  3177   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; |  | 
|  3178   rc = sqlite3_extended_errcode(db); |  | 
|  3179   Tcl_AppendResult(interp, (char *)t1ErrorName(rc), 0); |  | 
|  3180   return TCL_OK; |  | 
|  3181 } |  | 
|  3182  |  | 
|  3183  |  | 
|  3184 /* |  | 
|  3185 ** Usage: sqlite3_errcode DB |  | 
|  3186 ** |  | 
|  3187 ** Return the string representation of the most recent sqlite3_* API |  | 
|  3188 ** error code. e.g. "SQLITE_ERROR". |  | 
|  3189 */ |  | 
|  3190 static int test_errcode( |  | 
|  3191   void * clientData, |  | 
|  3192   Tcl_Interp *interp, |  | 
|  3193   int objc, |  | 
|  3194   Tcl_Obj *CONST objv[] |  | 
|  3195 ){ |  | 
|  3196   sqlite3 *db; |  | 
|  3197   int rc; |  | 
|  3198  |  | 
|  3199   if( objc!=2 ){ |  | 
|  3200     Tcl_AppendResult(interp, "wrong # args: should be \"",  |  | 
|  3201        Tcl_GetString(objv[0]), " DB", 0); |  | 
|  3202     return TCL_ERROR; |  | 
|  3203   } |  | 
|  3204   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; |  | 
|  3205   rc = sqlite3_errcode(db); |  | 
|  3206   Tcl_AppendResult(interp, (char *)t1ErrorName(rc), 0); |  | 
|  3207   return TCL_OK; |  | 
|  3208 } |  | 
|  3209  |  | 
|  3210 /* |  | 
|  3211 ** Usage:   sqlite3_errmsg DB |  | 
|  3212 ** |  | 
|  3213 ** Returns the UTF-8 representation of the error message string for the |  | 
|  3214 ** most recent sqlite3_* API call. |  | 
|  3215 */ |  | 
|  3216 static int test_errmsg( |  | 
|  3217   void * clientData, |  | 
|  3218   Tcl_Interp *interp, |  | 
|  3219   int objc, |  | 
|  3220   Tcl_Obj *CONST objv[] |  | 
|  3221 ){ |  | 
|  3222   sqlite3 *db; |  | 
|  3223   const char *zErr; |  | 
|  3224  |  | 
|  3225   if( objc!=2 ){ |  | 
|  3226     Tcl_AppendResult(interp, "wrong # args: should be \"",  |  | 
|  3227        Tcl_GetString(objv[0]), " DB", 0); |  | 
|  3228     return TCL_ERROR; |  | 
|  3229   } |  | 
|  3230   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; |  | 
|  3231  |  | 
|  3232   zErr = sqlite3_errmsg(db); |  | 
|  3233   Tcl_SetObjResult(interp, Tcl_NewStringObj(zErr, -1)); |  | 
|  3234   return TCL_OK; |  | 
|  3235 } |  | 
|  3236  |  | 
|  3237 /* |  | 
|  3238 ** Usage:   test_errmsg16 DB |  | 
|  3239 ** |  | 
|  3240 ** Returns the UTF-16 representation of the error message string for the |  | 
|  3241 ** most recent sqlite3_* API call. This is a byte array object at the TCL  |  | 
|  3242 ** level, and it includes the 0x00 0x00 terminator bytes at the end of the |  | 
|  3243 ** UTF-16 string. |  | 
|  3244 */ |  | 
|  3245 static int test_errmsg16( |  | 
|  3246   void * clientData, |  | 
|  3247   Tcl_Interp *interp, |  | 
|  3248   int objc, |  | 
|  3249   Tcl_Obj *CONST objv[] |  | 
|  3250 ){ |  | 
|  3251 #ifndef SQLITE_OMIT_UTF16 |  | 
|  3252   sqlite3 *db; |  | 
|  3253   const void *zErr; |  | 
|  3254   const char *z; |  | 
|  3255   int bytes = 0; |  | 
|  3256  |  | 
|  3257   if( objc!=2 ){ |  | 
|  3258     Tcl_AppendResult(interp, "wrong # args: should be \"",  |  | 
|  3259        Tcl_GetString(objv[0]), " DB", 0); |  | 
|  3260     return TCL_ERROR; |  | 
|  3261   } |  | 
|  3262   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; |  | 
|  3263  |  | 
|  3264   zErr = sqlite3_errmsg16(db); |  | 
|  3265   if( zErr ){ |  | 
|  3266     z = zErr; |  | 
|  3267     for(bytes=0; z[bytes] || z[bytes+1]; bytes+=2){} |  | 
|  3268   } |  | 
|  3269   Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(zErr, bytes)); |  | 
|  3270 #endif /* SQLITE_OMIT_UTF16 */ |  | 
|  3271   return TCL_OK; |  | 
|  3272 } |  | 
|  3273  |  | 
|  3274 /* |  | 
|  3275 ** Usage: sqlite3_prepare DB sql bytes ?tailvar? |  | 
|  3276 ** |  | 
|  3277 ** Compile up to <bytes> bytes of the supplied SQL string <sql> using |  | 
|  3278 ** database handle <DB>. The parameter <tailval> is the name of a global |  | 
|  3279 ** variable that is set to the unused portion of <sql> (if any). A |  | 
|  3280 ** STMT handle is returned. |  | 
|  3281 */ |  | 
|  3282 static int test_prepare( |  | 
|  3283   void * clientData, |  | 
|  3284   Tcl_Interp *interp, |  | 
|  3285   int objc, |  | 
|  3286   Tcl_Obj *CONST objv[] |  | 
|  3287 ){ |  | 
|  3288   sqlite3 *db; |  | 
|  3289   const char *zSql; |  | 
|  3290   int bytes; |  | 
|  3291   const char *zTail = 0; |  | 
|  3292   sqlite3_stmt *pStmt = 0; |  | 
|  3293   char zBuf[50]; |  | 
|  3294   int rc; |  | 
|  3295  |  | 
|  3296   if( objc!=5 && objc!=4 ){ |  | 
|  3297     Tcl_AppendResult(interp, "wrong # args: should be \"",  |  | 
|  3298        Tcl_GetString(objv[0]), " DB sql bytes ?tailvar?", 0); |  | 
|  3299     return TCL_ERROR; |  | 
|  3300   } |  | 
|  3301   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; |  | 
|  3302   zSql = Tcl_GetString(objv[2]); |  | 
|  3303   if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR; |  | 
|  3304  |  | 
|  3305   rc = sqlite3_prepare(db, zSql, bytes, &pStmt, objc>=5 ? &zTail : 0); |  | 
|  3306   if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; |  | 
|  3307   if( zTail && objc>=5 ){ |  | 
|  3308     if( bytes>=0 ){ |  | 
|  3309       bytes = bytes - (zTail-zSql); |  | 
|  3310     } |  | 
|  3311     if( strlen(zTail)<bytes ){ |  | 
|  3312       bytes = strlen(zTail); |  | 
|  3313     } |  | 
|  3314     Tcl_ObjSetVar2(interp, objv[4], 0, Tcl_NewStringObj(zTail, bytes), 0); |  | 
|  3315   } |  | 
|  3316   if( rc!=SQLITE_OK ){ |  | 
|  3317     assert( pStmt==0 ); |  | 
|  3318     sprintf(zBuf, "(%d) ", rc); |  | 
|  3319     Tcl_AppendResult(interp, zBuf, sqlite3_errmsg(db), 0); |  | 
|  3320     return TCL_ERROR; |  | 
|  3321   } |  | 
|  3322  |  | 
|  3323   if( pStmt ){ |  | 
|  3324     if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR; |  | 
|  3325     Tcl_AppendResult(interp, zBuf, 0); |  | 
|  3326   } |  | 
|  3327   return TCL_OK; |  | 
|  3328 } |  | 
|  3329  |  | 
|  3330 /* |  | 
|  3331 ** Usage: sqlite3_prepare_v2 DB sql bytes ?tailvar? |  | 
|  3332 ** |  | 
|  3333 ** Compile up to <bytes> bytes of the supplied SQL string <sql> using |  | 
|  3334 ** database handle <DB>. The parameter <tailval> is the name of a global |  | 
|  3335 ** variable that is set to the unused portion of <sql> (if any). A |  | 
|  3336 ** STMT handle is returned. |  | 
|  3337 */ |  | 
|  3338 static int test_prepare_v2( |  | 
|  3339   void * clientData, |  | 
|  3340   Tcl_Interp *interp, |  | 
|  3341   int objc, |  | 
|  3342   Tcl_Obj *CONST objv[] |  | 
|  3343 ){ |  | 
|  3344   sqlite3 *db; |  | 
|  3345   const char *zSql; |  | 
|  3346   int bytes; |  | 
|  3347   const char *zTail = 0; |  | 
|  3348   sqlite3_stmt *pStmt = 0; |  | 
|  3349   char zBuf[50]; |  | 
|  3350   int rc; |  | 
|  3351  |  | 
|  3352   if( objc!=5 && objc!=4 ){ |  | 
|  3353     Tcl_AppendResult(interp, "wrong # args: should be \"",  |  | 
|  3354        Tcl_GetString(objv[0]), " DB sql bytes tailvar", 0); |  | 
|  3355     return TCL_ERROR; |  | 
|  3356   } |  | 
|  3357   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; |  | 
|  3358   zSql = Tcl_GetString(objv[2]); |  | 
|  3359   if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR; |  | 
|  3360  |  | 
|  3361   rc = sqlite3_prepare_v2(db, zSql, bytes, &pStmt, objc>=5 ? &zTail : 0); |  | 
|  3362   assert(rc==SQLITE_OK || pStmt==0); |  | 
|  3363   if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; |  | 
|  3364   if( zTail && objc>=5 ){ |  | 
|  3365     if( bytes>=0 ){ |  | 
|  3366       bytes = bytes - (zTail-zSql); |  | 
|  3367     } |  | 
|  3368     Tcl_ObjSetVar2(interp, objv[4], 0, Tcl_NewStringObj(zTail, bytes), 0); |  | 
|  3369   } |  | 
|  3370   if( rc!=SQLITE_OK ){ |  | 
|  3371     assert( pStmt==0 ); |  | 
|  3372     sprintf(zBuf, "(%d) ", rc); |  | 
|  3373     Tcl_AppendResult(interp, zBuf, sqlite3_errmsg(db), 0); |  | 
|  3374     return TCL_ERROR; |  | 
|  3375   } |  | 
|  3376  |  | 
|  3377   if( pStmt ){ |  | 
|  3378     if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR; |  | 
|  3379     Tcl_AppendResult(interp, zBuf, 0); |  | 
|  3380   } |  | 
|  3381   return TCL_OK; |  | 
|  3382 } |  | 
|  3383  |  | 
|  3384 /* |  | 
|  3385 ** Usage: sqlite3_prepare_tkt3134 DB |  | 
|  3386 ** |  | 
|  3387 ** Generate a prepared statement for a zero-byte string as a test |  | 
|  3388 ** for ticket #3134.  The string should be preceeded by a zero byte. |  | 
|  3389 */ |  | 
|  3390 static int test_prepare_tkt3134( |  | 
|  3391   void * clientData, |  | 
|  3392   Tcl_Interp *interp, |  | 
|  3393   int objc, |  | 
|  3394   Tcl_Obj *CONST objv[] |  | 
|  3395 ){ |  | 
|  3396   sqlite3 *db; |  | 
|  3397   static const char zSql[] = "\000SELECT 1"; |  | 
|  3398   sqlite3_stmt *pStmt = 0; |  | 
|  3399   char zBuf[50]; |  | 
|  3400   int rc; |  | 
|  3401  |  | 
|  3402   if( objc!=2 ){ |  | 
|  3403     Tcl_AppendResult(interp, "wrong # args: should be \"",  |  | 
|  3404        Tcl_GetString(objv[0]), " DB sql bytes tailvar", 0); |  | 
|  3405     return TCL_ERROR; |  | 
|  3406   } |  | 
|  3407   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; |  | 
|  3408   rc = sqlite3_prepare_v2(db, &zSql[1], 0, &pStmt, 0); |  | 
|  3409   assert(rc==SQLITE_OK || pStmt==0); |  | 
|  3410   if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; |  | 
|  3411   if( rc!=SQLITE_OK ){ |  | 
|  3412     assert( pStmt==0 ); |  | 
|  3413     sprintf(zBuf, "(%d) ", rc); |  | 
|  3414     Tcl_AppendResult(interp, zBuf, sqlite3_errmsg(db), 0); |  | 
|  3415     return TCL_ERROR; |  | 
|  3416   } |  | 
|  3417  |  | 
|  3418   if( pStmt ){ |  | 
|  3419     if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR; |  | 
|  3420     Tcl_AppendResult(interp, zBuf, 0); |  | 
|  3421   } |  | 
|  3422   return TCL_OK; |  | 
|  3423 } |  | 
|  3424  |  | 
|  3425 /* |  | 
|  3426 ** Usage: sqlite3_prepare16 DB sql bytes tailvar |  | 
|  3427 ** |  | 
|  3428 ** Compile up to <bytes> bytes of the supplied SQL string <sql> using |  | 
|  3429 ** database handle <DB>. The parameter <tailval> is the name of a global |  | 
|  3430 ** variable that is set to the unused portion of <sql> (if any). A |  | 
|  3431 ** STMT handle is returned. |  | 
|  3432 */ |  | 
|  3433 static int test_prepare16( |  | 
|  3434   void * clientData, |  | 
|  3435   Tcl_Interp *interp, |  | 
|  3436   int objc, |  | 
|  3437   Tcl_Obj *CONST objv[] |  | 
|  3438 ){ |  | 
|  3439 #ifndef SQLITE_OMIT_UTF16 |  | 
|  3440   sqlite3 *db; |  | 
|  3441   const void *zSql; |  | 
|  3442   const void *zTail = 0; |  | 
|  3443   Tcl_Obj *pTail = 0; |  | 
|  3444   sqlite3_stmt *pStmt = 0; |  | 
|  3445   char zBuf[50];  |  | 
|  3446   int rc; |  | 
|  3447   int bytes;                /* The integer specified as arg 3 */ |  | 
|  3448   int objlen;               /* The byte-array length of arg 2 */ |  | 
|  3449  |  | 
|  3450   if( objc!=5 && objc!=4 ){ |  | 
|  3451     Tcl_AppendResult(interp, "wrong # args: should be \"",  |  | 
|  3452        Tcl_GetString(objv[0]), " DB sql bytes ?tailvar?", 0); |  | 
|  3453     return TCL_ERROR; |  | 
|  3454   } |  | 
|  3455   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; |  | 
|  3456   zSql = Tcl_GetByteArrayFromObj(objv[2], &objlen); |  | 
|  3457   if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR; |  | 
|  3458  |  | 
|  3459   rc = sqlite3_prepare16(db, zSql, bytes, &pStmt, objc>=5 ? &zTail : 0); |  | 
|  3460   if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; |  | 
|  3461   if( rc ){ |  | 
|  3462     return TCL_ERROR; |  | 
|  3463   } |  | 
|  3464  |  | 
|  3465   if( objc>=5 ){ |  | 
|  3466     if( zTail ){ |  | 
|  3467       objlen = objlen - ((u8 *)zTail-(u8 *)zSql); |  | 
|  3468     }else{ |  | 
|  3469       objlen = 0; |  | 
|  3470     } |  | 
|  3471     pTail = Tcl_NewByteArrayObj((u8 *)zTail, objlen); |  | 
|  3472     Tcl_IncrRefCount(pTail); |  | 
|  3473     Tcl_ObjSetVar2(interp, objv[4], 0, pTail, 0); |  | 
|  3474     Tcl_DecrRefCount(pTail); |  | 
|  3475   } |  | 
|  3476  |  | 
|  3477   if( pStmt ){ |  | 
|  3478     if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR; |  | 
|  3479   } |  | 
|  3480   Tcl_AppendResult(interp, zBuf, 0); |  | 
|  3481 #endif /* SQLITE_OMIT_UTF16 */ |  | 
|  3482   return TCL_OK; |  | 
|  3483 } |  | 
|  3484  |  | 
|  3485 /* |  | 
|  3486 ** Usage: sqlite3_prepare16_v2 DB sql bytes ?tailvar? |  | 
|  3487 ** |  | 
|  3488 ** Compile up to <bytes> bytes of the supplied SQL string <sql> using |  | 
|  3489 ** database handle <DB>. The parameter <tailval> is the name of a global |  | 
|  3490 ** variable that is set to the unused portion of <sql> (if any). A |  | 
|  3491 ** STMT handle is returned. |  | 
|  3492 */ |  | 
|  3493 static int test_prepare16_v2( |  | 
|  3494   void * clientData, |  | 
|  3495   Tcl_Interp *interp, |  | 
|  3496   int objc, |  | 
|  3497   Tcl_Obj *CONST objv[] |  | 
|  3498 ){ |  | 
|  3499 #ifndef SQLITE_OMIT_UTF16 |  | 
|  3500   sqlite3 *db; |  | 
|  3501   const void *zSql; |  | 
|  3502   const void *zTail = 0; |  | 
|  3503   Tcl_Obj *pTail = 0; |  | 
|  3504   sqlite3_stmt *pStmt = 0; |  | 
|  3505   char zBuf[50];  |  | 
|  3506   int rc; |  | 
|  3507   int bytes;                /* The integer specified as arg 3 */ |  | 
|  3508   int objlen;               /* The byte-array length of arg 2 */ |  | 
|  3509  |  | 
|  3510   if( objc!=5 && objc!=4 ){ |  | 
|  3511     Tcl_AppendResult(interp, "wrong # args: should be \"",  |  | 
|  3512        Tcl_GetString(objv[0]), " DB sql bytes ?tailvar?", 0); |  | 
|  3513     return TCL_ERROR; |  | 
|  3514   } |  | 
|  3515   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; |  | 
|  3516   zSql = Tcl_GetByteArrayFromObj(objv[2], &objlen); |  | 
|  3517   if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR; |  | 
|  3518  |  | 
|  3519   rc = sqlite3_prepare16_v2(db, zSql, bytes, &pStmt, objc>=5 ? &zTail : 0); |  | 
|  3520   if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; |  | 
|  3521   if( rc ){ |  | 
|  3522     return TCL_ERROR; |  | 
|  3523   } |  | 
|  3524  |  | 
|  3525   if( objc>=5 ){ |  | 
|  3526     if( zTail ){ |  | 
|  3527       objlen = objlen - ((u8 *)zTail-(u8 *)zSql); |  | 
|  3528     }else{ |  | 
|  3529       objlen = 0; |  | 
|  3530     } |  | 
|  3531     pTail = Tcl_NewByteArrayObj((u8 *)zTail, objlen); |  | 
|  3532     Tcl_IncrRefCount(pTail); |  | 
|  3533     Tcl_ObjSetVar2(interp, objv[4], 0, pTail, 0); |  | 
|  3534     Tcl_DecrRefCount(pTail); |  | 
|  3535   } |  | 
|  3536  |  | 
|  3537   if( pStmt ){ |  | 
|  3538     if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR; |  | 
|  3539   } |  | 
|  3540   Tcl_AppendResult(interp, zBuf, 0); |  | 
|  3541 #endif /* SQLITE_OMIT_UTF16 */ |  | 
|  3542   return TCL_OK; |  | 
|  3543 } |  | 
|  3544  |  | 
|  3545 /* |  | 
|  3546 ** Usage: sqlite3_open filename ?options-list? |  | 
|  3547 */ |  | 
|  3548 static int test_open( |  | 
|  3549   void * clientData, |  | 
|  3550   Tcl_Interp *interp, |  | 
|  3551   int objc, |  | 
|  3552   Tcl_Obj *CONST objv[] |  | 
|  3553 ){ |  | 
|  3554   const char *zFilename; |  | 
|  3555   sqlite3 *db; |  | 
|  3556   int rc; |  | 
|  3557   char zBuf[100]; |  | 
|  3558  |  | 
|  3559   if( objc!=3 && objc!=2 && objc!=1 ){ |  | 
|  3560     Tcl_AppendResult(interp, "wrong # args: should be \"",  |  | 
|  3561        Tcl_GetString(objv[0]), " filename options-list", 0); |  | 
|  3562     return TCL_ERROR; |  | 
|  3563   } |  | 
|  3564  |  | 
|  3565   zFilename = objc>1 ? Tcl_GetString(objv[1]) : 0; |  | 
|  3566   rc = sqlite3_open(zFilename, &db); |  | 
|  3567    |  | 
|  3568   if( sqlite3TestMakePointerStr(interp, zBuf, db) ) return TCL_ERROR; |  | 
|  3569   Tcl_AppendResult(interp, zBuf, 0); |  | 
|  3570   return TCL_OK; |  | 
|  3571 } |  | 
|  3572  |  | 
|  3573 /* |  | 
|  3574 ** Usage: sqlite3_open16 filename options |  | 
|  3575 */ |  | 
|  3576 static int test_open16( |  | 
|  3577   void * clientData, |  | 
|  3578   Tcl_Interp *interp, |  | 
|  3579   int objc, |  | 
|  3580   Tcl_Obj *CONST objv[] |  | 
|  3581 ){ |  | 
|  3582 #ifndef SQLITE_OMIT_UTF16 |  | 
|  3583   const void *zFilename; |  | 
|  3584   sqlite3 *db; |  | 
|  3585   int rc; |  | 
|  3586   char zBuf[100]; |  | 
|  3587  |  | 
|  3588   if( objc!=3 ){ |  | 
|  3589     Tcl_AppendResult(interp, "wrong # args: should be \"",  |  | 
|  3590        Tcl_GetString(objv[0]), " filename options-list", 0); |  | 
|  3591     return TCL_ERROR; |  | 
|  3592   } |  | 
|  3593  |  | 
|  3594   zFilename = Tcl_GetByteArrayFromObj(objv[1], 0); |  | 
|  3595   rc = sqlite3_open16(zFilename, &db); |  | 
|  3596    |  | 
|  3597   if( sqlite3TestMakePointerStr(interp, zBuf, db) ) return TCL_ERROR; |  | 
|  3598   Tcl_AppendResult(interp, zBuf, 0); |  | 
|  3599 #endif /* SQLITE_OMIT_UTF16 */ |  | 
|  3600   return TCL_OK; |  | 
|  3601 } |  | 
|  3602  |  | 
|  3603 /* |  | 
|  3604 ** Usage: sqlite3_complete16 <UTF-16 string> |  | 
|  3605 ** |  | 
|  3606 ** Return 1 if the supplied argument is a complete SQL statement, or zero |  | 
|  3607 ** otherwise. |  | 
|  3608 */ |  | 
|  3609 static int test_complete16( |  | 
|  3610   void * clientData, |  | 
|  3611   Tcl_Interp *interp, |  | 
|  3612   int objc, |  | 
|  3613   Tcl_Obj *CONST objv[] |  | 
|  3614 ){ |  | 
|  3615 #if !defined(SQLITE_OMIT_COMPLETE) && !defined(SQLITE_OMIT_UTF16) |  | 
|  3616   char *zBuf; |  | 
|  3617  |  | 
|  3618   if( objc!=2 ){ |  | 
|  3619     Tcl_WrongNumArgs(interp, 1, objv, "<utf-16 sql>"); |  | 
|  3620     return TCL_ERROR; |  | 
|  3621   } |  | 
|  3622  |  | 
|  3623   zBuf = (char*)Tcl_GetByteArrayFromObj(objv[1], 0); |  | 
|  3624   Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_complete16(zBuf))); |  | 
|  3625 #endif /* SQLITE_OMIT_COMPLETE && SQLITE_OMIT_UTF16 */ |  | 
|  3626   return TCL_OK; |  | 
|  3627 } |  | 
|  3628  |  | 
|  3629 /* |  | 
|  3630 ** Usage: sqlite3_step STMT |  | 
|  3631 ** |  | 
|  3632 ** Advance the statement to the next row. |  | 
|  3633 */ |  | 
|  3634 static int test_step( |  | 
|  3635   void * clientData, |  | 
|  3636   Tcl_Interp *interp, |  | 
|  3637   int objc, |  | 
|  3638   Tcl_Obj *CONST objv[] |  | 
|  3639 ){ |  | 
|  3640   sqlite3_stmt *pStmt; |  | 
|  3641   int rc; |  | 
|  3642  |  | 
|  3643   if( objc!=2 ){ |  | 
|  3644     Tcl_AppendResult(interp, "wrong # args: should be \"",  |  | 
|  3645        Tcl_GetString(objv[0]), " STMT", 0); |  | 
|  3646     return TCL_ERROR; |  | 
|  3647   } |  | 
|  3648  |  | 
|  3649   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; |  | 
|  3650   rc = sqlite3_step(pStmt); |  | 
|  3651  |  | 
|  3652   /* if( rc!=SQLITE_DONE && rc!=SQLITE_ROW ) return TCL_ERROR; */ |  | 
|  3653   Tcl_SetResult(interp, (char *)t1ErrorName(rc), 0); |  | 
|  3654   return TCL_OK; |  | 
|  3655 } |  | 
|  3656  |  | 
|  3657 static int test_sql( |  | 
|  3658   void * clientData, |  | 
|  3659   Tcl_Interp *interp, |  | 
|  3660   int objc, |  | 
|  3661   Tcl_Obj *CONST objv[] |  | 
|  3662 ){ |  | 
|  3663   sqlite3_stmt *pStmt; |  | 
|  3664  |  | 
|  3665   if( objc!=2 ){ |  | 
|  3666     Tcl_WrongNumArgs(interp, 1, objv, "STMT"); |  | 
|  3667     return TCL_ERROR; |  | 
|  3668   } |  | 
|  3669  |  | 
|  3670   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; |  | 
|  3671   Tcl_SetResult(interp, (char *)sqlite3_sql(pStmt), TCL_VOLATILE); |  | 
|  3672   return TCL_OK; |  | 
|  3673 } |  | 
|  3674  |  | 
|  3675 /* |  | 
|  3676 ** Usage: sqlite3_column_count STMT  |  | 
|  3677 ** |  | 
|  3678 ** Return the number of columns returned by the sql statement STMT. |  | 
|  3679 */ |  | 
|  3680 static int test_column_count( |  | 
|  3681   void * clientData, |  | 
|  3682   Tcl_Interp *interp, |  | 
|  3683   int objc, |  | 
|  3684   Tcl_Obj *CONST objv[] |  | 
|  3685 ){ |  | 
|  3686   sqlite3_stmt *pStmt; |  | 
|  3687  |  | 
|  3688   if( objc!=2 ){ |  | 
|  3689     Tcl_AppendResult(interp, "wrong # args: should be \"",  |  | 
|  3690        Tcl_GetString(objv[0]), " STMT column", 0); |  | 
|  3691     return TCL_ERROR; |  | 
|  3692   } |  | 
|  3693  |  | 
|  3694   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; |  | 
|  3695  |  | 
|  3696   Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_column_count(pStmt))); |  | 
|  3697   return TCL_OK; |  | 
|  3698 } |  | 
|  3699  |  | 
|  3700 /* |  | 
|  3701 ** Usage: sqlite3_column_type STMT column |  | 
|  3702 ** |  | 
|  3703 ** Return the type of the data in column 'column' of the current row. |  | 
|  3704 */ |  | 
|  3705 static int test_column_type( |  | 
|  3706   void * clientData, |  | 
|  3707   Tcl_Interp *interp, |  | 
|  3708   int objc, |  | 
|  3709   Tcl_Obj *CONST objv[] |  | 
|  3710 ){ |  | 
|  3711   sqlite3_stmt *pStmt; |  | 
|  3712   int col; |  | 
|  3713   int tp; |  | 
|  3714  |  | 
|  3715   if( objc!=3 ){ |  | 
|  3716     Tcl_AppendResult(interp, "wrong # args: should be \"",  |  | 
|  3717        Tcl_GetString(objv[0]), " STMT column", 0); |  | 
|  3718     return TCL_ERROR; |  | 
|  3719   } |  | 
|  3720  |  | 
|  3721   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; |  | 
|  3722   if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; |  | 
|  3723  |  | 
|  3724   tp = sqlite3_column_type(pStmt, col); |  | 
|  3725   switch( tp ){ |  | 
|  3726     case SQLITE_INTEGER:  |  | 
|  3727       Tcl_SetResult(interp, "INTEGER", TCL_STATIC);  |  | 
|  3728       break; |  | 
|  3729     case SQLITE_NULL: |  | 
|  3730       Tcl_SetResult(interp, "NULL", TCL_STATIC);  |  | 
|  3731       break; |  | 
|  3732     case SQLITE_FLOAT: |  | 
|  3733       Tcl_SetResult(interp, "FLOAT", TCL_STATIC);  |  | 
|  3734       break; |  | 
|  3735     case SQLITE_TEXT: |  | 
|  3736       Tcl_SetResult(interp, "TEXT", TCL_STATIC);  |  | 
|  3737       break; |  | 
|  3738     case SQLITE_BLOB: |  | 
|  3739       Tcl_SetResult(interp, "BLOB", TCL_STATIC);  |  | 
|  3740       break; |  | 
|  3741     default: |  | 
|  3742       assert(0); |  | 
|  3743   } |  | 
|  3744  |  | 
|  3745   return TCL_OK; |  | 
|  3746 } |  | 
|  3747  |  | 
|  3748 /* |  | 
|  3749 ** Usage: sqlite3_column_int64 STMT column |  | 
|  3750 ** |  | 
|  3751 ** Return the data in column 'column' of the current row cast as an |  | 
|  3752 ** wide (64-bit) integer. |  | 
|  3753 */ |  | 
|  3754 static int test_column_int64( |  | 
|  3755   void * clientData, |  | 
|  3756   Tcl_Interp *interp, |  | 
|  3757   int objc, |  | 
|  3758   Tcl_Obj *CONST objv[] |  | 
|  3759 ){ |  | 
|  3760   sqlite3_stmt *pStmt; |  | 
|  3761   int col; |  | 
|  3762   i64 iVal; |  | 
|  3763  |  | 
|  3764   if( objc!=3 ){ |  | 
|  3765     Tcl_AppendResult(interp, "wrong # args: should be \"",  |  | 
|  3766        Tcl_GetString(objv[0]), " STMT column", 0); |  | 
|  3767     return TCL_ERROR; |  | 
|  3768   } |  | 
|  3769  |  | 
|  3770   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; |  | 
|  3771   if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; |  | 
|  3772  |  | 
|  3773   iVal = sqlite3_column_int64(pStmt, col); |  | 
|  3774   Tcl_SetObjResult(interp, Tcl_NewWideIntObj(iVal)); |  | 
|  3775   return TCL_OK; |  | 
|  3776 } |  | 
|  3777  |  | 
|  3778 /* |  | 
|  3779 ** Usage: sqlite3_column_blob STMT column |  | 
|  3780 */ |  | 
|  3781 static int test_column_blob( |  | 
|  3782   void * clientData, |  | 
|  3783   Tcl_Interp *interp, |  | 
|  3784   int objc, |  | 
|  3785   Tcl_Obj *CONST objv[] |  | 
|  3786 ){ |  | 
|  3787   sqlite3_stmt *pStmt; |  | 
|  3788   int col; |  | 
|  3789  |  | 
|  3790   int len; |  | 
|  3791   const void *pBlob; |  | 
|  3792  |  | 
|  3793   if( objc!=3 ){ |  | 
|  3794     Tcl_AppendResult(interp, "wrong # args: should be \"",  |  | 
|  3795        Tcl_GetString(objv[0]), " STMT column", 0); |  | 
|  3796     return TCL_ERROR; |  | 
|  3797   } |  | 
|  3798  |  | 
|  3799   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; |  | 
|  3800   if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; |  | 
|  3801  |  | 
|  3802   len = sqlite3_column_bytes(pStmt, col); |  | 
|  3803   pBlob = sqlite3_column_blob(pStmt, col); |  | 
|  3804   Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(pBlob, len)); |  | 
|  3805   return TCL_OK; |  | 
|  3806 } |  | 
|  3807  |  | 
|  3808 /* |  | 
|  3809 ** Usage: sqlite3_column_double STMT column |  | 
|  3810 ** |  | 
|  3811 ** Return the data in column 'column' of the current row cast as a double. |  | 
|  3812 */ |  | 
|  3813 static int test_column_double( |  | 
|  3814   void * clientData, |  | 
|  3815   Tcl_Interp *interp, |  | 
|  3816   int objc, |  | 
|  3817   Tcl_Obj *CONST objv[] |  | 
|  3818 ){ |  | 
|  3819   sqlite3_stmt *pStmt; |  | 
|  3820   int col; |  | 
|  3821   double rVal; |  | 
|  3822  |  | 
|  3823   if( objc!=3 ){ |  | 
|  3824     Tcl_AppendResult(interp, "wrong # args: should be \"",  |  | 
|  3825        Tcl_GetString(objv[0]), " STMT column", 0); |  | 
|  3826     return TCL_ERROR; |  | 
|  3827   } |  | 
|  3828  |  | 
|  3829   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; |  | 
|  3830   if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; |  | 
|  3831  |  | 
|  3832   rVal = sqlite3_column_double(pStmt, col); |  | 
|  3833   Tcl_SetObjResult(interp, Tcl_NewDoubleObj(rVal)); |  | 
|  3834   return TCL_OK; |  | 
|  3835 } |  | 
|  3836  |  | 
|  3837 /* |  | 
|  3838 ** Usage: sqlite3_data_count STMT  |  | 
|  3839 ** |  | 
|  3840 ** Return the number of columns returned by the sql statement STMT. |  | 
|  3841 */ |  | 
|  3842 static int test_data_count( |  | 
|  3843   void * clientData, |  | 
|  3844   Tcl_Interp *interp, |  | 
|  3845   int objc, |  | 
|  3846   Tcl_Obj *CONST objv[] |  | 
|  3847 ){ |  | 
|  3848   sqlite3_stmt *pStmt; |  | 
|  3849  |  | 
|  3850   if( objc!=2 ){ |  | 
|  3851     Tcl_AppendResult(interp, "wrong # args: should be \"",  |  | 
|  3852        Tcl_GetString(objv[0]), " STMT column", 0); |  | 
|  3853     return TCL_ERROR; |  | 
|  3854   } |  | 
|  3855  |  | 
|  3856   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; |  | 
|  3857  |  | 
|  3858   Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_data_count(pStmt))); |  | 
|  3859   return TCL_OK; |  | 
|  3860 } |  | 
|  3861  |  | 
|  3862 /* |  | 
|  3863 ** Usage: sqlite3_column_text STMT column |  | 
|  3864 ** |  | 
|  3865 ** Usage: sqlite3_column_decltype STMT column |  | 
|  3866 ** |  | 
|  3867 ** Usage: sqlite3_column_name STMT column |  | 
|  3868 */ |  | 
|  3869 static int test_stmt_utf8( |  | 
|  3870   void * clientData,        /* Pointer to SQLite API function to be invoke */ |  | 
|  3871   Tcl_Interp *interp, |  | 
|  3872   int objc, |  | 
|  3873   Tcl_Obj *CONST objv[] |  | 
|  3874 ){ |  | 
|  3875   sqlite3_stmt *pStmt; |  | 
|  3876   int col; |  | 
|  3877   const char *(*xFunc)(sqlite3_stmt*, int); |  | 
|  3878   const char *zRet; |  | 
|  3879  |  | 
|  3880   xFunc = (const char *(*)(sqlite3_stmt*, int))clientData; |  | 
|  3881   if( objc!=3 ){ |  | 
|  3882     Tcl_AppendResult(interp, "wrong # args: should be \"",  |  | 
|  3883        Tcl_GetString(objv[0]), " STMT column", 0); |  | 
|  3884     return TCL_ERROR; |  | 
|  3885   } |  | 
|  3886  |  | 
|  3887   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; |  | 
|  3888   if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; |  | 
|  3889   zRet = xFunc(pStmt, col); |  | 
|  3890   if( zRet ){ |  | 
|  3891     Tcl_SetResult(interp, (char *)zRet, 0); |  | 
|  3892   } |  | 
|  3893   return TCL_OK; |  | 
|  3894 } |  | 
|  3895  |  | 
|  3896 static int test_global_recover( |  | 
|  3897   void * clientData, |  | 
|  3898   Tcl_Interp *interp, |  | 
|  3899   int objc, |  | 
|  3900   Tcl_Obj *CONST objv[] |  | 
|  3901 ){ |  | 
|  3902 #ifndef SQLITE_OMIT_GLOBALRECOVER |  | 
|  3903 #ifndef SQLITE_OMIT_DEPRECATED |  | 
|  3904   int rc; |  | 
|  3905   if( objc!=1 ){ |  | 
|  3906     Tcl_WrongNumArgs(interp, 1, objv, ""); |  | 
|  3907     return TCL_ERROR; |  | 
|  3908   } |  | 
|  3909   rc = sqlite3_global_recover(); |  | 
|  3910   Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC); |  | 
|  3911 #endif |  | 
|  3912 #endif |  | 
|  3913   return TCL_OK; |  | 
|  3914 } |  | 
|  3915  |  | 
|  3916 /* |  | 
|  3917 ** Usage: sqlite3_column_text STMT column |  | 
|  3918 ** |  | 
|  3919 ** Usage: sqlite3_column_decltype STMT column |  | 
|  3920 ** |  | 
|  3921 ** Usage: sqlite3_column_name STMT column |  | 
|  3922 */ |  | 
|  3923 static int test_stmt_utf16( |  | 
|  3924   void * clientData,     /* Pointer to SQLite API function to be invoked */ |  | 
|  3925   Tcl_Interp *interp, |  | 
|  3926   int objc, |  | 
|  3927   Tcl_Obj *CONST objv[] |  | 
|  3928 ){ |  | 
|  3929 #ifndef SQLITE_OMIT_UTF16 |  | 
|  3930   sqlite3_stmt *pStmt; |  | 
|  3931   int col; |  | 
|  3932   Tcl_Obj *pRet; |  | 
|  3933   const void *zName16; |  | 
|  3934   const void *(*xFunc)(sqlite3_stmt*, int); |  | 
|  3935  |  | 
|  3936   xFunc = (const void *(*)(sqlite3_stmt*, int))clientData; |  | 
|  3937   if( objc!=3 ){ |  | 
|  3938     Tcl_AppendResult(interp, "wrong # args: should be \"",  |  | 
|  3939        Tcl_GetString(objv[0]), " STMT column", 0); |  | 
|  3940     return TCL_ERROR; |  | 
|  3941   } |  | 
|  3942  |  | 
|  3943   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; |  | 
|  3944   if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; |  | 
|  3945  |  | 
|  3946   zName16 = xFunc(pStmt, col); |  | 
|  3947   if( zName16 ){ |  | 
|  3948     int n; |  | 
|  3949     const char *z = zName16; |  | 
|  3950     for(n=0; z[n] || z[n+1]; n+=2){} |  | 
|  3951     pRet = Tcl_NewByteArrayObj(zName16, n+2); |  | 
|  3952     Tcl_SetObjResult(interp, pRet); |  | 
|  3953   } |  | 
|  3954 #endif /* SQLITE_OMIT_UTF16 */ |  | 
|  3955  |  | 
|  3956   return TCL_OK; |  | 
|  3957 } |  | 
|  3958  |  | 
|  3959 /* |  | 
|  3960 ** Usage: sqlite3_column_int STMT column |  | 
|  3961 ** |  | 
|  3962 ** Usage: sqlite3_column_bytes STMT column |  | 
|  3963 ** |  | 
|  3964 ** Usage: sqlite3_column_bytes16 STMT column |  | 
|  3965 ** |  | 
|  3966 */ |  | 
|  3967 static int test_stmt_int( |  | 
|  3968   void * clientData,    /* Pointer to SQLite API function to be invoked */ |  | 
|  3969   Tcl_Interp *interp, |  | 
|  3970   int objc, |  | 
|  3971   Tcl_Obj *CONST objv[] |  | 
|  3972 ){ |  | 
|  3973   sqlite3_stmt *pStmt; |  | 
|  3974   int col; |  | 
|  3975   int (*xFunc)(sqlite3_stmt*, int); |  | 
|  3976  |  | 
|  3977   xFunc = (int (*)(sqlite3_stmt*, int))clientData; |  | 
|  3978   if( objc!=3 ){ |  | 
|  3979     Tcl_AppendResult(interp, "wrong # args: should be \"",  |  | 
|  3980        Tcl_GetString(objv[0]), " STMT column", 0); |  | 
|  3981     return TCL_ERROR; |  | 
|  3982   } |  | 
|  3983  |  | 
|  3984   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; |  | 
|  3985   if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; |  | 
|  3986  |  | 
|  3987   Tcl_SetObjResult(interp, Tcl_NewIntObj(xFunc(pStmt, col))); |  | 
|  3988   return TCL_OK; |  | 
|  3989 } |  | 
|  3990  |  | 
|  3991 /* |  | 
|  3992 ** Usage:  sqlite_set_magic  DB  MAGIC-NUMBER |  | 
|  3993 ** |  | 
|  3994 ** Set the db->magic value.  This is used to test error recovery logic. |  | 
|  3995 */ |  | 
|  3996 static int sqlite_set_magic( |  | 
|  3997   void * clientData, |  | 
|  3998   Tcl_Interp *interp, |  | 
|  3999   int argc, |  | 
|  4000   char **argv |  | 
|  4001 ){ |  | 
|  4002   sqlite3 *db; |  | 
|  4003   if( argc!=3 ){ |  | 
|  4004     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], |  | 
|  4005          " DB MAGIC", 0); |  | 
|  4006     return TCL_ERROR; |  | 
|  4007   } |  | 
|  4008   if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; |  | 
|  4009   if( strcmp(argv[2], "SQLITE_MAGIC_OPEN")==0 ){ |  | 
|  4010     db->magic = SQLITE_MAGIC_OPEN; |  | 
|  4011   }else if( strcmp(argv[2], "SQLITE_MAGIC_CLOSED")==0 ){ |  | 
|  4012     db->magic = SQLITE_MAGIC_CLOSED; |  | 
|  4013   }else if( strcmp(argv[2], "SQLITE_MAGIC_BUSY")==0 ){ |  | 
|  4014     db->magic = SQLITE_MAGIC_BUSY; |  | 
|  4015   }else if( strcmp(argv[2], "SQLITE_MAGIC_ERROR")==0 ){ |  | 
|  4016     db->magic = SQLITE_MAGIC_ERROR; |  | 
|  4017   }else if( Tcl_GetInt(interp, argv[2], (int*)&db->magic) ){ |  | 
|  4018     return TCL_ERROR; |  | 
|  4019   } |  | 
|  4020   return TCL_OK; |  | 
|  4021 } |  | 
|  4022  |  | 
|  4023 /* |  | 
|  4024 ** Usage:  sqlite3_interrupt  DB  |  | 
|  4025 ** |  | 
|  4026 ** Trigger an interrupt on DB |  | 
|  4027 */ |  | 
|  4028 static int test_interrupt( |  | 
|  4029   void * clientData, |  | 
|  4030   Tcl_Interp *interp, |  | 
|  4031   int argc, |  | 
|  4032   char **argv |  | 
|  4033 ){ |  | 
|  4034   sqlite3 *db; |  | 
|  4035   if( argc!=2 ){ |  | 
|  4036     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " DB", 0); |  | 
|  4037     return TCL_ERROR; |  | 
|  4038   } |  | 
|  4039   if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; |  | 
|  4040   sqlite3_interrupt(db); |  | 
|  4041   return TCL_OK; |  | 
|  4042 } |  | 
|  4043  |  | 
|  4044 static u8 *sqlite3_stack_baseline = 0; |  | 
|  4045  |  | 
|  4046 /* |  | 
|  4047 ** Fill the stack with a known bitpattern. |  | 
|  4048 */ |  | 
|  4049 static void prepStack(void){ |  | 
|  4050   int i; |  | 
|  4051   u32 bigBuf[65536]; |  | 
|  4052   for(i=0; i<sizeof(bigBuf); i++) bigBuf[i] = 0xdeadbeef; |  | 
|  4053   sqlite3_stack_baseline = (u8*)&bigBuf[65536]; |  | 
|  4054 } |  | 
|  4055  |  | 
|  4056 /* |  | 
|  4057 ** Get the current stack depth.  Used for debugging only. |  | 
|  4058 */ |  | 
|  4059 u64 sqlite3StackDepth(void){ |  | 
|  4060   u8 x; |  | 
|  4061   return (u64)(sqlite3_stack_baseline - &x); |  | 
|  4062 } |  | 
|  4063  |  | 
|  4064 /* |  | 
|  4065 ** Usage:  sqlite3_stack_used DB SQL |  | 
|  4066 ** |  | 
|  4067 ** Try to measure the amount of stack space used by a call to sqlite3_exec |  | 
|  4068 */ |  | 
|  4069 static int test_stack_used( |  | 
|  4070   void * clientData, |  | 
|  4071   Tcl_Interp *interp, |  | 
|  4072   int argc, |  | 
|  4073   char **argv |  | 
|  4074 ){ |  | 
|  4075   sqlite3 *db; |  | 
|  4076   int i; |  | 
|  4077   if( argc!=3 ){ |  | 
|  4078     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],  |  | 
|  4079         " DB SQL", 0); |  | 
|  4080     return TCL_ERROR; |  | 
|  4081   } |  | 
|  4082   if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; |  | 
|  4083   prepStack(); |  | 
|  4084   (void)sqlite3_exec(db, argv[2], 0, 0, 0); |  | 
|  4085   for(i=65535; i>=0 && ((u32*)sqlite3_stack_baseline)[-i]==0xdeadbeef; i--){} |  | 
|  4086   Tcl_SetObjResult(interp, Tcl_NewIntObj(i*4)); |  | 
|  4087   return TCL_OK; |  | 
|  4088 } |  | 
|  4089  |  | 
|  4090 /* |  | 
|  4091 ** Usage: sqlite_delete_function DB function-name |  | 
|  4092 ** |  | 
|  4093 ** Delete the user function 'function-name' from database handle DB. It |  | 
|  4094 ** is assumed that the user function was created as UTF8, any number of |  | 
|  4095 ** arguments (the way the TCL interface does it). |  | 
|  4096 */ |  | 
|  4097 static int delete_function( |  | 
|  4098   void * clientData, |  | 
|  4099   Tcl_Interp *interp, |  | 
|  4100   int argc, |  | 
|  4101   char **argv |  | 
|  4102 ){ |  | 
|  4103   int rc; |  | 
|  4104   sqlite3 *db; |  | 
|  4105   if( argc!=3 ){ |  | 
|  4106     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],  |  | 
|  4107         " DB function-name", 0); |  | 
|  4108     return TCL_ERROR; |  | 
|  4109   } |  | 
|  4110   if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; |  | 
|  4111   rc = sqlite3_create_function(db, argv[2], -1, SQLITE_UTF8, 0, 0, 0, 0); |  | 
|  4112   Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC); |  | 
|  4113   return TCL_OK; |  | 
|  4114 } |  | 
|  4115  |  | 
|  4116 /* |  | 
|  4117 ** Usage: sqlite_delete_collation DB collation-name |  | 
|  4118 ** |  | 
|  4119 ** Delete the collation sequence 'collation-name' from database handle  |  | 
|  4120 ** DB. It is assumed that the collation sequence was created as UTF8 (the  |  | 
|  4121 ** way the TCL interface does it). |  | 
|  4122 */ |  | 
|  4123 static int delete_collation( |  | 
|  4124   void * clientData, |  | 
|  4125   Tcl_Interp *interp, |  | 
|  4126   int argc, |  | 
|  4127   char **argv |  | 
|  4128 ){ |  | 
|  4129   int rc; |  | 
|  4130   sqlite3 *db; |  | 
|  4131   if( argc!=3 ){ |  | 
|  4132     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],  |  | 
|  4133         " DB function-name", 0); |  | 
|  4134     return TCL_ERROR; |  | 
|  4135   } |  | 
|  4136   if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; |  | 
|  4137   rc = sqlite3_create_collation(db, argv[2], SQLITE_UTF8, 0, 0); |  | 
|  4138   Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC); |  | 
|  4139   return TCL_OK; |  | 
|  4140 } |  | 
|  4141  |  | 
|  4142 /* |  | 
|  4143 ** Usage: sqlite3_get_autocommit DB |  | 
|  4144 ** |  | 
|  4145 ** Return true if the database DB is currently in auto-commit mode. |  | 
|  4146 ** Return false if not. |  | 
|  4147 */ |  | 
|  4148 static int get_autocommit( |  | 
|  4149   void * clientData, |  | 
|  4150   Tcl_Interp *interp, |  | 
|  4151   int argc, |  | 
|  4152   char **argv |  | 
|  4153 ){ |  | 
|  4154   char zBuf[30]; |  | 
|  4155   sqlite3 *db; |  | 
|  4156   if( argc!=2 ){ |  | 
|  4157     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],  |  | 
|  4158         " DB", 0); |  | 
|  4159     return TCL_ERROR; |  | 
|  4160   } |  | 
|  4161   if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; |  | 
|  4162   sprintf(zBuf, "%d", sqlite3_get_autocommit(db)); |  | 
|  4163   Tcl_AppendResult(interp, zBuf, 0); |  | 
|  4164   return TCL_OK; |  | 
|  4165 } |  | 
|  4166  |  | 
|  4167 /* |  | 
|  4168 ** Usage: sqlite3_busy_timeout DB MS |  | 
|  4169 ** |  | 
|  4170 ** Set the busy timeout.  This is more easily done using the timeout |  | 
|  4171 ** method of the TCL interface.  But we need a way to test the case |  | 
|  4172 ** where it returns SQLITE_MISUSE. |  | 
|  4173 */ |  | 
|  4174 static int test_busy_timeout( |  | 
|  4175   void * clientData, |  | 
|  4176   Tcl_Interp *interp, |  | 
|  4177   int argc, |  | 
|  4178   char **argv |  | 
|  4179 ){ |  | 
|  4180   int rc, ms; |  | 
|  4181   sqlite3 *db; |  | 
|  4182   if( argc!=3 ){ |  | 
|  4183     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],  |  | 
|  4184         " DB", 0); |  | 
|  4185     return TCL_ERROR; |  | 
|  4186   } |  | 
|  4187   if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; |  | 
|  4188   if( Tcl_GetInt(interp, argv[2], &ms) ) return TCL_ERROR; |  | 
|  4189   rc = sqlite3_busy_timeout(db, ms); |  | 
|  4190   Tcl_AppendResult(interp, sqlite3TestErrorName(rc), 0); |  | 
|  4191   return TCL_OK; |  | 
|  4192 } |  | 
|  4193  |  | 
|  4194 /* |  | 
|  4195 ** Usage:  tcl_variable_type VARIABLENAME |  | 
|  4196 ** |  | 
|  4197 ** Return the name of the internal representation for the |  | 
|  4198 ** value of the given variable. |  | 
|  4199 */ |  | 
|  4200 static int tcl_variable_type( |  | 
|  4201   void * clientData, |  | 
|  4202   Tcl_Interp *interp, |  | 
|  4203   int objc, |  | 
|  4204   Tcl_Obj *CONST objv[] |  | 
|  4205 ){ |  | 
|  4206   Tcl_Obj *pVar; |  | 
|  4207   if( objc!=2 ){ |  | 
|  4208     Tcl_WrongNumArgs(interp, 1, objv, "VARIABLE"); |  | 
|  4209     return TCL_ERROR; |  | 
|  4210   } |  | 
|  4211   pVar = Tcl_GetVar2Ex(interp, Tcl_GetString(objv[1]), 0, TCL_LEAVE_ERR_MSG); |  | 
|  4212   if( pVar==0 ) return TCL_ERROR; |  | 
|  4213   if( pVar->typePtr ){ |  | 
|  4214     Tcl_SetObjResult(interp, Tcl_NewStringObj(pVar->typePtr->name, -1)); |  | 
|  4215   } |  | 
|  4216   return TCL_OK; |  | 
|  4217 } |  | 
|  4218  |  | 
|  4219 /* |  | 
|  4220 ** Usage:  sqlite3_release_memory ?N? |  | 
|  4221 ** |  | 
|  4222 ** Attempt to release memory currently held but not actually required. |  | 
|  4223 ** The integer N is the number of bytes we are trying to release.  The  |  | 
|  4224 ** return value is the amount of memory actually released. |  | 
|  4225 */ |  | 
|  4226 static int test_release_memory( |  | 
|  4227   void * clientData, |  | 
|  4228   Tcl_Interp *interp, |  | 
|  4229   int objc, |  | 
|  4230   Tcl_Obj *CONST objv[] |  | 
|  4231 ){ |  | 
|  4232 #if defined(SQLITE_ENABLE_MEMORY_MANAGEMENT) && !defined(SQLITE_OMIT_DISKIO) |  | 
|  4233   int N; |  | 
|  4234   int amt; |  | 
|  4235   if( objc!=1 && objc!=2 ){ |  | 
|  4236     Tcl_WrongNumArgs(interp, 1, objv, "?N?"); |  | 
|  4237     return TCL_ERROR; |  | 
|  4238   } |  | 
|  4239   if( objc==2 ){ |  | 
|  4240     if( Tcl_GetIntFromObj(interp, objv[1], &N) ) return TCL_ERROR; |  | 
|  4241   }else{ |  | 
|  4242     N = -1; |  | 
|  4243   } |  | 
|  4244   amt = sqlite3_release_memory(N); |  | 
|  4245   Tcl_SetObjResult(interp, Tcl_NewIntObj(amt)); |  | 
|  4246 #endif |  | 
|  4247   return TCL_OK; |  | 
|  4248 } |  | 
|  4249  |  | 
|  4250 /* |  | 
|  4251 ** Usage:  sqlite3_soft_heap_limit ?N? |  | 
|  4252 ** |  | 
|  4253 ** Query or set the soft heap limit for the current thread.  The |  | 
|  4254 ** limit is only changed if the N is present.  The previous limit |  | 
|  4255 ** is returned. |  | 
|  4256 */ |  | 
|  4257 static int test_soft_heap_limit( |  | 
|  4258   void * clientData, |  | 
|  4259   Tcl_Interp *interp, |  | 
|  4260   int objc, |  | 
|  4261   Tcl_Obj *CONST objv[] |  | 
|  4262 ){ |  | 
|  4263   static int softHeapLimit = 0; |  | 
|  4264   int amt; |  | 
|  4265   if( objc!=1 && objc!=2 ){ |  | 
|  4266     Tcl_WrongNumArgs(interp, 1, objv, "?N?"); |  | 
|  4267     return TCL_ERROR; |  | 
|  4268   } |  | 
|  4269   amt = softHeapLimit; |  | 
|  4270   if( objc==2 ){ |  | 
|  4271     int N; |  | 
|  4272     if( Tcl_GetIntFromObj(interp, objv[1], &N) ) return TCL_ERROR; |  | 
|  4273     sqlite3_soft_heap_limit(N); |  | 
|  4274     softHeapLimit = N; |  | 
|  4275   } |  | 
|  4276   Tcl_SetObjResult(interp, Tcl_NewIntObj(amt)); |  | 
|  4277   return TCL_OK; |  | 
|  4278 } |  | 
|  4279  |  | 
|  4280 /* |  | 
|  4281 ** Usage:   sqlite3_thread_cleanup |  | 
|  4282 ** |  | 
|  4283 ** Call the sqlite3_thread_cleanup API. |  | 
|  4284 */ |  | 
|  4285 static int test_thread_cleanup( |  | 
|  4286   void * clientData, |  | 
|  4287   Tcl_Interp *interp, |  | 
|  4288   int objc, |  | 
|  4289   Tcl_Obj *CONST objv[] |  | 
|  4290 ){ |  | 
|  4291 #ifndef SQLITE_OMIT_DEPRECATED |  | 
|  4292   sqlite3_thread_cleanup(); |  | 
|  4293 #endif |  | 
|  4294   return TCL_OK; |  | 
|  4295 } |  | 
|  4296  |  | 
|  4297 /* |  | 
|  4298 ** Usage:   sqlite3_pager_refcounts  DB |  | 
|  4299 ** |  | 
|  4300 ** Return a list of numbers which are the PagerRefcount for all |  | 
|  4301 ** pagers on each database connection. |  | 
|  4302 */ |  | 
|  4303 static int test_pager_refcounts( |  | 
|  4304   void * clientData, |  | 
|  4305   Tcl_Interp *interp, |  | 
|  4306   int objc, |  | 
|  4307   Tcl_Obj *CONST objv[] |  | 
|  4308 ){ |  | 
|  4309   sqlite3 *db; |  | 
|  4310   int i; |  | 
|  4311   int v, *a; |  | 
|  4312   Tcl_Obj *pResult; |  | 
|  4313  |  | 
|  4314   if( objc!=2 ){ |  | 
|  4315     Tcl_AppendResult(interp, "wrong # args: should be \"", |  | 
|  4316         Tcl_GetStringFromObj(objv[0], 0), " DB", 0); |  | 
|  4317     return TCL_ERROR; |  | 
|  4318   } |  | 
|  4319   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; |  | 
|  4320   pResult = Tcl_NewObj(); |  | 
|  4321   for(i=0; i<db->nDb; i++){ |  | 
|  4322     if( db->aDb[i].pBt==0 ){ |  | 
|  4323       v = -1; |  | 
|  4324     }else{ |  | 
|  4325       sqlite3_mutex_enter(db->mutex); |  | 
|  4326       a = sqlite3PagerStats(sqlite3BtreePager(db->aDb[i].pBt)); |  | 
|  4327       v = a[0]; |  | 
|  4328       sqlite3_mutex_leave(db->mutex); |  | 
|  4329     } |  | 
|  4330     Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(v)); |  | 
|  4331   } |  | 
|  4332   Tcl_SetObjResult(interp, pResult); |  | 
|  4333   return TCL_OK; |  | 
|  4334 } |  | 
|  4335  |  | 
|  4336  |  | 
|  4337 /* |  | 
|  4338 ** tclcmd:   working_64bit_int |  | 
|  4339 ** |  | 
|  4340 ** Some TCL builds (ex: cygwin) do not support 64-bit integers.  This |  | 
|  4341 ** leads to a number of test failures.  The present command checks the |  | 
|  4342 ** TCL build to see whether or not it supports 64-bit integers.  It |  | 
|  4343 ** returns TRUE if it does and FALSE if not. |  | 
|  4344 ** |  | 
|  4345 ** This command is used to warn users that their TCL build is defective |  | 
|  4346 ** and that the errors they are seeing in the test scripts might be |  | 
|  4347 ** a result of their defective TCL rather than problems in SQLite. |  | 
|  4348 */ |  | 
|  4349 static int working_64bit_int( |  | 
|  4350   ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ |  | 
|  4351   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ |  | 
|  4352   int objc,              /* Number of arguments */ |  | 
|  4353   Tcl_Obj *CONST objv[]  /* Command arguments */ |  | 
|  4354 ){ |  | 
|  4355   Tcl_Obj *pTestObj; |  | 
|  4356   int working = 0; |  | 
|  4357  |  | 
|  4358   pTestObj = Tcl_NewWideIntObj(1000000*(i64)1234567890); |  | 
|  4359   working = strcmp(Tcl_GetString(pTestObj), "1234567890000000")==0; |  | 
|  4360   Tcl_DecrRefCount(pTestObj); |  | 
|  4361   Tcl_SetObjResult(interp, Tcl_NewBooleanObj(working)); |  | 
|  4362   return TCL_OK; |  | 
|  4363 } |  | 
|  4364  |  | 
|  4365  |  | 
|  4366 /* |  | 
|  4367 ** tclcmd:   vfs_unlink_test |  | 
|  4368 ** |  | 
|  4369 ** This TCL command unregisters the primary VFS and then registers |  | 
|  4370 ** it back again.  This is used to test the ability to register a |  | 
|  4371 ** VFS when none are previously registered, and the ability to  |  | 
|  4372 ** unregister the only available VFS.  Ticket #2738 |  | 
|  4373 */ |  | 
|  4374 static int vfs_unlink_test( |  | 
|  4375   ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ |  | 
|  4376   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ |  | 
|  4377   int objc,              /* Number of arguments */ |  | 
|  4378   Tcl_Obj *CONST objv[]  /* Command arguments */ |  | 
|  4379 ){ |  | 
|  4380   int i; |  | 
|  4381   sqlite3_vfs *pMain; |  | 
|  4382   sqlite3_vfs *apVfs[20]; |  | 
|  4383   sqlite3_vfs one, two; |  | 
|  4384  |  | 
|  4385   sqlite3_vfs_unregister(0);   /* Unregister of NULL is harmless */ |  | 
|  4386   one.zName = "__one"; |  | 
|  4387   two.zName = "__two"; |  | 
|  4388  |  | 
|  4389   /* Calling sqlite3_vfs_register with 2nd argument of 0 does not |  | 
|  4390   ** change the default VFS |  | 
|  4391   */ |  | 
|  4392   pMain = sqlite3_vfs_find(0); |  | 
|  4393   sqlite3_vfs_register(&one, 0); |  | 
|  4394   assert( pMain==0 || pMain==sqlite3_vfs_find(0) ); |  | 
|  4395   sqlite3_vfs_register(&two, 0); |  | 
|  4396   assert( pMain==0 || pMain==sqlite3_vfs_find(0) ); |  | 
|  4397  |  | 
|  4398   /* We can find a VFS by its name */ |  | 
|  4399   assert( sqlite3_vfs_find("__one")==&one ); |  | 
|  4400   assert( sqlite3_vfs_find("__two")==&two ); |  | 
|  4401  |  | 
|  4402   /* Calling sqlite_vfs_register with non-zero second parameter changes the |  | 
|  4403   ** default VFS, even if the 1st parameter is an existig VFS that is |  | 
|  4404   ** previously registered as the non-default. |  | 
|  4405   */ |  | 
|  4406   sqlite3_vfs_register(&one, 1); |  | 
|  4407   assert( sqlite3_vfs_find("__one")==&one ); |  | 
|  4408   assert( sqlite3_vfs_find("__two")==&two ); |  | 
|  4409   assert( sqlite3_vfs_find(0)==&one ); |  | 
|  4410   sqlite3_vfs_register(&two, 1); |  | 
|  4411   assert( sqlite3_vfs_find("__one")==&one ); |  | 
|  4412   assert( sqlite3_vfs_find("__two")==&two ); |  | 
|  4413   assert( sqlite3_vfs_find(0)==&two ); |  | 
|  4414   if( pMain ){ |  | 
|  4415     sqlite3_vfs_register(pMain, 1); |  | 
|  4416     assert( sqlite3_vfs_find("__one")==&one ); |  | 
|  4417     assert( sqlite3_vfs_find("__two")==&two ); |  | 
|  4418     assert( sqlite3_vfs_find(0)==pMain ); |  | 
|  4419   } |  | 
|  4420    |  | 
|  4421   /* Unlink the default VFS.  Repeat until there are no more VFSes |  | 
|  4422   ** registered. |  | 
|  4423   */ |  | 
|  4424   for(i=0; i<sizeof(apVfs)/sizeof(apVfs[0]); i++){ |  | 
|  4425     apVfs[i] = sqlite3_vfs_find(0); |  | 
|  4426     if( apVfs[i] ){ |  | 
|  4427       assert( apVfs[i]==sqlite3_vfs_find(apVfs[i]->zName) ); |  | 
|  4428       sqlite3_vfs_unregister(apVfs[i]); |  | 
|  4429       assert( 0==sqlite3_vfs_find(apVfs[i]->zName) ); |  | 
|  4430     } |  | 
|  4431   } |  | 
|  4432   assert( 0==sqlite3_vfs_find(0) ); |  | 
|  4433    |  | 
|  4434   /* Register the main VFS as non-default (will be made default, since |  | 
|  4435   ** it'll be the only one in existence). |  | 
|  4436   */ |  | 
|  4437   sqlite3_vfs_register(pMain, 0); |  | 
|  4438   assert( sqlite3_vfs_find(0)==pMain ); |  | 
|  4439    |  | 
|  4440   /* Un-register the main VFS again to restore an empty VFS list */ |  | 
|  4441   sqlite3_vfs_unregister(pMain); |  | 
|  4442   assert( 0==sqlite3_vfs_find(0) ); |  | 
|  4443  |  | 
|  4444   /* Relink all VFSes in reverse order. */   |  | 
|  4445   for(i=sizeof(apVfs)/sizeof(apVfs[0])-1; i>=0; i--){ |  | 
|  4446     if( apVfs[i] ){ |  | 
|  4447       sqlite3_vfs_register(apVfs[i], 1); |  | 
|  4448       assert( apVfs[i]==sqlite3_vfs_find(0) ); |  | 
|  4449       assert( apVfs[i]==sqlite3_vfs_find(apVfs[i]->zName) ); |  | 
|  4450     } |  | 
|  4451   } |  | 
|  4452  |  | 
|  4453   /* Unregister out sample VFSes. */ |  | 
|  4454   sqlite3_vfs_unregister(&one); |  | 
|  4455   sqlite3_vfs_unregister(&two); |  | 
|  4456  |  | 
|  4457   /* Unregistering a VFS that is not currently registered is harmless */ |  | 
|  4458   sqlite3_vfs_unregister(&one); |  | 
|  4459   sqlite3_vfs_unregister(&two); |  | 
|  4460   assert( sqlite3_vfs_find("__one")==0 ); |  | 
|  4461   assert( sqlite3_vfs_find("__two")==0 ); |  | 
|  4462  |  | 
|  4463   /* We should be left with the original default VFS back as the |  | 
|  4464   ** original */ |  | 
|  4465   assert( sqlite3_vfs_find(0)==pMain ); |  | 
|  4466  |  | 
|  4467   return TCL_OK; |  | 
|  4468 } |  | 
|  4469  |  | 
|  4470 /* |  | 
|  4471 ** tclcmd:   vfs_initfail_test |  | 
|  4472 ** |  | 
|  4473 ** This TCL command attempts to vfs_find and vfs_register when the |  | 
|  4474 ** sqlite3_initialize() interface is failing.  All calls should fail. |  | 
|  4475 */ |  | 
|  4476 static int vfs_initfail_test( |  | 
|  4477   ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ |  | 
|  4478   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ |  | 
|  4479   int objc,              /* Number of arguments */ |  | 
|  4480   Tcl_Obj *CONST objv[]  /* Command arguments */ |  | 
|  4481 ){ |  | 
|  4482   sqlite3_vfs one; |  | 
|  4483   one.zName = "__one"; |  | 
|  4484  |  | 
|  4485   if( sqlite3_vfs_find(0) ) return TCL_ERROR; |  | 
|  4486   sqlite3_vfs_register(&one, 0); |  | 
|  4487   if( sqlite3_vfs_find(0) ) return TCL_ERROR; |  | 
|  4488   sqlite3_vfs_register(&one, 1); |  | 
|  4489   if( sqlite3_vfs_find(0) ) return TCL_ERROR; |  | 
|  4490   return TCL_OK; |  | 
|  4491 } |  | 
|  4492  |  | 
|  4493 /* |  | 
|  4494 ** Saved VFSes |  | 
|  4495 */ |  | 
|  4496 static sqlite3_vfs *apVfs[20]; |  | 
|  4497 static int nVfs = 0; |  | 
|  4498  |  | 
|  4499 /* |  | 
|  4500 ** tclcmd:   vfs_unregister_all |  | 
|  4501 ** |  | 
|  4502 ** Unregister all VFSes. |  | 
|  4503 */ |  | 
|  4504 static int vfs_unregister_all( |  | 
|  4505   ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ |  | 
|  4506   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ |  | 
|  4507   int objc,              /* Number of arguments */ |  | 
|  4508   Tcl_Obj *CONST objv[]  /* Command arguments */ |  | 
|  4509 ){ |  | 
|  4510   int i; |  | 
|  4511   for(i=0; i<ArraySize(apVfs); i++){ |  | 
|  4512     apVfs[i] = sqlite3_vfs_find(0); |  | 
|  4513     if( apVfs[i]==0 ) break; |  | 
|  4514     sqlite3_vfs_unregister(apVfs[i]); |  | 
|  4515   } |  | 
|  4516   nVfs = i; |  | 
|  4517   return TCL_OK; |  | 
|  4518 } |  | 
|  4519 /* |  | 
|  4520 ** tclcmd:   vfs_reregister_all |  | 
|  4521 ** |  | 
|  4522 ** Restore all VFSes that were removed using vfs_unregister_all |  | 
|  4523 */ |  | 
|  4524 static int vfs_reregister_all( |  | 
|  4525   ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ |  | 
|  4526   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ |  | 
|  4527   int objc,              /* Number of arguments */ |  | 
|  4528   Tcl_Obj *CONST objv[]  /* Command arguments */ |  | 
|  4529 ){ |  | 
|  4530   int i; |  | 
|  4531   for(i=0; i<nVfs; i++){ |  | 
|  4532     sqlite3_vfs_register(apVfs[i], i==0); |  | 
|  4533   } |  | 
|  4534   return TCL_OK; |  | 
|  4535 } |  | 
|  4536  |  | 
|  4537  |  | 
|  4538 /* |  | 
|  4539 ** tclcmd:   file_control_test DB |  | 
|  4540 ** |  | 
|  4541 ** This TCL command runs the sqlite3_file_control interface and |  | 
|  4542 ** verifies correct operation of the same. |  | 
|  4543 */ |  | 
|  4544 static int file_control_test( |  | 
|  4545   ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ |  | 
|  4546   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ |  | 
|  4547   int objc,              /* Number of arguments */ |  | 
|  4548   Tcl_Obj *CONST objv[]  /* Command arguments */ |  | 
|  4549 ){ |  | 
|  4550   int iArg = 0; |  | 
|  4551   sqlite3 *db; |  | 
|  4552   int rc; |  | 
|  4553  |  | 
|  4554   if( objc!=2 ){ |  | 
|  4555     Tcl_AppendResult(interp, "wrong # args: should be \"", |  | 
|  4556         Tcl_GetStringFromObj(objv[0], 0), " DB", 0); |  | 
|  4557     return TCL_ERROR; |  | 
|  4558   } |  | 
|  4559   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; |  | 
|  4560   rc = sqlite3_file_control(db, 0, 0, &iArg); |  | 
|  4561   assert( rc==SQLITE_ERROR ); |  | 
|  4562   rc = sqlite3_file_control(db, "notadatabase", SQLITE_FCNTL_LOCKSTATE, &iArg); |  | 
|  4563   assert( rc==SQLITE_ERROR ); |  | 
|  4564   rc = sqlite3_file_control(db, "main", -1, &iArg); |  | 
|  4565   assert( rc==SQLITE_ERROR ); |  | 
|  4566   rc = sqlite3_file_control(db, "temp", -1, &iArg); |  | 
|  4567   assert( rc==SQLITE_ERROR ); |  | 
|  4568  |  | 
|  4569   return TCL_OK; |  | 
|  4570 } |  | 
|  4571  |  | 
|  4572  |  | 
|  4573 /* |  | 
|  4574 ** tclcmd:   file_control_lasterrno_test DB |  | 
|  4575 ** |  | 
|  4576 ** This TCL command runs the sqlite3_file_control interface and |  | 
|  4577 ** verifies correct operation of the SQLITE_LAST_ERRNO verb. |  | 
|  4578 */ |  | 
|  4579 static int file_control_lasterrno_test( |  | 
|  4580   ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ |  | 
|  4581   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ |  | 
|  4582   int objc,              /* Number of arguments */ |  | 
|  4583   Tcl_Obj *CONST objv[]  /* Command arguments */ |  | 
|  4584 ){ |  | 
|  4585   int iArg = 0; |  | 
|  4586   sqlite3 *db; |  | 
|  4587   int rc; |  | 
|  4588  |  | 
|  4589   if( objc!=2 ){ |  | 
|  4590     Tcl_AppendResult(interp, "wrong # args: should be \"", |  | 
|  4591         Tcl_GetStringFromObj(objv[0], 0), " DB", 0); |  | 
|  4592     return TCL_ERROR; |  | 
|  4593   } |  | 
|  4594   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){ |  | 
|  4595     return TCL_ERROR; |  | 
|  4596   } |  | 
|  4597   rc = sqlite3_file_control(db, NULL, SQLITE_LAST_ERRNO, &iArg); |  | 
|  4598   if( rc ){  |  | 
|  4599     Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));  |  | 
|  4600     return TCL_ERROR;  |  | 
|  4601   } |  | 
|  4602   if( iArg!=0 ) { |  | 
|  4603     Tcl_AppendResult(interp, "Unexpected non-zero errno: ", |  | 
|  4604                      Tcl_GetStringFromObj(Tcl_NewIntObj(iArg), 0), " ", 0); |  | 
|  4605     return TCL_ERROR; |  | 
|  4606   } |  | 
|  4607   return TCL_OK;   |  | 
|  4608 } |  | 
|  4609  |  | 
|  4610 /* |  | 
|  4611 ** tclcmd:   file_control_lockproxy_test DB |  | 
|  4612 ** |  | 
|  4613 ** This TCL command runs the sqlite3_file_control interface and |  | 
|  4614 ** verifies correct operation of the SQLITE_GET_LOCKPROXYFILE and |  | 
|  4615 ** SQLITE_SET_LOCKPROXYFILE verbs. |  | 
|  4616 */ |  | 
|  4617 static int file_control_lockproxy_test( |  | 
|  4618   ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ |  | 
|  4619   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ |  | 
|  4620   int objc,              /* Number of arguments */ |  | 
|  4621   Tcl_Obj *CONST objv[]  /* Command arguments */ |  | 
|  4622 ){ |  | 
|  4623   sqlite3 *db; |  | 
|  4624    |  | 
|  4625   if( objc!=2 ){ |  | 
|  4626     Tcl_AppendResult(interp, "wrong # args: should be \"", |  | 
|  4627                      Tcl_GetStringFromObj(objv[0], 0), " DB", 0); |  | 
|  4628     return TCL_ERROR; |  | 
|  4629   } |  | 
|  4630   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){ |  | 
|  4631    return TCL_ERROR; |  | 
|  4632   } |  | 
|  4633    |  | 
|  4634 #if !defined(SQLITE_ENABLE_LOCKING_STYLE) |  | 
|  4635 #  if defined(__APPLE__) |  | 
|  4636 #    define SQLITE_ENABLE_LOCKING_STYLE 1 |  | 
|  4637 #  else |  | 
|  4638 #    define SQLITE_ENABLE_LOCKING_STYLE 0 |  | 
|  4639 #  endif |  | 
|  4640 #endif |  | 
|  4641 #if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) |  | 
|  4642   { |  | 
|  4643     char *proxyPath = "test.proxy"; |  | 
|  4644     char *testPath; |  | 
|  4645     int rc; |  | 
|  4646     rc = sqlite3_file_control(db, NULL, SQLITE_SET_LOCKPROXYFILE, proxyPath); |  | 
|  4647     if( rc ){ |  | 
|  4648       Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));  |  | 
|  4649       return TCL_ERROR; |  | 
|  4650     } |  | 
|  4651     rc = sqlite3_file_control(db, NULL, SQLITE_GET_LOCKPROXYFILE, &testPath); |  | 
|  4652     if( strncmp(proxyPath,testPath,11) ){ |  | 
|  4653       Tcl_AppendResult(interp, "Lock proxy file did not match the " |  | 
|  4654                                "previously assigned value", 0); |  | 
|  4655       return TCL_ERROR; |  | 
|  4656     } |  | 
|  4657     if( rc ){ |  | 
|  4658       Tcl_SetObjResult(interp, Tcl_NewIntObj(rc)); |  | 
|  4659       return TCL_ERROR; |  | 
|  4660     } |  | 
|  4661     rc = sqlite3_file_control(db, NULL, SQLITE_SET_LOCKPROXYFILE, proxyPath); |  | 
|  4662     if( rc ){ |  | 
|  4663       Tcl_SetObjResult(interp, Tcl_NewIntObj(rc)); |  | 
|  4664       return TCL_ERROR; |  | 
|  4665     } |  | 
|  4666   } |  | 
|  4667 #endif |  | 
|  4668   return TCL_OK;   |  | 
|  4669 } |  | 
|  4670  |  | 
|  4671  |  | 
|  4672 /* |  | 
|  4673 ** tclcmd:   sqlite3_vfs_list |  | 
|  4674 ** |  | 
|  4675 **   Return a tcl list containing the names of all registered vfs's. |  | 
|  4676 */ |  | 
|  4677 static int vfs_list( |  | 
|  4678   ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ |  | 
|  4679   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ |  | 
|  4680   int objc,              /* Number of arguments */ |  | 
|  4681   Tcl_Obj *CONST objv[]  /* Command arguments */ |  | 
|  4682 ){ |  | 
|  4683   sqlite3_vfs *pVfs; |  | 
|  4684   Tcl_Obj *pRet = Tcl_NewObj(); |  | 
|  4685   if( objc!=1 ){ |  | 
|  4686     Tcl_WrongNumArgs(interp, 1, objv, ""); |  | 
|  4687     return TCL_ERROR; |  | 
|  4688   } |  | 
|  4689   for(pVfs=sqlite3_vfs_find(0); pVfs; pVfs=pVfs->pNext){ |  | 
|  4690     Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj(pVfs->zName, -1)); |  | 
|  4691   } |  | 
|  4692   Tcl_SetObjResult(interp, pRet); |  | 
|  4693   return TCL_OK;   |  | 
|  4694 } |  | 
|  4695  |  | 
|  4696 /* |  | 
|  4697 ** tclcmd:   sqlite3_limit DB ID VALUE |  | 
|  4698 ** |  | 
|  4699 ** This TCL command runs the sqlite3_limit interface and |  | 
|  4700 ** verifies correct operation of the same. |  | 
|  4701 */ |  | 
|  4702 static int test_limit( |  | 
|  4703   ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ |  | 
|  4704   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ |  | 
|  4705   int objc,              /* Number of arguments */ |  | 
|  4706   Tcl_Obj *CONST objv[]  /* Command arguments */ |  | 
|  4707 ){ |  | 
|  4708   sqlite3 *db; |  | 
|  4709   int rc; |  | 
|  4710   static const struct { |  | 
|  4711      char *zName; |  | 
|  4712      int id; |  | 
|  4713   } aId[] = { |  | 
|  4714     { "SQLITE_LIMIT_LENGTH",              SQLITE_LIMIT_LENGTH               }, |  | 
|  4715     { "SQLITE_LIMIT_SQL_LENGTH",          SQLITE_LIMIT_SQL_LENGTH           }, |  | 
|  4716     { "SQLITE_LIMIT_COLUMN",              SQLITE_LIMIT_COLUMN               }, |  | 
|  4717     { "SQLITE_LIMIT_EXPR_DEPTH",          SQLITE_LIMIT_EXPR_DEPTH           }, |  | 
|  4718     { "SQLITE_LIMIT_COMPOUND_SELECT",     SQLITE_LIMIT_COMPOUND_SELECT      }, |  | 
|  4719     { "SQLITE_LIMIT_VDBE_OP",             SQLITE_LIMIT_VDBE_OP              }, |  | 
|  4720     { "SQLITE_LIMIT_FUNCTION_ARG",        SQLITE_LIMIT_FUNCTION_ARG         }, |  | 
|  4721     { "SQLITE_LIMIT_ATTACHED",            SQLITE_LIMIT_ATTACHED             }, |  | 
|  4722     { "SQLITE_LIMIT_LIKE_PATTERN_LENGTH", SQLITE_LIMIT_LIKE_PATTERN_LENGTH  }, |  | 
|  4723     { "SQLITE_LIMIT_VARIABLE_NUMBER",     SQLITE_LIMIT_VARIABLE_NUMBER      }, |  | 
|  4724     { "SQLITE_LIMIT_TRIGGER_DEPTH",       SQLITE_LIMIT_TRIGGER_DEPTH        }, |  | 
|  4725      |  | 
|  4726     /* Out of range test cases */ |  | 
|  4727     { "SQLITE_LIMIT_TOOSMALL",            -1,                               }, |  | 
|  4728     { "SQLITE_LIMIT_TOOBIG",              SQLITE_LIMIT_TRIGGER_DEPTH+1      }, |  | 
|  4729   }; |  | 
|  4730   int i, id; |  | 
|  4731   int val; |  | 
|  4732   const char *zId; |  | 
|  4733  |  | 
|  4734   if( objc!=4 ){ |  | 
|  4735     Tcl_AppendResult(interp, "wrong # args: should be \"", |  | 
|  4736         Tcl_GetStringFromObj(objv[0], 0), " DB ID VALUE", 0); |  | 
|  4737     return TCL_ERROR; |  | 
|  4738   } |  | 
|  4739   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; |  | 
|  4740   zId = Tcl_GetString(objv[2]); |  | 
|  4741   for(i=0; i<sizeof(aId)/sizeof(aId[0]); i++){ |  | 
|  4742     if( strcmp(zId, aId[i].zName)==0 ){ |  | 
|  4743       id = aId[i].id; |  | 
|  4744       break; |  | 
|  4745     } |  | 
|  4746   } |  | 
|  4747   if( i>=sizeof(aId)/sizeof(aId[0]) ){ |  | 
|  4748     Tcl_AppendResult(interp, "unknown limit type: ", zId, (char*)0); |  | 
|  4749     return TCL_ERROR; |  | 
|  4750   } |  | 
|  4751   if( Tcl_GetIntFromObj(interp, objv[3], &val) ) return TCL_ERROR; |  | 
|  4752   rc = sqlite3_limit(db, id, val); |  | 
|  4753   Tcl_SetObjResult(interp, Tcl_NewIntObj(rc)); |  | 
|  4754   return TCL_OK;   |  | 
|  4755 } |  | 
|  4756  |  | 
|  4757 /* |  | 
|  4758 ** tclcmd:  save_prng_state |  | 
|  4759 ** |  | 
|  4760 ** Save the state of the pseudo-random number generator. |  | 
|  4761 ** At the same time, verify that sqlite3_test_control works even when |  | 
|  4762 ** called with an out-of-range opcode. |  | 
|  4763 */ |  | 
|  4764 static int save_prng_state( |  | 
|  4765   ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ |  | 
|  4766   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ |  | 
|  4767   int objc,              /* Number of arguments */ |  | 
|  4768   Tcl_Obj *CONST objv[]  /* Command arguments */ |  | 
|  4769 ){ |  | 
|  4770   int rc = sqlite3_test_control(9999); |  | 
|  4771   assert( rc==0 ); |  | 
|  4772   rc = sqlite3_test_control(-1); |  | 
|  4773   assert( rc==0 ); |  | 
|  4774   sqlite3_test_control(SQLITE_TESTCTRL_PRNG_SAVE); |  | 
|  4775   return TCL_OK; |  | 
|  4776 } |  | 
|  4777 /* |  | 
|  4778 ** tclcmd:  restore_prng_state |  | 
|  4779 */ |  | 
|  4780 static int restore_prng_state( |  | 
|  4781   ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ |  | 
|  4782   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ |  | 
|  4783   int objc,              /* Number of arguments */ |  | 
|  4784   Tcl_Obj *CONST objv[]  /* Command arguments */ |  | 
|  4785 ){ |  | 
|  4786   sqlite3_test_control(SQLITE_TESTCTRL_PRNG_RESTORE); |  | 
|  4787   return TCL_OK; |  | 
|  4788 } |  | 
|  4789 /* |  | 
|  4790 ** tclcmd:  reset_prng_state |  | 
|  4791 */ |  | 
|  4792 static int reset_prng_state( |  | 
|  4793   ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ |  | 
|  4794   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ |  | 
|  4795   int objc,              /* Number of arguments */ |  | 
|  4796   Tcl_Obj *CONST objv[]  /* Command arguments */ |  | 
|  4797 ){ |  | 
|  4798   sqlite3_test_control(SQLITE_TESTCTRL_PRNG_RESET); |  | 
|  4799   return TCL_OK; |  | 
|  4800 } |  | 
|  4801  |  | 
|  4802 /* |  | 
|  4803 ** tclcmd:  pcache_stats |  | 
|  4804 */ |  | 
|  4805 static int test_pcache_stats( |  | 
|  4806   ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ |  | 
|  4807   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ |  | 
|  4808   int objc,              /* Number of arguments */ |  | 
|  4809   Tcl_Obj *CONST objv[]  /* Command arguments */ |  | 
|  4810 ){ |  | 
|  4811   int nMin; |  | 
|  4812   int nMax; |  | 
|  4813   int nCurrent; |  | 
|  4814   int nRecyclable; |  | 
|  4815   Tcl_Obj *pRet; |  | 
|  4816  |  | 
|  4817   sqlite3PcacheStats(&nCurrent, &nMax, &nMin, &nRecyclable); |  | 
|  4818  |  | 
|  4819   pRet = Tcl_NewObj(); |  | 
|  4820   Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj("current", -1)); |  | 
|  4821   Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(nCurrent)); |  | 
|  4822   Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj("max", -1)); |  | 
|  4823   Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(nMax)); |  | 
|  4824   Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj("min", -1)); |  | 
|  4825   Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(nMin)); |  | 
|  4826   Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj("recyclable", -1)); |  | 
|  4827   Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(nRecyclable)); |  | 
|  4828  |  | 
|  4829   Tcl_SetObjResult(interp, pRet); |  | 
|  4830  |  | 
|  4831   return TCL_OK; |  | 
|  4832 } |  | 
|  4833  |  | 
|  4834 #ifdef SQLITE_ENABLE_UNLOCK_NOTIFY |  | 
|  4835 static void test_unlock_notify_cb(void **aArg, int nArg){ |  | 
|  4836   int ii; |  | 
|  4837   for(ii=0; ii<nArg; ii++){ |  | 
|  4838     Tcl_EvalEx((Tcl_Interp *)aArg[ii], "unlock_notify", -1, TCL_EVAL_GLOBAL); |  | 
|  4839   } |  | 
|  4840 } |  | 
|  4841 #endif /* SQLITE_ENABLE_UNLOCK_NOTIFY */ |  | 
|  4842  |  | 
|  4843 /* |  | 
|  4844 ** tclcmd:  sqlite3_unlock_notify db |  | 
|  4845 */ |  | 
|  4846 #ifdef SQLITE_ENABLE_UNLOCK_NOTIFY |  | 
|  4847 static int test_unlock_notify( |  | 
|  4848   ClientData clientData, /* Unused */ |  | 
|  4849   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ |  | 
|  4850   int objc,              /* Number of arguments */ |  | 
|  4851   Tcl_Obj *CONST objv[]  /* Command arguments */ |  | 
|  4852 ){ |  | 
|  4853   sqlite3 *db; |  | 
|  4854   int rc; |  | 
|  4855  |  | 
|  4856   if( objc!=2 ){ |  | 
|  4857     Tcl_WrongNumArgs(interp, 1, objv, "DB"); |  | 
|  4858     return TCL_ERROR; |  | 
|  4859   } |  | 
|  4860  |  | 
|  4861   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){ |  | 
|  4862     return TCL_ERROR; |  | 
|  4863   } |  | 
|  4864   rc = sqlite3_unlock_notify(db, test_unlock_notify_cb, (void *)interp); |  | 
|  4865   Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC); |  | 
|  4866   return TCL_OK; |  | 
|  4867 } |  | 
|  4868 #endif |  | 
|  4869  |  | 
|  4870  |  | 
|  4871 /* |  | 
|  4872 ** Register commands with the TCL interpreter. |  | 
|  4873 */ |  | 
|  4874 int Sqlitetest1_Init(Tcl_Interp *interp){ |  | 
|  4875   extern int sqlite3_search_count; |  | 
|  4876   extern int sqlite3_interrupt_count; |  | 
|  4877   extern int sqlite3_open_file_count; |  | 
|  4878   extern int sqlite3_sort_count; |  | 
|  4879   extern int sqlite3_current_time; |  | 
|  4880 #if SQLITE_OS_UNIX && defined(__APPLE__) |  | 
|  4881   extern int sqlite3_hostid_num; |  | 
|  4882 #endif |  | 
|  4883   extern int sqlite3_max_blobsize; |  | 
|  4884   extern int sqlite3BtreeSharedCacheReport(void*, |  | 
|  4885                                           Tcl_Interp*,int,Tcl_Obj*CONST*); |  | 
|  4886   static struct { |  | 
|  4887      char *zName; |  | 
|  4888      Tcl_CmdProc *xProc; |  | 
|  4889   } aCmd[] = { |  | 
|  4890      { "db_enter",                      (Tcl_CmdProc*)db_enter               }, |  | 
|  4891      { "db_leave",                      (Tcl_CmdProc*)db_leave               }, |  | 
|  4892      { "sqlite3_mprintf_int",           (Tcl_CmdProc*)sqlite3_mprintf_int    }, |  | 
|  4893      { "sqlite3_mprintf_int64",         (Tcl_CmdProc*)sqlite3_mprintf_int64  }, |  | 
|  4894      { "sqlite3_mprintf_long",          (Tcl_CmdProc*)sqlite3_mprintf_long   }, |  | 
|  4895      { "sqlite3_mprintf_str",           (Tcl_CmdProc*)sqlite3_mprintf_str    }, |  | 
|  4896      { "sqlite3_snprintf_str",          (Tcl_CmdProc*)sqlite3_snprintf_str   }, |  | 
|  4897      { "sqlite3_mprintf_stronly",       (Tcl_CmdProc*)sqlite3_mprintf_stronly}, |  | 
|  4898      { "sqlite3_mprintf_double",        (Tcl_CmdProc*)sqlite3_mprintf_double }, |  | 
|  4899      { "sqlite3_mprintf_scaled",        (Tcl_CmdProc*)sqlite3_mprintf_scaled }, |  | 
|  4900      { "sqlite3_mprintf_hexdouble",   (Tcl_CmdProc*)sqlite3_mprintf_hexdouble}, |  | 
|  4901      { "sqlite3_mprintf_z_test",        (Tcl_CmdProc*)test_mprintf_z        }, |  | 
|  4902      { "sqlite3_mprintf_n_test",        (Tcl_CmdProc*)test_mprintf_n        }, |  | 
|  4903      { "sqlite3_snprintf_int",          (Tcl_CmdProc*)test_snprintf_int     }, |  | 
|  4904      { "sqlite3_last_insert_rowid",     (Tcl_CmdProc*)test_last_rowid       }, |  | 
|  4905      { "sqlite3_exec_printf",           (Tcl_CmdProc*)test_exec_printf      }, |  | 
|  4906      { "sqlite3_exec_hex",              (Tcl_CmdProc*)test_exec_hex         }, |  | 
|  4907      { "sqlite3_exec",                  (Tcl_CmdProc*)test_exec             }, |  | 
|  4908      { "sqlite3_exec_nr",               (Tcl_CmdProc*)test_exec_nr          }, |  | 
|  4909 #ifndef SQLITE_OMIT_GET_TABLE |  | 
|  4910      { "sqlite3_get_table_printf",      (Tcl_CmdProc*)test_get_table_printf }, |  | 
|  4911 #endif |  | 
|  4912      { "sqlite3_close",                 (Tcl_CmdProc*)sqlite_test_close     }, |  | 
|  4913      { "sqlite3_create_function",       (Tcl_CmdProc*)test_create_function  }, |  | 
|  4914      { "sqlite3_create_aggregate",      (Tcl_CmdProc*)test_create_aggregate }, |  | 
|  4915      { "sqlite_register_test_function", (Tcl_CmdProc*)test_register_func    }, |  | 
|  4916      { "sqlite_abort",                  (Tcl_CmdProc*)sqlite_abort          }, |  | 
|  4917      { "sqlite_bind",                   (Tcl_CmdProc*)test_bind             }, |  | 
|  4918      { "breakpoint",                    (Tcl_CmdProc*)test_breakpoint       }, |  | 
|  4919      { "sqlite3_key",                   (Tcl_CmdProc*)test_key              }, |  | 
|  4920      { "sqlite3_rekey",                 (Tcl_CmdProc*)test_rekey            }, |  | 
|  4921      { "sqlite_set_magic",              (Tcl_CmdProc*)sqlite_set_magic      }, |  | 
|  4922      { "sqlite3_interrupt",             (Tcl_CmdProc*)test_interrupt        }, |  | 
|  4923      { "sqlite_delete_function",        (Tcl_CmdProc*)delete_function       }, |  | 
|  4924      { "sqlite_delete_collation",       (Tcl_CmdProc*)delete_collation      }, |  | 
|  4925      { "sqlite3_get_autocommit",        (Tcl_CmdProc*)get_autocommit        }, |  | 
|  4926      { "sqlite3_stack_used",            (Tcl_CmdProc*)test_stack_used       }, |  | 
|  4927      { "sqlite3_busy_timeout",          (Tcl_CmdProc*)test_busy_timeout     }, |  | 
|  4928      { "printf",                        (Tcl_CmdProc*)test_printf           }, |  | 
|  4929      { "sqlite3IoTrace",              (Tcl_CmdProc*)test_io_trace         }, |  | 
|  4930   }; |  | 
|  4931   static struct { |  | 
|  4932      char *zName; |  | 
|  4933      Tcl_ObjCmdProc *xProc; |  | 
|  4934      void *clientData; |  | 
|  4935   } aObjCmd[] = { |  | 
|  4936      { "sqlite3_connection_pointer",    get_sqlite_pointer, 0 }, |  | 
|  4937      { "sqlite3_bind_int",              test_bind_int,      0 }, |  | 
|  4938      { "sqlite3_bind_zeroblob",         test_bind_zeroblob, 0 }, |  | 
|  4939      { "sqlite3_bind_int64",            test_bind_int64,    0 }, |  | 
|  4940      { "sqlite3_bind_double",           test_bind_double,   0 }, |  | 
|  4941      { "sqlite3_bind_null",             test_bind_null     ,0 }, |  | 
|  4942      { "sqlite3_bind_text",             test_bind_text     ,0 }, |  | 
|  4943      { "sqlite3_bind_text16",           test_bind_text16   ,0 }, |  | 
|  4944      { "sqlite3_bind_blob",             test_bind_blob     ,0 }, |  | 
|  4945      { "sqlite3_bind_parameter_count",  test_bind_parameter_count, 0}, |  | 
|  4946      { "sqlite3_bind_parameter_name",   test_bind_parameter_name,  0}, |  | 
|  4947      { "sqlite3_bind_parameter_index",  test_bind_parameter_index, 0}, |  | 
|  4948      { "sqlite3_clear_bindings",        test_clear_bindings, 0}, |  | 
|  4949      { "sqlite3_sleep",                 test_sleep,          0}, |  | 
|  4950      { "sqlite3_errcode",               test_errcode       ,0 }, |  | 
|  4951      { "sqlite3_extended_errcode",      test_ex_errcode    ,0 }, |  | 
|  4952      { "sqlite3_errmsg",                test_errmsg        ,0 }, |  | 
|  4953      { "sqlite3_errmsg16",              test_errmsg16      ,0 }, |  | 
|  4954      { "sqlite3_open",                  test_open          ,0 }, |  | 
|  4955      { "sqlite3_open16",                test_open16        ,0 }, |  | 
|  4956      { "sqlite3_complete16",            test_complete16    ,0 }, |  | 
|  4957  |  | 
|  4958      { "sqlite3_prepare",               test_prepare       ,0 }, |  | 
|  4959      { "sqlite3_prepare16",             test_prepare16     ,0 }, |  | 
|  4960      { "sqlite3_prepare_v2",            test_prepare_v2    ,0 }, |  | 
|  4961      { "sqlite3_prepare_tkt3134",       test_prepare_tkt3134, 0}, |  | 
|  4962      { "sqlite3_prepare16_v2",          test_prepare16_v2  ,0 }, |  | 
|  4963      { "sqlite3_finalize",              test_finalize      ,0 }, |  | 
|  4964      { "sqlite3_stmt_status",           test_stmt_status   ,0 }, |  | 
|  4965      { "sqlite3_reset",                 test_reset         ,0 }, |  | 
|  4966      { "sqlite3_expired",               test_expired       ,0 }, |  | 
|  4967      { "sqlite3_transfer_bindings",     test_transfer_bind ,0 }, |  | 
|  4968      { "sqlite3_changes",               test_changes       ,0 }, |  | 
|  4969      { "sqlite3_step",                  test_step          ,0 }, |  | 
|  4970      { "sqlite3_sql",                   test_sql           ,0 }, |  | 
|  4971      { "sqlite3_next_stmt",             test_next_stmt     ,0 }, |  | 
|  4972  |  | 
|  4973      { "sqlite3_release_memory",        test_release_memory,     0}, |  | 
|  4974      { "sqlite3_soft_heap_limit",       test_soft_heap_limit,    0}, |  | 
|  4975      { "sqlite3_thread_cleanup",        test_thread_cleanup,     0}, |  | 
|  4976      { "sqlite3_pager_refcounts",       test_pager_refcounts,    0}, |  | 
|  4977  |  | 
|  4978      { "sqlite3_load_extension",        test_load_extension,     0}, |  | 
|  4979      { "sqlite3_enable_load_extension", test_enable_load,        0}, |  | 
|  4980      { "sqlite3_extended_result_codes", test_extended_result_codes, 0}, |  | 
|  4981      { "sqlite3_limit",                 test_limit,                 0}, |  | 
|  4982  |  | 
|  4983      { "save_prng_state",               save_prng_state,    0 }, |  | 
|  4984      { "restore_prng_state",            restore_prng_state, 0 }, |  | 
|  4985      { "reset_prng_state",              reset_prng_state,   0 }, |  | 
|  4986  |  | 
|  4987      /* sqlite3_column_*() API */ |  | 
|  4988      { "sqlite3_column_count",          test_column_count  ,0 }, |  | 
|  4989      { "sqlite3_data_count",            test_data_count    ,0 }, |  | 
|  4990      { "sqlite3_column_type",           test_column_type   ,0 }, |  | 
|  4991      { "sqlite3_column_blob",           test_column_blob   ,0 }, |  | 
|  4992      { "sqlite3_column_double",         test_column_double ,0 }, |  | 
|  4993      { "sqlite3_column_int64",          test_column_int64  ,0 }, |  | 
|  4994      { "sqlite3_column_text",   test_stmt_utf8,  (void*)sqlite3_column_text }, |  | 
|  4995      { "sqlite3_column_name",   test_stmt_utf8,  (void*)sqlite3_column_name }, |  | 
|  4996      { "sqlite3_column_int",    test_stmt_int,   (void*)sqlite3_column_int  }, |  | 
|  4997      { "sqlite3_column_bytes",  test_stmt_int,   (void*)sqlite3_column_bytes}, |  | 
|  4998 #ifndef SQLITE_OMIT_DECLTYPE |  | 
|  4999      { "sqlite3_column_decltype",test_stmt_utf8,(void*)sqlite3_column_decltype}, |  | 
|  5000 #endif |  | 
|  5001 #ifdef SQLITE_ENABLE_COLUMN_METADATA |  | 
|  5002 { "sqlite3_column_database_name",test_stmt_utf8,(void*)sqlite3_column_database_n
      ame}, |  | 
|  5003 { "sqlite3_column_table_name",test_stmt_utf8,(void*)sqlite3_column_table_name}, |  | 
|  5004 { "sqlite3_column_origin_name",test_stmt_utf8,(void*)sqlite3_column_origin_name}
      , |  | 
|  5005 #endif |  | 
|  5006  |  | 
|  5007 #ifndef SQLITE_OMIT_UTF16 |  | 
|  5008      { "sqlite3_column_bytes16", test_stmt_int, (void*)sqlite3_column_bytes16 }, |  | 
|  5009      { "sqlite3_column_text16",  test_stmt_utf16, (void*)sqlite3_column_text16}, |  | 
|  5010      { "sqlite3_column_name16",  test_stmt_utf16, (void*)sqlite3_column_name16}, |  | 
|  5011      { "add_alignment_test_collations", add_alignment_test_collations, 0      }, |  | 
|  5012 #ifndef SQLITE_OMIT_DECLTYPE |  | 
|  5013      { "sqlite3_column_decltype16",test_stmt_utf16,(void*)sqlite3_column_decltyp
      e16}, |  | 
|  5014 #endif |  | 
|  5015 #ifdef SQLITE_ENABLE_COLUMN_METADATA |  | 
|  5016 {"sqlite3_column_database_name16", |  | 
|  5017   test_stmt_utf16, sqlite3_column_database_name16}, |  | 
|  5018 {"sqlite3_column_table_name16", test_stmt_utf16, (void*)sqlite3_column_table_nam
      e16}, |  | 
|  5019 {"sqlite3_column_origin_name16", test_stmt_utf16, (void*)sqlite3_column_origin_n
      ame16}, |  | 
|  5020 #endif |  | 
|  5021 #endif |  | 
|  5022      { "sqlite3_create_collation_v2", test_create_collation_v2, 0 }, |  | 
|  5023      { "sqlite3_global_recover",     test_global_recover, 0   }, |  | 
|  5024      { "working_64bit_int",          working_64bit_int,   0   }, |  | 
|  5025      { "vfs_unlink_test",            vfs_unlink_test,     0   }, |  | 
|  5026      { "vfs_initfail_test",          vfs_initfail_test,   0   }, |  | 
|  5027      { "vfs_unregister_all",         vfs_unregister_all,  0   }, |  | 
|  5028      { "vfs_reregister_all",         vfs_reregister_all,  0   }, |  | 
|  5029      { "file_control_test",          file_control_test,   0   }, |  | 
|  5030      { "file_control_lasterrno_test", file_control_lasterrno_test,  0   }, |  | 
|  5031      { "file_control_lockproxy_test", file_control_lockproxy_test,  0   }, |  | 
|  5032      { "sqlite3_vfs_list",           vfs_list,     0   }, |  | 
|  5033  |  | 
|  5034      /* Functions from os.h */ |  | 
|  5035 #ifndef SQLITE_OMIT_UTF16 |  | 
|  5036      { "add_test_collate",        test_collate, 0            }, |  | 
|  5037      { "add_test_collate_needed", test_collate_needed, 0     }, |  | 
|  5038      { "add_test_function",       test_function, 0           }, |  | 
|  5039 #endif |  | 
|  5040      { "sqlite3_test_errstr",     test_errstr, 0             }, |  | 
|  5041      { "tcl_variable_type",       tcl_variable_type, 0       }, |  | 
|  5042 #ifndef SQLITE_OMIT_SHARED_CACHE |  | 
|  5043      { "sqlite3_enable_shared_cache", test_enable_shared, 0  }, |  | 
|  5044      { "sqlite3_shared_cache_report", sqlite3BtreeSharedCacheReport, 0}, |  | 
|  5045 #endif |  | 
|  5046      { "sqlite3_libversion_number", test_libversion_number, 0  }, |  | 
|  5047 #ifdef SQLITE_ENABLE_COLUMN_METADATA |  | 
|  5048      { "sqlite3_table_column_metadata", test_table_column_metadata, 0  }, |  | 
|  5049 #endif |  | 
|  5050 #ifndef SQLITE_OMIT_INCRBLOB |  | 
|  5051      { "sqlite3_blob_read",  test_blob_read, 0  }, |  | 
|  5052      { "sqlite3_blob_write", test_blob_write, 0  }, |  | 
|  5053 #endif |  | 
|  5054      { "pcache_stats",       test_pcache_stats, 0  }, |  | 
|  5055 #ifdef SQLITE_ENABLE_UNLOCK_NOTIFY |  | 
|  5056      { "sqlite3_unlock_notify", test_unlock_notify, 0  }, |  | 
|  5057 #endif |  | 
|  5058   }; |  | 
|  5059   static int bitmask_size = sizeof(Bitmask)*8; |  | 
|  5060   int i; |  | 
|  5061   extern int sqlite3_sync_count, sqlite3_fullsync_count; |  | 
|  5062   extern int sqlite3_opentemp_count; |  | 
|  5063   extern int sqlite3_like_count; |  | 
|  5064   extern int sqlite3_xferopt_count; |  | 
|  5065   extern int sqlite3_pager_readdb_count; |  | 
|  5066   extern int sqlite3_pager_writedb_count; |  | 
|  5067   extern int sqlite3_pager_writej_count; |  | 
|  5068 #if defined(__linux__) && defined(SQLITE_TEST) && SQLITE_THREADSAFE |  | 
|  5069   extern int threadsOverrideEachOthersLocks; |  | 
|  5070 #endif |  | 
|  5071 #if SQLITE_OS_WIN |  | 
|  5072   extern int sqlite3_os_type; |  | 
|  5073 #endif |  | 
|  5074 #ifdef SQLITE_DEBUG |  | 
|  5075   extern int sqlite3WhereTrace; |  | 
|  5076   extern int sqlite3OSTrace; |  | 
|  5077   extern int sqlite3VdbeAddopTrace; |  | 
|  5078 #endif |  | 
|  5079 #ifdef SQLITE_TEST |  | 
|  5080   extern char sqlite3_query_plan[]; |  | 
|  5081   static char *query_plan = sqlite3_query_plan; |  | 
|  5082 #ifdef SQLITE_ENABLE_FTS3 |  | 
|  5083   extern int sqlite3_fts3_enable_parentheses; |  | 
|  5084 #endif |  | 
|  5085 #endif |  | 
|  5086  |  | 
|  5087   for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){ |  | 
|  5088     Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0); |  | 
|  5089   } |  | 
|  5090   for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){ |  | 
|  5091     Tcl_CreateObjCommand(interp, aObjCmd[i].zName,  |  | 
|  5092         aObjCmd[i].xProc, aObjCmd[i].clientData, 0); |  | 
|  5093   } |  | 
|  5094   Tcl_LinkVar(interp, "sqlite_search_count",  |  | 
|  5095       (char*)&sqlite3_search_count, TCL_LINK_INT); |  | 
|  5096   Tcl_LinkVar(interp, "sqlite_sort_count",  |  | 
|  5097       (char*)&sqlite3_sort_count, TCL_LINK_INT); |  | 
|  5098   Tcl_LinkVar(interp, "sqlite3_max_blobsize",  |  | 
|  5099       (char*)&sqlite3_max_blobsize, TCL_LINK_INT); |  | 
|  5100   Tcl_LinkVar(interp, "sqlite_like_count",  |  | 
|  5101       (char*)&sqlite3_like_count, TCL_LINK_INT); |  | 
|  5102   Tcl_LinkVar(interp, "sqlite_interrupt_count",  |  | 
|  5103       (char*)&sqlite3_interrupt_count, TCL_LINK_INT); |  | 
|  5104   Tcl_LinkVar(interp, "sqlite_open_file_count",  |  | 
|  5105       (char*)&sqlite3_open_file_count, TCL_LINK_INT); |  | 
|  5106   Tcl_LinkVar(interp, "sqlite_current_time",  |  | 
|  5107       (char*)&sqlite3_current_time, TCL_LINK_INT); |  | 
|  5108 #if SQLITE_OS_UNIX && defined(__APPLE__) |  | 
|  5109   Tcl_LinkVar(interp, "sqlite_hostid_num",  |  | 
|  5110       (char*)&sqlite3_hostid_num, TCL_LINK_INT); |  | 
|  5111 #endif |  | 
|  5112   Tcl_LinkVar(interp, "sqlite3_xferopt_count", |  | 
|  5113       (char*)&sqlite3_xferopt_count, TCL_LINK_INT); |  | 
|  5114   Tcl_LinkVar(interp, "sqlite3_pager_readdb_count", |  | 
|  5115       (char*)&sqlite3_pager_readdb_count, TCL_LINK_INT); |  | 
|  5116   Tcl_LinkVar(interp, "sqlite3_pager_writedb_count", |  | 
|  5117       (char*)&sqlite3_pager_writedb_count, TCL_LINK_INT); |  | 
|  5118   Tcl_LinkVar(interp, "sqlite3_pager_writej_count", |  | 
|  5119       (char*)&sqlite3_pager_writej_count, TCL_LINK_INT); |  | 
|  5120 #ifndef SQLITE_OMIT_UTF16 |  | 
|  5121   Tcl_LinkVar(interp, "unaligned_string_counter", |  | 
|  5122       (char*)&unaligned_string_counter, TCL_LINK_INT); |  | 
|  5123 #endif |  | 
|  5124 #if defined(__linux__) && defined(SQLITE_TEST) && SQLITE_THREADSAFE |  | 
|  5125   Tcl_LinkVar(interp, "threadsOverrideEachOthersLocks", |  | 
|  5126       (char*)&threadsOverrideEachOthersLocks, TCL_LINK_INT); |  | 
|  5127 #endif |  | 
|  5128 #ifndef SQLITE_OMIT_UTF16 |  | 
|  5129   Tcl_LinkVar(interp, "sqlite_last_needed_collation", |  | 
|  5130       (char*)&pzNeededCollation, TCL_LINK_STRING|TCL_LINK_READ_ONLY); |  | 
|  5131 #endif |  | 
|  5132 #if SQLITE_OS_WIN |  | 
|  5133   Tcl_LinkVar(interp, "sqlite_os_type", |  | 
|  5134       (char*)&sqlite3_os_type, TCL_LINK_INT); |  | 
|  5135 #endif |  | 
|  5136 #ifdef SQLITE_TEST |  | 
|  5137   Tcl_LinkVar(interp, "sqlite_query_plan", |  | 
|  5138       (char*)&query_plan, TCL_LINK_STRING|TCL_LINK_READ_ONLY); |  | 
|  5139 #endif |  | 
|  5140 #ifdef SQLITE_DEBUG |  | 
|  5141   Tcl_LinkVar(interp, "sqlite_addop_trace", |  | 
|  5142       (char*)&sqlite3VdbeAddopTrace, TCL_LINK_INT); |  | 
|  5143   Tcl_LinkVar(interp, "sqlite_where_trace", |  | 
|  5144       (char*)&sqlite3WhereTrace, TCL_LINK_INT); |  | 
|  5145   Tcl_LinkVar(interp, "sqlite_os_trace", |  | 
|  5146       (char*)&sqlite3OSTrace, TCL_LINK_INT); |  | 
|  5147 #endif |  | 
|  5148 #ifndef SQLITE_OMIT_DISKIO |  | 
|  5149   Tcl_LinkVar(interp, "sqlite_opentemp_count", |  | 
|  5150       (char*)&sqlite3_opentemp_count, TCL_LINK_INT); |  | 
|  5151 #endif |  | 
|  5152   Tcl_LinkVar(interp, "sqlite_static_bind_value", |  | 
|  5153       (char*)&sqlite_static_bind_value, TCL_LINK_STRING); |  | 
|  5154   Tcl_LinkVar(interp, "sqlite_static_bind_nbyte", |  | 
|  5155       (char*)&sqlite_static_bind_nbyte, TCL_LINK_INT); |  | 
|  5156   Tcl_LinkVar(interp, "sqlite_temp_directory", |  | 
|  5157       (char*)&sqlite3_temp_directory, TCL_LINK_STRING); |  | 
|  5158   Tcl_LinkVar(interp, "bitmask_size", |  | 
|  5159       (char*)&bitmask_size, TCL_LINK_INT|TCL_LINK_READ_ONLY); |  | 
|  5160   Tcl_LinkVar(interp, "sqlite_sync_count", |  | 
|  5161       (char*)&sqlite3_sync_count, TCL_LINK_INT); |  | 
|  5162   Tcl_LinkVar(interp, "sqlite_fullsync_count", |  | 
|  5163       (char*)&sqlite3_fullsync_count, TCL_LINK_INT); |  | 
|  5164 #if defined(SQLITE_ENABLE_FTS3) && defined(SQLITE_TEST) |  | 
|  5165   Tcl_LinkVar(interp, "sqlite_fts3_enable_parentheses", |  | 
|  5166       (char*)&sqlite3_fts3_enable_parentheses, TCL_LINK_INT); |  | 
|  5167 #endif |  | 
|  5168   return TCL_OK; |  | 
|  5169 } |  | 
| OLD | NEW |