Annotation of embedaddon/sqlite3/src/test1.c, revision 1.1

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>