modernc.org/cc@v1.0.1/v2/testdata/_sqlite/src/test1.c (about)

     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  #include "sqliteInt.h"
    17  #if SQLITE_OS_WIN
    18  #  include "os_win.h"
    19  #endif
    20  
    21  #include "vdbeInt.h"
    22  #if defined(INCLUDE_SQLITE_TCL_H)
    23  #  include "sqlite_tcl.h"
    24  #else
    25  #  include "tcl.h"
    26  #endif
    27  #include <stdlib.h>
    28  #include <string.h>
    29  
    30  /*
    31  ** This is a copy of the first part of the SqliteDb structure in 
    32  ** tclsqlite.c.  We need it here so that the get_sqlite_pointer routine
    33  ** can extract the sqlite3* pointer from an existing Tcl SQLite
    34  ** connection.
    35  */
    36  struct SqliteDb {
    37    sqlite3 *db;
    38  };
    39  
    40  /*
    41  ** Convert text generated by the "%p" conversion format back into
    42  ** a pointer.
    43  */
    44  static int testHexToInt(int h){
    45    if( h>='0' && h<='9' ){
    46      return h - '0';
    47    }else if( h>='a' && h<='f' ){
    48      return h - 'a' + 10;
    49    }else{
    50      assert( h>='A' && h<='F' );
    51      return h - 'A' + 10;
    52    }
    53  }
    54  void *sqlite3TestTextToPtr(const char *z){
    55    void *p;
    56    u64 v;
    57    u32 v2;
    58    if( z[0]=='0' && z[1]=='x' ){
    59      z += 2;
    60    }
    61    v = 0;
    62    while( *z ){
    63      v = (v<<4) + testHexToInt(*z);
    64      z++;
    65    }
    66    if( sizeof(p)==sizeof(v) ){
    67      memcpy(&p, &v, sizeof(p));
    68    }else{
    69      assert( sizeof(p)==sizeof(v2) );
    70      v2 = (u32)v;
    71      memcpy(&p, &v2, sizeof(p));
    72    }
    73    return p;
    74  }
    75  
    76  
    77  /*
    78  ** A TCL command that returns the address of the sqlite* pointer
    79  ** for an sqlite connection instance.  Bad things happen if the
    80  ** input is not an sqlite connection.
    81  */
    82  static int SQLITE_TCLAPI get_sqlite_pointer(
    83    void * clientData,
    84    Tcl_Interp *interp,
    85    int objc,
    86    Tcl_Obj *CONST objv[]
    87  ){
    88    struct SqliteDb *p;
    89    Tcl_CmdInfo cmdInfo;
    90    char zBuf[100];
    91    if( objc!=2 ){
    92      Tcl_WrongNumArgs(interp, 1, objv, "SQLITE-CONNECTION");
    93      return TCL_ERROR;
    94    }
    95    if( !Tcl_GetCommandInfo(interp, Tcl_GetString(objv[1]), &cmdInfo) ){
    96      Tcl_AppendResult(interp, "command not found: ",
    97             Tcl_GetString(objv[1]), (char*)0);
    98      return TCL_ERROR;
    99    }
   100    p = (struct SqliteDb*)cmdInfo.objClientData;
   101    sqlite3_snprintf(sizeof(zBuf), zBuf, "%p", p->db);
   102    Tcl_AppendResult(interp, zBuf, 0);
   103    return TCL_OK;
   104  }
   105  
   106  /*
   107  ** Decode a pointer to an sqlite3 object.
   108  */
   109  int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb){
   110    struct SqliteDb *p;
   111    Tcl_CmdInfo cmdInfo;
   112    if( Tcl_GetCommandInfo(interp, zA, &cmdInfo) ){
   113      p = (struct SqliteDb*)cmdInfo.objClientData;
   114      *ppDb = p->db;
   115    }else{
   116      *ppDb = (sqlite3*)sqlite3TestTextToPtr(zA);
   117    }
   118    return TCL_OK;
   119  }
   120  
   121  #if SQLITE_OS_WIN
   122  /*
   123  ** Decode a Win32 HANDLE object.
   124  */
   125  int getWin32Handle(Tcl_Interp *interp, const char *zA, LPHANDLE phFile){
   126    *phFile = (HANDLE)sqlite3TestTextToPtr(zA);
   127    return TCL_OK;
   128  }
   129  #endif
   130  
   131  extern const char *sqlite3ErrName(int);
   132  #define t1ErrorName sqlite3ErrName
   133  
   134  /*
   135  ** Convert an sqlite3_stmt* into an sqlite3*.  This depends on the
   136  ** fact that the sqlite3* is the first field in the Vdbe structure.
   137  */
   138  #define StmtToDb(X)   sqlite3_db_handle(X)
   139  
   140  /*
   141  ** Check a return value to make sure it agrees with the results
   142  ** from sqlite3_errcode.
   143  */
   144  int sqlite3TestErrCode(Tcl_Interp *interp, sqlite3 *db, int rc){
   145    if( sqlite3_threadsafe()==0 && rc!=SQLITE_MISUSE && rc!=SQLITE_OK
   146     && sqlite3_errcode(db)!=rc ){
   147      char zBuf[200];
   148      int r2 = sqlite3_errcode(db);
   149      sqlite3_snprintf(sizeof(zBuf), zBuf,
   150         "error code %s (%d) does not match sqlite3_errcode %s (%d)",
   151         t1ErrorName(rc), rc, t1ErrorName(r2), r2);
   152      Tcl_ResetResult(interp);
   153      Tcl_AppendResult(interp, zBuf, 0);
   154      return 1;
   155    }
   156    return 0;
   157  }
   158  
   159  /*
   160  ** Decode a pointer to an sqlite3_stmt object.
   161  */
   162  static int getStmtPointer(
   163    Tcl_Interp *interp, 
   164    const char *zArg,  
   165    sqlite3_stmt **ppStmt
   166  ){
   167    *ppStmt = (sqlite3_stmt*)sqlite3TestTextToPtr(zArg);
   168    return TCL_OK;
   169  }
   170  
   171  /*
   172  ** Generate a text representation of a pointer that can be understood
   173  ** by the getDbPointer and getVmPointer routines above.
   174  **
   175  ** The problem is, on some machines (Solaris) if you do a printf with
   176  ** "%p" you cannot turn around and do a scanf with the same "%p" and
   177  ** get your pointer back.  You have to prepend a "0x" before it will
   178  ** work.  Or at least that is what is reported to me (drh).  But this
   179  ** behavior varies from machine to machine.  The solution used her is
   180  ** to test the string right after it is generated to see if it can be
   181  ** understood by scanf, and if not, try prepending an "0x" to see if
   182  ** that helps.  If nothing works, a fatal error is generated.
   183  */
   184  int sqlite3TestMakePointerStr(Tcl_Interp *interp, char *zPtr, void *p){
   185    sqlite3_snprintf(100, zPtr, "%p", p);
   186    return TCL_OK;
   187  }
   188  
   189  /*
   190  ** The callback routine for sqlite3_exec_printf().
   191  */
   192  static int exec_printf_cb(void *pArg, int argc, char **argv, char **name){
   193    Tcl_DString *str = (Tcl_DString*)pArg;
   194    int i;
   195  
   196    if( Tcl_DStringLength(str)==0 ){
   197      for(i=0; i<argc; i++){
   198        Tcl_DStringAppendElement(str, name[i] ? name[i] : "NULL");
   199      }
   200    }
   201    for(i=0; i<argc; i++){
   202      Tcl_DStringAppendElement(str, argv[i] ? argv[i] : "NULL");
   203    }
   204    return 0;
   205  }
   206  
   207  /*
   208  ** The I/O tracing callback.
   209  */
   210  #if !defined(SQLITE_OMIT_TRACE) && defined(SQLITE_ENABLE_IOTRACE)
   211  static FILE *iotrace_file = 0;
   212  static void io_trace_callback(const char *zFormat, ...){
   213    va_list ap;
   214    va_start(ap, zFormat);
   215    vfprintf(iotrace_file, zFormat, ap);
   216    va_end(ap);
   217    fflush(iotrace_file);
   218  }
   219  #endif
   220  
   221  /*
   222  ** Usage:  io_trace FILENAME
   223  **
   224  ** Turn I/O tracing on or off.  If FILENAME is not an empty string,
   225  ** I/O tracing begins going into FILENAME. If FILENAME is an empty
   226  ** string, I/O tracing is turned off.
   227  */
   228  static int SQLITE_TCLAPI test_io_trace(
   229    void *NotUsed,
   230    Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
   231    int argc,              /* Number of arguments */
   232    char **argv            /* Text of each argument */
   233  ){
   234  #if !defined(SQLITE_OMIT_TRACE) && defined(SQLITE_ENABLE_IOTRACE)
   235    if( argc!=2 ){
   236      Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
   237            " FILENAME\"", 0);
   238      return TCL_ERROR;
   239    }
   240    if( iotrace_file ){
   241      if( iotrace_file!=stdout && iotrace_file!=stderr ){
   242        fclose(iotrace_file);
   243      }
   244      iotrace_file = 0;
   245      sqlite3IoTrace = 0;
   246    }
   247    if( argv[1][0] ){
   248      if( strcmp(argv[1],"stdout")==0 ){
   249        iotrace_file = stdout;
   250      }else if( strcmp(argv[1],"stderr")==0 ){
   251        iotrace_file = stderr;
   252      }else{
   253        iotrace_file = fopen(argv[1], "w");
   254      }
   255      sqlite3IoTrace = io_trace_callback;
   256    }
   257  #endif
   258    return TCL_OK;
   259  }
   260  
   261  /*
   262  ** Usage:  clang_sanitize_address 
   263  **
   264  ** Returns true if the program was compiled using clang with the 
   265  ** -fsanitize=address switch on the command line. False otherwise.
   266  **
   267  ** Also return true if the OMIT_MISUSE environment variable exists.
   268  */
   269  static int SQLITE_TCLAPI clang_sanitize_address(
   270    void *NotUsed,
   271    Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
   272    int argc,              /* Number of arguments */
   273    char **argv            /* Text of each argument */
   274  ){
   275    int res = 0;
   276  #if defined(__has_feature)
   277  # if __has_feature(address_sanitizer)
   278    res = 1;
   279  # endif
   280  #endif
   281  #ifdef __SANITIZE_ADDRESS__
   282    res = 1;
   283  #endif
   284    if( res==0 && getenv("OMIT_MISUSE")!=0 ) res = 1;
   285    Tcl_SetObjResult(interp, Tcl_NewIntObj(res));
   286    return TCL_OK;
   287  }
   288    
   289  /*
   290  ** Usage:  sqlite3_exec_printf  DB  FORMAT  STRING
   291  **
   292  ** Invoke the sqlite3_exec_printf() interface using the open database
   293  ** DB.  The SQL is the string FORMAT.  The format string should contain
   294  ** one %s or %q.  STRING is the value inserted into %s or %q.
   295  */
   296  static int SQLITE_TCLAPI test_exec_printf(
   297    void *NotUsed,
   298    Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
   299    int argc,              /* Number of arguments */
   300    char **argv            /* Text of each argument */
   301  ){
   302    sqlite3 *db;
   303    Tcl_DString str;
   304    int rc;
   305    char *zErr = 0;
   306    char *zSql;
   307    char zBuf[30];
   308    if( argc!=4 ){
   309      Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 
   310         " DB FORMAT STRING", 0);
   311      return TCL_ERROR;
   312    }
   313    if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
   314    Tcl_DStringInit(&str);
   315    zSql = sqlite3_mprintf(argv[2], argv[3]);
   316    rc = sqlite3_exec(db, zSql, exec_printf_cb, &str, &zErr);
   317    sqlite3_free(zSql);
   318    sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", rc);
   319    Tcl_AppendElement(interp, zBuf);
   320    Tcl_AppendElement(interp, rc==SQLITE_OK ? Tcl_DStringValue(&str) : zErr);
   321    Tcl_DStringFree(&str);
   322    if( zErr ) sqlite3_free(zErr);
   323    if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
   324    return TCL_OK;
   325  }
   326  
   327  /*
   328  ** Usage:  sqlite3_exec_hex  DB  HEX
   329  **
   330  ** Invoke the sqlite3_exec() on a string that is obtained by translating
   331  ** HEX into ASCII.  Most characters are translated as is.  %HH becomes
   332  ** a hex character.
   333  */
   334  static int SQLITE_TCLAPI test_exec_hex(
   335    void *NotUsed,
   336    Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
   337    int argc,              /* Number of arguments */
   338    char **argv            /* Text of each argument */
   339  ){
   340    sqlite3 *db;
   341    Tcl_DString str;
   342    int rc, i, j;
   343    char *zErr = 0;
   344    char *zHex;
   345    char zSql[501];
   346    char zBuf[30];
   347    if( argc!=3 ){
   348      Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 
   349         " DB HEX", 0);
   350      return TCL_ERROR;
   351    }
   352    if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
   353    zHex = argv[2];
   354    for(i=j=0; i<(sizeof(zSql)-1) && zHex[j]; i++, j++){
   355      if( zHex[j]=='%' && zHex[j+2] && zHex[j+2] ){
   356        zSql[i] = (testHexToInt(zHex[j+1])<<4) + testHexToInt(zHex[j+2]);
   357        j += 2;
   358      }else{
   359        zSql[i] = zHex[j];
   360      }
   361    }
   362    zSql[i] = 0;
   363    Tcl_DStringInit(&str);
   364    rc = sqlite3_exec(db, zSql, exec_printf_cb, &str, &zErr);
   365    sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", rc);
   366    Tcl_AppendElement(interp, zBuf);
   367    Tcl_AppendElement(interp, rc==SQLITE_OK ? Tcl_DStringValue(&str) : zErr);
   368    Tcl_DStringFree(&str);
   369    if( zErr ) sqlite3_free(zErr);
   370    if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
   371    return TCL_OK;
   372  }
   373  
   374  /*
   375  ** Usage:  db_enter DB
   376  **         db_leave DB
   377  **
   378  ** Enter or leave the mutex on a database connection.
   379  */
   380  static int SQLITE_TCLAPI db_enter(
   381    void *NotUsed,
   382    Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
   383    int argc,              /* Number of arguments */
   384    char **argv            /* Text of each argument */
   385  ){
   386    sqlite3 *db;
   387    if( argc!=2 ){
   388      Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 
   389         " DB", 0);
   390      return TCL_ERROR;
   391    }
   392    if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
   393    sqlite3_mutex_enter(db->mutex);
   394    return TCL_OK;
   395  }
   396  static int SQLITE_TCLAPI db_leave(
   397    void *NotUsed,
   398    Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
   399    int argc,              /* Number of arguments */
   400    char **argv            /* Text of each argument */
   401  ){
   402    sqlite3 *db;
   403    if( argc!=2 ){
   404      Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 
   405         " DB", 0);
   406      return TCL_ERROR;
   407    }
   408    if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
   409    sqlite3_mutex_leave(db->mutex);
   410    return TCL_OK;
   411  }
   412  
   413  /*
   414  ** Usage:  sqlite3_exec  DB  SQL
   415  **
   416  ** Invoke the sqlite3_exec interface using the open database DB
   417  */
   418  static int SQLITE_TCLAPI test_exec(
   419    void *NotUsed,
   420    Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
   421    int argc,              /* Number of arguments */
   422    char **argv            /* Text of each argument */
   423  ){
   424    sqlite3 *db;
   425    Tcl_DString str;
   426    int rc;
   427    char *zErr = 0;
   428    char *zSql;
   429    int i, j;
   430    char zBuf[30];
   431    if( argc!=3 ){
   432      Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 
   433         " DB SQL", 0);
   434      return TCL_ERROR;
   435    }
   436    if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
   437    Tcl_DStringInit(&str);
   438    zSql = sqlite3_mprintf("%s", argv[2]);
   439    for(i=j=0; zSql[i];){
   440      if( zSql[i]=='%' ){
   441        zSql[j++] = (testHexToInt(zSql[i+1])<<4) + testHexToInt(zSql[i+2]);
   442        i += 3;
   443      }else{
   444        zSql[j++] = zSql[i++];
   445      }
   446    }
   447    zSql[j] = 0;
   448    rc = sqlite3_exec(db, zSql, exec_printf_cb, &str, &zErr);
   449    sqlite3_free(zSql);
   450    sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", rc);
   451    Tcl_AppendElement(interp, zBuf);
   452    Tcl_AppendElement(interp, rc==SQLITE_OK ? Tcl_DStringValue(&str) : zErr);
   453    Tcl_DStringFree(&str);
   454    if( zErr ) sqlite3_free(zErr);
   455    if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
   456    return TCL_OK;
   457  }
   458  
   459  /*
   460  ** Usage:  sqlite3_exec_nr  DB  SQL
   461  **
   462  ** Invoke the sqlite3_exec interface using the open database DB.  Discard
   463  ** all results
   464  */
   465  static int SQLITE_TCLAPI test_exec_nr(
   466    void *NotUsed,
   467    Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
   468    int argc,              /* Number of arguments */
   469    char **argv            /* Text of each argument */
   470  ){
   471    sqlite3 *db;
   472    int rc;
   473    char *zErr = 0;
   474    if( argc!=3 ){
   475      Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 
   476         " DB SQL", 0);
   477      return TCL_ERROR;
   478    }
   479    if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
   480    rc = sqlite3_exec(db, argv[2], 0, 0, &zErr);
   481    if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
   482    return TCL_OK;
   483  }
   484  
   485  /*
   486  ** Usage:  sqlite3_mprintf_z_test  SEPARATOR  ARG0  ARG1 ...
   487  **
   488  ** Test the %z format of sqlite_mprintf().  Use multiple mprintf() calls to 
   489  ** concatenate arg0 through argn using separator as the separator.
   490  ** Return the result.
   491  */
   492  static int SQLITE_TCLAPI test_mprintf_z(
   493    void *NotUsed,
   494    Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
   495    int argc,              /* Number of arguments */
   496    char **argv            /* Text of each argument */
   497  ){
   498    char *zResult = 0;
   499    int i;
   500  
   501    for(i=2; i<argc && (i==2 || zResult); i++){
   502      zResult = sqlite3_mprintf("%z%s%s", zResult, argv[1], argv[i]);
   503    }
   504    Tcl_AppendResult(interp, zResult, 0);
   505    sqlite3_free(zResult);
   506    return TCL_OK;
   507  }
   508  
   509  /*
   510  ** Usage:  sqlite3_mprintf_n_test  STRING
   511  **
   512  ** Test the %n format of sqlite_mprintf().  Return the length of the
   513  ** input string.
   514  */
   515  static int SQLITE_TCLAPI test_mprintf_n(
   516    void *NotUsed,
   517    Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
   518    int argc,              /* Number of arguments */
   519    char **argv            /* Text of each argument */
   520  ){
   521    char *zStr;
   522    int n = 0;
   523    zStr = sqlite3_mprintf("%s%n", argv[1], &n);
   524    sqlite3_free(zStr);
   525    Tcl_SetObjResult(interp, Tcl_NewIntObj(n));
   526    return TCL_OK;
   527  }
   528  
   529  /*
   530  ** Usage:  sqlite3_snprintf_int  SIZE FORMAT  INT
   531  **
   532  ** Test the of sqlite3_snprintf() routine.  SIZE is the size of the
   533  ** output buffer in bytes.  The maximum size is 100.  FORMAT is the
   534  ** format string.  INT is a single integer argument.  The FORMAT
   535  ** string must require no more than this one integer argument.  If
   536  ** You pass in a format string that requires more than one argument,
   537  ** bad things will happen.
   538  */
   539  static int SQLITE_TCLAPI test_snprintf_int(
   540    void *NotUsed,
   541    Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
   542    int argc,              /* Number of arguments */
   543    char **argv            /* Text of each argument */
   544  ){
   545    char zStr[100];
   546    int n = atoi(argv[1]);
   547    const char *zFormat = argv[2];
   548    int a1 = atoi(argv[3]);
   549    if( n>sizeof(zStr) ) n = sizeof(zStr);
   550    sqlite3_snprintf(sizeof(zStr), zStr, "abcdefghijklmnopqrstuvwxyz");
   551    sqlite3_snprintf(n, zStr, zFormat, a1);
   552    Tcl_AppendResult(interp, zStr, 0);
   553    return TCL_OK;
   554  }
   555  
   556  #ifndef SQLITE_OMIT_GET_TABLE
   557  
   558  /*
   559  ** Usage:  sqlite3_get_table_printf  DB  FORMAT  STRING  ?--no-counts?
   560  **
   561  ** Invoke the sqlite3_get_table_printf() interface using the open database
   562  ** DB.  The SQL is the string FORMAT.  The format string should contain
   563  ** one %s or %q.  STRING is the value inserted into %s or %q.
   564  */
   565  static int SQLITE_TCLAPI test_get_table_printf(
   566    void *NotUsed,
   567    Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
   568    int argc,              /* Number of arguments */
   569    char **argv            /* Text of each argument */
   570  ){
   571    sqlite3 *db;
   572    Tcl_DString str;
   573    int rc;
   574    char *zErr = 0;
   575    int nRow = 0, nCol = 0;
   576    char **aResult;
   577    int i;
   578    char zBuf[30];
   579    char *zSql;
   580    int resCount = -1;
   581    if( argc==5 ){
   582      if( Tcl_GetInt(interp, argv[4], &resCount) ) return TCL_ERROR;
   583    }
   584    if( argc!=4 && argc!=5 ){
   585      Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 
   586         " DB FORMAT STRING ?COUNT?", 0);
   587      return TCL_ERROR;
   588    }
   589    if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
   590    Tcl_DStringInit(&str);
   591    zSql = sqlite3_mprintf(argv[2],argv[3]);
   592    if( argc==5 ){
   593      rc = sqlite3_get_table(db, zSql, &aResult, 0, 0, &zErr);
   594    }else{
   595      rc = sqlite3_get_table(db, zSql, &aResult, &nRow, &nCol, &zErr);
   596      resCount = (nRow+1)*nCol;
   597    }
   598    sqlite3_free(zSql);
   599    sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", rc);
   600    Tcl_AppendElement(interp, zBuf);
   601    if( rc==SQLITE_OK ){
   602      if( argc==4 ){
   603        sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", nRow);
   604        Tcl_AppendElement(interp, zBuf);
   605        sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", nCol);
   606        Tcl_AppendElement(interp, zBuf);
   607      }
   608      for(i=0; i<resCount; i++){
   609        Tcl_AppendElement(interp, aResult[i] ? aResult[i] : "NULL");
   610      }
   611    }else{
   612      Tcl_AppendElement(interp, zErr);
   613    }
   614    sqlite3_free_table(aResult);
   615    if( zErr ) sqlite3_free(zErr);
   616    if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
   617    return TCL_OK;
   618  }
   619  
   620  #endif /* SQLITE_OMIT_GET_TABLE */
   621  
   622  
   623  /*
   624  ** Usage:  sqlite3_last_insert_rowid DB
   625  **
   626  ** Returns the integer ROWID of the most recent insert.
   627  */
   628  static int SQLITE_TCLAPI test_last_rowid(
   629    void *NotUsed,
   630    Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
   631    int argc,              /* Number of arguments */
   632    char **argv            /* Text of each argument */
   633  ){
   634    sqlite3 *db;
   635    char zBuf[30];
   636  
   637    if( argc!=2 ){
   638      Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " DB\"", 0);
   639      return TCL_ERROR;
   640    }
   641    if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
   642    sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", sqlite3_last_insert_rowid(db));
   643    Tcl_AppendResult(interp, zBuf, 0);
   644    return SQLITE_OK;
   645  }
   646  
   647  /*
   648  ** Usage:  sqlite3_key DB KEY
   649  **
   650  ** Set the codec key.
   651  */
   652  static int SQLITE_TCLAPI test_key(
   653    void *NotUsed,
   654    Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
   655    int argc,              /* Number of arguments */
   656    char **argv            /* Text of each argument */
   657  ){
   658  #if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_CODEC_FROM_TCL)
   659    sqlite3 *db;
   660    const char *zKey;
   661    int nKey;
   662    if( argc!=3 ){
   663      Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
   664         " FILENAME\"", 0);
   665      return TCL_ERROR;
   666    }
   667    if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
   668    zKey = argv[2];
   669    nKey = strlen(zKey);
   670    sqlite3_key(db, zKey, nKey);
   671  #endif
   672    return TCL_OK;
   673  }
   674  
   675  /*
   676  ** Usage:  sqlite3_rekey DB KEY
   677  **
   678  ** Change the codec key.
   679  */
   680  static int SQLITE_TCLAPI test_rekey(
   681    void *NotUsed,
   682    Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
   683    int argc,              /* Number of arguments */
   684    char **argv            /* Text of each argument */
   685  ){
   686  #ifdef SQLITE_HAS_CODEC
   687    sqlite3 *db;
   688    const char *zKey;
   689    int nKey;
   690    if( argc!=3 ){
   691      Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
   692         " FILENAME\"", 0);
   693      return TCL_ERROR;
   694    }
   695    if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
   696    zKey = argv[2];
   697    nKey = strlen(zKey);
   698    sqlite3_rekey(db, zKey, nKey);
   699  #endif
   700    return TCL_OK;
   701  }
   702  
   703  /*
   704  ** Usage:  sqlite3_close DB
   705  **
   706  ** Closes the database opened by sqlite3_open.
   707  */
   708  static int SQLITE_TCLAPI sqlite_test_close(
   709    void *NotUsed,
   710    Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
   711    int argc,              /* Number of arguments */
   712    char **argv            /* Text of each argument */
   713  ){
   714    sqlite3 *db;
   715    int rc;
   716    if( argc!=2 ){
   717      Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
   718         " FILENAME\"", 0);
   719      return TCL_ERROR;
   720    }
   721    if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
   722    rc = sqlite3_close(db);
   723    Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
   724    return TCL_OK;
   725  }
   726  
   727  /*
   728  ** Usage:  sqlite3_close_v2 DB
   729  **
   730  ** Closes the database opened by sqlite3_open.
   731  */
   732  static int SQLITE_TCLAPI sqlite_test_close_v2(
   733    void *NotUsed,
   734    Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
   735    int argc,              /* Number of arguments */
   736    char **argv            /* Text of each argument */
   737  ){
   738    sqlite3 *db;
   739    int rc;
   740    if( argc!=2 ){
   741      Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
   742         " FILENAME\"", 0);
   743      return TCL_ERROR;
   744    }
   745    if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
   746    rc = sqlite3_close_v2(db);
   747    Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
   748    return TCL_OK;
   749  }
   750  
   751  /*
   752  ** Implementation of the x_coalesce() function.
   753  ** Return the first argument non-NULL argument.
   754  */
   755  static void t1_ifnullFunc(
   756    sqlite3_context *context,
   757    int argc,
   758    sqlite3_value **argv
   759  ){
   760    int i;
   761    for(i=0; i<argc; i++){
   762      if( SQLITE_NULL!=sqlite3_value_type(argv[i]) ){
   763        int n = sqlite3_value_bytes(argv[i]);
   764        sqlite3_result_text(context, (char*)sqlite3_value_text(argv[i]),
   765            n, SQLITE_TRANSIENT);
   766        break;
   767      }
   768    }
   769  }
   770  
   771  /*
   772  ** These are test functions.    hex8() interprets its argument as
   773  ** UTF8 and returns a hex encoding.  hex16le() interprets its argument
   774  ** as UTF16le and returns a hex encoding.
   775  */
   776  static void hex8Func(sqlite3_context *p, int argc, sqlite3_value **argv){
   777    const unsigned char *z;
   778    int i;
   779    char zBuf[200];
   780    z = sqlite3_value_text(argv[0]);
   781    for(i=0; i<sizeof(zBuf)/2 - 2 && z[i]; i++){
   782      sqlite3_snprintf(sizeof(zBuf)-i*2, &zBuf[i*2], "%02x", z[i]);
   783    }
   784    zBuf[i*2] = 0;
   785    sqlite3_result_text(p, (char*)zBuf, -1, SQLITE_TRANSIENT);
   786  }
   787  #ifndef SQLITE_OMIT_UTF16
   788  static void hex16Func(sqlite3_context *p, int argc, sqlite3_value **argv){
   789    const unsigned short int *z;
   790    int i;
   791    char zBuf[400];
   792    z = sqlite3_value_text16(argv[0]);
   793    for(i=0; i<sizeof(zBuf)/4 - 4 && z[i]; i++){
   794      sqlite3_snprintf(sizeof(zBuf)-i*4, &zBuf[i*4],"%04x", z[i]&0xff);
   795    }
   796    zBuf[i*4] = 0;
   797    sqlite3_result_text(p, (char*)zBuf, -1, SQLITE_TRANSIENT);
   798  }
   799  #endif
   800  
   801  /*
   802  ** A structure into which to accumulate text.
   803  */
   804  struct dstr {
   805    int nAlloc;  /* Space allocated */
   806    int nUsed;   /* Space used */
   807    char *z;     /* The space */
   808  };
   809  
   810  /*
   811  ** Append text to a dstr
   812  */
   813  static void dstrAppend(struct dstr *p, const char *z, int divider){
   814    int n = (int)strlen(z);
   815    if( p->nUsed + n + 2 > p->nAlloc ){
   816      char *zNew;
   817      p->nAlloc = p->nAlloc*2 + n + 200;
   818      zNew = sqlite3_realloc(p->z, p->nAlloc);
   819      if( zNew==0 ){
   820        sqlite3_free(p->z);
   821        memset(p, 0, sizeof(*p));
   822        return;
   823      }
   824      p->z = zNew;
   825    }
   826    if( divider && p->nUsed>0 ){
   827      p->z[p->nUsed++] = divider;
   828    }
   829    memcpy(&p->z[p->nUsed], z, n+1);
   830    p->nUsed += n;
   831  }
   832  
   833  /*
   834  ** Invoked for each callback from sqlite3ExecFunc
   835  */
   836  static int execFuncCallback(void *pData, int argc, char **argv, char **NotUsed){
   837    struct dstr *p = (struct dstr*)pData;
   838    int i;
   839    for(i=0; i<argc; i++){
   840      if( argv[i]==0 ){
   841        dstrAppend(p, "NULL", ' ');
   842      }else{
   843        dstrAppend(p, argv[i], ' ');
   844      }
   845    }
   846    return 0;
   847  }
   848  
   849  /*
   850  ** Implementation of the x_sqlite_exec() function.  This function takes
   851  ** a single argument and attempts to execute that argument as SQL code.
   852  ** This is illegal and should set the SQLITE_MISUSE flag on the database.
   853  **
   854  ** 2004-Jan-07:  We have changed this to make it legal to call sqlite3_exec()
   855  ** from within a function call.  
   856  ** 
   857  ** This routine simulates the effect of having two threads attempt to
   858  ** use the same database at the same time.
   859  */
   860  static void sqlite3ExecFunc(
   861    sqlite3_context *context, 
   862    int argc,  
   863    sqlite3_value **argv
   864  ){
   865    struct dstr x;
   866    memset(&x, 0, sizeof(x));
   867    (void)sqlite3_exec((sqlite3*)sqlite3_user_data(context),
   868        (char*)sqlite3_value_text(argv[0]),
   869        execFuncCallback, &x, 0);
   870    sqlite3_result_text(context, x.z, x.nUsed, SQLITE_TRANSIENT);
   871    sqlite3_free(x.z);
   872  }
   873  
   874  /*
   875  ** Implementation of tkt2213func(), a scalar function that takes exactly
   876  ** one argument. It has two interesting features:
   877  **
   878  ** * It calls sqlite3_value_text() 3 times on the argument sqlite3_value*.
   879  **   If the three pointers returned are not the same an SQL error is raised.
   880  **
   881  ** * Otherwise it returns a copy of the text representation of its 
   882  **   argument in such a way as the VDBE representation is a Mem* cell 
   883  **   with the MEM_Term flag clear. 
   884  **
   885  ** Ticket #2213 can therefore be tested by evaluating the following
   886  ** SQL expression:
   887  **
   888  **   tkt2213func(tkt2213func('a string'));
   889  */
   890  static void tkt2213Function(
   891    sqlite3_context *context, 
   892    int argc,  
   893    sqlite3_value **argv
   894  ){
   895    int nText;
   896    unsigned char const *zText1;
   897    unsigned char const *zText2;
   898    unsigned char const *zText3;
   899  
   900    nText = sqlite3_value_bytes(argv[0]);
   901    zText1 = sqlite3_value_text(argv[0]);
   902    zText2 = sqlite3_value_text(argv[0]);
   903    zText3 = sqlite3_value_text(argv[0]);
   904  
   905    if( zText1!=zText2 || zText2!=zText3 ){
   906      sqlite3_result_error(context, "tkt2213 is not fixed", -1);
   907    }else{
   908      char *zCopy = (char *)sqlite3_malloc(nText);
   909      memcpy(zCopy, zText1, nText);
   910      sqlite3_result_text(context, zCopy, nText, sqlite3_free);
   911    }
   912  }
   913  
   914  /*
   915  ** The following SQL function takes 4 arguments.  The 2nd and
   916  ** 4th argument must be one of these strings:  'text', 'text16',
   917  ** or 'blob' corresponding to API functions
   918  **
   919  **      sqlite3_value_text()
   920  **      sqlite3_value_text16()
   921  **      sqlite3_value_blob()
   922  **
   923  ** The third argument is a string, either 'bytes' or 'bytes16' or 'noop',
   924  ** corresponding to APIs:
   925  **
   926  **      sqlite3_value_bytes()
   927  **      sqlite3_value_bytes16()
   928  **      noop
   929  **
   930  ** The APIs designated by the 2nd through 4th arguments are applied
   931  ** to the first argument in order.  If the pointers returned by the
   932  ** second and fourth are different, this routine returns 1.  Otherwise,
   933  ** this routine returns 0.
   934  **
   935  ** This function is used to test to see when returned pointers from
   936  ** the _text(), _text16() and _blob() APIs become invalidated.
   937  */
   938  static void ptrChngFunction(
   939    sqlite3_context *context, 
   940    int argc,  
   941    sqlite3_value **argv
   942  ){
   943    const void *p1, *p2;
   944    const char *zCmd;
   945    if( argc!=4 ) return;
   946    zCmd = (const char*)sqlite3_value_text(argv[1]);
   947    if( zCmd==0 ) return;
   948    if( strcmp(zCmd,"text")==0 ){
   949      p1 = (const void*)sqlite3_value_text(argv[0]);
   950  #ifndef SQLITE_OMIT_UTF16
   951    }else if( strcmp(zCmd, "text16")==0 ){
   952      p1 = (const void*)sqlite3_value_text16(argv[0]);
   953  #endif
   954    }else if( strcmp(zCmd, "blob")==0 ){
   955      p1 = (const void*)sqlite3_value_blob(argv[0]);
   956    }else{
   957      return;
   958    }
   959    zCmd = (const char*)sqlite3_value_text(argv[2]);
   960    if( zCmd==0 ) return;
   961    if( strcmp(zCmd,"bytes")==0 ){
   962      sqlite3_value_bytes(argv[0]);
   963  #ifndef SQLITE_OMIT_UTF16
   964    }else if( strcmp(zCmd, "bytes16")==0 ){
   965      sqlite3_value_bytes16(argv[0]);
   966  #endif
   967    }else if( strcmp(zCmd, "noop")==0 ){
   968      /* do nothing */
   969    }else{
   970      return;
   971    }
   972    zCmd = (const char*)sqlite3_value_text(argv[3]);
   973    if( zCmd==0 ) return;
   974    if( strcmp(zCmd,"text")==0 ){
   975      p2 = (const void*)sqlite3_value_text(argv[0]);
   976  #ifndef SQLITE_OMIT_UTF16
   977    }else if( strcmp(zCmd, "text16")==0 ){
   978      p2 = (const void*)sqlite3_value_text16(argv[0]);
   979  #endif
   980    }else if( strcmp(zCmd, "blob")==0 ){
   981      p2 = (const void*)sqlite3_value_blob(argv[0]);
   982    }else{
   983      return;
   984    }
   985    sqlite3_result_int(context, p1!=p2);
   986  }
   987  
   988  /*
   989  ** This SQL function returns a different answer each time it is called, even if
   990  ** the arguments are the same.
   991  */
   992  static void nondeterministicFunction(
   993    sqlite3_context *context, 
   994    int argc,  
   995    sqlite3_value **argv
   996  ){
   997    static int cnt = 0;
   998    sqlite3_result_int(context, cnt++);
   999  }
  1000  
  1001  /*
  1002  ** Usage:  sqlite3_create_function DB
  1003  **
  1004  ** Call the sqlite3_create_function API on the given database in order
  1005  ** to create a function named "x_coalesce".  This function does the same thing
  1006  ** as the "coalesce" function.  This function also registers an SQL function
  1007  ** named "x_sqlite_exec" that invokes sqlite3_exec().  Invoking sqlite3_exec()
  1008  ** in this way is illegal recursion and should raise an SQLITE_MISUSE error.
  1009  ** The effect is similar to trying to use the same database connection from
  1010  ** two threads at the same time.
  1011  **
  1012  ** The original motivation for this routine was to be able to call the
  1013  ** sqlite3_create_function function while a query is in progress in order
  1014  ** to test the SQLITE_MISUSE detection logic.
  1015  */
  1016  static int SQLITE_TCLAPI test_create_function(
  1017    void *NotUsed,
  1018    Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  1019    int argc,              /* Number of arguments */
  1020    char **argv            /* Text of each argument */
  1021  ){
  1022    int rc;
  1023    sqlite3 *db;
  1024  
  1025    if( argc!=2 ){
  1026      Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
  1027         " DB\"", 0);
  1028      return TCL_ERROR;
  1029    }
  1030    if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
  1031    rc = sqlite3_create_function(db, "x_coalesce", -1, SQLITE_UTF8, 0, 
  1032          t1_ifnullFunc, 0, 0);
  1033    if( rc==SQLITE_OK ){
  1034      rc = sqlite3_create_function(db, "hex8", 1, SQLITE_UTF8 | SQLITE_DETERMINISTIC,
  1035            0, hex8Func, 0, 0);
  1036    }
  1037  #ifndef SQLITE_OMIT_UTF16
  1038    if( rc==SQLITE_OK ){
  1039      rc = sqlite3_create_function(db, "hex16", 1, SQLITE_UTF16 | SQLITE_DETERMINISTIC,
  1040            0, hex16Func, 0, 0);
  1041    }
  1042  #endif
  1043    if( rc==SQLITE_OK ){
  1044      rc = sqlite3_create_function(db, "tkt2213func", 1, SQLITE_ANY, 0, 
  1045            tkt2213Function, 0, 0);
  1046    }
  1047    if( rc==SQLITE_OK ){
  1048      rc = sqlite3_create_function(db, "pointer_change", 4, SQLITE_ANY, 0, 
  1049            ptrChngFunction, 0, 0);
  1050    }
  1051  
  1052    /* Functions counter1() and counter2() have the same implementation - they
  1053    ** both return an ascending integer with each call.  But counter1() is marked
  1054    ** as non-deterministic and counter2() is marked as deterministic.
  1055    */
  1056    if( rc==SQLITE_OK ){
  1057      rc = sqlite3_create_function(db, "counter1", -1, SQLITE_UTF8,
  1058            0, nondeterministicFunction, 0, 0);
  1059    }
  1060    if( rc==SQLITE_OK ){
  1061      rc = sqlite3_create_function(db, "counter2", -1, SQLITE_UTF8|SQLITE_DETERMINISTIC,
  1062            0, nondeterministicFunction, 0, 0);
  1063    }
  1064  
  1065  #ifndef SQLITE_OMIT_UTF16
  1066    /* Use the sqlite3_create_function16() API here. Mainly for fun, but also 
  1067    ** because it is not tested anywhere else. */
  1068    if( rc==SQLITE_OK ){
  1069      const void *zUtf16;
  1070      sqlite3_value *pVal;
  1071      sqlite3_mutex_enter(db->mutex);
  1072      pVal = sqlite3ValueNew(db);
  1073      sqlite3ValueSetStr(pVal, -1, "x_sqlite_exec", SQLITE_UTF8, SQLITE_STATIC);
  1074      zUtf16 = sqlite3ValueText(pVal, SQLITE_UTF16NATIVE);
  1075      if( db->mallocFailed ){
  1076        rc = SQLITE_NOMEM;
  1077      }else{
  1078        rc = sqlite3_create_function16(db, zUtf16, 
  1079                  1, SQLITE_UTF16, db, sqlite3ExecFunc, 0, 0);
  1080      }
  1081      sqlite3ValueFree(pVal);
  1082      sqlite3_mutex_leave(db->mutex);
  1083    }
  1084  #endif
  1085  
  1086    if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
  1087    Tcl_SetResult(interp, (char *)t1ErrorName(rc), 0);
  1088    return TCL_OK;
  1089  }
  1090  
  1091  /*
  1092  ** Routines to implement the x_count() aggregate function.
  1093  **
  1094  ** x_count() counts the number of non-null arguments.  But there are
  1095  ** some twists for testing purposes.
  1096  **
  1097  ** If the argument to x_count() is 40 then a UTF-8 error is reported
  1098  ** on the step function.  If x_count(41) is seen, then a UTF-16 error
  1099  ** is reported on the step function.  If the total count is 42, then
  1100  ** a UTF-8 error is reported on the finalize function.
  1101  */
  1102  typedef struct t1CountCtx t1CountCtx;
  1103  struct t1CountCtx {
  1104    int n;
  1105  };
  1106  static void t1CountStep(
  1107    sqlite3_context *context,
  1108    int argc,
  1109    sqlite3_value **argv
  1110  ){
  1111    t1CountCtx *p;
  1112    p = sqlite3_aggregate_context(context, sizeof(*p));
  1113    if( (argc==0 || SQLITE_NULL!=sqlite3_value_type(argv[0]) ) && p ){
  1114      p->n++;
  1115    }
  1116    if( argc>0 ){
  1117      int v = sqlite3_value_int(argv[0]);
  1118      if( v==40 ){
  1119        sqlite3_result_error(context, "value of 40 handed to x_count", -1);
  1120  #ifndef SQLITE_OMIT_UTF16
  1121      }else if( v==41 ){
  1122        const char zUtf16ErrMsg[] = { 0, 0x61, 0, 0x62, 0, 0x63, 0, 0, 0};
  1123        sqlite3_result_error16(context, &zUtf16ErrMsg[1-SQLITE_BIGENDIAN], -1);
  1124  #endif
  1125      }
  1126    }
  1127  }   
  1128  static void t1CountFinalize(sqlite3_context *context){
  1129    t1CountCtx *p;
  1130    p = sqlite3_aggregate_context(context, sizeof(*p));
  1131    if( p ){
  1132      if( p->n==42 ){
  1133        sqlite3_result_error(context, "x_count totals to 42", -1);
  1134      }else{
  1135        sqlite3_result_int(context, p ? p->n : 0);
  1136      }
  1137    }
  1138  }
  1139  
  1140  #ifndef SQLITE_OMIT_DEPRECATED
  1141  static void legacyCountStep(
  1142    sqlite3_context *context,
  1143    int argc,
  1144    sqlite3_value **argv
  1145  ){
  1146    /* no-op */
  1147  }
  1148  
  1149  static void legacyCountFinalize(sqlite3_context *context){
  1150    sqlite3_result_int(context, sqlite3_aggregate_count(context));
  1151  }
  1152  #endif
  1153  
  1154  /*
  1155  ** Usage:  sqlite3_create_aggregate DB
  1156  **
  1157  ** Call the sqlite3_create_function API on the given database in order
  1158  ** to create a function named "x_count".  This function is similar
  1159  ** to the built-in count() function, with a few special quirks
  1160  ** for testing the sqlite3_result_error() APIs.
  1161  **
  1162  ** The original motivation for this routine was to be able to call the
  1163  ** sqlite3_create_aggregate function while a query is in progress in order
  1164  ** to test the SQLITE_MISUSE detection logic.  See misuse.test.
  1165  **
  1166  ** This routine was later extended to test the use of sqlite3_result_error()
  1167  ** within aggregate functions.
  1168  **
  1169  ** Later: It is now also extended to register the aggregate function
  1170  ** "legacy_count()" with the supplied database handle. This is used
  1171  ** to test the deprecated sqlite3_aggregate_count() API.
  1172  */
  1173  static int SQLITE_TCLAPI test_create_aggregate(
  1174    void *NotUsed,
  1175    Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  1176    int argc,              /* Number of arguments */
  1177    char **argv            /* Text of each argument */
  1178  ){
  1179    sqlite3 *db;
  1180    int rc;
  1181    if( argc!=2 ){
  1182      Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
  1183         " FILENAME\"", 0);
  1184      return TCL_ERROR;
  1185    }
  1186    if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
  1187    rc = sqlite3_create_function(db, "x_count", 0, SQLITE_UTF8, 0, 0,
  1188        t1CountStep,t1CountFinalize);
  1189    if( rc==SQLITE_OK ){
  1190      rc = sqlite3_create_function(db, "x_count", 1, SQLITE_UTF8, 0, 0,
  1191          t1CountStep,t1CountFinalize);
  1192    }
  1193  #ifndef SQLITE_OMIT_DEPRECATED
  1194    if( rc==SQLITE_OK ){
  1195      rc = sqlite3_create_function(db, "legacy_count", 0, SQLITE_ANY, 0, 0,
  1196          legacyCountStep, legacyCountFinalize
  1197      );
  1198    }
  1199  #endif
  1200    if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
  1201    Tcl_SetResult(interp, (char *)t1ErrorName(rc), 0);
  1202    return TCL_OK;
  1203  }
  1204  
  1205  
  1206  /*
  1207  ** Usage:  printf TEXT
  1208  **
  1209  ** Send output to printf.  Use this rather than puts to merge the output
  1210  ** in the correct sequence with debugging printfs inserted into C code.
  1211  ** Puts uses a separate buffer and debugging statements will be out of
  1212  ** sequence if it is used.
  1213  */
  1214  static int SQLITE_TCLAPI test_printf(
  1215    void *NotUsed,
  1216    Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  1217    int argc,              /* Number of arguments */
  1218    char **argv            /* Text of each argument */
  1219  ){
  1220    if( argc!=2 ){
  1221      Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
  1222         " TEXT\"", 0);
  1223      return TCL_ERROR;
  1224    }
  1225    printf("%s\n", argv[1]);
  1226    return TCL_OK;
  1227  }
  1228  
  1229  
  1230  
  1231  /*
  1232  ** Usage:  sqlite3_mprintf_int FORMAT INTEGER INTEGER INTEGER
  1233  **
  1234  ** Call mprintf with three integer arguments
  1235  */
  1236  static int SQLITE_TCLAPI sqlite3_mprintf_int(
  1237    void *NotUsed,
  1238    Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  1239    int argc,              /* Number of arguments */
  1240    char **argv            /* Text of each argument */
  1241  ){
  1242    int a[3], i;
  1243    char *z;
  1244    if( argc!=5 ){
  1245      Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
  1246         " FORMAT INT INT INT\"", 0);
  1247      return TCL_ERROR;
  1248    }
  1249    for(i=2; i<5; i++){
  1250      if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR;
  1251    }
  1252    z = sqlite3_mprintf(argv[1], a[0], a[1], a[2]);
  1253    Tcl_AppendResult(interp, z, 0);
  1254    sqlite3_free(z);
  1255    return TCL_OK;
  1256  }
  1257  
  1258  /*
  1259  ** Usage:  sqlite3_mprintf_int64 FORMAT INTEGER INTEGER INTEGER
  1260  **
  1261  ** Call mprintf with three 64-bit integer arguments
  1262  */
  1263  static int SQLITE_TCLAPI sqlite3_mprintf_int64(
  1264    void *NotUsed,
  1265    Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  1266    int argc,              /* Number of arguments */
  1267    char **argv            /* Text of each argument */
  1268  ){
  1269    int i;
  1270    sqlite_int64 a[3];
  1271    char *z;
  1272    if( argc!=5 ){
  1273      Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
  1274         " FORMAT INT INT INT\"", 0);
  1275      return TCL_ERROR;
  1276    }
  1277    for(i=2; i<5; i++){
  1278      if( sqlite3Atoi64(argv[i], &a[i-2], sqlite3Strlen30(argv[i]), SQLITE_UTF8) ){
  1279        Tcl_AppendResult(interp, "argument is not a valid 64-bit integer", 0);
  1280        return TCL_ERROR;
  1281      }
  1282    }
  1283    z = sqlite3_mprintf(argv[1], a[0], a[1], a[2]);
  1284    Tcl_AppendResult(interp, z, 0);
  1285    sqlite3_free(z);
  1286    return TCL_OK;
  1287  }
  1288  
  1289  /*
  1290  ** Usage:  sqlite3_mprintf_long FORMAT INTEGER INTEGER INTEGER
  1291  **
  1292  ** Call mprintf with three long integer arguments.   This might be the
  1293  ** same as sqlite3_mprintf_int or sqlite3_mprintf_int64, depending on
  1294  ** platform.
  1295  */
  1296  static int SQLITE_TCLAPI sqlite3_mprintf_long(
  1297    void *NotUsed,
  1298    Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  1299    int argc,              /* Number of arguments */
  1300    char **argv            /* Text of each argument */
  1301  ){
  1302    int i;
  1303    long int a[3];
  1304    int b[3];
  1305    char *z;
  1306    if( argc!=5 ){
  1307      Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
  1308         " FORMAT INT INT INT\"", 0);
  1309      return TCL_ERROR;
  1310    }
  1311    for(i=2; i<5; i++){
  1312      if( Tcl_GetInt(interp, argv[i], &b[i-2]) ) return TCL_ERROR;
  1313      a[i-2] = (long int)b[i-2];
  1314      a[i-2] &= (((u64)1)<<(sizeof(int)*8))-1;
  1315    }
  1316    z = sqlite3_mprintf(argv[1], a[0], a[1], a[2]);
  1317    Tcl_AppendResult(interp, z, 0);
  1318    sqlite3_free(z);
  1319    return TCL_OK;
  1320  }
  1321  
  1322  /*
  1323  ** Usage:  sqlite3_mprintf_str FORMAT INTEGER INTEGER STRING
  1324  **
  1325  ** Call mprintf with two integer arguments and one string argument
  1326  */
  1327  static int SQLITE_TCLAPI sqlite3_mprintf_str(
  1328    void *NotUsed,
  1329    Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  1330    int argc,              /* Number of arguments */
  1331    char **argv            /* Text of each argument */
  1332  ){
  1333    int a[3], i;
  1334    char *z;
  1335    if( argc<4 || argc>5 ){
  1336      Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
  1337         " FORMAT INT INT ?STRING?\"", 0);
  1338      return TCL_ERROR;
  1339    }
  1340    for(i=2; i<4; i++){
  1341      if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR;
  1342    }
  1343    z = sqlite3_mprintf(argv[1], a[0], a[1], argc>4 ? argv[4] : NULL);
  1344    Tcl_AppendResult(interp, z, 0);
  1345    sqlite3_free(z);
  1346    return TCL_OK;
  1347  }
  1348  
  1349  /*
  1350  ** Usage:  sqlite3_snprintf_str INTEGER FORMAT INTEGER INTEGER STRING
  1351  **
  1352  ** Call mprintf with two integer arguments and one string argument
  1353  */
  1354  static int SQLITE_TCLAPI sqlite3_snprintf_str(
  1355    void *NotUsed,
  1356    Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  1357    int argc,              /* Number of arguments */
  1358    char **argv            /* Text of each argument */
  1359  ){
  1360    int a[3], i;
  1361    int n;
  1362    char *z;
  1363    if( argc<5 || argc>6 ){
  1364      Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
  1365         " INT FORMAT INT INT ?STRING?\"", 0);
  1366      return TCL_ERROR;
  1367    }
  1368    if( Tcl_GetInt(interp, argv[1], &n) ) return TCL_ERROR;
  1369    if( n<0 ){
  1370      Tcl_AppendResult(interp, "N must be non-negative", 0);
  1371      return TCL_ERROR;
  1372    }
  1373    for(i=3; i<5; i++){
  1374      if( Tcl_GetInt(interp, argv[i], &a[i-3]) ) return TCL_ERROR;
  1375    }
  1376    z = sqlite3_malloc( n+1 );
  1377    sqlite3_snprintf(n, z, argv[2], a[0], a[1], argc>4 ? argv[5] : NULL);
  1378    Tcl_AppendResult(interp, z, 0);
  1379    sqlite3_free(z);
  1380    return TCL_OK;
  1381  }
  1382  
  1383  /*
  1384  ** Usage:  sqlite3_mprintf_double FORMAT INTEGER INTEGER DOUBLE
  1385  **
  1386  ** Call mprintf with two integer arguments and one double argument
  1387  */
  1388  static int SQLITE_TCLAPI sqlite3_mprintf_double(
  1389    void *NotUsed,
  1390    Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  1391    int argc,              /* Number of arguments */
  1392    char **argv            /* Text of each argument */
  1393  ){
  1394    int a[3], i;
  1395    double r;
  1396    char *z;
  1397    if( argc!=5 ){
  1398      Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
  1399         " FORMAT INT INT DOUBLE\"", 0);
  1400      return TCL_ERROR;
  1401    }
  1402    for(i=2; i<4; i++){
  1403      if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR;
  1404    }
  1405    if( Tcl_GetDouble(interp, argv[4], &r) ) return TCL_ERROR;
  1406    z = sqlite3_mprintf(argv[1], a[0], a[1], r);
  1407    Tcl_AppendResult(interp, z, 0);
  1408    sqlite3_free(z);
  1409    return TCL_OK;
  1410  }
  1411  
  1412  /*
  1413  ** Usage:  sqlite3_mprintf_scaled FORMAT DOUBLE DOUBLE
  1414  **
  1415  ** Call mprintf with a single double argument which is the product of the
  1416  ** two arguments given above.  This is used to generate overflow and underflow
  1417  ** doubles to test that they are converted properly.
  1418  */
  1419  static int SQLITE_TCLAPI sqlite3_mprintf_scaled(
  1420    void *NotUsed,
  1421    Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  1422    int argc,              /* Number of arguments */
  1423    char **argv            /* Text of each argument */
  1424  ){
  1425    int i;
  1426    double r[2];
  1427    char *z;
  1428    if( argc!=4 ){
  1429      Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
  1430         " FORMAT DOUBLE DOUBLE\"", 0);
  1431      return TCL_ERROR;
  1432    }
  1433    for(i=2; i<4; i++){
  1434      if( Tcl_GetDouble(interp, argv[i], &r[i-2]) ) return TCL_ERROR;
  1435    }
  1436    z = sqlite3_mprintf(argv[1], r[0]*r[1]);
  1437    Tcl_AppendResult(interp, z, 0);
  1438    sqlite3_free(z);
  1439    return TCL_OK;
  1440  }
  1441  
  1442  /*
  1443  ** Usage:  sqlite3_mprintf_stronly FORMAT STRING
  1444  **
  1445  ** Call mprintf with a single double argument which is the product of the
  1446  ** two arguments given above.  This is used to generate overflow and underflow
  1447  ** doubles to test that they are converted properly.
  1448  */
  1449  static int SQLITE_TCLAPI sqlite3_mprintf_stronly(
  1450    void *NotUsed,
  1451    Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  1452    int argc,              /* Number of arguments */
  1453    char **argv            /* Text of each argument */
  1454  ){
  1455    char *z;
  1456    if( argc!=3 ){
  1457      Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
  1458         " FORMAT STRING\"", 0);
  1459      return TCL_ERROR;
  1460    }
  1461    z = sqlite3_mprintf(argv[1], argv[2]);
  1462    Tcl_AppendResult(interp, z, 0);
  1463    sqlite3_free(z);
  1464    return TCL_OK;
  1465  }
  1466  
  1467  /*
  1468  ** Usage:  sqlite3_mprintf_hexdouble FORMAT HEX
  1469  **
  1470  ** Call mprintf with a single double argument which is derived from the
  1471  ** hexadecimal encoding of an IEEE double.
  1472  */
  1473  static int SQLITE_TCLAPI sqlite3_mprintf_hexdouble(
  1474    void *NotUsed,
  1475    Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  1476    int argc,              /* Number of arguments */
  1477    char **argv            /* Text of each argument */
  1478  ){
  1479    char *z;
  1480    double r;
  1481    unsigned int x1, x2;
  1482    sqlite_uint64 d;
  1483    if( argc!=3 ){
  1484      Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
  1485         " FORMAT STRING\"", 0);
  1486      return TCL_ERROR;
  1487    }
  1488    if( sscanf(argv[2], "%08x%08x", &x2, &x1)!=2 ){
  1489      Tcl_AppendResult(interp, "2nd argument should be 16-characters of hex", 0);
  1490      return TCL_ERROR;
  1491    }
  1492    d = x2;
  1493    d = (d<<32) + x1;
  1494    memcpy(&r, &d, sizeof(r));
  1495    z = sqlite3_mprintf(argv[1], r);
  1496    Tcl_AppendResult(interp, z, 0);
  1497    sqlite3_free(z);
  1498    return TCL_OK;
  1499  }
  1500  
  1501  /*
  1502  ** Usage: sqlite3_enable_shared_cache ?BOOLEAN?
  1503  **
  1504  */
  1505  #if !defined(SQLITE_OMIT_SHARED_CACHE)
  1506  static int SQLITE_TCLAPI test_enable_shared(
  1507    ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
  1508    Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  1509    int objc,              /* Number of arguments */
  1510    Tcl_Obj *CONST objv[]  /* Command arguments */
  1511  ){
  1512    int rc;
  1513    int enable;
  1514    int ret = 0;
  1515  
  1516    if( objc!=2 && objc!=1 ){
  1517      Tcl_WrongNumArgs(interp, 1, objv, "?BOOLEAN?");
  1518      return TCL_ERROR;
  1519    }
  1520    ret = sqlite3GlobalConfig.sharedCacheEnabled;
  1521  
  1522    if( objc==2 ){
  1523      if( Tcl_GetBooleanFromObj(interp, objv[1], &enable) ){
  1524        return TCL_ERROR;
  1525      }
  1526      rc = sqlite3_enable_shared_cache(enable);
  1527      if( rc!=SQLITE_OK ){
  1528        Tcl_SetResult(interp, (char *)sqlite3ErrStr(rc), TCL_STATIC);
  1529        return TCL_ERROR;
  1530      }
  1531    }
  1532    Tcl_SetObjResult(interp, Tcl_NewBooleanObj(ret));
  1533    return TCL_OK;
  1534  }
  1535  #endif
  1536  
  1537  
  1538  
  1539  /*
  1540  ** Usage: sqlite3_extended_result_codes   DB    BOOLEAN
  1541  **
  1542  */
  1543  static int SQLITE_TCLAPI test_extended_result_codes(
  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    int enable;
  1550    sqlite3 *db;
  1551  
  1552    if( objc!=3 ){
  1553      Tcl_WrongNumArgs(interp, 1, objv, "DB BOOLEAN");
  1554      return TCL_ERROR;
  1555    }
  1556    if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
  1557    if( Tcl_GetBooleanFromObj(interp, objv[2], &enable) ) return TCL_ERROR;
  1558    sqlite3_extended_result_codes(db, enable);
  1559    return TCL_OK;
  1560  }
  1561  
  1562  /*
  1563  ** Usage: sqlite3_libversion_number
  1564  **
  1565  */
  1566  static int SQLITE_TCLAPI test_libversion_number(
  1567    ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
  1568    Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  1569    int objc,              /* Number of arguments */
  1570    Tcl_Obj *CONST objv[]  /* Command arguments */
  1571  ){
  1572    Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_libversion_number()));
  1573    return TCL_OK;
  1574  }
  1575  
  1576  /*
  1577  ** Usage: sqlite3_table_column_metadata DB dbname tblname colname
  1578  **
  1579  */
  1580  static int SQLITE_TCLAPI test_table_column_metadata(
  1581    ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
  1582    Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  1583    int objc,              /* Number of arguments */
  1584    Tcl_Obj *CONST objv[]  /* Command arguments */
  1585  ){
  1586    sqlite3 *db;
  1587    const char *zDb;
  1588    const char *zTbl;
  1589    const char *zCol;
  1590    int rc;
  1591    Tcl_Obj *pRet;
  1592  
  1593    const char *zDatatype;
  1594    const char *zCollseq;
  1595    int notnull;
  1596    int primarykey;
  1597    int autoincrement;
  1598  
  1599    if( objc!=5 && objc!=4 ){
  1600      Tcl_WrongNumArgs(interp, 1, objv, "DB dbname tblname colname");
  1601      return TCL_ERROR;
  1602    }
  1603    if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
  1604    zDb = Tcl_GetString(objv[2]);
  1605    zTbl = Tcl_GetString(objv[3]);
  1606    zCol = objc==5 ? Tcl_GetString(objv[4]) : 0;
  1607  
  1608    if( strlen(zDb)==0 ) zDb = 0;
  1609  
  1610    rc = sqlite3_table_column_metadata(db, zDb, zTbl, zCol, 
  1611        &zDatatype, &zCollseq, &notnull, &primarykey, &autoincrement);
  1612  
  1613    if( rc!=SQLITE_OK ){
  1614      Tcl_AppendResult(interp, sqlite3_errmsg(db), 0);
  1615      return TCL_ERROR;
  1616    }
  1617  
  1618    pRet = Tcl_NewObj();
  1619    Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zDatatype, -1));
  1620    Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zCollseq, -1));
  1621    Tcl_ListObjAppendElement(0, pRet, Tcl_NewIntObj(notnull));
  1622    Tcl_ListObjAppendElement(0, pRet, Tcl_NewIntObj(primarykey));
  1623    Tcl_ListObjAppendElement(0, pRet, Tcl_NewIntObj(autoincrement));
  1624    Tcl_SetObjResult(interp, pRet);
  1625  
  1626    return TCL_OK;
  1627  }
  1628  
  1629  #ifndef SQLITE_OMIT_INCRBLOB
  1630  
  1631  static int SQLITE_TCLAPI blobHandleFromObj(
  1632    Tcl_Interp *interp, 
  1633    Tcl_Obj *pObj,
  1634    sqlite3_blob **ppBlob
  1635  ){
  1636    char *z;
  1637    int n;
  1638  
  1639    z = Tcl_GetStringFromObj(pObj, &n);
  1640    if( n==0 ){
  1641      *ppBlob = 0;
  1642    }else{
  1643      int notUsed;
  1644      Tcl_Channel channel;
  1645      ClientData instanceData;
  1646      
  1647      channel = Tcl_GetChannel(interp, z, &notUsed);
  1648      if( !channel ) return TCL_ERROR;
  1649  
  1650      Tcl_Flush(channel);
  1651      Tcl_Seek(channel, 0, SEEK_SET);
  1652  
  1653      instanceData = Tcl_GetChannelInstanceData(channel);
  1654      *ppBlob = *((sqlite3_blob **)instanceData);
  1655    }
  1656  
  1657    return TCL_OK;
  1658  }
  1659  
  1660  static int SQLITE_TCLAPI test_blob_reopen(
  1661    ClientData clientData, /* Not used */
  1662    Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  1663    int objc,              /* Number of arguments */
  1664    Tcl_Obj *CONST objv[]  /* Command arguments */
  1665  ){
  1666    Tcl_WideInt iRowid;
  1667    sqlite3_blob *pBlob;
  1668    int rc;
  1669  
  1670    if( objc!=3 ){
  1671      Tcl_WrongNumArgs(interp, 1, objv, "CHANNEL ROWID");
  1672      return TCL_ERROR;
  1673    }
  1674  
  1675    if( blobHandleFromObj(interp, objv[1], &pBlob) ) return TCL_ERROR;
  1676    if( Tcl_GetWideIntFromObj(interp, objv[2], &iRowid) ) return TCL_ERROR;
  1677  
  1678    rc = sqlite3_blob_reopen(pBlob, iRowid);
  1679    if( rc!=SQLITE_OK ){
  1680      Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);
  1681    }
  1682  
  1683    return (rc==SQLITE_OK ? TCL_OK : TCL_ERROR);
  1684  }
  1685  
  1686  #endif
  1687  
  1688  /*
  1689  ** Usage: sqlite3_create_collation_v2 DB-HANDLE NAME CMP-PROC DEL-PROC
  1690  **
  1691  **   This Tcl proc is used for testing the experimental
  1692  **   sqlite3_create_collation_v2() interface.
  1693  */
  1694  struct TestCollationX {
  1695    Tcl_Interp *interp;
  1696    Tcl_Obj *pCmp;
  1697    Tcl_Obj *pDel;
  1698  };
  1699  typedef struct TestCollationX TestCollationX;
  1700  static void testCreateCollationDel(void *pCtx){
  1701    TestCollationX *p = (TestCollationX *)pCtx;
  1702  
  1703    int rc = Tcl_EvalObjEx(p->interp, p->pDel, TCL_EVAL_DIRECT|TCL_EVAL_GLOBAL);
  1704    if( rc!=TCL_OK ){
  1705      Tcl_BackgroundError(p->interp);
  1706    }
  1707  
  1708    Tcl_DecrRefCount(p->pCmp);
  1709    Tcl_DecrRefCount(p->pDel);
  1710    sqlite3_free((void *)p);
  1711  }
  1712  static int testCreateCollationCmp(
  1713    void *pCtx,
  1714    int nLeft,
  1715    const void *zLeft,
  1716    int nRight,
  1717    const void *zRight
  1718  ){
  1719    TestCollationX *p = (TestCollationX *)pCtx;
  1720    Tcl_Obj *pScript = Tcl_DuplicateObj(p->pCmp);
  1721    int iRes = 0;
  1722  
  1723    Tcl_IncrRefCount(pScript);
  1724    Tcl_ListObjAppendElement(0, pScript, Tcl_NewStringObj((char *)zLeft, nLeft));
  1725    Tcl_ListObjAppendElement(0, pScript, Tcl_NewStringObj((char *)zRight,nRight));
  1726  
  1727    if( TCL_OK!=Tcl_EvalObjEx(p->interp, pScript, TCL_EVAL_DIRECT|TCL_EVAL_GLOBAL)
  1728     || TCL_OK!=Tcl_GetIntFromObj(p->interp, Tcl_GetObjResult(p->interp), &iRes)
  1729    ){
  1730      Tcl_BackgroundError(p->interp);
  1731    }
  1732    Tcl_DecrRefCount(pScript);
  1733  
  1734    return iRes;
  1735  }
  1736  static int SQLITE_TCLAPI test_create_collation_v2(
  1737    ClientData clientData, /* Not used */
  1738    Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  1739    int objc,              /* Number of arguments */
  1740    Tcl_Obj *CONST objv[]  /* Command arguments */
  1741  ){
  1742    TestCollationX *p;
  1743    sqlite3 *db;
  1744    int rc;
  1745  
  1746    if( objc!=5 ){
  1747      Tcl_WrongNumArgs(interp, 1, objv, "DB-HANDLE NAME CMP-PROC DEL-PROC");
  1748      return TCL_ERROR;
  1749    }
  1750    if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
  1751  
  1752    p = (TestCollationX *)sqlite3_malloc(sizeof(TestCollationX));
  1753    p->pCmp = objv[3];
  1754    p->pDel = objv[4];
  1755    p->interp = interp;
  1756    Tcl_IncrRefCount(p->pCmp);
  1757    Tcl_IncrRefCount(p->pDel);
  1758  
  1759    rc = sqlite3_create_collation_v2(db, Tcl_GetString(objv[2]), 16, 
  1760        (void *)p, testCreateCollationCmp, testCreateCollationDel
  1761    );
  1762    if( rc!=SQLITE_MISUSE ){
  1763      Tcl_AppendResult(interp, "sqlite3_create_collate_v2() failed to detect "
  1764        "an invalid encoding", (char*)0);
  1765      return TCL_ERROR;
  1766    }
  1767    rc = sqlite3_create_collation_v2(db, Tcl_GetString(objv[2]), SQLITE_UTF8, 
  1768        (void *)p, testCreateCollationCmp, testCreateCollationDel
  1769    );
  1770    return TCL_OK;
  1771  }
  1772  
  1773  /*
  1774  ** USAGE: sqlite3_create_function_v2 DB NAME NARG ENC ?SWITCHES?
  1775  **
  1776  ** Available switches are:
  1777  **
  1778  **   -func    SCRIPT
  1779  **   -step    SCRIPT
  1780  **   -final   SCRIPT
  1781  **   -destroy SCRIPT
  1782  */
  1783  typedef struct CreateFunctionV2 CreateFunctionV2;
  1784  struct CreateFunctionV2 {
  1785    Tcl_Interp *interp;
  1786    Tcl_Obj *pFunc;                 /* Script for function invocation */
  1787    Tcl_Obj *pStep;                 /* Script for agg. step invocation */
  1788    Tcl_Obj *pFinal;                /* Script for agg. finalization invocation */
  1789    Tcl_Obj *pDestroy;              /* Destructor script */
  1790  };
  1791  static void cf2Func(sqlite3_context *ctx, int nArg, sqlite3_value **aArg){
  1792  }
  1793  static void cf2Step(sqlite3_context *ctx, int nArg, sqlite3_value **aArg){
  1794  }
  1795  static void cf2Final(sqlite3_context *ctx){
  1796  }
  1797  static void cf2Destroy(void *pUser){
  1798    CreateFunctionV2 *p = (CreateFunctionV2 *)pUser;
  1799  
  1800    if( p->interp && p->pDestroy ){
  1801      int rc = Tcl_EvalObjEx(p->interp, p->pDestroy, 0);
  1802      if( rc!=TCL_OK ) Tcl_BackgroundError(p->interp);
  1803    }
  1804  
  1805    if( p->pFunc ) Tcl_DecrRefCount(p->pFunc); 
  1806    if( p->pStep ) Tcl_DecrRefCount(p->pStep); 
  1807    if( p->pFinal ) Tcl_DecrRefCount(p->pFinal); 
  1808    if( p->pDestroy ) Tcl_DecrRefCount(p->pDestroy); 
  1809    sqlite3_free(p);
  1810  }
  1811  static int SQLITE_TCLAPI test_create_function_v2(
  1812    ClientData clientData,          /* Not used */
  1813    Tcl_Interp *interp,             /* The invoking TCL interpreter */
  1814    int objc,                       /* Number of arguments */
  1815    Tcl_Obj *CONST objv[]           /* Command arguments */
  1816  ){
  1817    sqlite3 *db;
  1818    const char *zFunc;
  1819    int nArg;
  1820    int enc;
  1821    CreateFunctionV2 *p;
  1822    int i;
  1823    int rc;
  1824  
  1825    struct EncTable {
  1826      const char *zEnc;
  1827      int enc;
  1828    } aEnc[] = {
  1829      {"utf8",    SQLITE_UTF8 },
  1830      {"utf16",   SQLITE_UTF16 },
  1831      {"utf16le", SQLITE_UTF16LE },
  1832      {"utf16be", SQLITE_UTF16BE },
  1833      {"any",     SQLITE_ANY },
  1834      {"0", 0 }
  1835    };
  1836  
  1837    if( objc<5 || (objc%2)==0 ){
  1838      Tcl_WrongNumArgs(interp, 1, objv, "DB NAME NARG ENC SWITCHES...");
  1839      return TCL_ERROR;
  1840    }
  1841  
  1842    if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
  1843    zFunc = Tcl_GetString(objv[2]);
  1844    if( Tcl_GetIntFromObj(interp, objv[3], &nArg) ) return TCL_ERROR;
  1845    if( Tcl_GetIndexFromObjStruct(interp, objv[4], aEnc, sizeof(aEnc[0]), 
  1846            "encoding", 0, &enc)
  1847    ){
  1848      return TCL_ERROR;
  1849    }
  1850    enc = aEnc[enc].enc;
  1851  
  1852    p = sqlite3_malloc(sizeof(CreateFunctionV2));
  1853    assert( p );
  1854    memset(p, 0, sizeof(CreateFunctionV2));
  1855    p->interp = interp;
  1856  
  1857    for(i=5; i<objc; i+=2){
  1858      int iSwitch;
  1859      const char *azSwitch[] = {"-func", "-step", "-final", "-destroy", 0};
  1860      if( Tcl_GetIndexFromObj(interp, objv[i], azSwitch, "switch", 0, &iSwitch) ){
  1861        sqlite3_free(p);
  1862        return TCL_ERROR;
  1863      }
  1864  
  1865      switch( iSwitch ){
  1866        case 0: p->pFunc = objv[i+1];      break;
  1867        case 1: p->pStep = objv[i+1];      break;
  1868        case 2: p->pFinal = objv[i+1];     break;
  1869        case 3: p->pDestroy = objv[i+1];   break;
  1870      }
  1871    }
  1872    if( p->pFunc ) p->pFunc = Tcl_DuplicateObj(p->pFunc); 
  1873    if( p->pStep ) p->pStep = Tcl_DuplicateObj(p->pStep); 
  1874    if( p->pFinal ) p->pFinal = Tcl_DuplicateObj(p->pFinal); 
  1875    if( p->pDestroy ) p->pDestroy = Tcl_DuplicateObj(p->pDestroy); 
  1876  
  1877    if( p->pFunc ) Tcl_IncrRefCount(p->pFunc); 
  1878    if( p->pStep ) Tcl_IncrRefCount(p->pStep); 
  1879    if( p->pFinal ) Tcl_IncrRefCount(p->pFinal); 
  1880    if( p->pDestroy ) Tcl_IncrRefCount(p->pDestroy); 
  1881  
  1882    rc = sqlite3_create_function_v2(db, zFunc, nArg, enc, (void *)p, 
  1883        (p->pFunc ? cf2Func : 0),
  1884        (p->pStep ? cf2Step : 0),
  1885        (p->pFinal ? cf2Final : 0),
  1886        cf2Destroy
  1887    );
  1888    if( rc!=SQLITE_OK ){
  1889      Tcl_ResetResult(interp);
  1890      Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
  1891      return TCL_ERROR;
  1892    }
  1893    return TCL_OK;
  1894  }
  1895  
  1896  /*
  1897  ** Usage: sqlite3_load_extension DB-HANDLE FILE ?PROC?
  1898  */
  1899  static int SQLITE_TCLAPI test_load_extension(
  1900    ClientData clientData, /* Not used */
  1901    Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  1902    int objc,              /* Number of arguments */
  1903    Tcl_Obj *CONST objv[]  /* Command arguments */
  1904  ){
  1905    Tcl_CmdInfo cmdInfo;
  1906    sqlite3 *db;
  1907    int rc;
  1908    char *zDb;
  1909    char *zFile;
  1910    char *zProc = 0;
  1911    char *zErr = 0;
  1912  
  1913    if( objc!=4 && objc!=3 ){
  1914      Tcl_WrongNumArgs(interp, 1, objv, "DB-HANDLE FILE ?PROC?");
  1915      return TCL_ERROR;
  1916    }
  1917    zDb = Tcl_GetString(objv[1]);
  1918    zFile = Tcl_GetString(objv[2]);
  1919    if( objc==4 ){
  1920      zProc = Tcl_GetString(objv[3]);
  1921    }
  1922  
  1923    /* Extract the C database handle from the Tcl command name */
  1924    if( !Tcl_GetCommandInfo(interp, zDb, &cmdInfo) ){
  1925      Tcl_AppendResult(interp, "command not found: ", zDb, (char*)0);
  1926      return TCL_ERROR;
  1927    }
  1928    db = ((struct SqliteDb*)cmdInfo.objClientData)->db;
  1929    assert(db);
  1930  
  1931    /* Call the underlying C function. If an error occurs, set rc to 
  1932    ** TCL_ERROR and load any error string into the interpreter. If no 
  1933    ** error occurs, set rc to TCL_OK.
  1934    */
  1935  #ifdef SQLITE_OMIT_LOAD_EXTENSION
  1936    rc = SQLITE_ERROR;
  1937    zErr = sqlite3_mprintf("this build omits sqlite3_load_extension()");
  1938    (void)zProc;
  1939    (void)zFile;
  1940  #else
  1941    rc = sqlite3_load_extension(db, zFile, zProc, &zErr);
  1942  #endif
  1943    if( rc!=SQLITE_OK ){
  1944      Tcl_SetResult(interp, zErr ? zErr : "", TCL_VOLATILE);
  1945      rc = TCL_ERROR;
  1946    }else{
  1947      rc = TCL_OK;
  1948    }
  1949    sqlite3_free(zErr);
  1950  
  1951    return rc;
  1952  }
  1953  
  1954  /*
  1955  ** Usage: sqlite3_enable_load_extension DB-HANDLE ONOFF
  1956  */
  1957  static int SQLITE_TCLAPI test_enable_load(
  1958    ClientData clientData, /* Not used */
  1959    Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  1960    int objc,              /* Number of arguments */
  1961    Tcl_Obj *CONST objv[]  /* Command arguments */
  1962  ){
  1963    Tcl_CmdInfo cmdInfo;
  1964    sqlite3 *db;
  1965    char *zDb;
  1966    int onoff;
  1967  
  1968    if( objc!=3 ){
  1969      Tcl_WrongNumArgs(interp, 1, objv, "DB-HANDLE ONOFF");
  1970      return TCL_ERROR;
  1971    }
  1972    zDb = Tcl_GetString(objv[1]);
  1973  
  1974    /* Extract the C database handle from the Tcl command name */
  1975    if( !Tcl_GetCommandInfo(interp, zDb, &cmdInfo) ){
  1976      Tcl_AppendResult(interp, "command not found: ", zDb, (char*)0);
  1977      return TCL_ERROR;
  1978    }
  1979    db = ((struct SqliteDb*)cmdInfo.objClientData)->db;
  1980    assert(db);
  1981  
  1982    /* Get the onoff parameter */
  1983    if( Tcl_GetBooleanFromObj(interp, objv[2], &onoff) ){
  1984      return TCL_ERROR;
  1985    }
  1986  
  1987  #ifdef SQLITE_OMIT_LOAD_EXTENSION
  1988    Tcl_AppendResult(interp, "this build omits sqlite3_load_extension()");
  1989    return TCL_ERROR;
  1990  #else
  1991    sqlite3_enable_load_extension(db, onoff);
  1992    return TCL_OK;
  1993  #endif
  1994  }
  1995  
  1996  /*
  1997  ** Usage:  sqlite_abort
  1998  **
  1999  ** Shutdown the process immediately.  This is not a clean shutdown.
  2000  ** This command is used to test the recoverability of a database in
  2001  ** the event of a program crash.
  2002  */
  2003  static int SQLITE_TCLAPI sqlite_abort(
  2004    void *NotUsed,
  2005    Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  2006    int argc,              /* Number of arguments */
  2007    char **argv            /* Text of each argument */
  2008  ){
  2009  #if defined(_MSC_VER)
  2010    /* We do this, otherwise the test will halt with a popup message
  2011     * that we have to click away before the test will continue.
  2012     */
  2013    _set_abort_behavior( 0, _CALL_REPORTFAULT );
  2014  #endif
  2015    exit(255);
  2016    assert( interp==0 );   /* This will always fail */
  2017    return TCL_OK;
  2018  }
  2019  
  2020  /*
  2021  ** The following routine is a user-defined SQL function whose purpose
  2022  ** is to test the sqlite_set_result() API.
  2023  */
  2024  static void testFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
  2025    while( argc>=2 ){
  2026      const char *zArg0 = (char*)sqlite3_value_text(argv[0]);
  2027      if( zArg0 ){
  2028        if( 0==sqlite3StrICmp(zArg0, "int") ){
  2029          sqlite3_result_int(context, sqlite3_value_int(argv[1]));
  2030        }else if( sqlite3StrICmp(zArg0,"int64")==0 ){
  2031          sqlite3_result_int64(context, sqlite3_value_int64(argv[1]));
  2032        }else if( sqlite3StrICmp(zArg0,"string")==0 ){
  2033          sqlite3_result_text(context, (char*)sqlite3_value_text(argv[1]), -1,
  2034              SQLITE_TRANSIENT);
  2035        }else if( sqlite3StrICmp(zArg0,"double")==0 ){
  2036          sqlite3_result_double(context, sqlite3_value_double(argv[1]));
  2037        }else if( sqlite3StrICmp(zArg0,"null")==0 ){
  2038          sqlite3_result_null(context);
  2039        }else if( sqlite3StrICmp(zArg0,"value")==0 ){
  2040          sqlite3_result_value(context, argv[sqlite3_value_int(argv[1])]);
  2041        }else{
  2042          goto error_out;
  2043        }
  2044      }else{
  2045        goto error_out;
  2046      }
  2047      argc -= 2;
  2048      argv += 2;
  2049    }
  2050    return;
  2051  
  2052  error_out:
  2053    sqlite3_result_error(context,"first argument should be one of: "
  2054        "int int64 string double null value", -1);
  2055  }
  2056  
  2057  /*
  2058  ** Usage:   sqlite_register_test_function  DB  NAME
  2059  **
  2060  ** Register the test SQL function on the database DB under the name NAME.
  2061  */
  2062  static int SQLITE_TCLAPI test_register_func(
  2063    void *NotUsed,
  2064    Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  2065    int argc,              /* Number of arguments */
  2066    char **argv            /* Text of each argument */
  2067  ){
  2068    sqlite3 *db;
  2069    int rc;
  2070    if( argc!=3 ){
  2071      Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 
  2072         " DB FUNCTION-NAME", 0);
  2073      return TCL_ERROR;
  2074    }
  2075    if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
  2076    rc = sqlite3_create_function(db, argv[2], -1, SQLITE_UTF8, 0, 
  2077        testFunc, 0, 0);
  2078    if( rc!=0 ){
  2079      Tcl_AppendResult(interp, sqlite3ErrStr(rc), 0);
  2080      return TCL_ERROR;
  2081    }
  2082    if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
  2083    return TCL_OK;
  2084  }
  2085  
  2086  /*
  2087  ** Usage:  sqlite3_finalize  STMT 
  2088  **
  2089  ** Finalize a statement handle.
  2090  */
  2091  static int SQLITE_TCLAPI test_finalize(
  2092    void * clientData,
  2093    Tcl_Interp *interp,
  2094    int objc,
  2095    Tcl_Obj *CONST objv[]
  2096  ){
  2097    sqlite3_stmt *pStmt;
  2098    int rc;
  2099    sqlite3 *db = 0;
  2100  
  2101    if( objc!=2 ){
  2102      Tcl_AppendResult(interp, "wrong # args: should be \"",
  2103          Tcl_GetStringFromObj(objv[0], 0), " <STMT>", 0);
  2104      return TCL_ERROR;
  2105    }
  2106  
  2107    if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
  2108  
  2109    if( pStmt ){
  2110      db = StmtToDb(pStmt);
  2111    }
  2112    rc = sqlite3_finalize(pStmt);
  2113    Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
  2114    if( db && sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
  2115    return TCL_OK;
  2116  }
  2117  
  2118  /*
  2119  ** Usage:  sqlite3_stmt_status  STMT  CODE  RESETFLAG
  2120  **
  2121  ** Get the value of a status counter from a statement.
  2122  */
  2123  static int SQLITE_TCLAPI test_stmt_status(
  2124    void * clientData,
  2125    Tcl_Interp *interp,
  2126    int objc,
  2127    Tcl_Obj *CONST objv[]
  2128  ){
  2129    int iValue;
  2130    int i, op = 0, resetFlag;
  2131    const char *zOpName;
  2132    sqlite3_stmt *pStmt;
  2133  
  2134    static const struct {
  2135      const char *zName;
  2136      int op;
  2137    } aOp[] = {
  2138      { "SQLITE_STMTSTATUS_FULLSCAN_STEP",   SQLITE_STMTSTATUS_FULLSCAN_STEP   },
  2139      { "SQLITE_STMTSTATUS_SORT",            SQLITE_STMTSTATUS_SORT            },
  2140      { "SQLITE_STMTSTATUS_AUTOINDEX",       SQLITE_STMTSTATUS_AUTOINDEX       },
  2141      { "SQLITE_STMTSTATUS_VM_STEP",         SQLITE_STMTSTATUS_VM_STEP         },
  2142      { "SQLITE_STMTSTATUS_REPREPARE",       SQLITE_STMTSTATUS_REPREPARE       },
  2143      { "SQLITE_STMTSTATUS_RUN",             SQLITE_STMTSTATUS_RUN             },
  2144      { "SQLITE_STMTSTATUS_MEMUSED",         SQLITE_STMTSTATUS_MEMUSED         },
  2145    };
  2146    if( objc!=4 ){
  2147      Tcl_WrongNumArgs(interp, 1, objv, "STMT PARAMETER RESETFLAG");
  2148      return TCL_ERROR;
  2149    }
  2150    if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
  2151    zOpName = Tcl_GetString(objv[2]);
  2152    for(i=0; i<ArraySize(aOp); i++){
  2153      if( strcmp(aOp[i].zName, zOpName)==0 ){
  2154        op = aOp[i].op;
  2155        break;
  2156      }
  2157    }
  2158    if( i>=ArraySize(aOp) ){
  2159      if( Tcl_GetIntFromObj(interp, objv[2], &op) ) return TCL_ERROR;
  2160    }
  2161    if( Tcl_GetBooleanFromObj(interp, objv[3], &resetFlag) ) return TCL_ERROR;
  2162    iValue = sqlite3_stmt_status(pStmt, op, resetFlag);
  2163    Tcl_SetObjResult(interp, Tcl_NewIntObj(iValue));
  2164    return TCL_OK;
  2165  }
  2166  
  2167  #ifdef SQLITE_ENABLE_STMT_SCANSTATUS
  2168  /*
  2169  ** Usage:  sqlite3_stmt_scanstatus STMT IDX
  2170  */
  2171  static int SQLITE_TCLAPI test_stmt_scanstatus(
  2172    void * clientData,
  2173    Tcl_Interp *interp,
  2174    int objc,
  2175    Tcl_Obj *CONST objv[]
  2176  ){
  2177    sqlite3_stmt *pStmt;            /* First argument */
  2178    int idx;                        /* Second argument */
  2179  
  2180    const char *zName;
  2181    const char *zExplain;
  2182    sqlite3_int64 nLoop;
  2183    sqlite3_int64 nVisit;
  2184    double rEst;
  2185    int res;
  2186  
  2187    if( objc!=3 ){
  2188      Tcl_WrongNumArgs(interp, 1, objv, "STMT IDX");
  2189      return TCL_ERROR;
  2190    }
  2191    if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
  2192    if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
  2193  
  2194    res = sqlite3_stmt_scanstatus(pStmt, idx, SQLITE_SCANSTAT_NLOOP, (void*)&nLoop);
  2195    if( res==0 ){
  2196      Tcl_Obj *pRet = Tcl_NewObj();
  2197      Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("nLoop", -1));
  2198      Tcl_ListObjAppendElement(0, pRet, Tcl_NewWideIntObj(nLoop));
  2199      sqlite3_stmt_scanstatus(pStmt, idx, SQLITE_SCANSTAT_NVISIT, (void*)&nVisit);
  2200      Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("nVisit", -1));
  2201      Tcl_ListObjAppendElement(0, pRet, Tcl_NewWideIntObj(nVisit));
  2202      sqlite3_stmt_scanstatus(pStmt, idx, SQLITE_SCANSTAT_EST, (void*)&rEst);
  2203      Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("nEst", -1));
  2204      Tcl_ListObjAppendElement(0, pRet, Tcl_NewDoubleObj(rEst));
  2205      sqlite3_stmt_scanstatus(pStmt, idx, SQLITE_SCANSTAT_NAME, (void*)&zName);
  2206      Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("zName", -1));
  2207      Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zName, -1));
  2208      sqlite3_stmt_scanstatus(pStmt, idx, SQLITE_SCANSTAT_EXPLAIN, (void*)&zExplain);
  2209      Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("zExplain", -1));
  2210      Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zExplain, -1));
  2211      Tcl_SetObjResult(interp, pRet);
  2212    }else{
  2213      Tcl_ResetResult(interp);
  2214    }
  2215    return TCL_OK;
  2216  }
  2217  
  2218  /*
  2219  ** Usage:  sqlite3_stmt_scanstatus_reset  STMT
  2220  */
  2221  static int SQLITE_TCLAPI test_stmt_scanstatus_reset(
  2222    void * clientData,
  2223    Tcl_Interp *interp,
  2224    int objc,
  2225    Tcl_Obj *CONST objv[]
  2226  ){
  2227    sqlite3_stmt *pStmt;            /* First argument */
  2228    if( objc!=2 ){
  2229      Tcl_WrongNumArgs(interp, 1, objv, "STMT");
  2230      return TCL_ERROR;
  2231    }
  2232    if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
  2233    sqlite3_stmt_scanstatus_reset(pStmt);
  2234    return TCL_OK;
  2235  }
  2236  #endif
  2237  
  2238  #ifdef SQLITE_ENABLE_SQLLOG
  2239  /*
  2240  ** Usage:  sqlite3_config_sqllog
  2241  **
  2242  ** Zero the SQLITE_CONFIG_SQLLOG configuration
  2243  */
  2244  static int SQLITE_TCLAPI test_config_sqllog(
  2245    void * clientData,
  2246    Tcl_Interp *interp,
  2247    int objc,
  2248    Tcl_Obj *CONST objv[]
  2249  ){
  2250    if( objc!=1 ){
  2251      Tcl_WrongNumArgs(interp, 1, objv, "");
  2252      return TCL_ERROR;
  2253    }
  2254    sqlite3_config(SQLITE_CONFIG_SQLLOG, 0, 0);
  2255    return TCL_OK;
  2256  }
  2257  #endif
  2258  
  2259  /*
  2260  ** Usage: vfs_current_time_int64
  2261  **
  2262  ** Return the value returned by the default VFS's xCurrentTimeInt64 method.
  2263  */
  2264  static int SQLITE_TCLAPI vfsCurrentTimeInt64(
  2265    void * clientData,
  2266    Tcl_Interp *interp,
  2267    int objc,
  2268    Tcl_Obj *CONST objv[]
  2269  ){
  2270    i64 t;
  2271    sqlite3_vfs *pVfs = sqlite3_vfs_find(0);
  2272    if( objc!=1 ){
  2273      Tcl_WrongNumArgs(interp, 1, objv, "");
  2274      return TCL_ERROR;
  2275    }
  2276    pVfs->xCurrentTimeInt64(pVfs, &t);
  2277    Tcl_SetObjResult(interp, Tcl_NewWideIntObj(t));
  2278    return TCL_OK;
  2279  }
  2280  
  2281  #ifdef SQLITE_ENABLE_SNAPSHOT
  2282  /*
  2283  ** Usage: sqlite3_snapshot_get DB DBNAME
  2284  */
  2285  static int SQLITE_TCLAPI test_snapshot_get(
  2286    void * clientData,
  2287    Tcl_Interp *interp,
  2288    int objc,
  2289    Tcl_Obj *CONST objv[]
  2290  ){
  2291    int rc;
  2292    sqlite3 *db;
  2293    char *zName;
  2294    sqlite3_snapshot *pSnapshot = 0;
  2295  
  2296    if( objc!=3 ){
  2297      Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME");
  2298      return TCL_ERROR;
  2299    }
  2300    if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
  2301    zName = Tcl_GetString(objv[2]);
  2302  
  2303    rc = sqlite3_snapshot_get(db, zName, &pSnapshot);
  2304    if( rc!=SQLITE_OK ){
  2305      Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
  2306      return TCL_ERROR;
  2307    }else{
  2308      char zBuf[100];
  2309      if( sqlite3TestMakePointerStr(interp, zBuf, pSnapshot) ) return TCL_ERROR;
  2310      Tcl_SetObjResult(interp, Tcl_NewStringObj(zBuf, -1));
  2311    }
  2312    return TCL_OK;
  2313  }
  2314  #endif /* SQLITE_ENABLE_SNAPSHOT */
  2315  
  2316  #ifdef SQLITE_ENABLE_SNAPSHOT
  2317  /*
  2318  ** Usage: sqlite3_snapshot_recover DB DBNAME
  2319  */
  2320  static int SQLITE_TCLAPI test_snapshot_recover(
  2321    void * clientData,
  2322    Tcl_Interp *interp,
  2323    int objc,
  2324    Tcl_Obj *CONST objv[]
  2325  ){
  2326    int rc;
  2327    sqlite3 *db;
  2328    char *zName;
  2329  
  2330    if( objc!=3 ){
  2331      Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME");
  2332      return TCL_ERROR;
  2333    }
  2334    if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
  2335    zName = Tcl_GetString(objv[2]);
  2336  
  2337    rc = sqlite3_snapshot_recover(db, zName);
  2338    if( rc!=SQLITE_OK ){
  2339      Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
  2340      return TCL_ERROR;
  2341    }else{
  2342      Tcl_ResetResult(interp);
  2343    }
  2344    return TCL_OK;
  2345  }
  2346  #endif /* SQLITE_ENABLE_SNAPSHOT */
  2347  
  2348  #ifdef SQLITE_ENABLE_SNAPSHOT
  2349  /*
  2350  ** Usage: sqlite3_snapshot_open DB DBNAME SNAPSHOT
  2351  */
  2352  static int SQLITE_TCLAPI test_snapshot_open(
  2353    void * clientData,
  2354    Tcl_Interp *interp,
  2355    int objc,
  2356    Tcl_Obj *CONST objv[]
  2357  ){
  2358    int rc;
  2359    sqlite3 *db;
  2360    char *zName;
  2361    sqlite3_snapshot *pSnapshot;
  2362  
  2363    if( objc!=4 ){
  2364      Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME SNAPSHOT");
  2365      return TCL_ERROR;
  2366    }
  2367    if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
  2368    zName = Tcl_GetString(objv[2]);
  2369    pSnapshot = (sqlite3_snapshot*)sqlite3TestTextToPtr(Tcl_GetString(objv[3]));
  2370  
  2371    rc = sqlite3_snapshot_open(db, zName, pSnapshot);
  2372    if( rc!=SQLITE_OK ){
  2373      Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
  2374      return TCL_ERROR;
  2375    }
  2376    return TCL_OK;
  2377  }
  2378  #endif /* SQLITE_ENABLE_SNAPSHOT */
  2379  
  2380  #ifdef SQLITE_ENABLE_SNAPSHOT
  2381  /*
  2382  ** Usage: sqlite3_snapshot_free SNAPSHOT
  2383  */
  2384  static int SQLITE_TCLAPI test_snapshot_free(
  2385    void * clientData,
  2386    Tcl_Interp *interp,
  2387    int objc,
  2388    Tcl_Obj *CONST objv[]
  2389  ){
  2390    sqlite3_snapshot *pSnapshot;
  2391    if( objc!=2 ){
  2392      Tcl_WrongNumArgs(interp, 1, objv, "SNAPSHOT");
  2393      return TCL_ERROR;
  2394    }
  2395    pSnapshot = (sqlite3_snapshot*)sqlite3TestTextToPtr(Tcl_GetString(objv[1]));
  2396    sqlite3_snapshot_free(pSnapshot);
  2397    return TCL_OK;
  2398  }
  2399  #endif /* SQLITE_ENABLE_SNAPSHOT */
  2400  
  2401  #ifdef SQLITE_ENABLE_SNAPSHOT
  2402  /*
  2403  ** Usage: sqlite3_snapshot_cmp SNAPSHOT1 SNAPSHOT2
  2404  */
  2405  static int SQLITE_TCLAPI test_snapshot_cmp(
  2406    void * clientData,
  2407    Tcl_Interp *interp,
  2408    int objc,
  2409    Tcl_Obj *CONST objv[]
  2410  ){
  2411    int res;
  2412    sqlite3_snapshot *p1;
  2413    sqlite3_snapshot *p2;
  2414    if( objc!=3 ){
  2415      Tcl_WrongNumArgs(interp, 1, objv, "SNAPSHOT1 SNAPSHOT2");
  2416      return TCL_ERROR;
  2417    }
  2418    p1 = (sqlite3_snapshot*)sqlite3TestTextToPtr(Tcl_GetString(objv[1]));
  2419    p2 = (sqlite3_snapshot*)sqlite3TestTextToPtr(Tcl_GetString(objv[2]));
  2420    res = sqlite3_snapshot_cmp(p1, p2);
  2421    Tcl_SetObjResult(interp, Tcl_NewIntObj(res));
  2422    return TCL_OK;
  2423  }
  2424  #endif /* SQLITE_ENABLE_SNAPSHOT */
  2425  
  2426  #ifdef SQLITE_ENABLE_SNAPSHOT
  2427  /*
  2428  ** Usage: sqlite3_snapshot_get_blob DB DBNAME
  2429  */
  2430  static int SQLITE_TCLAPI test_snapshot_get_blob(
  2431    void * clientData,
  2432    Tcl_Interp *interp,
  2433    int objc,
  2434    Tcl_Obj *CONST objv[]
  2435  ){
  2436    int rc;
  2437    sqlite3 *db;
  2438    char *zName;
  2439    sqlite3_snapshot *pSnapshot = 0;
  2440  
  2441    if( objc!=3 ){
  2442      Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME");
  2443      return TCL_ERROR;
  2444    }
  2445    if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
  2446    zName = Tcl_GetString(objv[2]);
  2447  
  2448    rc = sqlite3_snapshot_get(db, zName, &pSnapshot);
  2449    if( rc!=SQLITE_OK ){
  2450      Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
  2451      return TCL_ERROR;
  2452    }else{
  2453      Tcl_SetObjResult(interp, 
  2454          Tcl_NewByteArrayObj((unsigned char*)pSnapshot, sizeof(sqlite3_snapshot))
  2455      );
  2456      sqlite3_snapshot_free(pSnapshot);
  2457    }
  2458    return TCL_OK;
  2459  }
  2460  #endif /* SQLITE_ENABLE_SNAPSHOT */
  2461  
  2462  #ifdef SQLITE_ENABLE_SNAPSHOT
  2463    /*
  2464    ** Usage: sqlite3_snapshot_open_blob DB DBNAME SNAPSHOT
  2465  */
  2466  static int SQLITE_TCLAPI test_snapshot_open_blob(
  2467    void * clientData,
  2468    Tcl_Interp *interp,
  2469    int objc,
  2470    Tcl_Obj *CONST objv[]
  2471  ){
  2472    int rc;
  2473    sqlite3 *db;
  2474    char *zName;
  2475    unsigned char *pBlob;
  2476    int nBlob;
  2477  
  2478    if( objc!=4 ){
  2479      Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME SNAPSHOT");
  2480      return TCL_ERROR;
  2481    }
  2482    if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
  2483    zName = Tcl_GetString(objv[2]);
  2484    pBlob = Tcl_GetByteArrayFromObj(objv[3], &nBlob);
  2485    if( nBlob!=sizeof(sqlite3_snapshot) ){
  2486      Tcl_AppendResult(interp, "bad SNAPSHOT", 0);
  2487      return TCL_ERROR;
  2488    }
  2489    rc = sqlite3_snapshot_open(db, zName, (sqlite3_snapshot*)pBlob);
  2490    if( rc!=SQLITE_OK ){
  2491      Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
  2492      return TCL_ERROR;
  2493    }
  2494    return TCL_OK;
  2495  }
  2496  #endif /* SQLITE_ENABLE_SNAPSHOT */
  2497  
  2498  #ifdef SQLITE_ENABLE_SNAPSHOT
  2499  /*
  2500  ** Usage: sqlite3_snapshot_cmp_blob SNAPSHOT1 SNAPSHOT2
  2501  */
  2502  static int SQLITE_TCLAPI test_snapshot_cmp_blob(
  2503    void * clientData,
  2504    Tcl_Interp *interp,
  2505    int objc,
  2506    Tcl_Obj *CONST objv[]
  2507  ){
  2508    int res;
  2509    unsigned char *p1;
  2510    unsigned char *p2;
  2511    int n1;
  2512    int n2;
  2513  
  2514    if( objc!=3 ){
  2515      Tcl_WrongNumArgs(interp, 1, objv, "SNAPSHOT1 SNAPSHOT2");
  2516      return TCL_ERROR;
  2517    }
  2518  
  2519    p1 = Tcl_GetByteArrayFromObj(objv[1], &n1);
  2520    p2 = Tcl_GetByteArrayFromObj(objv[2], &n2);
  2521  
  2522    if( n1!=sizeof(sqlite3_snapshot) || n1!=n2 ){
  2523      Tcl_AppendResult(interp, "bad SNAPSHOT", 0);
  2524      return TCL_ERROR;
  2525    }
  2526  
  2527    res = sqlite3_snapshot_cmp((sqlite3_snapshot*)p1, (sqlite3_snapshot*)p2);
  2528    Tcl_SetObjResult(interp, Tcl_NewIntObj(res));
  2529    return TCL_OK;
  2530  }
  2531  #endif /* SQLITE_ENABLE_SNAPSHOT */
  2532  
  2533  /*
  2534  ** Usage: sqlite3_delete_database FILENAME
  2535  */
  2536  int sqlite3_delete_database(const char*);   /* in test_delete.c */
  2537  static int SQLITE_TCLAPI test_delete_database(
  2538    void * clientData,
  2539    Tcl_Interp *interp,
  2540    int objc,
  2541    Tcl_Obj *CONST objv[]
  2542  ){
  2543    int rc;
  2544    const char *zFile;
  2545    if( objc!=2 ){
  2546      Tcl_WrongNumArgs(interp, 1, objv, "FILE");
  2547      return TCL_ERROR;
  2548    }
  2549    zFile = (const char*)Tcl_GetString(objv[1]);
  2550    rc = sqlite3_delete_database(zFile);
  2551  
  2552    Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
  2553    return TCL_OK;
  2554  }
  2555  
  2556  /*
  2557  ** Usage: atomic_batch_write PATH
  2558  */
  2559  static int SQLITE_TCLAPI test_atomic_batch_write(
  2560    void * clientData,
  2561    Tcl_Interp *interp,
  2562    int objc,
  2563    Tcl_Obj *CONST objv[]
  2564  ){
  2565    char *zFile = 0;                /* Path to file to test */
  2566    sqlite3 *db = 0;                /* Database handle */
  2567    sqlite3_file *pFd = 0;          /* SQLite fd open on zFile */
  2568    int bRes = 0;                   /* Integer result of this command */
  2569    int dc = 0;                     /* Device-characteristics mask */
  2570    int rc;                         /* sqlite3_open() return code */
  2571  
  2572    if( objc!=2 ){
  2573      Tcl_WrongNumArgs(interp, 1, objv, "PATH");
  2574      return TCL_ERROR;
  2575    }
  2576    zFile = Tcl_GetString(objv[1]);
  2577  
  2578    rc = sqlite3_open(zFile, &db);
  2579    if( rc!=SQLITE_OK ){
  2580      Tcl_AppendResult(interp, sqlite3_errmsg(db), 0);
  2581      sqlite3_close(db);
  2582      return TCL_ERROR;
  2583    }
  2584  
  2585    rc = sqlite3_file_control(db, "main", SQLITE_FCNTL_FILE_POINTER, (void*)&pFd);
  2586    dc = pFd->pMethods->xDeviceCharacteristics(pFd);
  2587    if( dc & SQLITE_IOCAP_BATCH_ATOMIC ){
  2588      bRes = 1;
  2589    }
  2590  
  2591    Tcl_SetObjResult(interp, Tcl_NewIntObj(bRes));
  2592    sqlite3_close(db);
  2593    return TCL_OK;
  2594  }
  2595  
  2596  /*
  2597  ** Usage:  sqlite3_next_stmt  DB  STMT
  2598  **
  2599  ** Return the next statment in sequence after STMT.
  2600  */
  2601  static int SQLITE_TCLAPI test_next_stmt(
  2602    void * clientData,
  2603    Tcl_Interp *interp,
  2604    int objc,
  2605    Tcl_Obj *CONST objv[]
  2606  ){
  2607    sqlite3_stmt *pStmt;
  2608    sqlite3 *db = 0;
  2609    char zBuf[50];
  2610  
  2611    if( objc!=3 ){
  2612      Tcl_AppendResult(interp, "wrong # args: should be \"",
  2613          Tcl_GetStringFromObj(objv[0], 0), " DB STMT", 0);
  2614      return TCL_ERROR;
  2615    }
  2616  
  2617    if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
  2618    if( getStmtPointer(interp, Tcl_GetString(objv[2]), &pStmt) ) return TCL_ERROR;
  2619    pStmt = sqlite3_next_stmt(db, pStmt);
  2620    if( pStmt ){
  2621      if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR;
  2622      Tcl_AppendResult(interp, zBuf, 0);
  2623    }
  2624    return TCL_OK;
  2625  }
  2626  
  2627  /*
  2628  ** Usage:  sqlite3_stmt_readonly  STMT
  2629  **
  2630  ** Return true if STMT is a NULL pointer or a pointer to a statement
  2631  ** that is guaranteed to leave the database unmodified.
  2632  */
  2633  static int SQLITE_TCLAPI test_stmt_readonly(
  2634    void * clientData,
  2635    Tcl_Interp *interp,
  2636    int objc,
  2637    Tcl_Obj *CONST objv[]
  2638  ){
  2639    sqlite3_stmt *pStmt;
  2640    int rc;
  2641  
  2642    if( objc!=2 ){
  2643      Tcl_AppendResult(interp, "wrong # args: should be \"",
  2644          Tcl_GetStringFromObj(objv[0], 0), " STMT", 0);
  2645      return TCL_ERROR;
  2646    }
  2647  
  2648    if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
  2649    rc = sqlite3_stmt_readonly(pStmt);
  2650    Tcl_SetObjResult(interp, Tcl_NewBooleanObj(rc));
  2651    return TCL_OK;
  2652  }
  2653  
  2654  /*
  2655  ** Usage:  sqlite3_stmt_busy  STMT
  2656  **
  2657  ** Return true if STMT is a non-NULL pointer to a statement
  2658  ** that has been stepped but not to completion.
  2659  */
  2660  static int SQLITE_TCLAPI test_stmt_busy(
  2661    void * clientData,
  2662    Tcl_Interp *interp,
  2663    int objc,
  2664    Tcl_Obj *CONST objv[]
  2665  ){
  2666    sqlite3_stmt *pStmt;
  2667    int rc;
  2668  
  2669    if( objc!=2 ){
  2670      Tcl_AppendResult(interp, "wrong # args: should be \"",
  2671          Tcl_GetStringFromObj(objv[0], 0), " STMT", 0);
  2672      return TCL_ERROR;
  2673    }
  2674  
  2675    if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
  2676    rc = sqlite3_stmt_busy(pStmt);
  2677    Tcl_SetObjResult(interp, Tcl_NewBooleanObj(rc));
  2678    return TCL_OK;
  2679  }
  2680  
  2681  /*
  2682  ** Usage:  uses_stmt_journal  STMT
  2683  **
  2684  ** Return true if STMT uses a statement journal.
  2685  */
  2686  static int SQLITE_TCLAPI uses_stmt_journal(
  2687    void * clientData,
  2688    Tcl_Interp *interp,
  2689    int objc,
  2690    Tcl_Obj *CONST objv[]
  2691  ){
  2692    sqlite3_stmt *pStmt;
  2693  
  2694    if( objc!=2 ){
  2695      Tcl_AppendResult(interp, "wrong # args: should be \"",
  2696          Tcl_GetStringFromObj(objv[0], 0), " STMT", 0);
  2697      return TCL_ERROR;
  2698    }
  2699  
  2700    if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
  2701    sqlite3_stmt_readonly(pStmt);
  2702    Tcl_SetObjResult(interp, Tcl_NewBooleanObj(((Vdbe *)pStmt)->usesStmtJournal));
  2703    return TCL_OK;
  2704  }
  2705  
  2706  
  2707  /*
  2708  ** Usage:  sqlite3_reset  STMT 
  2709  **
  2710  ** Reset a statement handle.
  2711  */
  2712  static int SQLITE_TCLAPI test_reset(
  2713    void * clientData,
  2714    Tcl_Interp *interp,
  2715    int objc,
  2716    Tcl_Obj *CONST objv[]
  2717  ){
  2718    sqlite3_stmt *pStmt;
  2719    int rc;
  2720  
  2721    if( objc!=2 ){
  2722      Tcl_AppendResult(interp, "wrong # args: should be \"",
  2723          Tcl_GetStringFromObj(objv[0], 0), " <STMT>", 0);
  2724      return TCL_ERROR;
  2725    }
  2726  
  2727    if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
  2728  
  2729    rc = sqlite3_reset(pStmt);
  2730    if( pStmt && sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ){
  2731      return TCL_ERROR;
  2732    }
  2733    Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
  2734  /*
  2735    if( rc ){
  2736      return TCL_ERROR;
  2737    }
  2738  */
  2739    return TCL_OK;
  2740  }
  2741  
  2742  /*
  2743  ** Usage:  sqlite3_expired STMT 
  2744  **
  2745  ** Return TRUE if a recompilation of the statement is recommended.
  2746  */
  2747  static int SQLITE_TCLAPI test_expired(
  2748    void * clientData,
  2749    Tcl_Interp *interp,
  2750    int objc,
  2751    Tcl_Obj *CONST objv[]
  2752  ){
  2753  #ifndef SQLITE_OMIT_DEPRECATED
  2754    sqlite3_stmt *pStmt;
  2755    if( objc!=2 ){
  2756      Tcl_AppendResult(interp, "wrong # args: should be \"",
  2757          Tcl_GetStringFromObj(objv[0], 0), " <STMT>", 0);
  2758      return TCL_ERROR;
  2759    }
  2760    if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
  2761    Tcl_SetObjResult(interp, Tcl_NewBooleanObj(sqlite3_expired(pStmt)));
  2762  #endif
  2763    return TCL_OK;
  2764  }
  2765  
  2766  /*
  2767  ** Usage:  sqlite3_transfer_bindings FROMSTMT TOSTMT
  2768  **
  2769  ** Transfer all bindings from FROMSTMT over to TOSTMT
  2770  */
  2771  static int SQLITE_TCLAPI test_transfer_bind(
  2772    void * clientData,
  2773    Tcl_Interp *interp,
  2774    int objc,
  2775    Tcl_Obj *CONST objv[]
  2776  ){
  2777  #ifndef SQLITE_OMIT_DEPRECATED
  2778    sqlite3_stmt *pStmt1, *pStmt2;
  2779    if( objc!=3 ){
  2780      Tcl_AppendResult(interp, "wrong # args: should be \"",
  2781          Tcl_GetStringFromObj(objv[0], 0), " FROM-STMT TO-STMT", 0);
  2782      return TCL_ERROR;
  2783    }
  2784    if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt1)) return TCL_ERROR;
  2785    if( getStmtPointer(interp, Tcl_GetString(objv[2]), &pStmt2)) return TCL_ERROR;
  2786    Tcl_SetObjResult(interp, 
  2787       Tcl_NewIntObj(sqlite3_transfer_bindings(pStmt1,pStmt2)));
  2788  #endif
  2789    return TCL_OK;
  2790  }
  2791  
  2792  /*
  2793  ** Usage:  sqlite3_changes DB
  2794  **
  2795  ** Return the number of changes made to the database by the last SQL
  2796  ** execution.
  2797  */
  2798  static int SQLITE_TCLAPI test_changes(
  2799    void * clientData,
  2800    Tcl_Interp *interp,
  2801    int objc,
  2802    Tcl_Obj *CONST objv[]
  2803  ){
  2804    sqlite3 *db;
  2805    if( objc!=2 ){
  2806      Tcl_AppendResult(interp, "wrong # args: should be \"",
  2807         Tcl_GetString(objv[0]), " DB", 0);
  2808      return TCL_ERROR;
  2809    }
  2810    if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
  2811    Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_changes(db)));
  2812    return TCL_OK;
  2813  }
  2814  
  2815  /*
  2816  ** This is the "static_bind_value" that variables are bound to when
  2817  ** the FLAG option of sqlite3_bind is "static"
  2818  */
  2819  static char *sqlite_static_bind_value = 0;
  2820  static int sqlite_static_bind_nbyte = 0;
  2821  
  2822  /*
  2823  ** Usage:  sqlite3_bind  VM  IDX  VALUE  FLAGS
  2824  **
  2825  ** Sets the value of the IDX-th occurrence of "?" in the original SQL
  2826  ** string.  VALUE is the new value.  If FLAGS=="null" then VALUE is
  2827  ** ignored and the value is set to NULL.  If FLAGS=="static" then
  2828  ** the value is set to the value of a static variable named
  2829  ** "sqlite_static_bind_value".  If FLAGS=="normal" then a copy
  2830  ** of the VALUE is made.  If FLAGS=="blob10" then a VALUE is ignored
  2831  ** an a 10-byte blob "abc\000xyz\000pq" is inserted.
  2832  */
  2833  static int SQLITE_TCLAPI test_bind(
  2834    void *NotUsed,
  2835    Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  2836    int argc,              /* Number of arguments */
  2837    char **argv            /* Text of each argument */
  2838  ){
  2839    sqlite3_stmt *pStmt;
  2840    int rc;
  2841    int idx;
  2842    if( argc!=5 ){
  2843      Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 
  2844         " VM IDX VALUE (null|static|normal)\"", 0);
  2845      return TCL_ERROR;
  2846    }
  2847    if( getStmtPointer(interp, argv[1], &pStmt) ) return TCL_ERROR;
  2848    if( Tcl_GetInt(interp, argv[2], &idx) ) return TCL_ERROR;
  2849    if( strcmp(argv[4],"null")==0 ){
  2850      rc = sqlite3_bind_null(pStmt, idx);
  2851    }else if( strcmp(argv[4],"static")==0 ){
  2852      rc = sqlite3_bind_text(pStmt, idx, sqlite_static_bind_value, -1, 0);
  2853    }else if( strcmp(argv[4],"static-nbytes")==0 ){
  2854      rc = sqlite3_bind_text(pStmt, idx, sqlite_static_bind_value,
  2855                                         sqlite_static_bind_nbyte, 0);
  2856    }else if( strcmp(argv[4],"normal")==0 ){
  2857      rc = sqlite3_bind_text(pStmt, idx, argv[3], -1, SQLITE_TRANSIENT);
  2858    }else if( strcmp(argv[4],"blob10")==0 ){
  2859      rc = sqlite3_bind_text(pStmt, idx, "abc\000xyz\000pq", 10, SQLITE_STATIC);
  2860    }else{
  2861      Tcl_AppendResult(interp, "4th argument should be "
  2862          "\"null\" or \"static\" or \"normal\"", 0);
  2863      return TCL_ERROR;
  2864    }
  2865    if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
  2866    if( rc ){
  2867      char zBuf[50];
  2868      sqlite3_snprintf(sizeof(zBuf), zBuf, "(%d) ", rc);
  2869      Tcl_AppendResult(interp, zBuf, sqlite3ErrStr(rc), 0);
  2870      return TCL_ERROR;
  2871    }
  2872    return TCL_OK;
  2873  }
  2874  
  2875  #ifndef SQLITE_OMIT_UTF16
  2876  /*
  2877  ** Usage: add_test_collate <db ptr> <utf8> <utf16le> <utf16be>
  2878  **
  2879  ** This function is used to test that SQLite selects the correct collation
  2880  ** sequence callback when multiple versions (for different text encodings)
  2881  ** are available.
  2882  **
  2883  ** Calling this routine registers the collation sequence "test_collate"
  2884  ** with database handle <db>. The second argument must be a list of three
  2885  ** boolean values. If the first is true, then a version of test_collate is
  2886  ** registered for UTF-8, if the second is true, a version is registered for
  2887  ** UTF-16le, if the third is true, a UTF-16be version is available.
  2888  ** Previous versions of test_collate are deleted.
  2889  **
  2890  ** The collation sequence test_collate is implemented by calling the
  2891  ** following TCL script:
  2892  **
  2893  **   "test_collate <enc> <lhs> <rhs>"
  2894  **
  2895  ** The <lhs> and <rhs> are the two values being compared, encoded in UTF-8.
  2896  ** The <enc> parameter is the encoding of the collation function that
  2897  ** SQLite selected to call. The TCL test script implements the
  2898  ** "test_collate" proc.
  2899  **
  2900  ** Note that this will only work with one interpreter at a time, as the
  2901  ** interp pointer to use when evaluating the TCL script is stored in
  2902  ** pTestCollateInterp.
  2903  */
  2904  static Tcl_Interp* pTestCollateInterp;
  2905  static int test_collate_func(
  2906    void *pCtx, 
  2907    int nA, const void *zA,
  2908    int nB, const void *zB
  2909  ){
  2910    Tcl_Interp *i = pTestCollateInterp;
  2911    int encin = SQLITE_PTR_TO_INT(pCtx);
  2912    int res;
  2913    int n;
  2914  
  2915    sqlite3_value *pVal;
  2916    Tcl_Obj *pX;
  2917  
  2918    pX = Tcl_NewStringObj("test_collate", -1);
  2919    Tcl_IncrRefCount(pX);
  2920  
  2921    switch( encin ){
  2922      case SQLITE_UTF8:
  2923        Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-8",-1));
  2924        break;
  2925      case SQLITE_UTF16LE:
  2926        Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-16LE",-1));
  2927        break;
  2928      case SQLITE_UTF16BE:
  2929        Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-16BE",-1));
  2930        break;
  2931      default:
  2932        assert(0);
  2933    }
  2934  
  2935    sqlite3BeginBenignMalloc();
  2936    pVal = sqlite3ValueNew(0);
  2937    if( pVal ){
  2938      sqlite3ValueSetStr(pVal, nA, zA, encin, SQLITE_STATIC);
  2939      n = sqlite3_value_bytes(pVal);
  2940      Tcl_ListObjAppendElement(i,pX,
  2941          Tcl_NewStringObj((char*)sqlite3_value_text(pVal),n));
  2942      sqlite3ValueSetStr(pVal, nB, zB, encin, SQLITE_STATIC);
  2943      n = sqlite3_value_bytes(pVal);
  2944      Tcl_ListObjAppendElement(i,pX,
  2945          Tcl_NewStringObj((char*)sqlite3_value_text(pVal),n));
  2946      sqlite3ValueFree(pVal);
  2947    }
  2948    sqlite3EndBenignMalloc();
  2949  
  2950    Tcl_EvalObjEx(i, pX, 0);
  2951    Tcl_DecrRefCount(pX);
  2952    Tcl_GetIntFromObj(i, Tcl_GetObjResult(i), &res);
  2953    return res;
  2954  }
  2955  static int SQLITE_TCLAPI test_collate(
  2956    void * clientData,
  2957    Tcl_Interp *interp,
  2958    int objc,
  2959    Tcl_Obj *CONST objv[]
  2960  ){
  2961    sqlite3 *db;
  2962    int val;
  2963    sqlite3_value *pVal;
  2964    int rc;
  2965  
  2966    if( objc!=5 ) goto bad_args;
  2967    pTestCollateInterp = interp;
  2968    if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
  2969  
  2970    if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[2], &val) ) return TCL_ERROR;
  2971    rc = sqlite3_create_collation(db, "test_collate", SQLITE_UTF8, 
  2972            (void *)SQLITE_UTF8, val?test_collate_func:0);
  2973    if( rc==SQLITE_OK ){
  2974      const void *zUtf16;
  2975      if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[3], &val) ) return TCL_ERROR;
  2976      rc = sqlite3_create_collation(db, "test_collate", SQLITE_UTF16LE, 
  2977              (void *)SQLITE_UTF16LE, val?test_collate_func:0);
  2978      if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[4], &val) ) return TCL_ERROR;
  2979  
  2980  #if 0
  2981      if( sqlite3_iMallocFail>0 ){
  2982        sqlite3_iMallocFail++;
  2983      }
  2984  #endif
  2985      sqlite3_mutex_enter(db->mutex);
  2986      pVal = sqlite3ValueNew(db);
  2987      sqlite3ValueSetStr(pVal, -1, "test_collate", SQLITE_UTF8, SQLITE_STATIC);
  2988      zUtf16 = sqlite3ValueText(pVal, SQLITE_UTF16NATIVE);
  2989      if( db->mallocFailed ){
  2990        rc = SQLITE_NOMEM;
  2991      }else{
  2992        rc = sqlite3_create_collation16(db, zUtf16, SQLITE_UTF16BE, 
  2993            (void *)SQLITE_UTF16BE, val?test_collate_func:0);
  2994      }
  2995      sqlite3ValueFree(pVal);
  2996      sqlite3_mutex_leave(db->mutex);
  2997    }
  2998    if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
  2999    
  3000    if( rc!=SQLITE_OK ){
  3001      Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
  3002      return TCL_ERROR;
  3003    }
  3004    return TCL_OK;
  3005  
  3006  bad_args:
  3007    Tcl_AppendResult(interp, "wrong # args: should be \"",
  3008        Tcl_GetStringFromObj(objv[0], 0), " <DB> <utf8> <utf16le> <utf16be>", 0);
  3009    return TCL_ERROR;
  3010  }
  3011  
  3012  /*
  3013  ** Usage: add_test_utf16bin_collate <db ptr>
  3014  **
  3015  ** Add a utf-16 collation sequence named "utf16bin" to the database
  3016  ** handle. This collation sequence compares arguments in the same way as the
  3017  ** built-in collation "binary".
  3018  */
  3019  static int test_utf16bin_collate_func(
  3020    void *pCtx, 
  3021    int nA, const void *zA,
  3022    int nB, const void *zB
  3023  ){
  3024    int nCmp = (nA>nB ? nB : nA);
  3025    int res = memcmp(zA, zB, nCmp);
  3026    if( res==0 ) res = nA - nB;
  3027    return res;
  3028  }
  3029  static int SQLITE_TCLAPI test_utf16bin_collate(
  3030    void * clientData,
  3031    Tcl_Interp *interp,
  3032    int objc,
  3033    Tcl_Obj *CONST objv[]
  3034  ){
  3035    sqlite3 *db;
  3036    int rc;
  3037  
  3038    if( objc!=2 ) goto bad_args;
  3039    if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
  3040  
  3041    rc = sqlite3_create_collation(db, "utf16bin", SQLITE_UTF16, 0, 
  3042        test_utf16bin_collate_func
  3043    );
  3044    if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
  3045    return TCL_OK;
  3046  
  3047  bad_args:
  3048    Tcl_WrongNumArgs(interp, 1, objv, "DB");
  3049    return TCL_ERROR;
  3050  }
  3051  
  3052  /*
  3053  ** When the collation needed callback is invoked, record the name of 
  3054  ** the requested collating function here.  The recorded name is linked
  3055  ** to a TCL variable and used to make sure that the requested collation
  3056  ** name is correct.
  3057  */
  3058  static char zNeededCollation[200];
  3059  static char *pzNeededCollation = zNeededCollation;
  3060  
  3061  
  3062  /*
  3063  ** Called when a collating sequence is needed.  Registered using
  3064  ** sqlite3_collation_needed16().
  3065  */
  3066  static void test_collate_needed_cb(
  3067    void *pCtx, 
  3068    sqlite3 *db,
  3069    int eTextRep,
  3070    const void *pName
  3071  ){
  3072    int enc = ENC(db);
  3073    int i;
  3074    char *z;
  3075    for(z = (char*)pName, i=0; *z || z[1]; z++){
  3076      if( *z ) zNeededCollation[i++] = *z;
  3077    }
  3078    zNeededCollation[i] = 0;
  3079    sqlite3_create_collation(
  3080        db, "test_collate", ENC(db), SQLITE_INT_TO_PTR(enc), test_collate_func);
  3081  }
  3082  
  3083  /*
  3084  ** Usage: add_test_collate_needed DB
  3085  */
  3086  static int SQLITE_TCLAPI test_collate_needed(
  3087    void * clientData,
  3088    Tcl_Interp *interp,
  3089    int objc,
  3090    Tcl_Obj *CONST objv[]
  3091  ){
  3092    sqlite3 *db;
  3093    int rc;
  3094  
  3095    if( objc!=2 ) goto bad_args;
  3096    if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
  3097    rc = sqlite3_collation_needed16(db, 0, test_collate_needed_cb);
  3098    zNeededCollation[0] = 0;
  3099    if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
  3100    return TCL_OK;
  3101  
  3102  bad_args:
  3103    Tcl_WrongNumArgs(interp, 1, objv, "DB");
  3104    return TCL_ERROR;
  3105  }
  3106  
  3107  /*
  3108  ** tclcmd:   add_alignment_test_collations  DB
  3109  **
  3110  ** Add two new collating sequences to the database DB
  3111  **
  3112  **     utf16_aligned
  3113  **     utf16_unaligned
  3114  **
  3115  ** Both collating sequences use the same sort order as BINARY.
  3116  ** The only difference is that the utf16_aligned collating
  3117  ** sequence is declared with the SQLITE_UTF16_ALIGNED flag.
  3118  ** Both collating functions increment the unaligned utf16 counter
  3119  ** whenever they see a string that begins on an odd byte boundary.
  3120  */
  3121  static int unaligned_string_counter = 0;
  3122  static int alignmentCollFunc(
  3123    void *NotUsed,
  3124    int nKey1, const void *pKey1,
  3125    int nKey2, const void *pKey2
  3126  ){
  3127    int rc, n;
  3128    n = nKey1<nKey2 ? nKey1 : nKey2;
  3129    if( nKey1>0 && 1==(1&(SQLITE_PTR_TO_INT(pKey1))) ) unaligned_string_counter++;
  3130    if( nKey2>0 && 1==(1&(SQLITE_PTR_TO_INT(pKey2))) ) unaligned_string_counter++;
  3131    rc = memcmp(pKey1, pKey2, n);
  3132    if( rc==0 ){
  3133      rc = nKey1 - nKey2;
  3134    }
  3135    return rc;
  3136  }
  3137  static int SQLITE_TCLAPI add_alignment_test_collations(
  3138    void * clientData,
  3139    Tcl_Interp *interp,
  3140    int objc,
  3141    Tcl_Obj *CONST objv[]
  3142  ){
  3143    sqlite3 *db;
  3144    if( objc>=2 ){
  3145      if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
  3146      sqlite3_create_collation(db, "utf16_unaligned", SQLITE_UTF16, 
  3147          0, alignmentCollFunc);
  3148      sqlite3_create_collation(db, "utf16_aligned", SQLITE_UTF16_ALIGNED, 
  3149          0, alignmentCollFunc);
  3150    }
  3151    return SQLITE_OK;
  3152  }
  3153  #endif /* !defined(SQLITE_OMIT_UTF16) */
  3154  
  3155  /*
  3156  ** Usage: add_test_function <db ptr> <utf8> <utf16le> <utf16be>
  3157  **
  3158  ** This function is used to test that SQLite selects the correct user
  3159  ** function callback when multiple versions (for different text encodings)
  3160  ** are available.
  3161  **
  3162  ** Calling this routine registers up to three versions of the user function
  3163  ** "test_function" with database handle <db>.  If the second argument is
  3164  ** true, then a version of test_function is registered for UTF-8, if the
  3165  ** third is true, a version is registered for UTF-16le, if the fourth is
  3166  ** true, a UTF-16be version is available.  Previous versions of
  3167  ** test_function are deleted.
  3168  **
  3169  ** The user function is implemented by calling the following TCL script:
  3170  **
  3171  **   "test_function <enc> <arg>"
  3172  **
  3173  ** Where <enc> is one of UTF-8, UTF-16LE or UTF16BE, and <arg> is the
  3174  ** single argument passed to the SQL function. The value returned by
  3175  ** the TCL script is used as the return value of the SQL function. It
  3176  ** is passed to SQLite using UTF-16BE for a UTF-8 test_function(), UTF-8
  3177  ** for a UTF-16LE test_function(), and UTF-16LE for an implementation that
  3178  ** prefers UTF-16BE.
  3179  */
  3180  #ifndef SQLITE_OMIT_UTF16
  3181  static void test_function_utf8(
  3182    sqlite3_context *pCtx, 
  3183    int nArg,
  3184    sqlite3_value **argv
  3185  ){
  3186    Tcl_Interp *interp;
  3187    Tcl_Obj *pX;
  3188    sqlite3_value *pVal;
  3189    interp = (Tcl_Interp *)sqlite3_user_data(pCtx);
  3190    pX = Tcl_NewStringObj("test_function", -1);
  3191    Tcl_IncrRefCount(pX);
  3192    Tcl_ListObjAppendElement(interp, pX, Tcl_NewStringObj("UTF-8", -1));
  3193    Tcl_ListObjAppendElement(interp, pX, 
  3194        Tcl_NewStringObj((char*)sqlite3_value_text(argv[0]), -1));
  3195    Tcl_EvalObjEx(interp, pX, 0);
  3196    Tcl_DecrRefCount(pX);
  3197    sqlite3_result_text(pCtx, Tcl_GetStringResult(interp), -1, SQLITE_TRANSIENT);
  3198    pVal = sqlite3ValueNew(0);
  3199    sqlite3ValueSetStr(pVal, -1, Tcl_GetStringResult(interp), 
  3200        SQLITE_UTF8, SQLITE_STATIC);
  3201    sqlite3_result_text16be(pCtx, sqlite3_value_text16be(pVal),
  3202        -1, SQLITE_TRANSIENT);
  3203    sqlite3ValueFree(pVal);
  3204  }
  3205  static void test_function_utf16le(
  3206    sqlite3_context *pCtx, 
  3207    int nArg,
  3208    sqlite3_value **argv
  3209  ){
  3210    Tcl_Interp *interp;
  3211    Tcl_Obj *pX;
  3212    sqlite3_value *pVal;
  3213    interp = (Tcl_Interp *)sqlite3_user_data(pCtx);
  3214    pX = Tcl_NewStringObj("test_function", -1);
  3215    Tcl_IncrRefCount(pX);
  3216    Tcl_ListObjAppendElement(interp, pX, Tcl_NewStringObj("UTF-16LE", -1));
  3217    Tcl_ListObjAppendElement(interp, pX, 
  3218        Tcl_NewStringObj((char*)sqlite3_value_text(argv[0]), -1));
  3219    Tcl_EvalObjEx(interp, pX, 0);
  3220    Tcl_DecrRefCount(pX);
  3221    pVal = sqlite3ValueNew(0);
  3222    sqlite3ValueSetStr(pVal, -1, Tcl_GetStringResult(interp), 
  3223        SQLITE_UTF8, SQLITE_STATIC);
  3224    sqlite3_result_text(pCtx,(char*)sqlite3_value_text(pVal),-1,SQLITE_TRANSIENT);
  3225    sqlite3ValueFree(pVal);
  3226  }
  3227  static void test_function_utf16be(
  3228    sqlite3_context *pCtx, 
  3229    int nArg,
  3230    sqlite3_value **argv
  3231  ){
  3232    Tcl_Interp *interp;
  3233    Tcl_Obj *pX;
  3234    sqlite3_value *pVal;
  3235    interp = (Tcl_Interp *)sqlite3_user_data(pCtx);
  3236    pX = Tcl_NewStringObj("test_function", -1);
  3237    Tcl_IncrRefCount(pX);
  3238    Tcl_ListObjAppendElement(interp, pX, Tcl_NewStringObj("UTF-16BE", -1));
  3239    Tcl_ListObjAppendElement(interp, pX, 
  3240        Tcl_NewStringObj((char*)sqlite3_value_text(argv[0]), -1));
  3241    Tcl_EvalObjEx(interp, pX, 0);
  3242    Tcl_DecrRefCount(pX);
  3243    pVal = sqlite3ValueNew(0);
  3244    sqlite3ValueSetStr(pVal, -1, Tcl_GetStringResult(interp), 
  3245        SQLITE_UTF8, SQLITE_STATIC);
  3246    sqlite3_result_text16(pCtx, sqlite3_value_text16le(pVal),
  3247        -1, SQLITE_TRANSIENT);
  3248    sqlite3_result_text16be(pCtx, sqlite3_value_text16le(pVal),
  3249        -1, SQLITE_TRANSIENT);
  3250    sqlite3_result_text16le(pCtx, sqlite3_value_text16le(pVal),
  3251        -1, SQLITE_TRANSIENT);
  3252    sqlite3ValueFree(pVal);
  3253  }
  3254  #endif /* SQLITE_OMIT_UTF16 */
  3255  static int SQLITE_TCLAPI test_function(
  3256    void * clientData,
  3257    Tcl_Interp *interp,
  3258    int objc,
  3259    Tcl_Obj *CONST objv[]
  3260  ){
  3261  #ifndef SQLITE_OMIT_UTF16
  3262    sqlite3 *db;
  3263    int val;
  3264  
  3265    if( objc!=5 ) goto bad_args;
  3266    if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
  3267  
  3268    if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[2], &val) ) return TCL_ERROR;
  3269    if( val ){
  3270      sqlite3_create_function(db, "test_function", 1, SQLITE_UTF8, 
  3271          interp, test_function_utf8, 0, 0);
  3272    }
  3273    if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[3], &val) ) return TCL_ERROR;
  3274    if( val ){
  3275      sqlite3_create_function(db, "test_function", 1, SQLITE_UTF16LE, 
  3276          interp, test_function_utf16le, 0, 0);
  3277    }
  3278    if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[4], &val) ) return TCL_ERROR;
  3279    if( val ){
  3280      sqlite3_create_function(db, "test_function", 1, SQLITE_UTF16BE, 
  3281          interp, test_function_utf16be, 0, 0);
  3282    }
  3283  
  3284    return TCL_OK;
  3285  bad_args:
  3286    Tcl_AppendResult(interp, "wrong # args: should be \"",
  3287        Tcl_GetStringFromObj(objv[0], 0), " <DB> <utf8> <utf16le> <utf16be>", 0);
  3288  #endif /* SQLITE_OMIT_UTF16 */
  3289    return TCL_ERROR;
  3290  }
  3291  
  3292  /*
  3293  ** Usage:         sqlite3_test_errstr <err code>
  3294  **
  3295  ** Test that the english language string equivalents for sqlite error codes
  3296  ** are sane. The parameter is an integer representing an sqlite error code.
  3297  ** The result is a list of two elements, the string representation of the
  3298  ** error code and the english language explanation.
  3299  */
  3300  static int SQLITE_TCLAPI test_errstr(
  3301    void * clientData,
  3302    Tcl_Interp *interp,
  3303    int objc,
  3304    Tcl_Obj *CONST objv[]
  3305  ){
  3306    char *zCode;
  3307    int i;
  3308    if( objc!=1 ){
  3309      Tcl_WrongNumArgs(interp, 1, objv, "<error code>");
  3310    }
  3311  
  3312    zCode = Tcl_GetString(objv[1]);
  3313    for(i=0; i<200; i++){
  3314      if( 0==strcmp(t1ErrorName(i), zCode) ) break;
  3315    }
  3316    Tcl_SetResult(interp, (char *)sqlite3ErrStr(i), 0);
  3317    return TCL_OK;
  3318  }
  3319  
  3320  /*
  3321  ** Usage:    breakpoint
  3322  **
  3323  ** This routine exists for one purpose - to provide a place to put a
  3324  ** breakpoint with GDB that can be triggered using TCL code.  The use
  3325  ** for this is when a particular test fails on (say) the 1485th iteration.
  3326  ** In the TCL test script, we can add code like this:
  3327  **
  3328  **     if {$i==1485} breakpoint
  3329  **
  3330  ** Then run testfixture in the debugger and wait for the breakpoint to
  3331  ** fire.  Then additional breakpoints can be set to trace down the bug.
  3332  */
  3333  static int SQLITE_TCLAPI test_breakpoint(
  3334    void *NotUsed,
  3335    Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  3336    int argc,              /* Number of arguments */
  3337    char **argv            /* Text of each argument */
  3338  ){
  3339    return TCL_OK;         /* Do nothing */
  3340  }
  3341  
  3342  /*
  3343  ** Usage:   sqlite3_bind_zeroblob  STMT IDX N
  3344  **
  3345  ** Test the sqlite3_bind_zeroblob interface.  STMT is a prepared statement.
  3346  ** IDX is the index of a wildcard in the prepared statement.  This command
  3347  ** binds a N-byte zero-filled BLOB to the wildcard.
  3348  */
  3349  static int SQLITE_TCLAPI test_bind_zeroblob(
  3350    void * clientData,
  3351    Tcl_Interp *interp,
  3352    int objc,
  3353    Tcl_Obj *CONST objv[]
  3354  ){
  3355    sqlite3_stmt *pStmt;
  3356    int idx;
  3357    int n;
  3358    int rc;
  3359  
  3360    if( objc!=4 ){
  3361      Tcl_WrongNumArgs(interp, 1, objv, "STMT IDX N");
  3362      return TCL_ERROR;
  3363    }
  3364  
  3365    if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
  3366    if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
  3367    if( Tcl_GetIntFromObj(interp, objv[3], &n) ) return TCL_ERROR;
  3368  
  3369    rc = sqlite3_bind_zeroblob(pStmt, idx, n);
  3370    if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
  3371    if( rc!=SQLITE_OK ){
  3372      return TCL_ERROR;
  3373    }
  3374  
  3375    return TCL_OK;
  3376  }
  3377  
  3378  /*
  3379  ** Usage:   sqlite3_bind_zeroblob64  STMT IDX N
  3380  **
  3381  ** Test the sqlite3_bind_zeroblob64 interface.  STMT is a prepared statement.
  3382  ** IDX is the index of a wildcard in the prepared statement.  This command
  3383  ** binds a N-byte zero-filled BLOB to the wildcard.
  3384  */
  3385  static int SQLITE_TCLAPI test_bind_zeroblob64(
  3386    void * clientData,
  3387    Tcl_Interp *interp,
  3388    int objc,
  3389    Tcl_Obj *CONST objv[]
  3390  ){
  3391    sqlite3_stmt *pStmt;
  3392    int idx;
  3393    Tcl_WideInt n;
  3394    int rc;
  3395  
  3396    if( objc!=4 ){
  3397      Tcl_WrongNumArgs(interp, 1, objv, "STMT IDX N");
  3398      return TCL_ERROR;
  3399    }
  3400  
  3401    if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
  3402    if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
  3403    if( Tcl_GetWideIntFromObj(interp, objv[3], &n) ) return TCL_ERROR;
  3404  
  3405    rc = sqlite3_bind_zeroblob64(pStmt, idx, n);
  3406    if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
  3407    if( rc!=SQLITE_OK ){
  3408      Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
  3409      return TCL_ERROR;
  3410    }
  3411  
  3412    return TCL_OK;
  3413  }
  3414  
  3415  /*
  3416  ** Usage:   sqlite3_bind_int  STMT N VALUE
  3417  **
  3418  ** Test the sqlite3_bind_int interface.  STMT is a prepared statement.
  3419  ** N is the index of a wildcard in the prepared statement.  This command
  3420  ** binds a 32-bit integer VALUE to that wildcard.
  3421  */
  3422  static int SQLITE_TCLAPI test_bind_int(
  3423    void * clientData,
  3424    Tcl_Interp *interp,
  3425    int objc,
  3426    Tcl_Obj *CONST objv[]
  3427  ){
  3428    sqlite3_stmt *pStmt;
  3429    int idx;
  3430    int value;
  3431    int rc;
  3432  
  3433    if( objc!=4 ){
  3434      Tcl_AppendResult(interp, "wrong # args: should be \"",
  3435          Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE", 0);
  3436      return TCL_ERROR;
  3437    }
  3438  
  3439    if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
  3440    if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
  3441    if( Tcl_GetIntFromObj(interp, objv[3], &value) ) return TCL_ERROR;
  3442  
  3443    rc = sqlite3_bind_int(pStmt, idx, value);
  3444    if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
  3445    if( rc!=SQLITE_OK ){
  3446      return TCL_ERROR;
  3447    }
  3448  
  3449    return TCL_OK;
  3450  }
  3451  
  3452  
  3453  /*
  3454  ** Usage:   intarray_addr  INT  ...
  3455  **
  3456  ** Return the address of a C-language array of 32-bit integers.
  3457  **
  3458  ** Space to hold the array is obtained from malloc().  Call this procedure once
  3459  ** with no arguments in order to release memory.  Each call to this procedure
  3460  ** overwrites the previous array.
  3461  */
  3462  static int SQLITE_TCLAPI test_intarray_addr(
  3463    void * clientData,
  3464    Tcl_Interp *interp,
  3465    int objc,
  3466    Tcl_Obj *CONST objv[]
  3467  ){
  3468    int i;
  3469    static int *p = 0;
  3470  
  3471    sqlite3_free(p);
  3472    p = 0;
  3473    if( objc>1 ){
  3474      p = sqlite3_malloc( sizeof(p[0])*(objc-1) );
  3475      if( p==0 ) return TCL_ERROR;
  3476      for(i=0; i<objc-1; i++){
  3477        if( Tcl_GetIntFromObj(interp, objv[1+i], &p[i]) ){
  3478          sqlite3_free(p);
  3479          p = 0;
  3480          return TCL_ERROR;
  3481        }
  3482      }
  3483    }  
  3484    Tcl_SetObjResult(interp, Tcl_NewWideIntObj((sqlite3_int64)p));
  3485    return TCL_OK;
  3486  }
  3487  /*
  3488  ** Usage:   intarray_addr  INT  ...
  3489  **
  3490  ** Return the address of a C-language array of 32-bit integers.
  3491  **
  3492  ** Space to hold the array is obtained from malloc().  Call this procedure once
  3493  ** with no arguments in order to release memory.  Each call to this procedure
  3494  ** overwrites the previous array.
  3495  */
  3496  static int SQLITE_TCLAPI test_int64array_addr(
  3497    void * clientData,
  3498    Tcl_Interp *interp,
  3499    int objc,
  3500    Tcl_Obj *CONST objv[]
  3501  ){
  3502    int i;
  3503    static sqlite3_int64 *p = 0;
  3504  
  3505    sqlite3_free(p);
  3506    p = 0;
  3507    if( objc>1 ){
  3508      p = sqlite3_malloc( sizeof(p[0])*(objc-1) );
  3509      if( p==0 ) return TCL_ERROR;
  3510      for(i=0; i<objc-1; i++){
  3511        Tcl_WideInt v;
  3512        if( Tcl_GetWideIntFromObj(interp, objv[1+i], &v) ){
  3513          sqlite3_free(p);
  3514          p = 0;
  3515          return TCL_ERROR;
  3516        }
  3517        p[i] = v;
  3518      }
  3519    }  
  3520    Tcl_SetObjResult(interp, Tcl_NewWideIntObj((sqlite3_int64)p));
  3521    return TCL_OK;
  3522  }
  3523  /*
  3524  ** Usage:   doublearray_addr  INT  ...
  3525  **
  3526  ** Return the address of a C-language array of doubles.
  3527  **
  3528  ** Space to hold the array is obtained from malloc().  Call this procedure once
  3529  ** with no arguments in order to release memory.  Each call to this procedure
  3530  ** overwrites the previous array.
  3531  */
  3532  static int SQLITE_TCLAPI test_doublearray_addr(
  3533    void * clientData,
  3534    Tcl_Interp *interp,
  3535    int objc,
  3536    Tcl_Obj *CONST objv[]
  3537  ){
  3538    int i;
  3539    static double *p = 0;
  3540  
  3541    sqlite3_free(p);
  3542    p = 0;
  3543    if( objc>1 ){
  3544      p = sqlite3_malloc( sizeof(p[0])*(objc-1) );
  3545      if( p==0 ) return TCL_ERROR;
  3546      for(i=0; i<objc-1; i++){
  3547        if( Tcl_GetDoubleFromObj(interp, objv[1+i], &p[i]) ){
  3548          sqlite3_free(p);
  3549          p = 0;
  3550          return TCL_ERROR;
  3551        }
  3552      }
  3553    }  
  3554    Tcl_SetObjResult(interp, Tcl_NewWideIntObj((sqlite3_int64)p));
  3555    return TCL_OK;
  3556  }
  3557  /*
  3558  ** Usage:   textarray_addr  TEXT ...
  3559  **
  3560  ** Return the address of a C-language array of strings.
  3561  **
  3562  ** Space to hold the array is obtained from malloc().  Call this procedure once
  3563  ** with no arguments in order to release memory.  Each call to this procedure
  3564  ** overwrites the previous array.
  3565  */
  3566  static int SQLITE_TCLAPI test_textarray_addr(
  3567    void * clientData,
  3568    Tcl_Interp *interp,
  3569    int objc,
  3570    Tcl_Obj *CONST objv[]
  3571  ){
  3572    int i;
  3573    static int n = 0;
  3574    static char **p = 0;
  3575  
  3576    for(i=0; i<n; i++) sqlite3_free(p[i]);
  3577    sqlite3_free(p);
  3578    p = 0;
  3579    if( objc>1 ){
  3580      p = sqlite3_malloc( sizeof(p[0])*(objc-1) );
  3581      if( p==0 ) return TCL_ERROR;
  3582      for(i=0; i<objc-1; i++){
  3583        p[i] = sqlite3_mprintf("%s", Tcl_GetString(objv[1+i]));
  3584      }
  3585    }
  3586    n = objc-1;
  3587    Tcl_SetObjResult(interp, Tcl_NewWideIntObj((sqlite3_int64)p));
  3588    return TCL_OK;
  3589  }
  3590  
  3591  
  3592  /*
  3593  ** Usage:   sqlite3_bind_int64  STMT N VALUE
  3594  **
  3595  ** Test the sqlite3_bind_int64 interface.  STMT is a prepared statement.
  3596  ** N is the index of a wildcard in the prepared statement.  This command
  3597  ** binds a 64-bit integer VALUE to that wildcard.
  3598  */
  3599  static int SQLITE_TCLAPI test_bind_int64(
  3600    void * clientData,
  3601    Tcl_Interp *interp,
  3602    int objc,
  3603    Tcl_Obj *CONST objv[]
  3604  ){
  3605    sqlite3_stmt *pStmt;
  3606    int idx;
  3607    Tcl_WideInt value;
  3608    int rc;
  3609  
  3610    if( objc!=4 ){
  3611      Tcl_AppendResult(interp, "wrong # args: should be \"",
  3612          Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE", 0);
  3613      return TCL_ERROR;
  3614    }
  3615  
  3616    if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
  3617    if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
  3618    if( Tcl_GetWideIntFromObj(interp, objv[3], &value) ) return TCL_ERROR;
  3619  
  3620    rc = sqlite3_bind_int64(pStmt, idx, value);
  3621    if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
  3622    if( rc!=SQLITE_OK ){
  3623      return TCL_ERROR;
  3624    }
  3625  
  3626    return TCL_OK;
  3627  }
  3628  
  3629  
  3630  /*
  3631  ** Usage:   sqlite3_bind_double  STMT N VALUE
  3632  **
  3633  ** Test the sqlite3_bind_double interface.  STMT is a prepared statement.
  3634  ** N is the index of a wildcard in the prepared statement.  This command
  3635  ** binds a 64-bit integer VALUE to that wildcard.
  3636  */
  3637  static int SQLITE_TCLAPI test_bind_double(
  3638    void * clientData,
  3639    Tcl_Interp *interp,
  3640    int objc,
  3641    Tcl_Obj *CONST objv[]
  3642  ){
  3643    sqlite3_stmt *pStmt;
  3644    int idx;
  3645    double value = 0;
  3646    int rc;
  3647    const char *zVal;
  3648    int i;
  3649    static const struct {
  3650      const char *zName;     /* Name of the special floating point value */
  3651      unsigned int iUpper;   /* Upper 32 bits */
  3652      unsigned int iLower;   /* Lower 32 bits */
  3653    } aSpecialFp[] = {
  3654      {  "NaN",      0x7fffffff, 0xffffffff },
  3655      {  "SNaN",     0x7ff7ffff, 0xffffffff },
  3656      {  "-NaN",     0xffffffff, 0xffffffff },
  3657      {  "-SNaN",    0xfff7ffff, 0xffffffff },
  3658      {  "+Inf",     0x7ff00000, 0x00000000 },
  3659      {  "-Inf",     0xfff00000, 0x00000000 },
  3660      {  "Epsilon",  0x00000000, 0x00000001 },
  3661      {  "-Epsilon", 0x80000000, 0x00000001 },
  3662      {  "NaN0",     0x7ff80000, 0x00000000 },
  3663      {  "-NaN0",    0xfff80000, 0x00000000 },
  3664    };
  3665  
  3666    if( objc!=4 ){
  3667      Tcl_AppendResult(interp, "wrong # args: should be \"",
  3668          Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE", 0);
  3669      return TCL_ERROR;
  3670    }
  3671  
  3672    if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
  3673    if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
  3674  
  3675    /* Intercept the string "NaN" and generate a NaN value for it.
  3676    ** All other strings are passed through to Tcl_GetDoubleFromObj().
  3677    ** Tcl_GetDoubleFromObj() should understand "NaN" but some versions
  3678    ** contain a bug.
  3679    */
  3680    zVal = Tcl_GetString(objv[3]);
  3681    for(i=0; i<sizeof(aSpecialFp)/sizeof(aSpecialFp[0]); i++){
  3682      if( strcmp(aSpecialFp[i].zName, zVal)==0 ){
  3683        sqlite3_uint64 x;
  3684        x = aSpecialFp[i].iUpper;
  3685        x <<= 32;
  3686        x |= aSpecialFp[i].iLower;
  3687        assert( sizeof(value)==8 );
  3688        assert( sizeof(x)==8 );
  3689        memcpy(&value, &x, 8);
  3690        break;
  3691      }
  3692    }
  3693    if( i>=sizeof(aSpecialFp)/sizeof(aSpecialFp[0]) &&
  3694           Tcl_GetDoubleFromObj(interp, objv[3], &value) ){
  3695      return TCL_ERROR;
  3696    }
  3697    rc = sqlite3_bind_double(pStmt, idx, value);
  3698    if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
  3699    if( rc!=SQLITE_OK ){
  3700      return TCL_ERROR;
  3701    }
  3702  
  3703    return TCL_OK;
  3704  }
  3705  
  3706  /*
  3707  ** Usage:   sqlite3_bind_null  STMT N
  3708  **
  3709  ** Test the sqlite3_bind_null interface.  STMT is a prepared statement.
  3710  ** N is the index of a wildcard in the prepared statement.  This command
  3711  ** binds a NULL to the wildcard.
  3712  */
  3713  static int SQLITE_TCLAPI test_bind_null(
  3714    void * clientData,
  3715    Tcl_Interp *interp,
  3716    int objc,
  3717    Tcl_Obj *CONST objv[]
  3718  ){
  3719    sqlite3_stmt *pStmt;
  3720    int idx;
  3721    int rc;
  3722  
  3723    if( objc!=3 ){
  3724      Tcl_AppendResult(interp, "wrong # args: should be \"",
  3725          Tcl_GetStringFromObj(objv[0], 0), " STMT N", 0);
  3726      return TCL_ERROR;
  3727    }
  3728  
  3729    if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
  3730    if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
  3731  
  3732    rc = sqlite3_bind_null(pStmt, idx);
  3733    if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
  3734    if( rc!=SQLITE_OK ){
  3735      return TCL_ERROR;
  3736    }
  3737  
  3738    return TCL_OK;
  3739  }
  3740  
  3741  /*
  3742  ** Usage:   sqlite3_bind_text  STMT N STRING BYTES
  3743  **
  3744  ** Test the sqlite3_bind_text interface.  STMT is a prepared statement.
  3745  ** N is the index of a wildcard in the prepared statement.  This command
  3746  ** binds a UTF-8 string STRING to the wildcard.  The string is BYTES bytes
  3747  ** long.
  3748  */
  3749  static int SQLITE_TCLAPI test_bind_text(
  3750    void * clientData,
  3751    Tcl_Interp *interp,
  3752    int objc,
  3753    Tcl_Obj *CONST objv[]
  3754  ){
  3755    sqlite3_stmt *pStmt;
  3756    int idx;
  3757    int bytes;
  3758    char *value;
  3759    int rc;
  3760  
  3761    if( objc!=5 ){
  3762      Tcl_AppendResult(interp, "wrong # args: should be \"",
  3763          Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE BYTES", 0);
  3764      return TCL_ERROR;
  3765    }
  3766  
  3767    if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
  3768    if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
  3769    value = (char*)Tcl_GetByteArrayFromObj(objv[3], &bytes);
  3770    if( Tcl_GetIntFromObj(interp, objv[4], &bytes) ) return TCL_ERROR;
  3771  
  3772    rc = sqlite3_bind_text(pStmt, idx, value, bytes, SQLITE_TRANSIENT);
  3773    if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
  3774    if( rc!=SQLITE_OK ){
  3775      Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
  3776      return TCL_ERROR;
  3777    }
  3778  
  3779    return TCL_OK;
  3780  }
  3781  
  3782  /*
  3783  ** Usage:   sqlite3_bind_text16 ?-static? STMT N STRING BYTES
  3784  **
  3785  ** Test the sqlite3_bind_text16 interface.  STMT is a prepared statement.
  3786  ** N is the index of a wildcard in the prepared statement.  This command
  3787  ** binds a UTF-16 string STRING to the wildcard.  The string is BYTES bytes
  3788  ** long.
  3789  */
  3790  static int SQLITE_TCLAPI test_bind_text16(
  3791    void * clientData,
  3792    Tcl_Interp *interp,
  3793    int objc,
  3794    Tcl_Obj *CONST objv[]
  3795  ){
  3796  #ifndef SQLITE_OMIT_UTF16
  3797    sqlite3_stmt *pStmt;
  3798    int idx;
  3799    int bytes;
  3800    char *value;
  3801    int rc;
  3802  
  3803    void (*xDel)(void*) = (objc==6?SQLITE_STATIC:SQLITE_TRANSIENT);
  3804    Tcl_Obj *oStmt    = objv[objc-4];
  3805    Tcl_Obj *oN       = objv[objc-3];
  3806    Tcl_Obj *oString  = objv[objc-2];
  3807    Tcl_Obj *oBytes   = objv[objc-1];
  3808  
  3809    if( objc!=5 && objc!=6){
  3810      Tcl_AppendResult(interp, "wrong # args: should be \"",
  3811          Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE BYTES", 0);
  3812      return TCL_ERROR;
  3813    }
  3814  
  3815    if( getStmtPointer(interp, Tcl_GetString(oStmt), &pStmt) ) return TCL_ERROR;
  3816    if( Tcl_GetIntFromObj(interp, oN, &idx) ) return TCL_ERROR;
  3817    value = (char*)Tcl_GetByteArrayFromObj(oString, 0);
  3818    if( Tcl_GetIntFromObj(interp, oBytes, &bytes) ) return TCL_ERROR;
  3819  
  3820    rc = sqlite3_bind_text16(pStmt, idx, (void *)value, bytes, xDel);
  3821    if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
  3822    if( rc!=SQLITE_OK ){
  3823      Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
  3824      return TCL_ERROR;
  3825    }
  3826  
  3827  #endif /* SQLITE_OMIT_UTF16 */
  3828    return TCL_OK;
  3829  }
  3830  
  3831  /*
  3832  ** Usage:   sqlite3_bind_blob ?-static? STMT N DATA BYTES
  3833  **
  3834  ** Test the sqlite3_bind_blob interface.  STMT is a prepared statement.
  3835  ** N is the index of a wildcard in the prepared statement.  This command
  3836  ** binds a BLOB to the wildcard.  The BLOB is BYTES bytes in size.
  3837  */
  3838  static int SQLITE_TCLAPI test_bind_blob(
  3839    void * clientData,
  3840    Tcl_Interp *interp,
  3841    int objc,
  3842    Tcl_Obj *CONST objv[]
  3843  ){
  3844    sqlite3_stmt *pStmt;
  3845    int len, idx;
  3846    int bytes;
  3847    char *value;
  3848    int rc;
  3849    sqlite3_destructor_type xDestructor = SQLITE_TRANSIENT;
  3850  
  3851    if( objc!=5 && objc!=6 ){
  3852      Tcl_AppendResult(interp, "wrong # args: should be \"",
  3853          Tcl_GetStringFromObj(objv[0], 0), " STMT N DATA BYTES", 0);
  3854      return TCL_ERROR;
  3855    }
  3856  
  3857    if( objc==6 ){
  3858      xDestructor = SQLITE_STATIC;
  3859      objv++;
  3860    }
  3861  
  3862    if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
  3863    if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
  3864  
  3865    value = (char*)Tcl_GetByteArrayFromObj(objv[3], &len);
  3866    if( Tcl_GetIntFromObj(interp, objv[4], &bytes) ) return TCL_ERROR;
  3867  
  3868    if( bytes>len ){
  3869      char zBuf[200];
  3870      sqlite3_snprintf(sizeof(zBuf), zBuf,
  3871                       "cannot use %d blob bytes, have %d", bytes, len);
  3872      Tcl_AppendResult(interp, zBuf, -1);
  3873      return TCL_ERROR;
  3874    }
  3875  
  3876    rc = sqlite3_bind_blob(pStmt, idx, value, bytes, xDestructor);
  3877    if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
  3878    if( rc!=SQLITE_OK ){
  3879      return TCL_ERROR;
  3880    }
  3881  
  3882    return TCL_OK;
  3883  }
  3884  
  3885  /*
  3886  ** Usage:   sqlite3_bind_parameter_count  STMT
  3887  **
  3888  ** Return the number of wildcards in the given statement.
  3889  */
  3890  static int SQLITE_TCLAPI test_bind_parameter_count(
  3891    void * clientData,
  3892    Tcl_Interp *interp,
  3893    int objc,
  3894    Tcl_Obj *CONST objv[]
  3895  ){
  3896    sqlite3_stmt *pStmt;
  3897  
  3898    if( objc!=2 ){
  3899      Tcl_WrongNumArgs(interp, 1, objv, "STMT");
  3900      return TCL_ERROR;
  3901    }
  3902    if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
  3903    Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_bind_parameter_count(pStmt)));
  3904    return TCL_OK;
  3905  }
  3906  
  3907  /*
  3908  ** Usage:   sqlite3_bind_parameter_name  STMT  N
  3909  **
  3910  ** Return the name of the Nth wildcard.  The first wildcard is 1.
  3911  ** An empty string is returned if N is out of range or if the wildcard
  3912  ** is nameless.
  3913  */
  3914  static int SQLITE_TCLAPI test_bind_parameter_name(
  3915    void * clientData,
  3916    Tcl_Interp *interp,
  3917    int objc,
  3918    Tcl_Obj *CONST objv[]
  3919  ){
  3920    sqlite3_stmt *pStmt;
  3921    int i;
  3922  
  3923    if( objc!=3 ){
  3924      Tcl_WrongNumArgs(interp, 1, objv, "STMT N");
  3925      return TCL_ERROR;
  3926    }
  3927    if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
  3928    if( Tcl_GetIntFromObj(interp, objv[2], &i) ) return TCL_ERROR;
  3929    Tcl_SetObjResult(interp, 
  3930       Tcl_NewStringObj(sqlite3_bind_parameter_name(pStmt,i),-1)
  3931    );
  3932    return TCL_OK;
  3933  }
  3934  
  3935  /*
  3936  ** Usage:   sqlite3_bind_parameter_index  STMT  NAME
  3937  **
  3938  ** Return the index of the wildcard called NAME.  Return 0 if there is
  3939  ** no such wildcard.
  3940  */
  3941  static int SQLITE_TCLAPI test_bind_parameter_index(
  3942    void * clientData,
  3943    Tcl_Interp *interp,
  3944    int objc,
  3945    Tcl_Obj *CONST objv[]
  3946  ){
  3947    sqlite3_stmt *pStmt;
  3948  
  3949    if( objc!=3 ){
  3950      Tcl_WrongNumArgs(interp, 1, objv, "STMT NAME");
  3951      return TCL_ERROR;
  3952    }
  3953    if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
  3954    Tcl_SetObjResult(interp, 
  3955       Tcl_NewIntObj(
  3956         sqlite3_bind_parameter_index(pStmt,Tcl_GetString(objv[2]))
  3957       )
  3958    );
  3959    return TCL_OK;
  3960  }
  3961  
  3962  /*
  3963  ** Usage:   sqlite3_clear_bindings STMT
  3964  **
  3965  */
  3966  static int SQLITE_TCLAPI test_clear_bindings(
  3967    void * clientData,
  3968    Tcl_Interp *interp,
  3969    int objc,
  3970    Tcl_Obj *CONST objv[]
  3971  ){
  3972    sqlite3_stmt *pStmt;
  3973  
  3974    if( objc!=2 ){
  3975      Tcl_WrongNumArgs(interp, 1, objv, "STMT");
  3976      return TCL_ERROR;
  3977    }
  3978    if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
  3979    Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_clear_bindings(pStmt)));
  3980    return TCL_OK;
  3981  }
  3982  
  3983  /*
  3984  ** Usage:   sqlite3_sleep MILLISECONDS
  3985  */
  3986  static int SQLITE_TCLAPI test_sleep(
  3987    void * clientData,
  3988    Tcl_Interp *interp,
  3989    int objc,
  3990    Tcl_Obj *CONST objv[]
  3991  ){
  3992    int ms;
  3993  
  3994    if( objc!=2 ){
  3995      Tcl_WrongNumArgs(interp, 1, objv, "MILLISECONDS");
  3996      return TCL_ERROR;
  3997    }
  3998    if( Tcl_GetIntFromObj(interp, objv[1], &ms) ){
  3999      return TCL_ERROR;
  4000    }
  4001    Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_sleep(ms)));
  4002    return TCL_OK;
  4003  }
  4004  
  4005  /*
  4006  ** Usage: sqlite3_extended_errcode DB
  4007  **
  4008  ** Return the string representation of the most recent sqlite3_* API
  4009  ** error code. e.g. "SQLITE_ERROR".
  4010  */
  4011  static int SQLITE_TCLAPI test_ex_errcode(
  4012    void * clientData,
  4013    Tcl_Interp *interp,
  4014    int objc,
  4015    Tcl_Obj *CONST objv[]
  4016  ){
  4017    sqlite3 *db;
  4018    int rc;
  4019  
  4020    if( objc!=2 ){
  4021      Tcl_AppendResult(interp, "wrong # args: should be \"", 
  4022         Tcl_GetString(objv[0]), " DB", 0);
  4023      return TCL_ERROR;
  4024    }
  4025    if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
  4026    rc = sqlite3_extended_errcode(db);
  4027    Tcl_AppendResult(interp, (char *)t1ErrorName(rc), 0);
  4028    return TCL_OK;
  4029  }
  4030  
  4031  
  4032  /*
  4033  ** Usage: sqlite3_errcode DB
  4034  **
  4035  ** Return the string representation of the most recent sqlite3_* API
  4036  ** error code. e.g. "SQLITE_ERROR".
  4037  */
  4038  static int SQLITE_TCLAPI test_errcode(
  4039    void * clientData,
  4040    Tcl_Interp *interp,
  4041    int objc,
  4042    Tcl_Obj *CONST objv[]
  4043  ){
  4044    sqlite3 *db;
  4045    int rc;
  4046  
  4047    if( objc!=2 ){
  4048      Tcl_AppendResult(interp, "wrong # args: should be \"", 
  4049         Tcl_GetString(objv[0]), " DB", 0);
  4050      return TCL_ERROR;
  4051    }
  4052    if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
  4053    rc = sqlite3_errcode(db);
  4054    Tcl_AppendResult(interp, (char *)t1ErrorName(rc), 0);
  4055    return TCL_OK;
  4056  }
  4057  
  4058  /*
  4059  ** Usage:   sqlite3_errmsg DB
  4060  **
  4061  ** Returns the UTF-8 representation of the error message string for the
  4062  ** most recent sqlite3_* API call.
  4063  */
  4064  static int SQLITE_TCLAPI test_errmsg(
  4065    void * clientData,
  4066    Tcl_Interp *interp,
  4067    int objc,
  4068    Tcl_Obj *CONST objv[]
  4069  ){
  4070    sqlite3 *db;
  4071    const char *zErr;
  4072  
  4073    if( objc!=2 ){
  4074      Tcl_AppendResult(interp, "wrong # args: should be \"", 
  4075         Tcl_GetString(objv[0]), " DB", 0);
  4076      return TCL_ERROR;
  4077    }
  4078    if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
  4079  
  4080    zErr = sqlite3_errmsg(db);
  4081    Tcl_SetObjResult(interp, Tcl_NewStringObj(zErr, -1));
  4082    return TCL_OK;
  4083  }
  4084  
  4085  /*
  4086  ** Usage:   test_errmsg16 DB
  4087  **
  4088  ** Returns the UTF-16 representation of the error message string for the
  4089  ** most recent sqlite3_* API call. This is a byte array object at the TCL 
  4090  ** level, and it includes the 0x00 0x00 terminator bytes at the end of the
  4091  ** UTF-16 string.
  4092  */
  4093  static int SQLITE_TCLAPI test_errmsg16(
  4094    void * clientData,
  4095    Tcl_Interp *interp,
  4096    int objc,
  4097    Tcl_Obj *CONST objv[]
  4098  ){
  4099  #ifndef SQLITE_OMIT_UTF16
  4100    sqlite3 *db;
  4101    const void *zErr;
  4102    const char *z;
  4103    int bytes = 0;
  4104  
  4105    if( objc!=2 ){
  4106      Tcl_AppendResult(interp, "wrong # args: should be \"", 
  4107         Tcl_GetString(objv[0]), " DB", 0);
  4108      return TCL_ERROR;
  4109    }
  4110    if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
  4111  
  4112    zErr = sqlite3_errmsg16(db);
  4113    if( zErr ){
  4114      z = zErr;
  4115      for(bytes=0; z[bytes] || z[bytes+1]; bytes+=2){}
  4116    }
  4117    Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(zErr, bytes));
  4118  #endif /* SQLITE_OMIT_UTF16 */
  4119    return TCL_OK;
  4120  }
  4121  
  4122  /*
  4123  ** Usage: sqlite3_prepare DB sql bytes ?tailvar?
  4124  **
  4125  ** Compile up to <bytes> bytes of the supplied SQL string <sql> using
  4126  ** database handle <DB>. The parameter <tailval> is the name of a global
  4127  ** variable that is set to the unused portion of <sql> (if any). A
  4128  ** STMT handle is returned.
  4129  */
  4130  static int SQLITE_TCLAPI test_prepare(
  4131    void * clientData,
  4132    Tcl_Interp *interp,
  4133    int objc,
  4134    Tcl_Obj *CONST objv[]
  4135  ){
  4136    sqlite3 *db;
  4137    const char *zSql;
  4138    int bytes;
  4139    const char *zTail = 0;
  4140    sqlite3_stmt *pStmt = 0;
  4141    char zBuf[50];
  4142    int rc;
  4143  
  4144    if( objc!=5 && objc!=4 ){
  4145      Tcl_AppendResult(interp, "wrong # args: should be \"", 
  4146         Tcl_GetString(objv[0]), " DB sql bytes ?tailvar?", 0);
  4147      return TCL_ERROR;
  4148    }
  4149    if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
  4150    zSql = Tcl_GetString(objv[2]);
  4151    if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR;
  4152  
  4153    rc = sqlite3_prepare(db, zSql, bytes, &pStmt, objc>=5 ? &zTail : 0);
  4154    Tcl_ResetResult(interp);
  4155    if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
  4156    if( zTail && objc>=5 ){
  4157      if( bytes>=0 ){
  4158        bytes = bytes - (int)(zTail-zSql);
  4159      }
  4160      if( (int)strlen(zTail)<bytes ){
  4161        bytes = (int)strlen(zTail);
  4162      }
  4163      Tcl_ObjSetVar2(interp, objv[4], 0, Tcl_NewStringObj(zTail, bytes), 0);
  4164    }
  4165    if( rc!=SQLITE_OK ){
  4166      assert( pStmt==0 );
  4167      sqlite3_snprintf(sizeof(zBuf), zBuf, "(%d) ", rc);
  4168      Tcl_AppendResult(interp, zBuf, sqlite3_errmsg(db), 0);
  4169      return TCL_ERROR;
  4170    }
  4171  
  4172    if( pStmt ){
  4173      if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR;
  4174      Tcl_AppendResult(interp, zBuf, 0);
  4175    }
  4176    return TCL_OK;
  4177  }
  4178  
  4179  /*
  4180  ** Usage: sqlite3_prepare_v2 DB sql bytes ?tailvar?
  4181  **
  4182  ** Compile up to <bytes> bytes of the supplied SQL string <sql> using
  4183  ** database handle <DB>. The parameter <tailval> is the name of a global
  4184  ** variable that is set to the unused portion of <sql> (if any). A
  4185  ** STMT handle is returned.
  4186  */
  4187  static int SQLITE_TCLAPI test_prepare_v2(
  4188    void * clientData,
  4189    Tcl_Interp *interp,
  4190    int objc,
  4191    Tcl_Obj *CONST objv[]
  4192  ){
  4193    sqlite3 *db;
  4194    const char *zSql;
  4195    char *zCopy = 0;                /* malloc() copy of zSql */
  4196    int bytes;
  4197    const char *zTail = 0;
  4198    sqlite3_stmt *pStmt = 0;
  4199    char zBuf[50];
  4200    int rc;
  4201  
  4202    if( objc!=5 && objc!=4 ){
  4203      Tcl_AppendResult(interp, "wrong # args: should be \"", 
  4204         Tcl_GetString(objv[0]), " DB sql bytes tailvar", 0);
  4205      return TCL_ERROR;
  4206    }
  4207    if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
  4208    zSql = Tcl_GetString(objv[2]);
  4209    if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR;
  4210  
  4211    /* Instead of using zSql directly, make a copy into a buffer obtained
  4212    ** directly from malloc(). The idea is to make it easier for valgrind
  4213    ** to spot buffer overreads.  */
  4214    if( bytes>=0 ){
  4215      zCopy = malloc(bytes);
  4216      memcpy(zCopy, zSql, bytes);
  4217    }else{
  4218      int n = (int)strlen(zSql) + 1;
  4219      zCopy = malloc(n);
  4220      memcpy(zCopy, zSql, n);
  4221    }
  4222    rc = sqlite3_prepare_v2(db, zCopy, bytes, &pStmt, objc>=5 ? &zTail : 0);
  4223    free(zCopy);
  4224    zTail = &zSql[(zTail - zCopy)];
  4225  
  4226    assert(rc==SQLITE_OK || pStmt==0);
  4227    Tcl_ResetResult(interp);
  4228    if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
  4229    if( rc==SQLITE_OK && zTail && objc>=5 ){
  4230      if( bytes>=0 ){
  4231        bytes = bytes - (int)(zTail-zSql);
  4232      }
  4233      Tcl_ObjSetVar2(interp, objv[4], 0, Tcl_NewStringObj(zTail, bytes), 0);
  4234    }
  4235    if( rc!=SQLITE_OK ){
  4236      assert( pStmt==0 );
  4237      sqlite3_snprintf(sizeof(zBuf), zBuf, "(%d) ", rc);
  4238      Tcl_AppendResult(interp, zBuf, sqlite3_errmsg(db), 0);
  4239      return TCL_ERROR;
  4240    }
  4241  
  4242    if( pStmt ){
  4243      if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR;
  4244      Tcl_AppendResult(interp, zBuf, 0);
  4245    }
  4246    return TCL_OK;
  4247  }
  4248  
  4249  /*
  4250  ** Usage: sqlite3_prepare_tkt3134 DB
  4251  **
  4252  ** Generate a prepared statement for a zero-byte string as a test
  4253  ** for ticket #3134.  The string should be preceded by a zero byte.
  4254  */
  4255  static int SQLITE_TCLAPI test_prepare_tkt3134(
  4256    void * clientData,
  4257    Tcl_Interp *interp,
  4258    int objc,
  4259    Tcl_Obj *CONST objv[]
  4260  ){
  4261    sqlite3 *db;
  4262    static const char zSql[] = "\000SELECT 1";
  4263    sqlite3_stmt *pStmt = 0;
  4264    char zBuf[50];
  4265    int rc;
  4266  
  4267    if( objc!=2 ){
  4268      Tcl_AppendResult(interp, "wrong # args: should be \"", 
  4269         Tcl_GetString(objv[0]), " DB sql bytes tailvar", 0);
  4270      return TCL_ERROR;
  4271    }
  4272    if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
  4273    rc = sqlite3_prepare_v2(db, &zSql[1], 0, &pStmt, 0);
  4274    assert(rc==SQLITE_OK || pStmt==0);
  4275    if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
  4276    if( rc!=SQLITE_OK ){
  4277      assert( pStmt==0 );
  4278      sqlite3_snprintf(sizeof(zBuf), zBuf, "(%d) ", rc);
  4279      Tcl_AppendResult(interp, zBuf, sqlite3_errmsg(db), 0);
  4280      return TCL_ERROR;
  4281    }
  4282  
  4283    if( pStmt ){
  4284      if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR;
  4285      Tcl_AppendResult(interp, zBuf, 0);
  4286    }
  4287    return TCL_OK;
  4288  }
  4289  
  4290  /*
  4291  ** Usage: sqlite3_prepare16 DB sql bytes tailvar
  4292  **
  4293  ** Compile up to <bytes> bytes of the supplied SQL string <sql> using
  4294  ** database handle <DB>. The parameter <tailval> is the name of a global
  4295  ** variable that is set to the unused portion of <sql> (if any). A
  4296  ** STMT handle is returned.
  4297  */
  4298  static int SQLITE_TCLAPI test_prepare16(
  4299    void * clientData,
  4300    Tcl_Interp *interp,
  4301    int objc,
  4302    Tcl_Obj *CONST objv[]
  4303  ){
  4304  #ifndef SQLITE_OMIT_UTF16
  4305    sqlite3 *db;
  4306    const void *zSql;
  4307    const void *zTail = 0;
  4308    Tcl_Obj *pTail = 0;
  4309    sqlite3_stmt *pStmt = 0;
  4310    char zBuf[50]; 
  4311    int rc;
  4312    int bytes;                /* The integer specified as arg 3 */
  4313    int objlen;               /* The byte-array length of arg 2 */
  4314  
  4315    if( objc!=5 && objc!=4 ){
  4316      Tcl_AppendResult(interp, "wrong # args: should be \"", 
  4317         Tcl_GetString(objv[0]), " DB sql bytes ?tailvar?", 0);
  4318      return TCL_ERROR;
  4319    }
  4320    if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
  4321    zSql = Tcl_GetByteArrayFromObj(objv[2], &objlen);
  4322    if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR;
  4323  
  4324    rc = sqlite3_prepare16(db, zSql, bytes, &pStmt, objc>=5 ? &zTail : 0);
  4325    if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
  4326    if( rc ){
  4327      return TCL_ERROR;
  4328    }
  4329  
  4330    if( objc>=5 ){
  4331      if( zTail ){
  4332        objlen = objlen - (int)((u8 *)zTail-(u8 *)zSql);
  4333      }else{
  4334        objlen = 0;
  4335      }
  4336      pTail = Tcl_NewByteArrayObj((u8 *)zTail, objlen);
  4337      Tcl_IncrRefCount(pTail);
  4338      Tcl_ObjSetVar2(interp, objv[4], 0, pTail, 0);
  4339      Tcl_DecrRefCount(pTail);
  4340    }
  4341  
  4342    if( pStmt ){
  4343      if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR;
  4344    }
  4345    Tcl_AppendResult(interp, zBuf, 0);
  4346  #endif /* SQLITE_OMIT_UTF16 */
  4347    return TCL_OK;
  4348  }
  4349  
  4350  /*
  4351  ** Usage: sqlite3_prepare16_v2 DB sql bytes ?tailvar?
  4352  **
  4353  ** Compile up to <bytes> bytes of the supplied SQL string <sql> using
  4354  ** database handle <DB>. The parameter <tailval> is the name of a global
  4355  ** variable that is set to the unused portion of <sql> (if any). A
  4356  ** STMT handle is returned.
  4357  */
  4358  static int SQLITE_TCLAPI test_prepare16_v2(
  4359    void * clientData,
  4360    Tcl_Interp *interp,
  4361    int objc,
  4362    Tcl_Obj *CONST objv[]
  4363  ){
  4364  #ifndef SQLITE_OMIT_UTF16
  4365    sqlite3 *db;
  4366    const void *zSql;
  4367    const void *zTail = 0;
  4368    Tcl_Obj *pTail = 0;
  4369    sqlite3_stmt *pStmt = 0;
  4370    char zBuf[50]; 
  4371    int rc;
  4372    int bytes;                /* The integer specified as arg 3 */
  4373    int objlen;               /* The byte-array length of arg 2 */
  4374  
  4375    if( objc!=5 && objc!=4 ){
  4376      Tcl_AppendResult(interp, "wrong # args: should be \"", 
  4377         Tcl_GetString(objv[0]), " DB sql bytes ?tailvar?", 0);
  4378      return TCL_ERROR;
  4379    }
  4380    if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
  4381    zSql = Tcl_GetByteArrayFromObj(objv[2], &objlen);
  4382    if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR;
  4383  
  4384    rc = sqlite3_prepare16_v2(db, zSql, bytes, &pStmt, objc>=5 ? &zTail : 0);
  4385    if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
  4386    if( rc ){
  4387      return TCL_ERROR;
  4388    }
  4389  
  4390    if( objc>=5 ){
  4391      if( zTail ){
  4392        objlen = objlen - (int)((u8 *)zTail-(u8 *)zSql);
  4393      }else{
  4394        objlen = 0;
  4395      }
  4396      pTail = Tcl_NewByteArrayObj((u8 *)zTail, objlen);
  4397      Tcl_IncrRefCount(pTail);
  4398      Tcl_ObjSetVar2(interp, objv[4], 0, pTail, 0);
  4399      Tcl_DecrRefCount(pTail);
  4400    }
  4401  
  4402    if( pStmt ){
  4403      if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR;
  4404    }
  4405    Tcl_AppendResult(interp, zBuf, 0);
  4406  #endif /* SQLITE_OMIT_UTF16 */
  4407    return TCL_OK;
  4408  }
  4409  
  4410  /*
  4411  ** Usage: sqlite3_open filename ?options-list?
  4412  */
  4413  static int SQLITE_TCLAPI test_open(
  4414    void * clientData,
  4415    Tcl_Interp *interp,
  4416    int objc,
  4417    Tcl_Obj *CONST objv[]
  4418  ){
  4419    const char *zFilename;
  4420    sqlite3 *db;
  4421    char zBuf[100];
  4422  
  4423    if( objc!=3 && objc!=2 && objc!=1 ){
  4424      Tcl_AppendResult(interp, "wrong # args: should be \"", 
  4425         Tcl_GetString(objv[0]), " filename options-list", 0);
  4426      return TCL_ERROR;
  4427    }
  4428  
  4429    zFilename = objc>1 ? Tcl_GetString(objv[1]) : 0;
  4430    sqlite3_open(zFilename, &db);
  4431    
  4432    if( sqlite3TestMakePointerStr(interp, zBuf, db) ) return TCL_ERROR;
  4433    Tcl_AppendResult(interp, zBuf, 0);
  4434    return TCL_OK;
  4435  }
  4436  
  4437  /*
  4438  ** Usage: sqlite3_open_v2 FILENAME FLAGS VFS
  4439  */
  4440  static int SQLITE_TCLAPI test_open_v2(
  4441    void * clientData,
  4442    Tcl_Interp *interp,
  4443    int objc,
  4444    Tcl_Obj *CONST objv[]
  4445  ){
  4446    const char *zFilename;
  4447    const char *zVfs;
  4448    int flags = 0;
  4449    sqlite3 *db;
  4450    int rc;
  4451    char zBuf[100];
  4452  
  4453    int nFlag;
  4454    Tcl_Obj **apFlag;
  4455    int i;
  4456  
  4457    if( objc!=4 ){
  4458      Tcl_WrongNumArgs(interp, 1, objv, "FILENAME FLAGS VFS");
  4459      return TCL_ERROR;
  4460    }
  4461    zFilename = Tcl_GetString(objv[1]);
  4462    zVfs = Tcl_GetString(objv[3]);
  4463    if( zVfs[0]==0x00 ) zVfs = 0;
  4464  
  4465    rc = Tcl_ListObjGetElements(interp, objv[2], &nFlag, &apFlag);
  4466    if( rc!=TCL_OK ) return rc;
  4467    for(i=0; i<nFlag; i++){
  4468      int iFlag;
  4469      struct OpenFlag {
  4470        const char *zFlag;
  4471        int flag;
  4472      } aFlag[] = {
  4473        { "SQLITE_OPEN_READONLY", SQLITE_OPEN_READONLY },
  4474        { "SQLITE_OPEN_READWRITE", SQLITE_OPEN_READWRITE },
  4475        { "SQLITE_OPEN_CREATE", SQLITE_OPEN_CREATE },
  4476        { "SQLITE_OPEN_DELETEONCLOSE", SQLITE_OPEN_DELETEONCLOSE },
  4477        { "SQLITE_OPEN_EXCLUSIVE", SQLITE_OPEN_EXCLUSIVE },
  4478        { "SQLITE_OPEN_AUTOPROXY", SQLITE_OPEN_AUTOPROXY },
  4479        { "SQLITE_OPEN_MAIN_DB", SQLITE_OPEN_MAIN_DB },
  4480        { "SQLITE_OPEN_TEMP_DB", SQLITE_OPEN_TEMP_DB },
  4481        { "SQLITE_OPEN_TRANSIENT_DB", SQLITE_OPEN_TRANSIENT_DB },
  4482        { "SQLITE_OPEN_MAIN_JOURNAL", SQLITE_OPEN_MAIN_JOURNAL },
  4483        { "SQLITE_OPEN_TEMP_JOURNAL", SQLITE_OPEN_TEMP_JOURNAL },
  4484        { "SQLITE_OPEN_SUBJOURNAL", SQLITE_OPEN_SUBJOURNAL },
  4485        { "SQLITE_OPEN_MASTER_JOURNAL", SQLITE_OPEN_MASTER_JOURNAL },
  4486        { "SQLITE_OPEN_NOMUTEX", SQLITE_OPEN_NOMUTEX },
  4487        { "SQLITE_OPEN_FULLMUTEX", SQLITE_OPEN_FULLMUTEX },
  4488        { "SQLITE_OPEN_SHAREDCACHE", SQLITE_OPEN_SHAREDCACHE },
  4489        { "SQLITE_OPEN_PRIVATECACHE", SQLITE_OPEN_PRIVATECACHE },
  4490        { "SQLITE_OPEN_WAL", SQLITE_OPEN_WAL },
  4491        { "SQLITE_OPEN_URI", SQLITE_OPEN_URI },
  4492        { 0, 0 }
  4493      };
  4494      rc = Tcl_GetIndexFromObjStruct(interp, apFlag[i], aFlag, sizeof(aFlag[0]), 
  4495          "flag", 0, &iFlag
  4496      );
  4497      if( rc!=TCL_OK ) return rc;
  4498      flags |= aFlag[iFlag].flag;
  4499    }
  4500  
  4501    rc = sqlite3_open_v2(zFilename, &db, flags, zVfs);
  4502    if( sqlite3TestMakePointerStr(interp, zBuf, db) ) return TCL_ERROR;
  4503    Tcl_AppendResult(interp, zBuf, 0);
  4504    return TCL_OK;
  4505  }
  4506  
  4507  /*
  4508  ** Usage: sqlite3_open16 filename options
  4509  */
  4510  static int SQLITE_TCLAPI test_open16(
  4511    void * clientData,
  4512    Tcl_Interp *interp,
  4513    int objc,
  4514    Tcl_Obj *CONST objv[]
  4515  ){
  4516  #ifndef SQLITE_OMIT_UTF16
  4517    const void *zFilename;
  4518    sqlite3 *db;
  4519    char zBuf[100];
  4520  
  4521    if( objc!=3 ){
  4522      Tcl_AppendResult(interp, "wrong # args: should be \"", 
  4523         Tcl_GetString(objv[0]), " filename options-list", 0);
  4524      return TCL_ERROR;
  4525    }
  4526  
  4527    zFilename = Tcl_GetByteArrayFromObj(objv[1], 0);
  4528    sqlite3_open16(zFilename, &db);
  4529    
  4530    if( sqlite3TestMakePointerStr(interp, zBuf, db) ) return TCL_ERROR;
  4531    Tcl_AppendResult(interp, zBuf, 0);
  4532  #endif /* SQLITE_OMIT_UTF16 */
  4533    return TCL_OK;
  4534  }
  4535  
  4536  /*
  4537  ** Usage: sqlite3_complete16 <UTF-16 string>
  4538  **
  4539  ** Return 1 if the supplied argument is a complete SQL statement, or zero
  4540  ** otherwise.
  4541  */
  4542  static int SQLITE_TCLAPI test_complete16(
  4543    void * clientData,
  4544    Tcl_Interp *interp,
  4545    int objc,
  4546    Tcl_Obj *CONST objv[]
  4547  ){
  4548  #if !defined(SQLITE_OMIT_COMPLETE) && !defined(SQLITE_OMIT_UTF16)
  4549    char *zBuf;
  4550  
  4551    if( objc!=2 ){
  4552      Tcl_WrongNumArgs(interp, 1, objv, "<utf-16 sql>");
  4553      return TCL_ERROR;
  4554    }
  4555  
  4556    zBuf = (char*)Tcl_GetByteArrayFromObj(objv[1], 0);
  4557    Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_complete16(zBuf)));
  4558  #endif /* SQLITE_OMIT_COMPLETE && SQLITE_OMIT_UTF16 */
  4559    return TCL_OK;
  4560  }
  4561  
  4562  /*
  4563  ** Usage: sqlite3_step STMT
  4564  **
  4565  ** Advance the statement to the next row.
  4566  */
  4567  static int SQLITE_TCLAPI test_step(
  4568    void * clientData,
  4569    Tcl_Interp *interp,
  4570    int objc,
  4571    Tcl_Obj *CONST objv[]
  4572  ){
  4573    sqlite3_stmt *pStmt;
  4574    int rc;
  4575  
  4576    if( objc!=2 ){
  4577      Tcl_AppendResult(interp, "wrong # args: should be \"", 
  4578         Tcl_GetString(objv[0]), " STMT", 0);
  4579      return TCL_ERROR;
  4580    }
  4581  
  4582    if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
  4583    rc = sqlite3_step(pStmt);
  4584  
  4585    /* if( rc!=SQLITE_DONE && rc!=SQLITE_ROW ) return TCL_ERROR; */
  4586    Tcl_SetResult(interp, (char *)t1ErrorName(rc), 0);
  4587    return TCL_OK;
  4588  }
  4589  
  4590  static int SQLITE_TCLAPI test_sql(
  4591    void * clientData,
  4592    Tcl_Interp *interp,
  4593    int objc,
  4594    Tcl_Obj *CONST objv[]
  4595  ){
  4596    sqlite3_stmt *pStmt;
  4597  
  4598    if( objc!=2 ){
  4599      Tcl_WrongNumArgs(interp, 1, objv, "STMT");
  4600      return TCL_ERROR;
  4601    }
  4602  
  4603    if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
  4604    Tcl_SetResult(interp, (char *)sqlite3_sql(pStmt), TCL_VOLATILE);
  4605    return TCL_OK;
  4606  }
  4607  static int SQLITE_TCLAPI test_ex_sql(
  4608    void * clientData,
  4609    Tcl_Interp *interp,
  4610    int objc,
  4611    Tcl_Obj *CONST objv[]
  4612  ){
  4613    sqlite3_stmt *pStmt;
  4614    char *z;
  4615  
  4616    if( objc!=2 ){
  4617      Tcl_WrongNumArgs(interp, 1, objv, "STMT");
  4618      return TCL_ERROR;
  4619    }
  4620  
  4621    if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
  4622    z = sqlite3_expanded_sql(pStmt);
  4623    Tcl_SetResult(interp, z, TCL_VOLATILE);
  4624    sqlite3_free(z);
  4625    return TCL_OK;
  4626  }
  4627  
  4628  /*
  4629  ** Usage: sqlite3_column_count STMT 
  4630  **
  4631  ** Return the number of columns returned by the sql statement STMT.
  4632  */
  4633  static int SQLITE_TCLAPI test_column_count(
  4634    void * clientData,
  4635    Tcl_Interp *interp,
  4636    int objc,
  4637    Tcl_Obj *CONST objv[]
  4638  ){
  4639    sqlite3_stmt *pStmt;
  4640  
  4641    if( objc!=2 ){
  4642      Tcl_AppendResult(interp, "wrong # args: should be \"", 
  4643         Tcl_GetString(objv[0]), " STMT column", 0);
  4644      return TCL_ERROR;
  4645    }
  4646  
  4647    if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
  4648  
  4649    Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_column_count(pStmt)));
  4650    return TCL_OK;
  4651  }
  4652  
  4653  /*
  4654  ** Usage: sqlite3_column_type STMT column
  4655  **
  4656  ** Return the type of the data in column 'column' of the current row.
  4657  */
  4658  static int SQLITE_TCLAPI test_column_type(
  4659    void * clientData,
  4660    Tcl_Interp *interp,
  4661    int objc,
  4662    Tcl_Obj *CONST objv[]
  4663  ){
  4664    sqlite3_stmt *pStmt;
  4665    int col;
  4666    int tp;
  4667  
  4668    if( objc!=3 ){
  4669      Tcl_AppendResult(interp, "wrong # args: should be \"", 
  4670         Tcl_GetString(objv[0]), " STMT column", 0);
  4671      return TCL_ERROR;
  4672    }
  4673  
  4674    if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
  4675    if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
  4676  
  4677    tp = sqlite3_column_type(pStmt, col);
  4678    switch( tp ){
  4679      case SQLITE_INTEGER: 
  4680        Tcl_SetResult(interp, "INTEGER", TCL_STATIC); 
  4681        break;
  4682      case SQLITE_NULL:
  4683        Tcl_SetResult(interp, "NULL", TCL_STATIC); 
  4684        break;
  4685      case SQLITE_FLOAT:
  4686        Tcl_SetResult(interp, "FLOAT", TCL_STATIC); 
  4687        break;
  4688      case SQLITE_TEXT:
  4689        Tcl_SetResult(interp, "TEXT", TCL_STATIC); 
  4690        break;
  4691      case SQLITE_BLOB:
  4692        Tcl_SetResult(interp, "BLOB", TCL_STATIC); 
  4693        break;
  4694      default:
  4695        assert(0);
  4696    }
  4697  
  4698    return TCL_OK;
  4699  }
  4700  
  4701  /*
  4702  ** Usage: sqlite3_column_int64 STMT column
  4703  **
  4704  ** Return the data in column 'column' of the current row cast as an
  4705  ** wide (64-bit) integer.
  4706  */
  4707  static int SQLITE_TCLAPI test_column_int64(
  4708    void * clientData,
  4709    Tcl_Interp *interp,
  4710    int objc,
  4711    Tcl_Obj *CONST objv[]
  4712  ){
  4713    sqlite3_stmt *pStmt;
  4714    int col;
  4715    i64 iVal;
  4716  
  4717    if( objc!=3 ){
  4718      Tcl_AppendResult(interp, "wrong # args: should be \"", 
  4719         Tcl_GetString(objv[0]), " STMT column", 0);
  4720      return TCL_ERROR;
  4721    }
  4722  
  4723    if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
  4724    if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
  4725  
  4726    iVal = sqlite3_column_int64(pStmt, col);
  4727    Tcl_SetObjResult(interp, Tcl_NewWideIntObj(iVal));
  4728    return TCL_OK;
  4729  }
  4730  
  4731  /*
  4732  ** Usage: sqlite3_column_blob STMT column
  4733  */
  4734  static int SQLITE_TCLAPI test_column_blob(
  4735    void * clientData,
  4736    Tcl_Interp *interp,
  4737    int objc,
  4738    Tcl_Obj *CONST objv[]
  4739  ){
  4740    sqlite3_stmt *pStmt;
  4741    int col;
  4742  
  4743    int len;
  4744    const void *pBlob;
  4745  
  4746    if( objc!=3 ){
  4747      Tcl_AppendResult(interp, "wrong # args: should be \"", 
  4748         Tcl_GetString(objv[0]), " STMT column", 0);
  4749      return TCL_ERROR;
  4750    }
  4751  
  4752    if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
  4753    if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
  4754  
  4755    len = sqlite3_column_bytes(pStmt, col);
  4756    pBlob = sqlite3_column_blob(pStmt, col);
  4757    Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(pBlob, len));
  4758    return TCL_OK;
  4759  }
  4760  
  4761  /*
  4762  ** Usage: sqlite3_column_double STMT column
  4763  **
  4764  ** Return the data in column 'column' of the current row cast as a double.
  4765  */
  4766  static int SQLITE_TCLAPI test_column_double(
  4767    void * clientData,
  4768    Tcl_Interp *interp,
  4769    int objc,
  4770    Tcl_Obj *CONST objv[]
  4771  ){
  4772    sqlite3_stmt *pStmt;
  4773    int col;
  4774    double rVal;
  4775  
  4776    if( objc!=3 ){
  4777      Tcl_AppendResult(interp, "wrong # args: should be \"", 
  4778         Tcl_GetString(objv[0]), " STMT column", 0);
  4779      return TCL_ERROR;
  4780    }
  4781  
  4782    if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
  4783    if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
  4784  
  4785    rVal = sqlite3_column_double(pStmt, col);
  4786    Tcl_SetObjResult(interp, Tcl_NewDoubleObj(rVal));
  4787    return TCL_OK;
  4788  }
  4789  
  4790  /*
  4791  ** Usage: sqlite3_data_count STMT 
  4792  **
  4793  ** Return the number of columns returned by the sql statement STMT.
  4794  */
  4795  static int SQLITE_TCLAPI test_data_count(
  4796    void * clientData,
  4797    Tcl_Interp *interp,
  4798    int objc,
  4799    Tcl_Obj *CONST objv[]
  4800  ){
  4801    sqlite3_stmt *pStmt;
  4802  
  4803    if( objc!=2 ){
  4804      Tcl_AppendResult(interp, "wrong # args: should be \"", 
  4805         Tcl_GetString(objv[0]), " STMT column", 0);
  4806      return TCL_ERROR;
  4807    }
  4808  
  4809    if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
  4810  
  4811    Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_data_count(pStmt)));
  4812    return TCL_OK;
  4813  }
  4814  
  4815  /*
  4816  ** Usage: sqlite3_column_text STMT column
  4817  **
  4818  ** Usage: sqlite3_column_decltype STMT column
  4819  **
  4820  ** Usage: sqlite3_column_name STMT column
  4821  */
  4822  static int SQLITE_TCLAPI test_stmt_utf8(
  4823    void * clientData,        /* Pointer to SQLite API function to be invoke */
  4824    Tcl_Interp *interp,
  4825    int objc,
  4826    Tcl_Obj *CONST objv[]
  4827  ){
  4828    sqlite3_stmt *pStmt;
  4829    int col;
  4830    const char *(*xFunc)(sqlite3_stmt*, int);
  4831    const char *zRet;
  4832  
  4833    xFunc = (const char *(*)(sqlite3_stmt*, int))clientData;
  4834    if( objc!=3 ){
  4835      Tcl_AppendResult(interp, "wrong # args: should be \"", 
  4836         Tcl_GetString(objv[0]), " STMT column", 0);
  4837      return TCL_ERROR;
  4838    }
  4839  
  4840    if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
  4841    if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
  4842    zRet = xFunc(pStmt, col);
  4843    if( zRet ){
  4844      Tcl_SetResult(interp, (char *)zRet, 0);
  4845    }
  4846    return TCL_OK;
  4847  }
  4848  
  4849  static int SQLITE_TCLAPI test_global_recover(
  4850    void * clientData,
  4851    Tcl_Interp *interp,
  4852    int objc,
  4853    Tcl_Obj *CONST objv[]
  4854  ){
  4855  #ifndef SQLITE_OMIT_DEPRECATED
  4856    int rc;
  4857    if( objc!=1 ){
  4858      Tcl_WrongNumArgs(interp, 1, objv, "");
  4859      return TCL_ERROR;
  4860    }
  4861    rc = sqlite3_global_recover();
  4862    Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
  4863  #endif
  4864    return TCL_OK;
  4865  }
  4866  
  4867  /*
  4868  ** Usage: sqlite3_column_text STMT column
  4869  **
  4870  ** Usage: sqlite3_column_decltype STMT column
  4871  **
  4872  ** Usage: sqlite3_column_name STMT column
  4873  */
  4874  static int SQLITE_TCLAPI test_stmt_utf16(
  4875    void * clientData,     /* Pointer to SQLite API function to be invoked */
  4876    Tcl_Interp *interp,
  4877    int objc,
  4878    Tcl_Obj *CONST objv[]
  4879  ){
  4880  #ifndef SQLITE_OMIT_UTF16
  4881    sqlite3_stmt *pStmt;
  4882    int col;
  4883    Tcl_Obj *pRet;
  4884    const void *zName16;
  4885    const void *(*xFunc)(sqlite3_stmt*, int);
  4886  
  4887    xFunc = (const void *(*)(sqlite3_stmt*, int))clientData;
  4888    if( objc!=3 ){
  4889      Tcl_AppendResult(interp, "wrong # args: should be \"", 
  4890         Tcl_GetString(objv[0]), " STMT column", 0);
  4891      return TCL_ERROR;
  4892    }
  4893  
  4894    if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
  4895    if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
  4896  
  4897    zName16 = xFunc(pStmt, col);
  4898    if( zName16 ){
  4899      int n;
  4900      const char *z = zName16;
  4901      for(n=0; z[n] || z[n+1]; n+=2){}
  4902      pRet = Tcl_NewByteArrayObj(zName16, n+2);
  4903      Tcl_SetObjResult(interp, pRet);
  4904    }
  4905  #endif /* SQLITE_OMIT_UTF16 */
  4906  
  4907    return TCL_OK;
  4908  }
  4909  
  4910  /*
  4911  ** Usage: sqlite3_column_int STMT column
  4912  **
  4913  ** Usage: sqlite3_column_bytes STMT column
  4914  **
  4915  ** Usage: sqlite3_column_bytes16 STMT column
  4916  **
  4917  */
  4918  static int SQLITE_TCLAPI test_stmt_int(
  4919    void * clientData,    /* Pointer to SQLite API function to be invoked */
  4920    Tcl_Interp *interp,
  4921    int objc,
  4922    Tcl_Obj *CONST objv[]
  4923  ){
  4924    sqlite3_stmt *pStmt;
  4925    int col;
  4926    int (*xFunc)(sqlite3_stmt*, int);
  4927  
  4928    xFunc = (int (*)(sqlite3_stmt*, int))clientData;
  4929    if( objc!=3 ){
  4930      Tcl_AppendResult(interp, "wrong # args: should be \"", 
  4931         Tcl_GetString(objv[0]), " STMT column", 0);
  4932      return TCL_ERROR;
  4933    }
  4934  
  4935    if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
  4936    if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
  4937  
  4938    Tcl_SetObjResult(interp, Tcl_NewIntObj(xFunc(pStmt, col)));
  4939    return TCL_OK;
  4940  }
  4941  
  4942  /*
  4943  ** Usage:  sqlite_set_magic  DB  MAGIC-NUMBER
  4944  **
  4945  ** Set the db->magic value.  This is used to test error recovery logic.
  4946  */
  4947  static int SQLITE_TCLAPI sqlite_set_magic(
  4948    void * clientData,
  4949    Tcl_Interp *interp,
  4950    int argc,
  4951    char **argv
  4952  ){
  4953    sqlite3 *db;
  4954    if( argc!=3 ){
  4955      Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
  4956           " DB MAGIC", 0);
  4957      return TCL_ERROR;
  4958    }
  4959    if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
  4960    if( strcmp(argv[2], "SQLITE_MAGIC_OPEN")==0 ){
  4961      db->magic = SQLITE_MAGIC_OPEN;
  4962    }else if( strcmp(argv[2], "SQLITE_MAGIC_CLOSED")==0 ){
  4963      db->magic = SQLITE_MAGIC_CLOSED;
  4964    }else if( strcmp(argv[2], "SQLITE_MAGIC_BUSY")==0 ){
  4965      db->magic = SQLITE_MAGIC_BUSY;
  4966    }else if( strcmp(argv[2], "SQLITE_MAGIC_ERROR")==0 ){
  4967      db->magic = SQLITE_MAGIC_ERROR;
  4968    }else if( Tcl_GetInt(interp, argv[2], (int*)&db->magic) ){
  4969      return TCL_ERROR;
  4970    }
  4971    return TCL_OK;
  4972  }
  4973  
  4974  /*
  4975  ** Usage:  sqlite3_interrupt  DB 
  4976  **
  4977  ** Trigger an interrupt on DB
  4978  */
  4979  static int SQLITE_TCLAPI test_interrupt(
  4980    void * clientData,
  4981    Tcl_Interp *interp,
  4982    int argc,
  4983    char **argv
  4984  ){
  4985    sqlite3 *db;
  4986    if( argc!=2 ){
  4987      Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " DB", 0);
  4988      return TCL_ERROR;
  4989    }
  4990    if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
  4991    sqlite3_interrupt(db);
  4992    return TCL_OK;
  4993  }
  4994  
  4995  /*
  4996  ** Usage: sqlite_delete_function DB function-name
  4997  **
  4998  ** Delete the user function 'function-name' from database handle DB. It
  4999  ** is assumed that the user function was created as UTF8, any number of
  5000  ** arguments (the way the TCL interface does it).
  5001  */
  5002  static int SQLITE_TCLAPI delete_function(
  5003    void * clientData,
  5004    Tcl_Interp *interp,
  5005    int argc,
  5006    char **argv
  5007  ){
  5008    int rc;
  5009    sqlite3 *db;
  5010    if( argc!=3 ){
  5011      Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 
  5012          " DB function-name", 0);
  5013      return TCL_ERROR;
  5014    }
  5015    if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
  5016    rc = sqlite3_create_function(db, argv[2], -1, SQLITE_UTF8, 0, 0, 0, 0);
  5017    Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
  5018    return TCL_OK;
  5019  }
  5020  
  5021  /*
  5022  ** Usage: sqlite_delete_collation DB collation-name
  5023  **
  5024  ** Delete the collation sequence 'collation-name' from database handle 
  5025  ** DB. It is assumed that the collation sequence was created as UTF8 (the 
  5026  ** way the TCL interface does it).
  5027  */
  5028  static int SQLITE_TCLAPI delete_collation(
  5029    void * clientData,
  5030    Tcl_Interp *interp,
  5031    int argc,
  5032    char **argv
  5033  ){
  5034    int rc;
  5035    sqlite3 *db;
  5036    if( argc!=3 ){
  5037      Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 
  5038          " DB function-name", 0);
  5039      return TCL_ERROR;
  5040    }
  5041    if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
  5042    rc = sqlite3_create_collation(db, argv[2], SQLITE_UTF8, 0, 0);
  5043    Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
  5044    return TCL_OK;
  5045  }
  5046  
  5047  /*
  5048  ** Usage: sqlite3_get_autocommit DB
  5049  **
  5050  ** Return true if the database DB is currently in auto-commit mode.
  5051  ** Return false if not.
  5052  */
  5053  static int SQLITE_TCLAPI get_autocommit(
  5054    void * clientData,
  5055    Tcl_Interp *interp,
  5056    int argc,
  5057    char **argv
  5058  ){
  5059    char zBuf[30];
  5060    sqlite3 *db;
  5061    if( argc!=2 ){
  5062      Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 
  5063          " DB", 0);
  5064      return TCL_ERROR;
  5065    }
  5066    if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
  5067    sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", sqlite3_get_autocommit(db));
  5068    Tcl_AppendResult(interp, zBuf, 0);
  5069    return TCL_OK;
  5070  }
  5071  
  5072  /*
  5073  ** Usage: sqlite3_busy_timeout DB MS
  5074  **
  5075  ** Set the busy timeout.  This is more easily done using the timeout
  5076  ** method of the TCL interface.  But we need a way to test the case
  5077  ** where it returns SQLITE_MISUSE.
  5078  */
  5079  static int SQLITE_TCLAPI test_busy_timeout(
  5080    void * clientData,
  5081    Tcl_Interp *interp,
  5082    int argc,
  5083    char **argv
  5084  ){
  5085    int rc, ms;
  5086    sqlite3 *db;
  5087    if( argc!=3 ){
  5088      Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 
  5089          " DB", 0);
  5090      return TCL_ERROR;
  5091    }
  5092    if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
  5093    if( Tcl_GetInt(interp, argv[2], &ms) ) return TCL_ERROR;
  5094    rc = sqlite3_busy_timeout(db, ms);
  5095    Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
  5096    return TCL_OK;
  5097  }
  5098  
  5099  /*
  5100  ** Usage:  tcl_variable_type VARIABLENAME
  5101  **
  5102  ** Return the name of the internal representation for the
  5103  ** value of the given variable.
  5104  */
  5105  static int SQLITE_TCLAPI tcl_variable_type(
  5106    void * clientData,
  5107    Tcl_Interp *interp,
  5108    int objc,
  5109    Tcl_Obj *CONST objv[]
  5110  ){
  5111    Tcl_Obj *pVar;
  5112    if( objc!=2 ){
  5113      Tcl_WrongNumArgs(interp, 1, objv, "VARIABLE");
  5114      return TCL_ERROR;
  5115    }
  5116    pVar = Tcl_GetVar2Ex(interp, Tcl_GetString(objv[1]), 0, TCL_LEAVE_ERR_MSG);
  5117    if( pVar==0 ) return TCL_ERROR;
  5118    if( pVar->typePtr ){
  5119      Tcl_SetObjResult(interp, Tcl_NewStringObj(pVar->typePtr->name, -1));
  5120    }
  5121    return TCL_OK;
  5122  }
  5123  
  5124  /*
  5125  ** Usage:  sqlite3_release_memory ?N?
  5126  **
  5127  ** Attempt to release memory currently held but not actually required.
  5128  ** The integer N is the number of bytes we are trying to release.  The 
  5129  ** return value is the amount of memory actually released.
  5130  */
  5131  static int SQLITE_TCLAPI test_release_memory(
  5132    void * clientData,
  5133    Tcl_Interp *interp,
  5134    int objc,
  5135    Tcl_Obj *CONST objv[]
  5136  ){
  5137  #if defined(SQLITE_ENABLE_MEMORY_MANAGEMENT) && !defined(SQLITE_OMIT_DISKIO)
  5138    int N;
  5139    int amt;
  5140    if( objc!=1 && objc!=2 ){
  5141      Tcl_WrongNumArgs(interp, 1, objv, "?N?");
  5142      return TCL_ERROR;
  5143    }
  5144    if( objc==2 ){
  5145      if( Tcl_GetIntFromObj(interp, objv[1], &N) ) return TCL_ERROR;
  5146    }else{
  5147      N = -1;
  5148    }
  5149    amt = sqlite3_release_memory(N);
  5150    Tcl_SetObjResult(interp, Tcl_NewIntObj(amt));
  5151  #endif
  5152    return TCL_OK;
  5153  }
  5154  
  5155  
  5156  /*
  5157  ** Usage:  sqlite3_db_release_memory DB
  5158  **
  5159  ** Attempt to release memory currently held by database DB.  Return the
  5160  ** result code (which in the current implementation is always zero).
  5161  */
  5162  static int SQLITE_TCLAPI test_db_release_memory(
  5163    void * clientData,
  5164    Tcl_Interp *interp,
  5165    int objc,
  5166    Tcl_Obj *CONST objv[]
  5167  ){
  5168    sqlite3 *db;
  5169    int rc;
  5170    if( objc!=2 ){
  5171      Tcl_WrongNumArgs(interp, 1, objv, "DB");
  5172      return TCL_ERROR;
  5173    }
  5174    if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
  5175    rc = sqlite3_db_release_memory(db);
  5176    Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
  5177    return TCL_OK;
  5178  }
  5179  
  5180  /*
  5181  ** Usage:  sqlite3_db_cacheflush DB
  5182  **
  5183  ** Attempt to flush any dirty pages to disk.
  5184  */
  5185  static int SQLITE_TCLAPI test_db_cacheflush(
  5186    void * clientData,
  5187    Tcl_Interp *interp,
  5188    int objc,
  5189    Tcl_Obj *CONST objv[]
  5190  ){
  5191    sqlite3 *db;
  5192    int rc;
  5193    if( objc!=2 ){
  5194      Tcl_WrongNumArgs(interp, 1, objv, "DB");
  5195      return TCL_ERROR;
  5196    }
  5197    if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
  5198    rc = sqlite3_db_cacheflush(db);
  5199    if( rc ){
  5200      Tcl_SetResult(interp, (char *)sqlite3ErrStr(rc), TCL_STATIC);
  5201      return TCL_ERROR;
  5202    }
  5203  
  5204    Tcl_ResetResult(interp);
  5205    return TCL_OK;
  5206  }
  5207  
  5208  /*
  5209  ** Usage:  sqlite3_system_errno DB
  5210  **
  5211  ** Return the low-level system errno value.
  5212  */
  5213  static int SQLITE_TCLAPI test_system_errno(
  5214    void * clientData,
  5215    Tcl_Interp *interp,
  5216    int objc,
  5217    Tcl_Obj *CONST objv[]
  5218  ){
  5219    sqlite3 *db;
  5220    int iErrno;
  5221    if( objc!=2 ){
  5222      Tcl_WrongNumArgs(interp, 1, objv, "DB");
  5223      return TCL_ERROR;
  5224    }
  5225    if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
  5226    iErrno = sqlite3_system_errno(db);
  5227    Tcl_SetObjResult(interp, Tcl_NewIntObj(iErrno));
  5228    return TCL_OK;
  5229  }
  5230  
  5231  /*
  5232  ** Usage:  sqlite3_db_filename DB DBNAME
  5233  **
  5234  ** Return the name of a file associated with a database.
  5235  */
  5236  static int SQLITE_TCLAPI test_db_filename(
  5237    void * clientData,
  5238    Tcl_Interp *interp,
  5239    int objc,
  5240    Tcl_Obj *CONST objv[]
  5241  ){
  5242    sqlite3 *db;
  5243    const char *zDbName;
  5244    if( objc!=3 ){
  5245      Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME");
  5246      return TCL_ERROR;
  5247    }
  5248    if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
  5249    zDbName = Tcl_GetString(objv[2]);
  5250    Tcl_AppendResult(interp, sqlite3_db_filename(db, zDbName), (void*)0);
  5251    return TCL_OK;
  5252  }
  5253  
  5254  /*
  5255  ** Usage:  sqlite3_db_readonly DB DBNAME
  5256  **
  5257  ** Return 1 or 0 if DBNAME is readonly or not.  Return -1 if DBNAME does
  5258  ** not exist.
  5259  */
  5260  static int SQLITE_TCLAPI test_db_readonly(
  5261    void * clientData,
  5262    Tcl_Interp *interp,
  5263    int objc,
  5264    Tcl_Obj *CONST objv[]
  5265  ){
  5266    sqlite3 *db;
  5267    const char *zDbName;
  5268    if( objc!=3 ){
  5269      Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME");
  5270      return TCL_ERROR;
  5271    }
  5272    if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
  5273    zDbName = Tcl_GetString(objv[2]);
  5274    Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_db_readonly(db, zDbName)));
  5275    return TCL_OK;
  5276  }
  5277  
  5278  /*
  5279  ** Usage:  sqlite3_soft_heap_limit ?N?
  5280  **
  5281  ** Query or set the soft heap limit for the current thread.  The
  5282  ** limit is only changed if the N is present.  The previous limit
  5283  ** is returned.
  5284  */
  5285  static int SQLITE_TCLAPI test_soft_heap_limit(
  5286    void * clientData,
  5287    Tcl_Interp *interp,
  5288    int objc,
  5289    Tcl_Obj *CONST objv[]
  5290  ){
  5291    sqlite3_int64 amt;
  5292    Tcl_WideInt N = -1;
  5293    if( objc!=1 && objc!=2 ){
  5294      Tcl_WrongNumArgs(interp, 1, objv, "?N?");
  5295      return TCL_ERROR;
  5296    }
  5297    if( objc==2 ){
  5298      if( Tcl_GetWideIntFromObj(interp, objv[1], &N) ) return TCL_ERROR;
  5299    }
  5300    amt = sqlite3_soft_heap_limit64(N);
  5301    Tcl_SetObjResult(interp, Tcl_NewWideIntObj(amt));
  5302    return TCL_OK;
  5303  }
  5304  
  5305  /*
  5306  ** Usage:   sqlite3_thread_cleanup
  5307  **
  5308  ** Call the sqlite3_thread_cleanup API.
  5309  */
  5310  static int SQLITE_TCLAPI test_thread_cleanup(
  5311    void * clientData,
  5312    Tcl_Interp *interp,
  5313    int objc,
  5314    Tcl_Obj *CONST objv[]
  5315  ){
  5316  #ifndef SQLITE_OMIT_DEPRECATED
  5317    sqlite3_thread_cleanup();
  5318  #endif
  5319    return TCL_OK;
  5320  }
  5321  
  5322  /*
  5323  ** Usage:   sqlite3_pager_refcounts  DB
  5324  **
  5325  ** Return a list of numbers which are the PagerRefcount for all
  5326  ** pagers on each database connection.
  5327  */
  5328  static int SQLITE_TCLAPI test_pager_refcounts(
  5329    void * clientData,
  5330    Tcl_Interp *interp,
  5331    int objc,
  5332    Tcl_Obj *CONST objv[]
  5333  ){
  5334    sqlite3 *db;
  5335    int i;
  5336    int v, *a;
  5337    Tcl_Obj *pResult;
  5338  
  5339    if( objc!=2 ){
  5340      Tcl_AppendResult(interp, "wrong # args: should be \"",
  5341          Tcl_GetStringFromObj(objv[0], 0), " DB", 0);
  5342      return TCL_ERROR;
  5343    }
  5344    if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
  5345    pResult = Tcl_NewObj();
  5346    for(i=0; i<db->nDb; i++){
  5347      if( db->aDb[i].pBt==0 ){
  5348        v = -1;
  5349      }else{
  5350        sqlite3_mutex_enter(db->mutex);
  5351        a = sqlite3PagerStats(sqlite3BtreePager(db->aDb[i].pBt));
  5352        v = a[0];
  5353        sqlite3_mutex_leave(db->mutex);
  5354      }
  5355      Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(v));
  5356    }
  5357    Tcl_SetObjResult(interp, pResult);
  5358    return TCL_OK;
  5359  }
  5360  
  5361  
  5362  /*
  5363  ** tclcmd:   working_64bit_int
  5364  **
  5365  ** Some TCL builds (ex: cygwin) do not support 64-bit integers.  This
  5366  ** leads to a number of test failures.  The present command checks the
  5367  ** TCL build to see whether or not it supports 64-bit integers.  It
  5368  ** returns TRUE if it does and FALSE if not.
  5369  **
  5370  ** This command is used to warn users that their TCL build is defective
  5371  ** and that the errors they are seeing in the test scripts might be
  5372  ** a result of their defective TCL rather than problems in SQLite.
  5373  */
  5374  static int SQLITE_TCLAPI working_64bit_int(
  5375    ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
  5376    Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  5377    int objc,              /* Number of arguments */
  5378    Tcl_Obj *CONST objv[]  /* Command arguments */
  5379  ){
  5380    Tcl_Obj *pTestObj;
  5381    int working = 0;
  5382  
  5383    pTestObj = Tcl_NewWideIntObj(1000000*(i64)1234567890);
  5384    working = strcmp(Tcl_GetString(pTestObj), "1234567890000000")==0;
  5385    Tcl_DecrRefCount(pTestObj);
  5386    Tcl_SetObjResult(interp, Tcl_NewBooleanObj(working));
  5387    return TCL_OK;
  5388  }
  5389  
  5390  
  5391  /*
  5392  ** tclcmd:   vfs_unlink_test
  5393  **
  5394  ** This TCL command unregisters the primary VFS and then registers
  5395  ** it back again.  This is used to test the ability to register a
  5396  ** VFS when none are previously registered, and the ability to 
  5397  ** unregister the only available VFS.  Ticket #2738
  5398  */
  5399  static int SQLITE_TCLAPI vfs_unlink_test(
  5400    ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
  5401    Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  5402    int objc,              /* Number of arguments */
  5403    Tcl_Obj *CONST objv[]  /* Command arguments */
  5404  ){
  5405    int i;
  5406    sqlite3_vfs *pMain;
  5407    sqlite3_vfs *apVfs[20];
  5408    sqlite3_vfs one, two;
  5409  
  5410    sqlite3_vfs_unregister(0);   /* Unregister of NULL is harmless */
  5411    one.zName = "__one";
  5412    two.zName = "__two";
  5413  
  5414    /* Calling sqlite3_vfs_register with 2nd argument of 0 does not
  5415    ** change the default VFS
  5416    */
  5417    pMain = sqlite3_vfs_find(0);
  5418    sqlite3_vfs_register(&one, 0);
  5419    assert( pMain==0 || pMain==sqlite3_vfs_find(0) );
  5420    sqlite3_vfs_register(&two, 0);
  5421    assert( pMain==0 || pMain==sqlite3_vfs_find(0) );
  5422  
  5423    /* We can find a VFS by its name */
  5424    assert( sqlite3_vfs_find("__one")==&one );
  5425    assert( sqlite3_vfs_find("__two")==&two );
  5426  
  5427    /* Calling sqlite_vfs_register with non-zero second parameter changes the
  5428    ** default VFS, even if the 1st parameter is an existig VFS that is
  5429    ** previously registered as the non-default.
  5430    */
  5431    sqlite3_vfs_register(&one, 1);
  5432    assert( sqlite3_vfs_find("__one")==&one );
  5433    assert( sqlite3_vfs_find("__two")==&two );
  5434    assert( sqlite3_vfs_find(0)==&one );
  5435    sqlite3_vfs_register(&two, 1);
  5436    assert( sqlite3_vfs_find("__one")==&one );
  5437    assert( sqlite3_vfs_find("__two")==&two );
  5438    assert( sqlite3_vfs_find(0)==&two );
  5439    if( pMain ){
  5440      sqlite3_vfs_register(pMain, 1);
  5441      assert( sqlite3_vfs_find("__one")==&one );
  5442      assert( sqlite3_vfs_find("__two")==&two );
  5443      assert( sqlite3_vfs_find(0)==pMain );
  5444    }
  5445    
  5446    /* Unlink the default VFS.  Repeat until there are no more VFSes
  5447    ** registered.
  5448    */
  5449    for(i=0; i<sizeof(apVfs)/sizeof(apVfs[0]); i++){
  5450      apVfs[i] = sqlite3_vfs_find(0);
  5451      if( apVfs[i] ){
  5452        assert( apVfs[i]==sqlite3_vfs_find(apVfs[i]->zName) );
  5453        sqlite3_vfs_unregister(apVfs[i]);
  5454        assert( 0==sqlite3_vfs_find(apVfs[i]->zName) );
  5455      }
  5456    }
  5457    assert( 0==sqlite3_vfs_find(0) );
  5458    
  5459    /* Register the main VFS as non-default (will be made default, since
  5460    ** it'll be the only one in existence).
  5461    */
  5462    sqlite3_vfs_register(pMain, 0);
  5463    assert( sqlite3_vfs_find(0)==pMain );
  5464    
  5465    /* Un-register the main VFS again to restore an empty VFS list */
  5466    sqlite3_vfs_unregister(pMain);
  5467    assert( 0==sqlite3_vfs_find(0) );
  5468  
  5469    /* Relink all VFSes in reverse order. */  
  5470    for(i=sizeof(apVfs)/sizeof(apVfs[0])-1; i>=0; i--){
  5471      if( apVfs[i] ){
  5472        sqlite3_vfs_register(apVfs[i], 1);
  5473        assert( apVfs[i]==sqlite3_vfs_find(0) );
  5474        assert( apVfs[i]==sqlite3_vfs_find(apVfs[i]->zName) );
  5475      }
  5476    }
  5477  
  5478    /* Unregister out sample VFSes. */
  5479    sqlite3_vfs_unregister(&one);
  5480    sqlite3_vfs_unregister(&two);
  5481  
  5482    /* Unregistering a VFS that is not currently registered is harmless */
  5483    sqlite3_vfs_unregister(&one);
  5484    sqlite3_vfs_unregister(&two);
  5485    assert( sqlite3_vfs_find("__one")==0 );
  5486    assert( sqlite3_vfs_find("__two")==0 );
  5487  
  5488    /* We should be left with the original default VFS back as the
  5489    ** original */
  5490    assert( sqlite3_vfs_find(0)==pMain );
  5491  
  5492    return TCL_OK;
  5493  }
  5494  
  5495  /*
  5496  ** tclcmd:   vfs_initfail_test
  5497  **
  5498  ** This TCL command attempts to vfs_find and vfs_register when the
  5499  ** sqlite3_initialize() interface is failing.  All calls should fail.
  5500  */
  5501  static int SQLITE_TCLAPI vfs_initfail_test(
  5502    ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
  5503    Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  5504    int objc,              /* Number of arguments */
  5505    Tcl_Obj *CONST objv[]  /* Command arguments */
  5506  ){
  5507    sqlite3_vfs one;
  5508    one.zName = "__one";
  5509  
  5510    if( sqlite3_vfs_find(0) ) return TCL_ERROR;
  5511    sqlite3_vfs_register(&one, 0);
  5512    if( sqlite3_vfs_find(0) ) return TCL_ERROR;
  5513    sqlite3_vfs_register(&one, 1);
  5514    if( sqlite3_vfs_find(0) ) return TCL_ERROR;
  5515    return TCL_OK;
  5516  }
  5517  
  5518  /*
  5519  ** Saved VFSes
  5520  */
  5521  static sqlite3_vfs *apVfs[20];
  5522  static int nVfs = 0;
  5523  
  5524  /*
  5525  ** tclcmd:   vfs_unregister_all
  5526  **
  5527  ** Unregister all VFSes.
  5528  */
  5529  static int SQLITE_TCLAPI vfs_unregister_all(
  5530    ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
  5531    Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  5532    int objc,              /* Number of arguments */
  5533    Tcl_Obj *CONST objv[]  /* Command arguments */
  5534  ){
  5535    int i;
  5536    for(i=0; i<ArraySize(apVfs); i++){
  5537      apVfs[i] = sqlite3_vfs_find(0);
  5538      if( apVfs[i]==0 ) break;
  5539      sqlite3_vfs_unregister(apVfs[i]);
  5540    }
  5541    nVfs = i;
  5542    return TCL_OK;
  5543  }
  5544  /*
  5545  ** tclcmd:   vfs_reregister_all
  5546  **
  5547  ** Restore all VFSes that were removed using vfs_unregister_all. Taking
  5548  ** care to put the linked list back together in the same order as it was
  5549  ** in before vfs_unregister_all was invoked.
  5550  */
  5551  static int SQLITE_TCLAPI vfs_reregister_all(
  5552    ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
  5553    Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  5554    int objc,              /* Number of arguments */
  5555    Tcl_Obj *CONST objv[]  /* Command arguments */
  5556  ){
  5557    int i;
  5558    for(i=nVfs-1; i>=0; i--){
  5559      sqlite3_vfs_register(apVfs[i], 1);
  5560    }
  5561    return TCL_OK;
  5562  }
  5563  
  5564  
  5565  /*
  5566  ** tclcmd:   file_control_test DB
  5567  **
  5568  ** This TCL command runs the sqlite3_file_control interface and
  5569  ** verifies correct operation of the same.
  5570  */
  5571  static int SQLITE_TCLAPI file_control_test(
  5572    ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
  5573    Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  5574    int objc,              /* Number of arguments */
  5575    Tcl_Obj *CONST objv[]  /* Command arguments */
  5576  ){
  5577    int iArg = 0;
  5578    sqlite3 *db;
  5579    int rc;
  5580  
  5581    if( objc!=2 ){
  5582      Tcl_AppendResult(interp, "wrong # args: should be \"",
  5583          Tcl_GetStringFromObj(objv[0], 0), " DB", 0);
  5584      return TCL_ERROR;
  5585    }
  5586    if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
  5587    rc = sqlite3_file_control(db, 0, 0, &iArg);
  5588    assert( rc==SQLITE_NOTFOUND );
  5589    rc = sqlite3_file_control(db, "notadatabase", SQLITE_FCNTL_LOCKSTATE, &iArg);
  5590    assert( rc==SQLITE_ERROR );
  5591    rc = sqlite3_file_control(db, "main", -1, &iArg);
  5592    assert( rc==SQLITE_NOTFOUND );
  5593    rc = sqlite3_file_control(db, "temp", -1, &iArg);
  5594    assert( rc==SQLITE_NOTFOUND || rc==SQLITE_ERROR );
  5595  
  5596    return TCL_OK;
  5597  }
  5598  
  5599  
  5600  /*
  5601  ** tclcmd:   file_control_lasterrno_test DB
  5602  **
  5603  ** This TCL command runs the sqlite3_file_control interface and
  5604  ** verifies correct operation of the SQLITE_LAST_ERRNO verb.
  5605  */
  5606  static int SQLITE_TCLAPI file_control_lasterrno_test(
  5607    ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
  5608    Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  5609    int objc,              /* Number of arguments */
  5610    Tcl_Obj *CONST objv[]  /* Command arguments */
  5611  ){
  5612    int iArg = 0;
  5613    sqlite3 *db;
  5614    int rc;
  5615  
  5616    if( objc!=2 ){
  5617      Tcl_AppendResult(interp, "wrong # args: should be \"",
  5618          Tcl_GetStringFromObj(objv[0], 0), " DB", 0);
  5619      return TCL_ERROR;
  5620    }
  5621    if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
  5622      return TCL_ERROR;
  5623    }
  5624    rc = sqlite3_file_control(db, NULL, SQLITE_LAST_ERRNO, &iArg);
  5625    if( rc ){ 
  5626      Tcl_SetObjResult(interp, Tcl_NewIntObj(rc)); 
  5627      return TCL_ERROR; 
  5628    }
  5629    if( iArg!=0 ) {
  5630      Tcl_AppendResult(interp, "Unexpected non-zero errno: ",
  5631                       Tcl_GetStringFromObj(Tcl_NewIntObj(iArg), 0), " ", 0);
  5632      return TCL_ERROR;
  5633    }
  5634    return TCL_OK;  
  5635  }
  5636  
  5637  /*
  5638  ** tclcmd:   file_control_chunksize_test DB DBNAME SIZE
  5639  **
  5640  ** This TCL command runs the sqlite3_file_control interface and
  5641  ** verifies correct operation of the SQLITE_GET_LOCKPROXYFILE and
  5642  ** SQLITE_SET_LOCKPROXYFILE verbs.
  5643  */
  5644  static int SQLITE_TCLAPI file_control_chunksize_test(
  5645    ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
  5646    Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  5647    int objc,              /* Number of arguments */
  5648    Tcl_Obj *CONST objv[]  /* Command arguments */
  5649  ){
  5650    int nSize;                      /* New chunk size */
  5651    char *zDb;                      /* Db name ("main", "temp" etc.) */
  5652    sqlite3 *db;                    /* Database handle */
  5653    int rc;                         /* file_control() return code */
  5654  
  5655    if( objc!=4 ){
  5656      Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME SIZE");
  5657      return TCL_ERROR;
  5658    }
  5659    if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) 
  5660     || Tcl_GetIntFromObj(interp, objv[3], &nSize)
  5661    ){
  5662     return TCL_ERROR;
  5663    }
  5664    zDb = Tcl_GetString(objv[2]);
  5665    if( zDb[0]=='\0' ) zDb = NULL;
  5666  
  5667    rc = sqlite3_file_control(db, zDb, SQLITE_FCNTL_CHUNK_SIZE, (void *)&nSize);
  5668    if( rc ){
  5669      Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_STATIC);
  5670      return TCL_ERROR;
  5671    }
  5672    return TCL_OK;
  5673  }
  5674  
  5675  /*
  5676  ** tclcmd:   file_control_sizehint_test DB DBNAME SIZE
  5677  **
  5678  ** This TCL command runs the sqlite3_file_control interface 
  5679  ** with SQLITE_FCNTL_SIZE_HINT
  5680  */
  5681  static int SQLITE_TCLAPI file_control_sizehint_test(
  5682    ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
  5683    Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  5684    int objc,              /* Number of arguments */
  5685    Tcl_Obj *CONST objv[]  /* Command arguments */
  5686  ){
  5687    Tcl_WideInt nSize;              /* Hinted size */
  5688    char *zDb;                      /* Db name ("main", "temp" etc.) */
  5689    sqlite3 *db;                    /* Database handle */
  5690    int rc;                         /* file_control() return code */
  5691  
  5692    if( objc!=4 ){
  5693      Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME SIZE");
  5694      return TCL_ERROR;
  5695    }
  5696    if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) 
  5697     || Tcl_GetWideIntFromObj(interp, objv[3], &nSize)
  5698    ){
  5699     return TCL_ERROR;
  5700    }
  5701    zDb = Tcl_GetString(objv[2]);
  5702    if( zDb[0]=='\0' ) zDb = NULL;
  5703  
  5704    rc = sqlite3_file_control(db, zDb, SQLITE_FCNTL_SIZE_HINT, (void *)&nSize);
  5705    if( rc ){
  5706      Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_STATIC);
  5707      return TCL_ERROR;
  5708    }
  5709    return TCL_OK;
  5710  }
  5711  
  5712  /*
  5713  ** tclcmd:   file_control_lockproxy_test DB PWD
  5714  **
  5715  ** This TCL command runs the sqlite3_file_control interface and
  5716  ** verifies correct operation of the SQLITE_GET_LOCKPROXYFILE and
  5717  ** SQLITE_SET_LOCKPROXYFILE verbs.
  5718  */
  5719  static int SQLITE_TCLAPI file_control_lockproxy_test(
  5720    ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
  5721    Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  5722    int objc,              /* Number of arguments */
  5723    Tcl_Obj *CONST objv[]  /* Command arguments */
  5724  ){
  5725    sqlite3 *db;
  5726    
  5727    if( objc!=3 ){
  5728      Tcl_AppendResult(interp, "wrong # args: should be \"",
  5729                       Tcl_GetStringFromObj(objv[0], 0), " DB PWD", 0);
  5730      return TCL_ERROR;
  5731    }
  5732    if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
  5733     return TCL_ERROR;
  5734    }
  5735    
  5736  #if !defined(SQLITE_ENABLE_LOCKING_STYLE)
  5737  #  if defined(__APPLE__)
  5738  #    define SQLITE_ENABLE_LOCKING_STYLE 1
  5739  #  else
  5740  #    define SQLITE_ENABLE_LOCKING_STYLE 0
  5741  #  endif
  5742  #endif
  5743  #if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
  5744    {
  5745      char *testPath;
  5746      int rc;
  5747      int nPwd;
  5748      const char *zPwd;
  5749      char proxyPath[400];
  5750      
  5751      zPwd = Tcl_GetStringFromObj(objv[2], &nPwd);
  5752      if( sizeof(proxyPath)<nPwd+20 ){
  5753        Tcl_AppendResult(interp, "PWD too big", (void*)0);
  5754        return TCL_ERROR;
  5755      }
  5756      sqlite3_snprintf(sizeof(proxyPath), proxyPath, "%s/test.proxy", zPwd);
  5757      rc = sqlite3_file_control(db, NULL, SQLITE_SET_LOCKPROXYFILE, proxyPath);
  5758      if( rc ){
  5759        Tcl_SetObjResult(interp, Tcl_NewIntObj(rc)); 
  5760        return TCL_ERROR;
  5761      }
  5762      rc = sqlite3_file_control(db, NULL, SQLITE_GET_LOCKPROXYFILE, &testPath);
  5763      if( strncmp(proxyPath,testPath,11) ){
  5764        Tcl_AppendResult(interp, "Lock proxy file did not match the "
  5765                                 "previously assigned value", 0);
  5766        return TCL_ERROR;
  5767      }
  5768      if( rc ){
  5769        Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
  5770        return TCL_ERROR;
  5771      }
  5772      rc = sqlite3_file_control(db, NULL, SQLITE_SET_LOCKPROXYFILE, proxyPath);
  5773      if( rc ){
  5774        Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
  5775        return TCL_ERROR;
  5776      }
  5777    }
  5778  #endif
  5779    return TCL_OK;  
  5780  }
  5781  
  5782  #if SQLITE_OS_WIN
  5783  /*
  5784  ** tclcmd:   file_control_win32_av_retry DB  NRETRY  DELAY
  5785  **
  5786  ** This TCL command runs the sqlite3_file_control interface with
  5787  ** the SQLITE_FCNTL_WIN32_AV_RETRY opcode.
  5788  */
  5789  static int SQLITE_TCLAPI file_control_win32_av_retry(
  5790    ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
  5791    Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  5792    int objc,              /* Number of arguments */
  5793    Tcl_Obj *CONST objv[]  /* Command arguments */
  5794  ){
  5795    sqlite3 *db;
  5796    int rc;
  5797    int a[2];
  5798    char z[100];
  5799  
  5800    if( objc!=4 ){
  5801      Tcl_AppendResult(interp, "wrong # args: should be \"",
  5802          Tcl_GetStringFromObj(objv[0], 0), " DB NRETRY DELAY", 0);
  5803      return TCL_ERROR;
  5804    }
  5805    if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
  5806      return TCL_ERROR;
  5807    }
  5808    if( Tcl_GetIntFromObj(interp, objv[2], &a[0]) ) return TCL_ERROR;
  5809    if( Tcl_GetIntFromObj(interp, objv[3], &a[1]) ) return TCL_ERROR;
  5810    rc = sqlite3_file_control(db, NULL, SQLITE_FCNTL_WIN32_AV_RETRY, (void*)a);
  5811    sqlite3_snprintf(sizeof(z), z, "%d %d %d", rc, a[0], a[1]);
  5812    Tcl_AppendResult(interp, z, (char*)0);
  5813    return TCL_OK;  
  5814  }
  5815  
  5816  /*
  5817  ** tclcmd:   file_control_win32_get_handle DB
  5818  **
  5819  ** This TCL command runs the sqlite3_file_control interface with
  5820  ** the SQLITE_FCNTL_WIN32_GET_HANDLE opcode.
  5821  */
  5822  static int file_control_win32_get_handle(
  5823    ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
  5824    Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  5825    int objc,              /* Number of arguments */
  5826    Tcl_Obj *CONST objv[]  /* Command arguments */
  5827  ){
  5828    sqlite3 *db;
  5829    int rc;
  5830    HANDLE hFile = NULL;
  5831    char z[100];
  5832  
  5833    if( objc!=2 ){
  5834      Tcl_AppendResult(interp, "wrong # args: should be \"",
  5835          Tcl_GetStringFromObj(objv[0], 0), " DB", 0);
  5836      return TCL_ERROR;
  5837    }
  5838    if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
  5839      return TCL_ERROR;
  5840    }
  5841    rc = sqlite3_file_control(db, NULL, SQLITE_FCNTL_WIN32_GET_HANDLE,
  5842                              (void*)&hFile);
  5843    sqlite3_snprintf(sizeof(z), z, "%d %p", rc, (void*)hFile);
  5844    Tcl_AppendResult(interp, z, (char*)0);
  5845    return TCL_OK;
  5846  }
  5847  
  5848  /*
  5849  ** tclcmd:   file_control_win32_set_handle DB HANDLE
  5850  **
  5851  ** This TCL command runs the sqlite3_file_control interface with
  5852  ** the SQLITE_FCNTL_WIN32_SET_HANDLE opcode.
  5853  */
  5854  static int SQLITE_TCLAPI file_control_win32_set_handle(
  5855    ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
  5856    Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  5857    int objc,              /* Number of arguments */
  5858    Tcl_Obj *CONST objv[]  /* Command arguments */
  5859  ){
  5860    sqlite3 *db;
  5861    int rc;
  5862    HANDLE hFile = NULL;
  5863    char z[100];
  5864  
  5865    if( objc!=3 ){
  5866      Tcl_AppendResult(interp, "wrong # args: should be \"",
  5867          Tcl_GetStringFromObj(objv[0], 0), " DB HANDLE", 0);
  5868      return TCL_ERROR;
  5869    }
  5870    if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
  5871      return TCL_ERROR;
  5872    }
  5873    if( getWin32Handle(interp, Tcl_GetString(objv[2]), &hFile) ){
  5874      return TCL_ERROR;
  5875    }
  5876    rc = sqlite3_file_control(db, NULL, SQLITE_FCNTL_WIN32_SET_HANDLE,
  5877                              (void*)&hFile);
  5878    sqlite3_snprintf(sizeof(z), z, "%d %p", rc, (void*)hFile);
  5879    Tcl_AppendResult(interp, z, (char*)0);
  5880    return TCL_OK;  
  5881  }
  5882  #endif
  5883  
  5884  /*
  5885  ** tclcmd:   file_control_persist_wal DB PERSIST-FLAG
  5886  **
  5887  ** This TCL command runs the sqlite3_file_control interface with
  5888  ** the SQLITE_FCNTL_PERSIST_WAL opcode.
  5889  */
  5890  static int SQLITE_TCLAPI file_control_persist_wal(
  5891    ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
  5892    Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  5893    int objc,              /* Number of arguments */
  5894    Tcl_Obj *CONST objv[]  /* Command arguments */
  5895  ){
  5896    sqlite3 *db;
  5897    int rc;
  5898    int bPersist;
  5899    char z[100];
  5900  
  5901    if( objc!=3 ){
  5902      Tcl_AppendResult(interp, "wrong # args: should be \"",
  5903          Tcl_GetStringFromObj(objv[0], 0), " DB FLAG", 0);
  5904      return TCL_ERROR;
  5905    }
  5906    if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
  5907      return TCL_ERROR;
  5908    }
  5909    if( Tcl_GetIntFromObj(interp, objv[2], &bPersist) ) return TCL_ERROR;
  5910    rc = sqlite3_file_control(db, NULL, SQLITE_FCNTL_PERSIST_WAL, (void*)&bPersist);
  5911    sqlite3_snprintf(sizeof(z), z, "%d %d", rc, bPersist);
  5912    Tcl_AppendResult(interp, z, (char*)0);
  5913    return TCL_OK;  
  5914  }
  5915  
  5916  /*
  5917  ** tclcmd:   file_control_powersafe_overwrite DB PSOW-FLAG
  5918  **
  5919  ** This TCL command runs the sqlite3_file_control interface with
  5920  ** the SQLITE_FCNTL_POWERSAFE_OVERWRITE opcode.
  5921  */
  5922  static int SQLITE_TCLAPI file_control_powersafe_overwrite(
  5923    ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
  5924    Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  5925    int objc,              /* Number of arguments */
  5926    Tcl_Obj *CONST objv[]  /* Command arguments */
  5927  ){
  5928    sqlite3 *db;
  5929    int rc;
  5930    int b;
  5931    char z[100];
  5932  
  5933    if( objc!=3 ){
  5934      Tcl_AppendResult(interp, "wrong # args: should be \"",
  5935          Tcl_GetStringFromObj(objv[0], 0), " DB FLAG", 0);
  5936      return TCL_ERROR;
  5937    }
  5938    if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
  5939      return TCL_ERROR;
  5940    }
  5941    if( Tcl_GetIntFromObj(interp, objv[2], &b) ) return TCL_ERROR;
  5942    rc = sqlite3_file_control(db,NULL,SQLITE_FCNTL_POWERSAFE_OVERWRITE,(void*)&b);
  5943    sqlite3_snprintf(sizeof(z), z, "%d %d", rc, b);
  5944    Tcl_AppendResult(interp, z, (char*)0);
  5945    return TCL_OK;  
  5946  }
  5947  
  5948  
  5949  /*
  5950  ** tclcmd:   file_control_vfsname DB ?AUXDB?
  5951  **
  5952  ** Return a string that describes the stack of VFSes.
  5953  */
  5954  static int SQLITE_TCLAPI file_control_vfsname(
  5955    ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
  5956    Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  5957    int objc,              /* Number of arguments */
  5958    Tcl_Obj *CONST objv[]  /* Command arguments */
  5959  ){
  5960    sqlite3 *db;
  5961    const char *zDbName = "main";
  5962    char *zVfsName = 0;
  5963  
  5964    if( objc!=2 && objc!=3 ){
  5965      Tcl_AppendResult(interp, "wrong # args: should be \"",
  5966          Tcl_GetStringFromObj(objv[0], 0), " DB ?AUXDB?", 0);
  5967      return TCL_ERROR;
  5968    }
  5969    if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
  5970      return TCL_ERROR;
  5971    }
  5972    if( objc==3 ){
  5973      zDbName = Tcl_GetString(objv[2]);
  5974    }
  5975    sqlite3_file_control(db, zDbName, SQLITE_FCNTL_VFSNAME,(void*)&zVfsName);
  5976    Tcl_AppendResult(interp, zVfsName, (char*)0);
  5977    sqlite3_free(zVfsName);
  5978    return TCL_OK;  
  5979  }
  5980  
  5981  /*
  5982  ** tclcmd:   file_control_tempfilename DB ?AUXDB?
  5983  **
  5984  ** Return a string that is a temporary filename
  5985  */
  5986  static int SQLITE_TCLAPI file_control_tempfilename(
  5987    ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
  5988    Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  5989    int objc,              /* Number of arguments */
  5990    Tcl_Obj *CONST objv[]  /* Command arguments */
  5991  ){
  5992    sqlite3 *db;
  5993    const char *zDbName = "main";
  5994    char *zTName = 0;
  5995  
  5996    if( objc!=2 && objc!=3 ){
  5997      Tcl_AppendResult(interp, "wrong # args: should be \"",
  5998          Tcl_GetStringFromObj(objv[0], 0), " DB ?AUXDB?", 0);
  5999      return TCL_ERROR;
  6000    }
  6001    if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
  6002      return TCL_ERROR;
  6003    }
  6004    if( objc==3 ){
  6005      zDbName = Tcl_GetString(objv[2]);
  6006    }
  6007    sqlite3_file_control(db, zDbName, SQLITE_FCNTL_TEMPFILENAME, (void*)&zTName);
  6008    Tcl_AppendResult(interp, zTName, (char*)0);
  6009    sqlite3_free(zTName);
  6010    return TCL_OK;  
  6011  }
  6012  
  6013  
  6014  /*
  6015  ** tclcmd:   sqlite3_vfs_list
  6016  **
  6017  **   Return a tcl list containing the names of all registered vfs's.
  6018  */
  6019  static int SQLITE_TCLAPI vfs_list(
  6020    ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
  6021    Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  6022    int objc,              /* Number of arguments */
  6023    Tcl_Obj *CONST objv[]  /* Command arguments */
  6024  ){
  6025    sqlite3_vfs *pVfs;
  6026    Tcl_Obj *pRet = Tcl_NewObj();
  6027    if( objc!=1 ){
  6028      Tcl_WrongNumArgs(interp, 1, objv, "");
  6029      return TCL_ERROR;
  6030    }
  6031    for(pVfs=sqlite3_vfs_find(0); pVfs; pVfs=pVfs->pNext){
  6032      Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj(pVfs->zName, -1));
  6033    }
  6034    Tcl_SetObjResult(interp, pRet);
  6035    return TCL_OK;  
  6036  }
  6037  
  6038  /*
  6039  ** tclcmd:   sqlite3_limit DB ID VALUE
  6040  **
  6041  ** This TCL command runs the sqlite3_limit interface and
  6042  ** verifies correct operation of the same.
  6043  */
  6044  static int SQLITE_TCLAPI test_limit(
  6045    ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
  6046    Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  6047    int objc,              /* Number of arguments */
  6048    Tcl_Obj *CONST objv[]  /* Command arguments */
  6049  ){
  6050    sqlite3 *db;
  6051    int rc;
  6052    static const struct {
  6053       char *zName;
  6054       int id;
  6055    } aId[] = {
  6056      { "SQLITE_LIMIT_LENGTH",              SQLITE_LIMIT_LENGTH               },
  6057      { "SQLITE_LIMIT_SQL_LENGTH",          SQLITE_LIMIT_SQL_LENGTH           },
  6058      { "SQLITE_LIMIT_COLUMN",              SQLITE_LIMIT_COLUMN               },
  6059      { "SQLITE_LIMIT_EXPR_DEPTH",          SQLITE_LIMIT_EXPR_DEPTH           },
  6060      { "SQLITE_LIMIT_COMPOUND_SELECT",     SQLITE_LIMIT_COMPOUND_SELECT      },
  6061      { "SQLITE_LIMIT_VDBE_OP",             SQLITE_LIMIT_VDBE_OP              },
  6062      { "SQLITE_LIMIT_FUNCTION_ARG",        SQLITE_LIMIT_FUNCTION_ARG         },
  6063      { "SQLITE_LIMIT_ATTACHED",            SQLITE_LIMIT_ATTACHED             },
  6064      { "SQLITE_LIMIT_LIKE_PATTERN_LENGTH", SQLITE_LIMIT_LIKE_PATTERN_LENGTH  },
  6065      { "SQLITE_LIMIT_VARIABLE_NUMBER",     SQLITE_LIMIT_VARIABLE_NUMBER      },
  6066      { "SQLITE_LIMIT_TRIGGER_DEPTH",       SQLITE_LIMIT_TRIGGER_DEPTH        },
  6067      { "SQLITE_LIMIT_WORKER_THREADS",      SQLITE_LIMIT_WORKER_THREADS       },
  6068      
  6069      /* Out of range test cases */
  6070      { "SQLITE_LIMIT_TOOSMALL",            -1,                               },
  6071      { "SQLITE_LIMIT_TOOBIG",              SQLITE_LIMIT_WORKER_THREADS+1     },
  6072    };
  6073    int i, id = 0;
  6074    int val;
  6075    const char *zId;
  6076  
  6077    if( objc!=4 ){
  6078      Tcl_AppendResult(interp, "wrong # args: should be \"",
  6079          Tcl_GetStringFromObj(objv[0], 0), " DB ID VALUE", 0);
  6080      return TCL_ERROR;
  6081    }
  6082    if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
  6083    zId = Tcl_GetString(objv[2]);
  6084    for(i=0; i<sizeof(aId)/sizeof(aId[0]); i++){
  6085      if( strcmp(zId, aId[i].zName)==0 ){
  6086        id = aId[i].id;
  6087        break;
  6088      }
  6089    }
  6090    if( i>=sizeof(aId)/sizeof(aId[0]) ){
  6091      Tcl_AppendResult(interp, "unknown limit type: ", zId, (char*)0);
  6092      return TCL_ERROR;
  6093    }
  6094    if( Tcl_GetIntFromObj(interp, objv[3], &val) ) return TCL_ERROR;
  6095    rc = sqlite3_limit(db, id, val);
  6096    Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
  6097    return TCL_OK;  
  6098  }
  6099  
  6100  /*
  6101  ** tclcmd:  save_prng_state
  6102  **
  6103  ** Save the state of the pseudo-random number generator.
  6104  ** At the same time, verify that sqlite3_test_control works even when
  6105  ** called with an out-of-range opcode.
  6106  */
  6107  static int SQLITE_TCLAPI save_prng_state(
  6108    ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
  6109    Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  6110    int objc,              /* Number of arguments */
  6111    Tcl_Obj *CONST objv[]  /* Command arguments */
  6112  ){
  6113    int rc = sqlite3_test_control(9999);
  6114    assert( rc==0 );
  6115    rc = sqlite3_test_control(-1);
  6116    assert( rc==0 );
  6117    sqlite3_test_control(SQLITE_TESTCTRL_PRNG_SAVE);
  6118    return TCL_OK;
  6119  }
  6120  /*
  6121  ** tclcmd:  restore_prng_state
  6122  */
  6123  static int SQLITE_TCLAPI restore_prng_state(
  6124    ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
  6125    Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  6126    int objc,              /* Number of arguments */
  6127    Tcl_Obj *CONST objv[]  /* Command arguments */
  6128  ){
  6129    sqlite3_test_control(SQLITE_TESTCTRL_PRNG_RESTORE);
  6130    return TCL_OK;
  6131  }
  6132  /*
  6133  ** tclcmd:  reset_prng_state
  6134  */
  6135  static int SQLITE_TCLAPI reset_prng_state(
  6136    ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
  6137    Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  6138    int objc,              /* Number of arguments */
  6139    Tcl_Obj *CONST objv[]  /* Command arguments */
  6140  ){
  6141    sqlite3_test_control(SQLITE_TESTCTRL_PRNG_RESET);
  6142    return TCL_OK;
  6143  }
  6144  
  6145  /*
  6146  ** tclcmd:  database_may_be_corrupt
  6147  **
  6148  ** Indicate that database files might be corrupt.  In other words, set the normal
  6149  ** state of operation.
  6150  */
  6151  static int SQLITE_TCLAPI database_may_be_corrupt(
  6152    ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
  6153    Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  6154    int objc,              /* Number of arguments */
  6155    Tcl_Obj *CONST objv[]  /* Command arguments */
  6156  ){
  6157    sqlite3_test_control(SQLITE_TESTCTRL_NEVER_CORRUPT, 0);
  6158    return TCL_OK;
  6159  }
  6160  /*
  6161  ** tclcmd:  database_never_corrupt
  6162  **
  6163  ** Indicate that database files are always well-formed.  This enables extra assert()
  6164  ** statements that test conditions that are always true for well-formed databases.
  6165  */
  6166  static int SQLITE_TCLAPI database_never_corrupt(
  6167    ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
  6168    Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  6169    int objc,              /* Number of arguments */
  6170    Tcl_Obj *CONST objv[]  /* Command arguments */
  6171  ){
  6172    sqlite3_test_control(SQLITE_TESTCTRL_NEVER_CORRUPT, 1);
  6173    return TCL_OK;
  6174  }
  6175  
  6176  /*
  6177  ** tclcmd:  pcache_stats
  6178  */
  6179  static int SQLITE_TCLAPI test_pcache_stats(
  6180    ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
  6181    Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  6182    int objc,              /* Number of arguments */
  6183    Tcl_Obj *CONST objv[]  /* Command arguments */
  6184  ){
  6185    int nMin;
  6186    int nMax;
  6187    int nCurrent;
  6188    int nRecyclable;
  6189    Tcl_Obj *pRet;
  6190  
  6191    sqlite3PcacheStats(&nCurrent, &nMax, &nMin, &nRecyclable);
  6192  
  6193    pRet = Tcl_NewObj();
  6194    Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj("current", -1));
  6195    Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(nCurrent));
  6196    Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj("max", -1));
  6197    Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(nMax));
  6198    Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj("min", -1));
  6199    Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(nMin));
  6200    Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj("recyclable", -1));
  6201    Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(nRecyclable));
  6202  
  6203    Tcl_SetObjResult(interp, pRet);
  6204  
  6205    return TCL_OK;
  6206  }
  6207  
  6208  #ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
  6209  static void test_unlock_notify_cb(void **aArg, int nArg){
  6210    int ii;
  6211    for(ii=0; ii<nArg; ii++){
  6212      Tcl_EvalEx((Tcl_Interp *)aArg[ii], "unlock_notify", -1, TCL_EVAL_GLOBAL);
  6213    }
  6214  }
  6215  #endif /* SQLITE_ENABLE_UNLOCK_NOTIFY */
  6216  
  6217  /*
  6218  ** tclcmd:  sqlite3_unlock_notify db
  6219  */
  6220  #ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
  6221  static int SQLITE_TCLAPI test_unlock_notify(
  6222    ClientData clientData, /* Unused */
  6223    Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  6224    int objc,              /* Number of arguments */
  6225    Tcl_Obj *CONST objv[]  /* Command arguments */
  6226  ){
  6227    sqlite3 *db;
  6228    int rc;
  6229  
  6230    if( objc!=2 ){
  6231      Tcl_WrongNumArgs(interp, 1, objv, "DB");
  6232      return TCL_ERROR;
  6233    }
  6234  
  6235    if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
  6236      return TCL_ERROR;
  6237    }
  6238    rc = sqlite3_unlock_notify(db, test_unlock_notify_cb, (void *)interp);
  6239    Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
  6240    return TCL_OK;
  6241  }
  6242  #endif
  6243  
  6244  /*
  6245  ** tclcmd:  sqlite3_wal_checkpoint db ?NAME?
  6246  */
  6247  static int SQLITE_TCLAPI test_wal_checkpoint(
  6248    ClientData clientData, /* Unused */
  6249    Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  6250    int objc,              /* Number of arguments */
  6251    Tcl_Obj *CONST objv[]  /* Command arguments */
  6252  ){
  6253    char *zDb = 0;
  6254    sqlite3 *db;
  6255    int rc;
  6256  
  6257    if( objc!=3 && objc!=2 ){
  6258      Tcl_WrongNumArgs(interp, 1, objv, "DB ?NAME?");
  6259      return TCL_ERROR;
  6260    }
  6261  
  6262    if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
  6263      return TCL_ERROR;
  6264    }
  6265    if( objc==3 ){
  6266      zDb = Tcl_GetString(objv[2]);
  6267    }
  6268    rc = sqlite3_wal_checkpoint(db, zDb);
  6269    Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
  6270    return TCL_OK;
  6271  }
  6272  
  6273  /*
  6274  ** tclcmd:  sqlite3_wal_checkpoint_v2 db MODE ?NAME?
  6275  **
  6276  ** This command calls the wal_checkpoint_v2() function with the specified
  6277  ** mode argument (passive, full or restart). If present, the database name
  6278  ** NAME is passed as the second argument to wal_checkpoint_v2(). If it the
  6279  ** NAME argument is not present, a NULL pointer is passed instead.
  6280  **
  6281  ** If wal_checkpoint_v2() returns any value other than SQLITE_BUSY or
  6282  ** SQLITE_OK, then this command returns TCL_ERROR. The Tcl result is set
  6283  ** to the error message obtained from sqlite3_errmsg().
  6284  **
  6285  ** Otherwise, this command returns a list of three integers. The first integer
  6286  ** is 1 if SQLITE_BUSY was returned, or 0 otherwise. The following two integers
  6287  ** are the values returned via the output parameters by wal_checkpoint_v2() -
  6288  ** the number of frames in the log and the number of frames in the log
  6289  ** that have been checkpointed.
  6290  */
  6291  static int SQLITE_TCLAPI test_wal_checkpoint_v2(
  6292    ClientData clientData, /* Unused */
  6293    Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  6294    int objc,              /* Number of arguments */
  6295    Tcl_Obj *CONST objv[]  /* Command arguments */
  6296  ){
  6297    char *zDb = 0;
  6298    sqlite3 *db;
  6299    int rc;
  6300  
  6301    int eMode;
  6302    int nLog = -555;
  6303    int nCkpt = -555;
  6304    Tcl_Obj *pRet;
  6305  
  6306    const char * aMode[] = { "passive", "full", "restart", "truncate", 0 };
  6307    assert( SQLITE_CHECKPOINT_PASSIVE==0 );
  6308    assert( SQLITE_CHECKPOINT_FULL==1 );
  6309    assert( SQLITE_CHECKPOINT_RESTART==2 );
  6310    assert( SQLITE_CHECKPOINT_TRUNCATE==3 );
  6311  
  6312    if( objc!=3 && objc!=4 ){
  6313      Tcl_WrongNumArgs(interp, 1, objv, "DB MODE ?NAME?");
  6314      return TCL_ERROR;
  6315    }
  6316  
  6317    if( objc==4 ){
  6318      zDb = Tcl_GetString(objv[3]);
  6319    }
  6320    if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) || (
  6321        TCL_OK!=Tcl_GetIntFromObj(0, objv[2], &eMode)
  6322     && TCL_OK!=Tcl_GetIndexFromObj(interp, objv[2], aMode, "mode", 0, &eMode) 
  6323    )){
  6324      return TCL_ERROR;
  6325    }
  6326  
  6327    rc = sqlite3_wal_checkpoint_v2(db, zDb, eMode, &nLog, &nCkpt);
  6328    if( rc!=SQLITE_OK && rc!=SQLITE_BUSY ){
  6329      const char *zErrCode = sqlite3ErrName(rc);
  6330      Tcl_ResetResult(interp);
  6331      Tcl_AppendResult(interp, zErrCode, " - ", (char *)sqlite3_errmsg(db), 0);
  6332      return TCL_ERROR;
  6333    }
  6334  
  6335    pRet = Tcl_NewObj();
  6336    Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(rc==SQLITE_BUSY?1:0));
  6337    Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(nLog));
  6338    Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(nCkpt));
  6339    Tcl_SetObjResult(interp, pRet);
  6340  
  6341    return TCL_OK;
  6342  }
  6343  
  6344  /*
  6345  ** tclcmd:  sqlite3_wal_autocheckpoint db VALUE
  6346  */
  6347  static int SQLITE_TCLAPI test_wal_autocheckpoint(
  6348    ClientData clientData, /* Unused */
  6349    Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  6350    int objc,              /* Number of arguments */
  6351    Tcl_Obj *CONST objv[]  /* Command arguments */
  6352  ){
  6353    sqlite3 *db;
  6354    int rc;
  6355    int iVal;
  6356  
  6357  
  6358    if( objc!=3 ){
  6359      Tcl_WrongNumArgs(interp, 1, objv, "DB VALUE");
  6360      return TCL_ERROR;
  6361    }
  6362  
  6363    if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) 
  6364     || Tcl_GetIntFromObj(0, objv[2], &iVal)
  6365    ){
  6366      return TCL_ERROR;
  6367    }
  6368  
  6369    rc = sqlite3_wal_autocheckpoint(db, iVal);
  6370    Tcl_ResetResult(interp);
  6371    if( rc!=SQLITE_OK ){
  6372      const char *zErrCode = sqlite3ErrName(rc);
  6373      Tcl_SetObjResult(interp, Tcl_NewStringObj(zErrCode, -1));
  6374      return TCL_ERROR;
  6375    }
  6376  
  6377    return TCL_OK;
  6378  }
  6379  
  6380  
  6381  /*
  6382  ** tclcmd:  test_sqlite3_log ?SCRIPT?
  6383  */
  6384  static struct LogCallback {
  6385    Tcl_Interp *pInterp;
  6386    Tcl_Obj *pObj;
  6387  } logcallback = {0, 0};
  6388  static void xLogcallback(void *unused, int err, char *zMsg){
  6389    Tcl_Obj *pNew = Tcl_DuplicateObj(logcallback.pObj);
  6390    Tcl_IncrRefCount(pNew);
  6391    Tcl_ListObjAppendElement(
  6392        0, pNew, Tcl_NewStringObj(sqlite3ErrName(err), -1)
  6393    );
  6394    Tcl_ListObjAppendElement(0, pNew, Tcl_NewStringObj(zMsg, -1));
  6395    Tcl_EvalObjEx(logcallback.pInterp, pNew, TCL_EVAL_GLOBAL|TCL_EVAL_DIRECT);
  6396    Tcl_DecrRefCount(pNew);
  6397  }
  6398  static int SQLITE_TCLAPI test_sqlite3_log(
  6399    ClientData clientData,
  6400    Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  6401    int objc,              /* Number of arguments */
  6402    Tcl_Obj *CONST objv[]  /* Command arguments */
  6403  ){
  6404    if( objc>2 ){
  6405      Tcl_WrongNumArgs(interp, 1, objv, "SCRIPT");
  6406      return TCL_ERROR;
  6407    }
  6408    if( logcallback.pObj ){
  6409      Tcl_DecrRefCount(logcallback.pObj);
  6410      logcallback.pObj = 0;
  6411      logcallback.pInterp = 0;
  6412      sqlite3_config(SQLITE_CONFIG_LOG, (void*)0, (void*)0);
  6413    }
  6414    if( objc>1 ){
  6415      logcallback.pObj = objv[1];
  6416      Tcl_IncrRefCount(logcallback.pObj);
  6417      logcallback.pInterp = interp;
  6418      sqlite3_config(SQLITE_CONFIG_LOG, xLogcallback, (void*)0);
  6419    }
  6420    return TCL_OK;
  6421  }
  6422  
  6423  /*
  6424  **     tcl_objproc COMMANDNAME ARGS...
  6425  **
  6426  ** Run a TCL command using its objProc interface.  Throw an error if
  6427  ** the command has no objProc interface.
  6428  */
  6429  static int SQLITE_TCLAPI runAsObjProc(
  6430    void * clientData,
  6431    Tcl_Interp *interp,
  6432    int objc,
  6433    Tcl_Obj *CONST objv[]
  6434  ){
  6435    Tcl_CmdInfo cmdInfo;
  6436    if( objc<2 ){
  6437      Tcl_WrongNumArgs(interp, 1, objv, "COMMAND ...");
  6438      return TCL_ERROR;
  6439    }
  6440    if( !Tcl_GetCommandInfo(interp, Tcl_GetString(objv[1]), &cmdInfo) ){
  6441      Tcl_AppendResult(interp, "command not found: ",
  6442             Tcl_GetString(objv[1]), (char*)0);
  6443      return TCL_ERROR;
  6444    }
  6445    if( cmdInfo.objProc==0 ){
  6446      Tcl_AppendResult(interp, "command has no objProc: ",
  6447             Tcl_GetString(objv[1]), (char*)0);
  6448      return TCL_ERROR;
  6449    }
  6450    return cmdInfo.objProc(cmdInfo.objClientData, interp, objc-1, objv+1);
  6451  }
  6452  
  6453  #ifndef SQLITE_OMIT_EXPLAIN
  6454  /*
  6455  ** WARNING: The following function, printExplainQueryPlan() is an exact
  6456  ** copy of example code from eqp.in (eqp.html). If this code is modified,
  6457  ** then the documentation copy needs to be modified as well.
  6458  */
  6459  /*
  6460  ** Argument pStmt is a prepared SQL statement. This function compiles
  6461  ** an EXPLAIN QUERY PLAN command to report on the prepared statement,
  6462  ** and prints the report to stdout using printf().
  6463  */
  6464  int printExplainQueryPlan(sqlite3_stmt *pStmt){
  6465    const char *zSql;               /* Input SQL */
  6466    char *zExplain;                 /* SQL with EXPLAIN QUERY PLAN prepended */
  6467    sqlite3_stmt *pExplain;         /* Compiled EXPLAIN QUERY PLAN command */
  6468    int rc;                         /* Return code from sqlite3_prepare_v2() */
  6469  
  6470    zSql = sqlite3_sql(pStmt);
  6471    if( zSql==0 ) return SQLITE_ERROR;
  6472  
  6473    zExplain = sqlite3_mprintf("EXPLAIN QUERY PLAN %s", zSql);
  6474    if( zExplain==0 ) return SQLITE_NOMEM;
  6475  
  6476    rc = sqlite3_prepare_v2(sqlite3_db_handle(pStmt), zExplain, -1, &pExplain, 0);
  6477    sqlite3_free(zExplain);
  6478    if( rc!=SQLITE_OK ) return rc;
  6479  
  6480    while( SQLITE_ROW==sqlite3_step(pExplain) ){
  6481      int iSelectid = sqlite3_column_int(pExplain, 0);
  6482      int iOrder = sqlite3_column_int(pExplain, 1);
  6483      int iFrom = sqlite3_column_int(pExplain, 2);
  6484      const char *zDetail = (const char *)sqlite3_column_text(pExplain, 3);
  6485  
  6486      printf("%d %d %d %s\n", iSelectid, iOrder, iFrom, zDetail);
  6487    }
  6488  
  6489    return sqlite3_finalize(pExplain);
  6490  }
  6491  
  6492  static int SQLITE_TCLAPI test_print_eqp(
  6493    void * clientData,
  6494    Tcl_Interp *interp,
  6495    int objc,
  6496    Tcl_Obj *CONST objv[]
  6497  ){
  6498    int rc;
  6499    sqlite3_stmt *pStmt;
  6500  
  6501    if( objc!=2 ){
  6502      Tcl_WrongNumArgs(interp, 1, objv, "STMT");
  6503      return TCL_ERROR;
  6504    }
  6505    if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
  6506    rc = printExplainQueryPlan(pStmt);
  6507    /* This is needed on Windows so that a test case using this 
  6508    ** function can open a read pipe and get the output of
  6509    ** printExplainQueryPlan() immediately.
  6510    */
  6511    fflush(stdout);
  6512    Tcl_SetResult(interp, (char *)t1ErrorName(rc), 0);
  6513    return TCL_OK;
  6514  }
  6515  #endif /* SQLITE_OMIT_EXPLAIN */
  6516  
  6517  /*
  6518  ** sqlite3_test_control VERB ARGS...
  6519  */
  6520  static int SQLITE_TCLAPI test_test_control(
  6521    void * clientData,
  6522    Tcl_Interp *interp,
  6523    int objc,
  6524    Tcl_Obj *CONST objv[]
  6525  ){
  6526    struct Verb {
  6527      const char *zName;
  6528      int i;
  6529    } aVerb[] = {
  6530      { "SQLITE_TESTCTRL_LOCALTIME_FAULT", SQLITE_TESTCTRL_LOCALTIME_FAULT }, 
  6531      { "SQLITE_TESTCTRL_SORTER_MMAP",     SQLITE_TESTCTRL_SORTER_MMAP     }, 
  6532      { "SQLITE_TESTCTRL_IMPOSTER",        SQLITE_TESTCTRL_IMPOSTER        },
  6533    };
  6534    int iVerb;
  6535    int iFlag;
  6536    int rc;
  6537  
  6538    if( objc<2 ){
  6539      Tcl_WrongNumArgs(interp, 1, objv, "VERB ARGS...");
  6540      return TCL_ERROR;
  6541    }
  6542  
  6543    rc = Tcl_GetIndexFromObjStruct(
  6544        interp, objv[1], aVerb, sizeof(aVerb[0]), "VERB", 0, &iVerb
  6545    );
  6546    if( rc!=TCL_OK ) return rc;
  6547  
  6548    iFlag = aVerb[iVerb].i;
  6549    switch( iFlag ){
  6550      case SQLITE_TESTCTRL_LOCALTIME_FAULT: {
  6551        int val;
  6552        if( objc!=3 ){
  6553          Tcl_WrongNumArgs(interp, 2, objv, "ONOFF");
  6554          return TCL_ERROR;
  6555        }
  6556        if( Tcl_GetBooleanFromObj(interp, objv[2], &val) ) return TCL_ERROR;
  6557        sqlite3_test_control(SQLITE_TESTCTRL_LOCALTIME_FAULT, val);
  6558        break;
  6559      }
  6560  
  6561      case SQLITE_TESTCTRL_SORTER_MMAP: {
  6562        int val;
  6563        sqlite3 *db;
  6564        if( objc!=4 ){
  6565          Tcl_WrongNumArgs(interp, 2, objv, "DB LIMIT");
  6566          return TCL_ERROR;
  6567        }
  6568        if( getDbPointer(interp, Tcl_GetString(objv[2]), &db) ) return TCL_ERROR;
  6569        if( Tcl_GetIntFromObj(interp, objv[3], &val) ) return TCL_ERROR;
  6570        sqlite3_test_control(SQLITE_TESTCTRL_SORTER_MMAP, db, val);
  6571        break;
  6572      }
  6573  
  6574      case SQLITE_TESTCTRL_IMPOSTER: {
  6575        int onOff, tnum;
  6576        const char *zDbName;
  6577        sqlite3 *db;
  6578        if( objc!=6 ){
  6579          Tcl_WrongNumArgs(interp, 2, objv, "DB dbName onOff tnum");
  6580          return TCL_ERROR;
  6581        }
  6582        if( getDbPointer(interp, Tcl_GetString(objv[2]), &db) ) return TCL_ERROR;
  6583        zDbName = Tcl_GetString(objv[3]);
  6584        if( Tcl_GetIntFromObj(interp, objv[4], &onOff) ) return TCL_ERROR;
  6585        if( Tcl_GetIntFromObj(interp, objv[5], &tnum) ) return TCL_ERROR;
  6586        sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, db, zDbName, onOff, tnum);
  6587        break;
  6588      }
  6589    }
  6590  
  6591    Tcl_ResetResult(interp);
  6592    return TCL_OK;
  6593  }
  6594  
  6595  #if SQLITE_OS_UNIX
  6596  #include <sys/time.h>
  6597  #include <sys/resource.h>
  6598  
  6599  static int SQLITE_TCLAPI test_getrusage(
  6600    void * clientData,
  6601    Tcl_Interp *interp,
  6602    int objc,
  6603    Tcl_Obj *CONST objv[]
  6604  ){
  6605    char buf[1024];
  6606    struct rusage r;
  6607    memset(&r, 0, sizeof(r));
  6608    getrusage(RUSAGE_SELF, &r);
  6609  
  6610    sqlite3_snprintf(sizeof(buf), buf,
  6611      "ru_utime=%d.%06d ru_stime=%d.%06d ru_minflt=%d ru_majflt=%d", 
  6612      (int)r.ru_utime.tv_sec, (int)r.ru_utime.tv_usec, 
  6613      (int)r.ru_stime.tv_sec, (int)r.ru_stime.tv_usec, 
  6614      (int)r.ru_minflt, (int)r.ru_majflt
  6615    );
  6616    Tcl_SetObjResult(interp, Tcl_NewStringObj(buf, -1));
  6617    return TCL_OK;
  6618  }
  6619  #endif
  6620  
  6621  #if SQLITE_OS_WIN
  6622  /*
  6623  ** Information passed from the main thread into the windows file locker
  6624  ** background thread.
  6625  */
  6626  struct win32FileLocker {
  6627    char *evName;       /* Name of event to signal thread startup */
  6628    HANDLE h;           /* Handle of the file to be locked */
  6629    int delay1;         /* Delay before locking */
  6630    int delay2;         /* Delay before unlocking */
  6631    int ok;             /* Finished ok */
  6632    int err;            /* True if an error occurs */
  6633  };
  6634  #endif
  6635  
  6636  
  6637  #if SQLITE_OS_WIN
  6638  #include <process.h>
  6639  /*
  6640  ** The background thread that does file locking.
  6641  */
  6642  static void SQLITE_CDECL win32_file_locker(void *pAppData){
  6643    struct win32FileLocker *p = (struct win32FileLocker*)pAppData;
  6644    if( p->evName ){
  6645      HANDLE ev = OpenEvent(EVENT_MODIFY_STATE, FALSE, p->evName);
  6646      if ( ev ){
  6647        SetEvent(ev);
  6648        CloseHandle(ev);
  6649      }
  6650    }
  6651    if( p->delay1 ) Sleep(p->delay1);
  6652    if( LockFile(p->h, 0, 0, 100000000, 0) ){
  6653      Sleep(p->delay2);
  6654      UnlockFile(p->h, 0, 0, 100000000, 0);
  6655      p->ok = 1;
  6656    }else{
  6657      p->err = 1;
  6658    }
  6659    CloseHandle(p->h);
  6660    p->h = 0;
  6661    p->delay1 = 0;
  6662    p->delay2 = 0;
  6663  }
  6664  #endif
  6665  
  6666  #if SQLITE_OS_WIN
  6667  /*
  6668  **      lock_win32_file FILENAME DELAY1 DELAY2
  6669  **
  6670  ** Get an exclusive manditory lock on file for DELAY2 milliseconds.
  6671  ** Wait DELAY1 milliseconds before acquiring the lock.
  6672  */
  6673  static int SQLITE_TCLAPI win32_file_lock(
  6674    void * clientData,
  6675    Tcl_Interp *interp,
  6676    int objc,
  6677    Tcl_Obj *CONST objv[]
  6678  ){
  6679    static struct win32FileLocker x = { "win32_file_lock", 0, 0, 0, 0, 0 };
  6680    const char *zFilename;
  6681    char zBuf[200];
  6682    int retry = 0;
  6683    HANDLE ev;
  6684    DWORD wResult;
  6685    
  6686    if( objc!=4 && objc!=1 ){
  6687      Tcl_WrongNumArgs(interp, 1, objv, "FILENAME DELAY1 DELAY2");
  6688      return TCL_ERROR;
  6689    }
  6690    if( objc==1 ){
  6691      sqlite3_snprintf(sizeof(zBuf), zBuf, "%d %d %d %d %d",
  6692                       x.ok, x.err, x.delay1, x.delay2, x.h);
  6693      Tcl_AppendResult(interp, zBuf, (char*)0);
  6694      return TCL_OK;
  6695    }
  6696    while( x.h && retry<30 ){
  6697      retry++;
  6698      Sleep(100);
  6699    }
  6700    if( x.h ){
  6701      Tcl_AppendResult(interp, "busy", (char*)0);
  6702      return TCL_ERROR;
  6703    }
  6704    if( Tcl_GetIntFromObj(interp, objv[2], &x.delay1) ) return TCL_ERROR;
  6705    if( Tcl_GetIntFromObj(interp, objv[3], &x.delay2) ) return TCL_ERROR;
  6706    zFilename = Tcl_GetString(objv[1]);
  6707    x.h = CreateFile(zFilename, GENERIC_READ|GENERIC_WRITE,
  6708                FILE_SHARE_READ|FILE_SHARE_WRITE, 0, OPEN_ALWAYS,
  6709                FILE_ATTRIBUTE_NORMAL, 0);
  6710    if( !x.h ){
  6711      Tcl_AppendResult(interp, "cannot open file: ", zFilename, (char*)0);
  6712      return TCL_ERROR;
  6713    }
  6714    ev = CreateEvent(NULL, TRUE, FALSE, x.evName);
  6715    if ( !ev ){
  6716      Tcl_AppendResult(interp, "cannot create event: ", x.evName, (char*)0);
  6717      return TCL_ERROR;
  6718    }
  6719    _beginthread(win32_file_locker, 0, (void*)&x);
  6720    Sleep(0);
  6721    if ( (wResult = WaitForSingleObject(ev, 10000))!=WAIT_OBJECT_0 ){
  6722      sqlite3_snprintf(sizeof(zBuf), zBuf, "0x%x", wResult);
  6723      Tcl_AppendResult(interp, "wait failed: ", zBuf, (char*)0);
  6724      CloseHandle(ev);
  6725      return TCL_ERROR;
  6726    }
  6727    CloseHandle(ev);
  6728    return TCL_OK;
  6729  }
  6730  
  6731  /*
  6732  **      exists_win32_path PATH
  6733  **
  6734  ** Returns non-zero if the specified path exists, whose fully qualified name
  6735  ** may exceed 260 characters if it is prefixed with "\\?\".
  6736  */
  6737  static int SQLITE_TCLAPI win32_exists_path(
  6738    void *clientData,
  6739    Tcl_Interp *interp,
  6740    int objc,
  6741    Tcl_Obj *CONST objv[]
  6742  ){
  6743    if( objc!=2 ){
  6744      Tcl_WrongNumArgs(interp, 1, objv, "PATH");
  6745      return TCL_ERROR;
  6746    }
  6747    Tcl_SetObjResult(interp, Tcl_NewBooleanObj(
  6748        GetFileAttributesW( Tcl_GetUnicode(objv[1]))!=INVALID_FILE_ATTRIBUTES ));
  6749    return TCL_OK;
  6750  }
  6751  
  6752  /*
  6753  **      find_win32_file PATTERN
  6754  **
  6755  ** Returns a list of entries in a directory that match the specified pattern,
  6756  ** whose fully qualified name may exceed 248 characters if it is prefixed with
  6757  ** "\\?\".
  6758  */
  6759  static int SQLITE_TCLAPI win32_find_file(
  6760    void *clientData,
  6761    Tcl_Interp *interp,
  6762    int objc,
  6763    Tcl_Obj *CONST objv[]
  6764  ){
  6765    HANDLE hFindFile = INVALID_HANDLE_VALUE;
  6766    WIN32_FIND_DATAW findData;
  6767    Tcl_Obj *listObj;
  6768    DWORD lastErrno;
  6769    if( objc!=2 ){
  6770      Tcl_WrongNumArgs(interp, 1, objv, "PATTERN");
  6771      return TCL_ERROR;
  6772    }
  6773    hFindFile = FindFirstFileW(Tcl_GetUnicode(objv[1]), &findData);
  6774    if( hFindFile==INVALID_HANDLE_VALUE ){
  6775      Tcl_SetObjResult(interp, Tcl_NewWideIntObj(GetLastError()));
  6776      return TCL_ERROR;
  6777    }
  6778    listObj = Tcl_NewObj();
  6779    Tcl_IncrRefCount(listObj);
  6780    do {
  6781      Tcl_ListObjAppendElement(interp, listObj, Tcl_NewUnicodeObj(
  6782          findData.cFileName, -1));
  6783      Tcl_ListObjAppendElement(interp, listObj, Tcl_NewWideIntObj(
  6784          findData.dwFileAttributes));
  6785    } while( FindNextFileW(hFindFile, &findData) );
  6786    lastErrno = GetLastError();
  6787    if( lastErrno!=NO_ERROR && lastErrno!=ERROR_NO_MORE_FILES ){
  6788      FindClose(hFindFile);
  6789      Tcl_DecrRefCount(listObj);
  6790      Tcl_SetObjResult(interp, Tcl_NewWideIntObj(GetLastError()));
  6791      return TCL_ERROR;
  6792    }
  6793    FindClose(hFindFile);
  6794    Tcl_SetObjResult(interp, listObj);
  6795    return TCL_OK;
  6796  }
  6797  
  6798  /*
  6799  **      delete_win32_file FILENAME
  6800  **
  6801  ** Deletes the specified file, whose fully qualified name may exceed 260
  6802  ** characters if it is prefixed with "\\?\".
  6803  */
  6804  static int SQLITE_TCLAPI win32_delete_file(
  6805    void *clientData,
  6806    Tcl_Interp *interp,
  6807    int objc,
  6808    Tcl_Obj *CONST objv[]
  6809  ){
  6810    if( objc!=2 ){
  6811      Tcl_WrongNumArgs(interp, 1, objv, "FILENAME");
  6812      return TCL_ERROR;
  6813    }
  6814    if( !DeleteFileW(Tcl_GetUnicode(objv[1])) ){
  6815      Tcl_SetObjResult(interp, Tcl_NewWideIntObj(GetLastError()));
  6816      return TCL_ERROR;
  6817    }
  6818    Tcl_ResetResult(interp);
  6819    return TCL_OK;
  6820  }
  6821  
  6822  /*
  6823  **      make_win32_dir DIRECTORY
  6824  **
  6825  ** Creates the specified directory, whose fully qualified name may exceed 248
  6826  ** characters if it is prefixed with "\\?\".
  6827  */
  6828  static int SQLITE_TCLAPI win32_mkdir(
  6829    void *clientData,
  6830    Tcl_Interp *interp,
  6831    int objc,
  6832    Tcl_Obj *CONST objv[]
  6833  ){
  6834    if( objc!=2 ){
  6835      Tcl_WrongNumArgs(interp, 1, objv, "DIRECTORY");
  6836      return TCL_ERROR;
  6837    }
  6838    if( !CreateDirectoryW(Tcl_GetUnicode(objv[1]), NULL) ){
  6839      Tcl_SetObjResult(interp, Tcl_NewWideIntObj(GetLastError()));
  6840      return TCL_ERROR;
  6841    }
  6842    Tcl_ResetResult(interp);
  6843    return TCL_OK;
  6844  }
  6845  
  6846  /*
  6847  **      remove_win32_dir DIRECTORY
  6848  **
  6849  ** Removes the specified directory, whose fully qualified name may exceed 248
  6850  ** characters if it is prefixed with "\\?\".
  6851  */
  6852  static int SQLITE_TCLAPI win32_rmdir(
  6853    void *clientData,
  6854    Tcl_Interp *interp,
  6855    int objc,
  6856    Tcl_Obj *CONST objv[]
  6857  ){
  6858    if( objc!=2 ){
  6859      Tcl_WrongNumArgs(interp, 1, objv, "DIRECTORY");
  6860      return TCL_ERROR;
  6861    }
  6862    if( !RemoveDirectoryW(Tcl_GetUnicode(objv[1])) ){
  6863      Tcl_SetObjResult(interp, Tcl_NewWideIntObj(GetLastError()));
  6864      return TCL_ERROR;
  6865    }
  6866    Tcl_ResetResult(interp);
  6867    return TCL_OK;
  6868  }
  6869  #endif
  6870  
  6871  
  6872  /*
  6873  **      optimization_control DB OPT BOOLEAN
  6874  **
  6875  ** Enable or disable query optimizations using the sqlite3_test_control()
  6876  ** interface.  Disable if BOOLEAN is false and enable if BOOLEAN is true.
  6877  ** OPT is the name of the optimization to be disabled.
  6878  */
  6879  static int SQLITE_TCLAPI optimization_control(
  6880    void * clientData,
  6881    Tcl_Interp *interp,
  6882    int objc,
  6883    Tcl_Obj *CONST objv[]
  6884  ){
  6885    int i;
  6886    sqlite3 *db;
  6887    const char *zOpt;
  6888    int onoff;
  6889    int mask = 0;
  6890    static const struct {
  6891      const char *zOptName;
  6892      int mask;
  6893    } aOpt[] = {
  6894      { "all",                 SQLITE_AllOpts        },
  6895      { "none",                0                     },
  6896      { "query-flattener",     SQLITE_QueryFlattener },
  6897      { "column-cache",        SQLITE_ColumnCache    },
  6898      { "groupby-order",       SQLITE_GroupByOrder   },
  6899      { "factor-constants",    SQLITE_FactorOutConst },
  6900      { "distinct-opt",        SQLITE_DistinctOpt    },
  6901      { "cover-idx-scan",      SQLITE_CoverIdxScan   },
  6902      { "order-by-idx-join",   SQLITE_OrderByIdxJoin },
  6903      { "transitive",          SQLITE_Transitive     },
  6904      { "omit-noop-join",      SQLITE_OmitNoopJoin   },
  6905      { "stat3",               SQLITE_Stat34         },
  6906      { "stat4",               SQLITE_Stat34         },
  6907    };
  6908  
  6909    if( objc!=4 ){
  6910      Tcl_WrongNumArgs(interp, 1, objv, "DB OPT BOOLEAN");
  6911      return TCL_ERROR;
  6912    }
  6913    if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
  6914    if( Tcl_GetBooleanFromObj(interp, objv[3], &onoff) ) return TCL_ERROR;
  6915    zOpt = Tcl_GetString(objv[2]);
  6916    for(i=0; i<sizeof(aOpt)/sizeof(aOpt[0]); i++){
  6917      if( strcmp(zOpt, aOpt[i].zOptName)==0 ){
  6918        mask = aOpt[i].mask;
  6919        break;
  6920      }
  6921    }
  6922    if( onoff ) mask = ~mask;
  6923    if( i>=sizeof(aOpt)/sizeof(aOpt[0]) ){
  6924      Tcl_AppendResult(interp, "unknown optimization - should be one of:",
  6925                       (char*)0);
  6926      for(i=0; i<sizeof(aOpt)/sizeof(aOpt[0]); i++){
  6927        Tcl_AppendResult(interp, " ", aOpt[i].zOptName, (char*)0);
  6928      }
  6929      return TCL_ERROR;
  6930    }
  6931    sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS, db, mask);
  6932    return TCL_OK;
  6933  }
  6934  
  6935  /*
  6936  **     load_static_extension DB NAME ...
  6937  **
  6938  ** Load one or more statically linked extensions.
  6939  */
  6940  static int SQLITE_TCLAPI tclLoadStaticExtensionCmd(
  6941    void * clientData,
  6942    Tcl_Interp *interp,
  6943    int objc,
  6944    Tcl_Obj *CONST objv[]
  6945  ){
  6946    extern int sqlite3_amatch_init(sqlite3*,char**,const sqlite3_api_routines*);
  6947    extern int sqlite3_carray_init(sqlite3*,char**,const sqlite3_api_routines*);
  6948    extern int sqlite3_closure_init(sqlite3*,char**,const sqlite3_api_routines*);
  6949    extern int sqlite3_csv_init(sqlite3*,char**,const sqlite3_api_routines*);
  6950    extern int sqlite3_eval_init(sqlite3*,char**,const sqlite3_api_routines*);
  6951    extern int sqlite3_fileio_init(sqlite3*,char**,const sqlite3_api_routines*);
  6952    extern int sqlite3_fuzzer_init(sqlite3*,char**,const sqlite3_api_routines*);
  6953    extern int sqlite3_ieee_init(sqlite3*,char**,const sqlite3_api_routines*);
  6954    extern int sqlite3_nextchar_init(sqlite3*,char**,const sqlite3_api_routines*);
  6955    extern int sqlite3_percentile_init(sqlite3*,char**,const sqlite3_api_routines*);
  6956    extern int sqlite3_regexp_init(sqlite3*,char**,const sqlite3_api_routines*);
  6957    extern int sqlite3_remember_init(sqlite3*,char**,const sqlite3_api_routines*);
  6958    extern int sqlite3_series_init(sqlite3*,char**,const sqlite3_api_routines*);
  6959    extern int sqlite3_spellfix_init(sqlite3*,char**,const sqlite3_api_routines*);
  6960    extern int sqlite3_totype_init(sqlite3*,char**,const sqlite3_api_routines*);
  6961    extern int sqlite3_wholenumber_init(sqlite3*,char**,const sqlite3_api_routines*);
  6962    extern int sqlite3_unionvtab_init(sqlite3*,char**,const sqlite3_api_routines*);
  6963    static const struct {
  6964      const char *zExtName;
  6965      int (*pInit)(sqlite3*,char**,const sqlite3_api_routines*);
  6966    } aExtension[] = {
  6967      { "amatch",                sqlite3_amatch_init               },
  6968      { "carray",                sqlite3_carray_init               },
  6969      { "closure",               sqlite3_closure_init              },
  6970      { "csv",                   sqlite3_csv_init                  },
  6971      { "eval",                  sqlite3_eval_init                 },
  6972      { "fileio",                sqlite3_fileio_init               },
  6973      { "fuzzer",                sqlite3_fuzzer_init               },
  6974      { "ieee754",               sqlite3_ieee_init                 },
  6975      { "nextchar",              sqlite3_nextchar_init             },
  6976      { "percentile",            sqlite3_percentile_init           },
  6977      { "regexp",                sqlite3_regexp_init               },
  6978      { "remember",              sqlite3_remember_init             },
  6979      { "series",                sqlite3_series_init               },
  6980      { "spellfix",              sqlite3_spellfix_init             },
  6981      { "totype",                sqlite3_totype_init               },
  6982      { "unionvtab",             sqlite3_unionvtab_init            },
  6983      { "wholenumber",           sqlite3_wholenumber_init          },
  6984    };
  6985    sqlite3 *db;
  6986    const char *zName;
  6987    int i, j, rc;
  6988    char *zErrMsg = 0;
  6989    if( objc<3 ){
  6990      Tcl_WrongNumArgs(interp, 1, objv, "DB NAME ...");
  6991      return TCL_ERROR;
  6992    }
  6993    if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
  6994    for(j=2; j<objc; j++){
  6995      zName = Tcl_GetString(objv[j]);
  6996      for(i=0; i<ArraySize(aExtension); i++){
  6997        if( strcmp(zName, aExtension[i].zExtName)==0 ) break;
  6998      }
  6999      if( i>=ArraySize(aExtension) ){
  7000        Tcl_AppendResult(interp, "no such extension: ", zName, (char*)0);
  7001        return TCL_ERROR;
  7002      }
  7003      if( aExtension[i].pInit ){
  7004        rc = aExtension[i].pInit(db, &zErrMsg, 0);
  7005      }else{
  7006        rc = SQLITE_OK;
  7007      }
  7008      if( rc!=SQLITE_OK || zErrMsg ){
  7009        Tcl_AppendResult(interp, "initialization of ", zName, " failed: ", zErrMsg,
  7010                         (char*)0);
  7011        sqlite3_free(zErrMsg);
  7012        return TCL_ERROR;
  7013      }
  7014    }
  7015    return TCL_OK;
  7016  }
  7017  
  7018  /*
  7019  **     sorter_test_fakeheap BOOL
  7020  **
  7021  */
  7022  static int SQLITE_TCLAPI sorter_test_fakeheap(
  7023    void * clientData,
  7024    Tcl_Interp *interp,
  7025    int objc,
  7026    Tcl_Obj *CONST objv[]
  7027  ){
  7028    int bArg;
  7029    if( objc!=2 ){
  7030      Tcl_WrongNumArgs(interp, 1, objv, "BOOL");
  7031      return TCL_ERROR;
  7032    }
  7033  
  7034    if( Tcl_GetBooleanFromObj(interp, objv[1], &bArg) ){
  7035      return TCL_ERROR;
  7036    }
  7037  
  7038    if( bArg ){
  7039      if( sqlite3GlobalConfig.pHeap==0 ){
  7040        sqlite3GlobalConfig.pHeap = SQLITE_INT_TO_PTR(-1);
  7041      }
  7042    }else{
  7043      if( sqlite3GlobalConfig.pHeap==SQLITE_INT_TO_PTR(-1) ){
  7044        sqlite3GlobalConfig.pHeap = 0;
  7045      }
  7046    }
  7047  
  7048    Tcl_ResetResult(interp);
  7049    return TCL_OK;
  7050  }
  7051  
  7052  /*
  7053  **     sorter_test_sort4_helper DB SQL1 NSTEP SQL2
  7054  **
  7055  ** Compile SQL statement $SQL1 and step it $NSTEP times. For each row, 
  7056  ** check that the leftmost and rightmost columns returned are both integers,
  7057  ** and that both contain the same value.
  7058  **
  7059  ** Then execute statement $SQL2. Check that the statement returns the same
  7060  ** set of integers in the same order as in the previous step (using $SQL1).
  7061  */
  7062  static int SQLITE_TCLAPI sorter_test_sort4_helper(
  7063    void * clientData,
  7064    Tcl_Interp *interp,
  7065    int objc,
  7066    Tcl_Obj *CONST objv[]
  7067  ){
  7068    const char *zSql1;
  7069    const char *zSql2;
  7070    int nStep; 
  7071    int iStep; 
  7072    unsigned int iCksum1 = 0; 
  7073    unsigned int iCksum2 = 0; 
  7074    int rc;
  7075    int iB;
  7076    sqlite3 *db;
  7077    sqlite3_stmt *pStmt;
  7078    
  7079    if( objc!=5 ){
  7080      Tcl_WrongNumArgs(interp, 1, objv, "DB SQL1 NSTEP SQL2");
  7081      return TCL_ERROR;
  7082    }
  7083  
  7084    if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
  7085    zSql1 = Tcl_GetString(objv[2]);
  7086    if( Tcl_GetIntFromObj(interp, objv[3], &nStep) ) return TCL_ERROR;
  7087    zSql2 = Tcl_GetString(objv[4]);
  7088  
  7089    rc = sqlite3_prepare_v2(db, zSql1, -1, &pStmt, 0);
  7090    if( rc!=SQLITE_OK ) goto sql_error;
  7091  
  7092    iB = sqlite3_column_count(pStmt)-1;
  7093    for(iStep=0; iStep<nStep && SQLITE_ROW==sqlite3_step(pStmt); iStep++){
  7094      int a = sqlite3_column_int(pStmt, 0);
  7095      if( a!=sqlite3_column_int(pStmt, iB) ){
  7096        Tcl_AppendResult(interp, "data error: (a!=b)", 0);
  7097        return TCL_ERROR;
  7098      }
  7099  
  7100      iCksum1 += (iCksum1 << 3) + (unsigned int)a;
  7101    }
  7102    rc = sqlite3_finalize(pStmt);
  7103    if( rc!=SQLITE_OK ) goto sql_error;
  7104  
  7105    rc = sqlite3_prepare_v2(db, zSql2, -1, &pStmt, 0);
  7106    if( rc!=SQLITE_OK ) goto sql_error;
  7107    for(iStep=0; SQLITE_ROW==sqlite3_step(pStmt); iStep++){
  7108      int a = sqlite3_column_int(pStmt, 0);
  7109      iCksum2 += (iCksum2 << 3) + (unsigned int)a;
  7110    }
  7111    rc = sqlite3_finalize(pStmt);
  7112    if( rc!=SQLITE_OK ) goto sql_error;
  7113  
  7114    if( iCksum1!=iCksum2 ){
  7115      Tcl_AppendResult(interp, "checksum mismatch", 0);
  7116      return TCL_ERROR;
  7117    }
  7118  
  7119    return TCL_OK;
  7120   sql_error:
  7121    Tcl_AppendResult(interp, "sql error: ", sqlite3_errmsg(db), 0);
  7122    return TCL_ERROR;
  7123  }
  7124  
  7125  
  7126  #ifdef SQLITE_USER_AUTHENTICATION
  7127  #include "sqlite3userauth.h"
  7128  /*
  7129  ** tclcmd:  sqlite3_user_authenticate DB USERNAME PASSWORD
  7130  */
  7131  static int SQLITE_TCLAPI test_user_authenticate(
  7132    ClientData clientData, /* Unused */
  7133    Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  7134    int objc,              /* Number of arguments */
  7135    Tcl_Obj *CONST objv[]  /* Command arguments */
  7136  ){
  7137    char *zUser = 0;
  7138    char *zPasswd = 0;
  7139    int nPasswd = 0;
  7140    sqlite3 *db;
  7141    int rc;
  7142  
  7143    if( objc!=4 ){
  7144      Tcl_WrongNumArgs(interp, 1, objv, "DB USERNAME PASSWORD");
  7145      return TCL_ERROR;
  7146    }
  7147    if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
  7148      return TCL_ERROR;
  7149    }
  7150    zUser = Tcl_GetString(objv[2]);
  7151    zPasswd = Tcl_GetStringFromObj(objv[3], &nPasswd);
  7152    rc = sqlite3_user_authenticate(db, zUser, zPasswd, nPasswd);
  7153    Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
  7154    return TCL_OK;
  7155  }
  7156  #endif /* SQLITE_USER_AUTHENTICATION */
  7157  
  7158  #ifdef SQLITE_USER_AUTHENTICATION
  7159  /*
  7160  ** tclcmd:  sqlite3_user_add DB USERNAME PASSWORD ISADMIN
  7161  */
  7162  static int SQLITE_TCLAPI test_user_add(
  7163    ClientData clientData, /* Unused */
  7164    Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  7165    int objc,              /* Number of arguments */
  7166    Tcl_Obj *CONST objv[]  /* Command arguments */
  7167  ){
  7168    char *zUser = 0;
  7169    char *zPasswd = 0;
  7170    int nPasswd = 0;
  7171    int isAdmin = 0;
  7172    sqlite3 *db;
  7173    int rc;
  7174  
  7175    if( objc!=5 ){
  7176      Tcl_WrongNumArgs(interp, 1, objv, "DB USERNAME PASSWORD ISADMIN");
  7177      return TCL_ERROR;
  7178    }
  7179    if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
  7180      return TCL_ERROR;
  7181    }
  7182    zUser = Tcl_GetString(objv[2]);
  7183    zPasswd = Tcl_GetStringFromObj(objv[3], &nPasswd);
  7184    Tcl_GetBooleanFromObj(interp, objv[4], &isAdmin);
  7185    rc = sqlite3_user_add(db, zUser, zPasswd, nPasswd, isAdmin);
  7186    Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
  7187    return TCL_OK;
  7188  }
  7189  #endif /* SQLITE_USER_AUTHENTICATION */
  7190  
  7191  #ifdef SQLITE_USER_AUTHENTICATION
  7192  /*
  7193  ** tclcmd:  sqlite3_user_change DB USERNAME PASSWORD ISADMIN
  7194  */
  7195  static int SQLITE_TCLAPI test_user_change(
  7196    ClientData clientData, /* Unused */
  7197    Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  7198    int objc,              /* Number of arguments */
  7199    Tcl_Obj *CONST objv[]  /* Command arguments */
  7200  ){
  7201    char *zUser = 0;
  7202    char *zPasswd = 0;
  7203    int nPasswd = 0;
  7204    int isAdmin = 0;
  7205    sqlite3 *db;
  7206    int rc;
  7207  
  7208    if( objc!=5 ){
  7209      Tcl_WrongNumArgs(interp, 1, objv, "DB USERNAME PASSWORD ISADMIN");
  7210      return TCL_ERROR;
  7211    }
  7212    if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
  7213      return TCL_ERROR;
  7214    }
  7215    zUser = Tcl_GetString(objv[2]);
  7216    zPasswd = Tcl_GetStringFromObj(objv[3], &nPasswd);
  7217    Tcl_GetBooleanFromObj(interp, objv[4], &isAdmin);
  7218    rc = sqlite3_user_change(db, zUser, zPasswd, nPasswd, isAdmin);
  7219    Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
  7220    return TCL_OK;
  7221  }
  7222  #endif /* SQLITE_USER_AUTHENTICATION */
  7223  
  7224  #ifdef SQLITE_USER_AUTHENTICATION
  7225  /*
  7226  ** tclcmd:  sqlite3_user_delete DB USERNAME
  7227  */
  7228  static int SQLITE_TCLAPI test_user_delete(
  7229    ClientData clientData, /* Unused */
  7230    Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  7231    int objc,              /* Number of arguments */
  7232    Tcl_Obj *CONST objv[]  /* Command arguments */
  7233  ){
  7234    char *zUser = 0;
  7235    sqlite3 *db;
  7236    int rc;
  7237  
  7238    if( objc!=3 ){
  7239      Tcl_WrongNumArgs(interp, 1, objv, "DB USERNAME");
  7240      return TCL_ERROR;
  7241    }
  7242    if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
  7243      return TCL_ERROR;
  7244    }
  7245    zUser = Tcl_GetString(objv[2]);
  7246    rc = sqlite3_user_delete(db, zUser);
  7247    Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
  7248    return TCL_OK;
  7249  }
  7250  #endif /* SQLITE_USER_AUTHENTICATION */
  7251  
  7252  /*
  7253  ** tclcmd: bad_behavior TYPE
  7254  **
  7255  ** Do some things that should trigger a valgrind or -fsanitize=undefined
  7256  ** warning.  This is used to verify that errors and warnings output by those
  7257  ** tools are detected by the test scripts.
  7258  **
  7259  **       TYPE       BEHAVIOR
  7260  **       1          Overflow a signed integer
  7261  **       2          Jump based on an uninitialized variable
  7262  **       3          Read after free
  7263  **       4          Panic
  7264  */
  7265  static int SQLITE_TCLAPI test_bad_behavior(
  7266    ClientData clientData, /* Pointer to an integer containing zero */
  7267    Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  7268    int objc,              /* Number of arguments */
  7269    Tcl_Obj *CONST objv[]  /* Command arguments */
  7270  ){
  7271    int iType;
  7272    int xyz;
  7273    int i = *(int*)clientData;
  7274    int j;
  7275    int w[10];
  7276    int *a;
  7277    if( objc!=2 ){
  7278      Tcl_WrongNumArgs(interp, 1, objv, "TYPE");
  7279      return TCL_ERROR;
  7280    }
  7281    if( Tcl_GetIntFromObj(interp, objv[1], &iType) ) return TCL_ERROR;
  7282    switch( iType ){
  7283      case 1: {
  7284        xyz = 0x7fffff00 - i;
  7285        xyz += 0x100;
  7286        Tcl_SetObjResult(interp, Tcl_NewIntObj(xyz));
  7287        break;
  7288      }
  7289      case 2: {
  7290        w[1] = 5;
  7291        if( w[i]>0 ) w[1]++;
  7292        Tcl_SetObjResult(interp, Tcl_NewIntObj(w[1]));
  7293        break;
  7294      }
  7295      case 3: {
  7296        a = malloc( sizeof(int)*10 );
  7297        for(j=0; j<10; j++) a[j] = j;
  7298        free(a);
  7299        Tcl_SetObjResult(interp, Tcl_NewIntObj(a[i]));
  7300        break;
  7301      }
  7302      case 4: {
  7303        Tcl_Panic("Deliberate panic");
  7304        break;
  7305      }
  7306    }
  7307    return TCL_OK;
  7308  }  
  7309  
  7310  /*
  7311  ** tclcmd:   register_dbstat_vtab DB
  7312  **
  7313  ** Cause the dbstat virtual table to be available on the connection DB
  7314  */
  7315  static int SQLITE_TCLAPI test_register_dbstat_vtab(
  7316    void *clientData,
  7317    Tcl_Interp *interp,
  7318    int objc,
  7319    Tcl_Obj *CONST objv[]
  7320  ){
  7321  #ifdef SQLITE_OMIT_VIRTUALTABLE
  7322    Tcl_AppendResult(interp, "dbstat not available because of "
  7323                             "SQLITE_OMIT_VIRTUALTABLE", (void*)0);
  7324    return TCL_ERROR;
  7325  #else
  7326    struct SqliteDb { sqlite3 *db; };
  7327    char *zDb;
  7328    Tcl_CmdInfo cmdInfo;
  7329  
  7330    if( objc!=2 ){
  7331      Tcl_WrongNumArgs(interp, 1, objv, "DB");
  7332      return TCL_ERROR;
  7333    }
  7334  
  7335    zDb = Tcl_GetString(objv[1]);
  7336    if( Tcl_GetCommandInfo(interp, zDb, &cmdInfo) ){
  7337      sqlite3* db = ((struct SqliteDb*)cmdInfo.objClientData)->db;
  7338      sqlite3DbstatRegister(db);
  7339    }
  7340    return TCL_OK;
  7341  #endif /* SQLITE_OMIT_VIRTUALTABLE */
  7342  }
  7343  
  7344  /*
  7345  ** tclcmd:   sqlite3_db_config DB SETTING VALUE
  7346  **
  7347  ** Invoke sqlite3_db_config() for one of the setting values.
  7348  */
  7349  static int SQLITE_TCLAPI test_sqlite3_db_config(
  7350    void *clientData,
  7351    Tcl_Interp *interp,
  7352    int objc,
  7353    Tcl_Obj *CONST objv[]
  7354  ){
  7355    static const struct {
  7356      const char *zName;
  7357      int eVal;
  7358    } aSetting[] = {
  7359      { "FKEY",            SQLITE_DBCONFIG_ENABLE_FKEY },
  7360      { "TRIGGER",         SQLITE_DBCONFIG_ENABLE_TRIGGER },
  7361      { "FTS3_TOKENIZER",  SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER },
  7362      { "LOAD_EXTENSION",  SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION },
  7363      { "NO_CKPT_ON_CLOSE",SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE },
  7364      { "QPSG",            SQLITE_DBCONFIG_ENABLE_QPSG },
  7365    };
  7366    int i;
  7367    int v;
  7368    const char *zSetting;
  7369    sqlite3 *db;
  7370  
  7371    if( objc!=4 ){
  7372      Tcl_WrongNumArgs(interp, 1, objv, "DB SETTING VALUE");
  7373      return TCL_ERROR;
  7374    }
  7375    if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
  7376    zSetting = Tcl_GetString(objv[2]);
  7377    if( sqlite3_strglob("SQLITE_*", zSetting)==0 ) zSetting += 7;
  7378    if( sqlite3_strglob("DBCONFIG_*", zSetting)==0 ) zSetting += 9;
  7379    if( sqlite3_strglob("ENABLE_*", zSetting)==0 ) zSetting += 7;
  7380    for(i=0; i<ArraySize(aSetting); i++){
  7381      if( strcmp(zSetting, aSetting[i].zName)==0 ) break;
  7382    }
  7383    if( i>=ArraySize(aSetting) ){
  7384      Tcl_SetObjResult(interp,
  7385        Tcl_NewStringObj("unknown sqlite3_db_config setting", -1));
  7386      return TCL_ERROR;
  7387    }
  7388    if( Tcl_GetIntFromObj(interp, objv[3], &v) ) return TCL_ERROR;
  7389    sqlite3_db_config(db, aSetting[i].eVal, v, &v);
  7390    Tcl_SetObjResult(interp, Tcl_NewIntObj(v));
  7391    return TCL_OK;
  7392  }
  7393  
  7394  /*
  7395  ** Change the name of the main database schema from "main" to "icecube".
  7396  */
  7397  static int SQLITE_TCLAPI test_dbconfig_maindbname_icecube(
  7398    void * clientData,
  7399    Tcl_Interp *interp,
  7400    int objc,
  7401    Tcl_Obj *CONST objv[]
  7402  ){
  7403    int rc;
  7404    sqlite3 *db;
  7405    extern int getDbPointer(Tcl_Interp*, const char*, sqlite3**);
  7406    if( objc!=2 ){
  7407      Tcl_WrongNumArgs(interp, 1, objv, "DB");
  7408      return TCL_ERROR;
  7409    }else{
  7410      if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
  7411      rc = sqlite3_db_config(db, SQLITE_DBCONFIG_MAINDBNAME, "icecube");
  7412      Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
  7413      return TCL_OK;
  7414    }
  7415  }
  7416  
  7417  /*
  7418  ** Usage: sqlite3_mmap_warm DB DBNAME
  7419  */
  7420  static int SQLITE_TCLAPI test_mmap_warm(
  7421    void * clientData,
  7422    Tcl_Interp *interp,
  7423    int objc,
  7424    Tcl_Obj *CONST objv[]
  7425  ){
  7426    extern int getDbPointer(Tcl_Interp*, const char*, sqlite3**);
  7427    extern int sqlite3_mmap_warm(sqlite3 *db, const char *);
  7428  
  7429    if( objc!=2 && objc!=3 ){
  7430      Tcl_WrongNumArgs(interp, 1, objv, "DB ?DBNAME?");
  7431      return TCL_ERROR;
  7432    }else{
  7433      int rc;
  7434      sqlite3 *db;
  7435      const char *zDb = 0;
  7436      if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
  7437      if( objc==3 ){
  7438        zDb = Tcl_GetString(objv[2]);
  7439      }
  7440      rc = sqlite3_mmap_warm(db, zDb);
  7441      Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
  7442      return TCL_OK;
  7443    }
  7444  }
  7445  
  7446  /*
  7447  ** Register commands with the TCL interpreter.
  7448  */
  7449  int Sqlitetest1_Init(Tcl_Interp *interp){
  7450    extern int sqlite3_search_count;
  7451    extern int sqlite3_found_count;
  7452    extern int sqlite3_interrupt_count;
  7453    extern int sqlite3_open_file_count;
  7454    extern int sqlite3_sort_count;
  7455    extern int sqlite3_current_time;
  7456  #if SQLITE_OS_UNIX && defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
  7457    extern int sqlite3_hostid_num;
  7458  #endif
  7459    extern int sqlite3_max_blobsize;
  7460    extern int SQLITE_TCLAPI sqlite3BtreeSharedCacheReport(void*,
  7461                                            Tcl_Interp*,int,Tcl_Obj*CONST*);
  7462    static int iZero = 0;
  7463    static struct {
  7464       char *zName;
  7465       Tcl_CmdProc *xProc;
  7466    } aCmd[] = {
  7467       { "db_enter",                      (Tcl_CmdProc*)db_enter               },
  7468       { "db_leave",                      (Tcl_CmdProc*)db_leave               },
  7469       { "sqlite3_mprintf_int",           (Tcl_CmdProc*)sqlite3_mprintf_int    },
  7470       { "sqlite3_mprintf_int64",         (Tcl_CmdProc*)sqlite3_mprintf_int64  },
  7471       { "sqlite3_mprintf_long",          (Tcl_CmdProc*)sqlite3_mprintf_long   },
  7472       { "sqlite3_mprintf_str",           (Tcl_CmdProc*)sqlite3_mprintf_str    },
  7473       { "sqlite3_snprintf_str",          (Tcl_CmdProc*)sqlite3_snprintf_str   },
  7474       { "sqlite3_mprintf_stronly",       (Tcl_CmdProc*)sqlite3_mprintf_stronly},
  7475       { "sqlite3_mprintf_double",        (Tcl_CmdProc*)sqlite3_mprintf_double },
  7476       { "sqlite3_mprintf_scaled",        (Tcl_CmdProc*)sqlite3_mprintf_scaled },
  7477       { "sqlite3_mprintf_hexdouble",   (Tcl_CmdProc*)sqlite3_mprintf_hexdouble},
  7478       { "sqlite3_mprintf_z_test",        (Tcl_CmdProc*)test_mprintf_z        },
  7479       { "sqlite3_mprintf_n_test",        (Tcl_CmdProc*)test_mprintf_n        },
  7480       { "sqlite3_snprintf_int",          (Tcl_CmdProc*)test_snprintf_int     },
  7481       { "sqlite3_last_insert_rowid",     (Tcl_CmdProc*)test_last_rowid       },
  7482       { "sqlite3_exec_printf",           (Tcl_CmdProc*)test_exec_printf      },
  7483       { "sqlite3_exec_hex",              (Tcl_CmdProc*)test_exec_hex         },
  7484       { "sqlite3_exec",                  (Tcl_CmdProc*)test_exec             },
  7485       { "sqlite3_exec_nr",               (Tcl_CmdProc*)test_exec_nr          },
  7486  #ifndef SQLITE_OMIT_GET_TABLE
  7487       { "sqlite3_get_table_printf",      (Tcl_CmdProc*)test_get_table_printf },
  7488  #endif
  7489       { "sqlite3_close",                 (Tcl_CmdProc*)sqlite_test_close     },
  7490       { "sqlite3_close_v2",              (Tcl_CmdProc*)sqlite_test_close_v2  },
  7491       { "sqlite3_create_function",       (Tcl_CmdProc*)test_create_function  },
  7492       { "sqlite3_create_aggregate",      (Tcl_CmdProc*)test_create_aggregate },
  7493       { "sqlite_register_test_function", (Tcl_CmdProc*)test_register_func    },
  7494       { "sqlite_abort",                  (Tcl_CmdProc*)sqlite_abort          },
  7495       { "sqlite_bind",                   (Tcl_CmdProc*)test_bind             },
  7496       { "breakpoint",                    (Tcl_CmdProc*)test_breakpoint       },
  7497       { "sqlite3_key",                   (Tcl_CmdProc*)test_key              },
  7498       { "sqlite3_rekey",                 (Tcl_CmdProc*)test_rekey            },
  7499       { "sqlite_set_magic",              (Tcl_CmdProc*)sqlite_set_magic      },
  7500       { "sqlite3_interrupt",             (Tcl_CmdProc*)test_interrupt        },
  7501       { "sqlite_delete_function",        (Tcl_CmdProc*)delete_function       },
  7502       { "sqlite_delete_collation",       (Tcl_CmdProc*)delete_collation      },
  7503       { "sqlite3_get_autocommit",        (Tcl_CmdProc*)get_autocommit        },
  7504       { "sqlite3_busy_timeout",          (Tcl_CmdProc*)test_busy_timeout     },
  7505       { "printf",                        (Tcl_CmdProc*)test_printf           },
  7506       { "sqlite3IoTrace",              (Tcl_CmdProc*)test_io_trace         },
  7507       { "clang_sanitize_address",        (Tcl_CmdProc*)clang_sanitize_address },
  7508    };
  7509    static struct {
  7510       char *zName;
  7511       Tcl_ObjCmdProc *xProc;
  7512       void *clientData;
  7513    } aObjCmd[] = {
  7514       { "sqlite3_db_config",             test_sqlite3_db_config, 0 },
  7515       { "bad_behavior",                  test_bad_behavior,  (void*)&iZero },
  7516       { "register_dbstat_vtab",          test_register_dbstat_vtab  },
  7517       { "sqlite3_connection_pointer",    get_sqlite_pointer, 0 },
  7518       { "intarray_addr",                 test_intarray_addr, 0 },
  7519       { "int64array_addr",               test_int64array_addr, 0 },
  7520       { "doublearray_addr",              test_doublearray_addr, 0 },
  7521       { "textarray_addr",                test_textarray_addr, 0 },
  7522       { "sqlite3_bind_int",              test_bind_int,      0 },
  7523       { "sqlite3_bind_zeroblob",         test_bind_zeroblob, 0 },
  7524       { "sqlite3_bind_zeroblob64",       test_bind_zeroblob64, 0 },
  7525       { "sqlite3_bind_int64",            test_bind_int64,    0 },
  7526       { "sqlite3_bind_double",           test_bind_double,   0 },
  7527       { "sqlite3_bind_null",             test_bind_null     ,0 },
  7528       { "sqlite3_bind_text",             test_bind_text     ,0 },
  7529       { "sqlite3_bind_text16",           test_bind_text16   ,0 },
  7530       { "sqlite3_bind_blob",             test_bind_blob     ,0 },
  7531       { "sqlite3_bind_parameter_count",  test_bind_parameter_count, 0},
  7532       { "sqlite3_bind_parameter_name",   test_bind_parameter_name,  0},
  7533       { "sqlite3_bind_parameter_index",  test_bind_parameter_index, 0},
  7534       { "sqlite3_clear_bindings",        test_clear_bindings, 0},
  7535       { "sqlite3_sleep",                 test_sleep,          0},
  7536       { "sqlite3_errcode",               test_errcode       ,0 },
  7537       { "sqlite3_extended_errcode",      test_ex_errcode    ,0 },
  7538       { "sqlite3_errmsg",                test_errmsg        ,0 },
  7539       { "sqlite3_errmsg16",              test_errmsg16      ,0 },
  7540       { "sqlite3_open",                  test_open          ,0 },
  7541       { "sqlite3_open16",                test_open16        ,0 },
  7542       { "sqlite3_open_v2",               test_open_v2       ,0 },
  7543       { "sqlite3_complete16",            test_complete16    ,0 },
  7544  
  7545       { "sqlite3_prepare",               test_prepare       ,0 },
  7546       { "sqlite3_prepare16",             test_prepare16     ,0 },
  7547       { "sqlite3_prepare_v2",            test_prepare_v2    ,0 },
  7548       { "sqlite3_prepare_tkt3134",       test_prepare_tkt3134, 0},
  7549       { "sqlite3_prepare16_v2",          test_prepare16_v2  ,0 },
  7550       { "sqlite3_finalize",              test_finalize      ,0 },
  7551       { "sqlite3_stmt_status",           test_stmt_status   ,0 },
  7552       { "sqlite3_reset",                 test_reset         ,0 },
  7553       { "sqlite3_expired",               test_expired       ,0 },
  7554       { "sqlite3_transfer_bindings",     test_transfer_bind ,0 },
  7555       { "sqlite3_changes",               test_changes       ,0 },
  7556       { "sqlite3_step",                  test_step          ,0 },
  7557       { "sqlite3_sql",                   test_sql           ,0 },
  7558       { "sqlite3_expanded_sql",          test_ex_sql        ,0 },
  7559       { "sqlite3_next_stmt",             test_next_stmt     ,0 },
  7560       { "sqlite3_stmt_readonly",         test_stmt_readonly ,0 },
  7561       { "sqlite3_stmt_busy",             test_stmt_busy     ,0 },
  7562       { "uses_stmt_journal",             uses_stmt_journal ,0 },
  7563  
  7564       { "sqlite3_release_memory",        test_release_memory,     0},
  7565       { "sqlite3_db_release_memory",     test_db_release_memory,  0},
  7566       { "sqlite3_db_cacheflush",         test_db_cacheflush,      0},
  7567       { "sqlite3_system_errno",          test_system_errno,       0},
  7568       { "sqlite3_db_filename",           test_db_filename,        0},
  7569       { "sqlite3_db_readonly",           test_db_readonly,        0},
  7570       { "sqlite3_soft_heap_limit",       test_soft_heap_limit,    0},
  7571       { "sqlite3_thread_cleanup",        test_thread_cleanup,     0},
  7572       { "sqlite3_pager_refcounts",       test_pager_refcounts,    0},
  7573  
  7574       { "sqlite3_load_extension",        test_load_extension,     0},
  7575       { "sqlite3_enable_load_extension", test_enable_load,        0},
  7576       { "sqlite3_extended_result_codes", test_extended_result_codes, 0},
  7577       { "sqlite3_limit",                 test_limit,                 0},
  7578       { "dbconfig_maindbname_icecube",   test_dbconfig_maindbname_icecube },
  7579  
  7580       { "save_prng_state",               save_prng_state,    0 },
  7581       { "restore_prng_state",            restore_prng_state, 0 },
  7582       { "reset_prng_state",              reset_prng_state,   0 },
  7583       { "database_never_corrupt",        database_never_corrupt, 0},
  7584       { "database_may_be_corrupt",       database_may_be_corrupt, 0},
  7585       { "optimization_control",          optimization_control,0},
  7586  #if SQLITE_OS_WIN
  7587       { "lock_win32_file",               win32_file_lock,    0 },
  7588       { "exists_win32_path",             win32_exists_path,  0 },
  7589       { "find_win32_file",               win32_find_file,    0 },
  7590       { "delete_win32_file",             win32_delete_file,  0 },
  7591       { "make_win32_dir",                win32_mkdir,        0 },
  7592       { "remove_win32_dir",              win32_rmdir,        0 },
  7593  #endif
  7594       { "tcl_objproc",                   runAsObjProc,       0 },
  7595  
  7596       /* sqlite3_column_*() API */
  7597       { "sqlite3_column_count",          test_column_count  ,0 },
  7598       { "sqlite3_data_count",            test_data_count    ,0 },
  7599       { "sqlite3_column_type",           test_column_type   ,0 },
  7600       { "sqlite3_column_blob",           test_column_blob   ,0 },
  7601       { "sqlite3_column_double",         test_column_double ,0 },
  7602       { "sqlite3_column_int64",          test_column_int64  ,0 },
  7603       { "sqlite3_column_text",   test_stmt_utf8,  (void*)sqlite3_column_text },
  7604       { "sqlite3_column_name",   test_stmt_utf8,  (void*)sqlite3_column_name },
  7605       { "sqlite3_column_int",    test_stmt_int,   (void*)sqlite3_column_int  },
  7606       { "sqlite3_column_bytes",  test_stmt_int,   (void*)sqlite3_column_bytes},
  7607  #ifndef SQLITE_OMIT_DECLTYPE
  7608       { "sqlite3_column_decltype",test_stmt_utf8,(void*)sqlite3_column_decltype},
  7609  #endif
  7610  #ifdef SQLITE_ENABLE_COLUMN_METADATA
  7611  { "sqlite3_column_database_name",test_stmt_utf8,(void*)sqlite3_column_database_name},
  7612  { "sqlite3_column_table_name",test_stmt_utf8,(void*)sqlite3_column_table_name},
  7613  { "sqlite3_column_origin_name",test_stmt_utf8,(void*)sqlite3_column_origin_name},
  7614  #endif
  7615  
  7616  #ifndef SQLITE_OMIT_UTF16
  7617       { "sqlite3_column_bytes16", test_stmt_int, (void*)sqlite3_column_bytes16 },
  7618       { "sqlite3_column_text16",  test_stmt_utf16, (void*)sqlite3_column_text16},
  7619       { "sqlite3_column_name16",  test_stmt_utf16, (void*)sqlite3_column_name16},
  7620       { "add_alignment_test_collations", add_alignment_test_collations, 0      },
  7621  #ifndef SQLITE_OMIT_DECLTYPE
  7622       { "sqlite3_column_decltype16",test_stmt_utf16,(void*)sqlite3_column_decltype16},
  7623  #endif
  7624  #ifdef SQLITE_ENABLE_COLUMN_METADATA
  7625  {"sqlite3_column_database_name16",
  7626    test_stmt_utf16, (void*)sqlite3_column_database_name16},
  7627  {"sqlite3_column_table_name16", test_stmt_utf16, (void*)sqlite3_column_table_name16},
  7628  {"sqlite3_column_origin_name16", test_stmt_utf16, (void*)sqlite3_column_origin_name16},
  7629  #endif
  7630  #endif
  7631       { "sqlite3_create_collation_v2", test_create_collation_v2, 0 },
  7632       { "sqlite3_global_recover",     test_global_recover, 0   },
  7633       { "working_64bit_int",          working_64bit_int,   0   },
  7634       { "vfs_unlink_test",            vfs_unlink_test,     0   },
  7635       { "vfs_initfail_test",          vfs_initfail_test,   0   },
  7636       { "vfs_unregister_all",         vfs_unregister_all,  0   },
  7637       { "vfs_reregister_all",         vfs_reregister_all,  0   },
  7638       { "file_control_test",          file_control_test,   0   },
  7639       { "file_control_lasterrno_test", file_control_lasterrno_test,  0   },
  7640       { "file_control_lockproxy_test", file_control_lockproxy_test,  0   },
  7641       { "file_control_chunksize_test", file_control_chunksize_test,  0   },
  7642       { "file_control_sizehint_test",  file_control_sizehint_test,   0   },
  7643  #if SQLITE_OS_WIN
  7644       { "file_control_win32_av_retry", file_control_win32_av_retry,  0   },
  7645       { "file_control_win32_get_handle", file_control_win32_get_handle, 0  },
  7646       { "file_control_win32_set_handle", file_control_win32_set_handle, 0  },
  7647  #endif
  7648       { "file_control_persist_wal",    file_control_persist_wal,     0   },
  7649       { "file_control_powersafe_overwrite",file_control_powersafe_overwrite,0},
  7650       { "file_control_vfsname",        file_control_vfsname,         0   },
  7651       { "file_control_tempfilename",   file_control_tempfilename,    0   },
  7652       { "sqlite3_vfs_list",           vfs_list,     0   },
  7653       { "sqlite3_create_function_v2", test_create_function_v2, 0 },
  7654  
  7655       /* Functions from os.h */
  7656  #ifndef SQLITE_OMIT_UTF16
  7657       { "add_test_collate",        test_collate, 0            },
  7658       { "add_test_collate_needed", test_collate_needed, 0     },
  7659       { "add_test_function",       test_function, 0           },
  7660       { "add_test_utf16bin_collate",    test_utf16bin_collate, 0        },
  7661  #endif
  7662       { "sqlite3_test_errstr",     test_errstr, 0             },
  7663       { "tcl_variable_type",       tcl_variable_type, 0       },
  7664  #ifndef SQLITE_OMIT_SHARED_CACHE
  7665       { "sqlite3_enable_shared_cache", test_enable_shared, 0  },
  7666       { "sqlite3_shared_cache_report", sqlite3BtreeSharedCacheReport, 0},
  7667  #endif
  7668       { "sqlite3_libversion_number", test_libversion_number, 0  },
  7669       { "sqlite3_table_column_metadata", test_table_column_metadata, 0  },
  7670  #ifndef SQLITE_OMIT_INCRBLOB
  7671       { "sqlite3_blob_reopen", test_blob_reopen, 0  },
  7672  #endif
  7673       { "pcache_stats",       test_pcache_stats, 0  },
  7674  #ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
  7675       { "sqlite3_unlock_notify", test_unlock_notify, 0  },
  7676  #endif
  7677       { "sqlite3_wal_checkpoint",   test_wal_checkpoint, 0  },
  7678       { "sqlite3_wal_checkpoint_v2",test_wal_checkpoint_v2, 0  },
  7679       { "sqlite3_wal_autocheckpoint",test_wal_autocheckpoint, 0  },
  7680       { "test_sqlite3_log",         test_sqlite3_log, 0  },
  7681  #ifndef SQLITE_OMIT_EXPLAIN
  7682       { "print_explain_query_plan", test_print_eqp, 0  },
  7683  #endif
  7684       { "sqlite3_test_control", test_test_control },
  7685  #if SQLITE_OS_UNIX
  7686       { "getrusage", test_getrusage },
  7687  #endif
  7688       { "load_static_extension", tclLoadStaticExtensionCmd },
  7689       { "sorter_test_fakeheap", sorter_test_fakeheap },
  7690       { "sorter_test_sort4_helper", sorter_test_sort4_helper },
  7691  #ifdef SQLITE_USER_AUTHENTICATION
  7692       { "sqlite3_user_authenticate", test_user_authenticate, 0 },
  7693       { "sqlite3_user_add",          test_user_add,          0 },
  7694       { "sqlite3_user_change",       test_user_change,       0 },
  7695       { "sqlite3_user_delete",       test_user_delete,       0 },
  7696  #endif
  7697  #ifdef SQLITE_ENABLE_STMT_SCANSTATUS
  7698       { "sqlite3_stmt_scanstatus",       test_stmt_scanstatus,   0 },
  7699       { "sqlite3_stmt_scanstatus_reset", test_stmt_scanstatus_reset,   0 },
  7700  #endif
  7701  #ifdef SQLITE_ENABLE_SQLLOG
  7702       { "sqlite3_config_sqllog",         test_config_sqllog,   0 },
  7703  #endif
  7704       { "vfs_current_time_int64",           vfsCurrentTimeInt64,   0 },
  7705  #ifdef SQLITE_ENABLE_SNAPSHOT
  7706       { "sqlite3_snapshot_get", test_snapshot_get, 0 },
  7707       { "sqlite3_snapshot_open", test_snapshot_open, 0 },
  7708       { "sqlite3_snapshot_free", test_snapshot_free, 0 },
  7709       { "sqlite3_snapshot_cmp", test_snapshot_cmp, 0 },
  7710       { "sqlite3_snapshot_recover", test_snapshot_recover, 0 },
  7711       { "sqlite3_snapshot_get_blob", test_snapshot_get_blob, 0 },
  7712       { "sqlite3_snapshot_open_blob", test_snapshot_open_blob, 0 },
  7713       { "sqlite3_snapshot_cmp_blob", test_snapshot_cmp_blob, 0 },
  7714  #endif
  7715       { "sqlite3_delete_database", test_delete_database,    0 },
  7716       { "atomic_batch_write",      test_atomic_batch_write, 0 },
  7717       { "sqlite3_mmap_warm",       test_mmap_warm,          0 },
  7718    };
  7719    static int bitmask_size = sizeof(Bitmask)*8;
  7720    static int longdouble_size = sizeof(LONGDOUBLE_TYPE);
  7721    int i;
  7722    extern int sqlite3_sync_count, sqlite3_fullsync_count;
  7723    extern int sqlite3_opentemp_count;
  7724    extern int sqlite3_like_count;
  7725    extern int sqlite3_xferopt_count;
  7726    extern int sqlite3_pager_readdb_count;
  7727    extern int sqlite3_pager_writedb_count;
  7728    extern int sqlite3_pager_writej_count;
  7729  #if SQLITE_OS_WIN
  7730    extern LONG volatile sqlite3_os_type;
  7731  #endif
  7732  #ifdef SQLITE_DEBUG
  7733    extern int sqlite3WhereTrace;
  7734    extern int sqlite3OSTrace;
  7735    extern int sqlite3WalTrace;
  7736  #endif
  7737  #ifdef SQLITE_TEST
  7738  #ifdef SQLITE_ENABLE_FTS3
  7739    extern int sqlite3_fts3_enable_parentheses;
  7740  #endif
  7741  #endif
  7742  
  7743    for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){
  7744      Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0);
  7745    }
  7746    for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
  7747      Tcl_CreateObjCommand(interp, aObjCmd[i].zName, 
  7748          aObjCmd[i].xProc, aObjCmd[i].clientData, 0);
  7749    }
  7750    Tcl_LinkVar(interp, "sqlite_search_count", 
  7751        (char*)&sqlite3_search_count, TCL_LINK_INT);
  7752    Tcl_LinkVar(interp, "sqlite_found_count", 
  7753        (char*)&sqlite3_found_count, TCL_LINK_INT);
  7754    Tcl_LinkVar(interp, "sqlite_sort_count", 
  7755        (char*)&sqlite3_sort_count, TCL_LINK_INT);
  7756    Tcl_LinkVar(interp, "sqlite3_max_blobsize", 
  7757        (char*)&sqlite3_max_blobsize, TCL_LINK_INT);
  7758    Tcl_LinkVar(interp, "sqlite_like_count", 
  7759        (char*)&sqlite3_like_count, TCL_LINK_INT);
  7760    Tcl_LinkVar(interp, "sqlite_interrupt_count", 
  7761        (char*)&sqlite3_interrupt_count, TCL_LINK_INT);
  7762    Tcl_LinkVar(interp, "sqlite_open_file_count", 
  7763        (char*)&sqlite3_open_file_count, TCL_LINK_INT);
  7764    Tcl_LinkVar(interp, "sqlite_current_time", 
  7765        (char*)&sqlite3_current_time, TCL_LINK_INT);
  7766  #if SQLITE_OS_UNIX && defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
  7767    Tcl_LinkVar(interp, "sqlite_hostid_num", 
  7768        (char*)&sqlite3_hostid_num, TCL_LINK_INT);
  7769  #endif
  7770    Tcl_LinkVar(interp, "sqlite3_xferopt_count",
  7771        (char*)&sqlite3_xferopt_count, TCL_LINK_INT);
  7772    Tcl_LinkVar(interp, "sqlite3_pager_readdb_count",
  7773        (char*)&sqlite3_pager_readdb_count, TCL_LINK_INT);
  7774    Tcl_LinkVar(interp, "sqlite3_pager_writedb_count",
  7775        (char*)&sqlite3_pager_writedb_count, TCL_LINK_INT);
  7776    Tcl_LinkVar(interp, "sqlite3_pager_writej_count",
  7777        (char*)&sqlite3_pager_writej_count, TCL_LINK_INT);
  7778  #ifndef SQLITE_OMIT_UTF16
  7779    Tcl_LinkVar(interp, "unaligned_string_counter",
  7780        (char*)&unaligned_string_counter, TCL_LINK_INT);
  7781  #endif
  7782  #ifndef SQLITE_OMIT_UTF16
  7783    Tcl_LinkVar(interp, "sqlite_last_needed_collation",
  7784        (char*)&pzNeededCollation, TCL_LINK_STRING|TCL_LINK_READ_ONLY);
  7785  #endif
  7786  #if SQLITE_OS_WIN
  7787    Tcl_LinkVar(interp, "sqlite_os_type",
  7788        (char*)&sqlite3_os_type, TCL_LINK_LONG);
  7789  #endif
  7790  #ifdef SQLITE_TEST
  7791    {
  7792      static const char *query_plan = "*** OBSOLETE VARIABLE ***";
  7793      Tcl_LinkVar(interp, "sqlite_query_plan",
  7794         (char*)&query_plan, TCL_LINK_STRING|TCL_LINK_READ_ONLY);
  7795    }
  7796  #endif
  7797  #ifdef SQLITE_DEBUG
  7798    Tcl_LinkVar(interp, "sqlite_where_trace",
  7799        (char*)&sqlite3WhereTrace, TCL_LINK_INT);
  7800    Tcl_LinkVar(interp, "sqlite_os_trace",
  7801        (char*)&sqlite3OSTrace, TCL_LINK_INT);
  7802  #ifndef SQLITE_OMIT_WAL
  7803    Tcl_LinkVar(interp, "sqlite_wal_trace",
  7804        (char*)&sqlite3WalTrace, TCL_LINK_INT);
  7805  #endif
  7806  #endif
  7807  #ifndef SQLITE_OMIT_DISKIO
  7808    Tcl_LinkVar(interp, "sqlite_opentemp_count",
  7809        (char*)&sqlite3_opentemp_count, TCL_LINK_INT);
  7810  #endif
  7811    Tcl_LinkVar(interp, "sqlite_static_bind_value",
  7812        (char*)&sqlite_static_bind_value, TCL_LINK_STRING);
  7813    Tcl_LinkVar(interp, "sqlite_static_bind_nbyte",
  7814        (char*)&sqlite_static_bind_nbyte, TCL_LINK_INT);
  7815    Tcl_LinkVar(interp, "sqlite_temp_directory",
  7816        (char*)&sqlite3_temp_directory, TCL_LINK_STRING);
  7817    Tcl_LinkVar(interp, "sqlite_data_directory",
  7818        (char*)&sqlite3_data_directory, TCL_LINK_STRING);
  7819    Tcl_LinkVar(interp, "bitmask_size",
  7820        (char*)&bitmask_size, TCL_LINK_INT|TCL_LINK_READ_ONLY);
  7821    Tcl_LinkVar(interp, "longdouble_size",
  7822        (char*)&longdouble_size, TCL_LINK_INT|TCL_LINK_READ_ONLY);
  7823    Tcl_LinkVar(interp, "sqlite_sync_count",
  7824        (char*)&sqlite3_sync_count, TCL_LINK_INT);
  7825    Tcl_LinkVar(interp, "sqlite_fullsync_count",
  7826        (char*)&sqlite3_fullsync_count, TCL_LINK_INT);
  7827  #if defined(SQLITE_ENABLE_FTS3) && defined(SQLITE_TEST)
  7828    Tcl_LinkVar(interp, "sqlite_fts3_enable_parentheses",
  7829        (char*)&sqlite3_fts3_enable_parentheses, TCL_LINK_INT);
  7830  #endif
  7831    return TCL_OK;
  7832  }