1d1bf3512Sdrh /* 2b19a2bc6Sdrh ** 2001 September 15 3d1bf3512Sdrh ** 4b19a2bc6Sdrh ** The author disclaims copyright to this source code. In place of 5b19a2bc6Sdrh ** a legal notice, here is a blessing: 6d1bf3512Sdrh ** 7b19a2bc6Sdrh ** May you do good and not evil. 8b19a2bc6Sdrh ** May you find forgiveness for yourself and forgive others. 9b19a2bc6Sdrh ** May you share freely, never taking more than you give. 10d1bf3512Sdrh ** 11d1bf3512Sdrh ************************************************************************* 12d1bf3512Sdrh ** Code for testing the printf() interface to SQLite. This code 13d1bf3512Sdrh ** is not included in the SQLite library. It is used for automated 14d1bf3512Sdrh ** testing of the SQLite library. 15d1bf3512Sdrh ** 16*27d258a3Sdrh ** $Id: test1.c,v 1.105 2004/10/30 20:23:09 drh Exp $ 17d1bf3512Sdrh */ 18d1bf3512Sdrh #include "sqliteInt.h" 19d1bf3512Sdrh #include "tcl.h" 2094e92032Sdrh #include "os.h" 21d1bf3512Sdrh #include <stdlib.h> 22d1bf3512Sdrh #include <string.h> 23d1bf3512Sdrh 246622cce3Sdanielk1977 static const char * errorName(int rc){ 256622cce3Sdanielk1977 const char *zName = 0; 266622cce3Sdanielk1977 switch( rc ){ 276622cce3Sdanielk1977 case SQLITE_OK: zName = "SQLITE_OK"; break; 286622cce3Sdanielk1977 case SQLITE_ERROR: zName = "SQLITE_ERROR"; break; 296622cce3Sdanielk1977 case SQLITE_INTERNAL: zName = "SQLITE_INTERNAL"; break; 306622cce3Sdanielk1977 case SQLITE_PERM: zName = "SQLITE_PERM"; break; 316622cce3Sdanielk1977 case SQLITE_ABORT: zName = "SQLITE_ABORT"; break; 326622cce3Sdanielk1977 case SQLITE_BUSY: zName = "SQLITE_BUSY"; break; 336622cce3Sdanielk1977 case SQLITE_LOCKED: zName = "SQLITE_LOCKED"; break; 346622cce3Sdanielk1977 case SQLITE_NOMEM: zName = "SQLITE_NOMEM"; break; 356622cce3Sdanielk1977 case SQLITE_READONLY: zName = "SQLITE_READONLY"; break; 366622cce3Sdanielk1977 case SQLITE_INTERRUPT: zName = "SQLITE_INTERRUPT"; break; 376622cce3Sdanielk1977 case SQLITE_IOERR: zName = "SQLITE_IOERR"; break; 386622cce3Sdanielk1977 case SQLITE_CORRUPT: zName = "SQLITE_CORRUPT"; break; 396622cce3Sdanielk1977 case SQLITE_NOTFOUND: zName = "SQLITE_NOTFOUND"; break; 406622cce3Sdanielk1977 case SQLITE_FULL: zName = "SQLITE_FULL"; break; 416622cce3Sdanielk1977 case SQLITE_CANTOPEN: zName = "SQLITE_CANTOPEN"; break; 426622cce3Sdanielk1977 case SQLITE_PROTOCOL: zName = "SQLITE_PROTOCOL"; break; 436622cce3Sdanielk1977 case SQLITE_EMPTY: zName = "SQLITE_EMPTY"; break; 446622cce3Sdanielk1977 case SQLITE_SCHEMA: zName = "SQLITE_SCHEMA"; break; 456622cce3Sdanielk1977 case SQLITE_TOOBIG: zName = "SQLITE_TOOBIG"; break; 466622cce3Sdanielk1977 case SQLITE_CONSTRAINT: zName = "SQLITE_CONSTRAINT"; break; 476622cce3Sdanielk1977 case SQLITE_MISMATCH: zName = "SQLITE_MISMATCH"; break; 486622cce3Sdanielk1977 case SQLITE_MISUSE: zName = "SQLITE_MISUSE"; break; 496622cce3Sdanielk1977 case SQLITE_NOLFS: zName = "SQLITE_NOLFS"; break; 506622cce3Sdanielk1977 case SQLITE_AUTH: zName = "SQLITE_AUTH"; break; 516622cce3Sdanielk1977 case SQLITE_FORMAT: zName = "SQLITE_FORMAT"; break; 526622cce3Sdanielk1977 case SQLITE_RANGE: zName = "SQLITE_RANGE"; break; 536622cce3Sdanielk1977 case SQLITE_ROW: zName = "SQLITE_ROW"; break; 546622cce3Sdanielk1977 case SQLITE_DONE: zName = "SQLITE_DONE"; break; 55312d6b36Sdanielk1977 case SQLITE_NOTADB: zName = "SQLITE_NOTADB"; break; 566622cce3Sdanielk1977 default: zName = "SQLITE_Unknown"; break; 576622cce3Sdanielk1977 } 586622cce3Sdanielk1977 return zName; 596622cce3Sdanielk1977 } 606622cce3Sdanielk1977 61d1bf3512Sdrh /* 62c60d0446Sdrh ** Convert an sqlite3_stmt* into an sqlite3*. This depends on the 63c60d0446Sdrh ** fact that the sqlite3* is the first field in the Vdbe structure. 64c60d0446Sdrh */ 65c60d0446Sdrh #define StmtToDb(X) (*(sqlite3**)(X)) 66c60d0446Sdrh 67c60d0446Sdrh /* 68c60d0446Sdrh ** Check a return value to make sure it agrees with the results 69c60d0446Sdrh ** from sqlite3_errcode. 70c60d0446Sdrh */ 71c60d0446Sdrh int sqlite3TestErrCode(Tcl_Interp *interp, sqlite3 *db, int rc){ 72c60d0446Sdrh if( rc!=SQLITE_MISUSE && rc!=SQLITE_OK && sqlite3_errcode(db)!=rc ){ 73c60d0446Sdrh char zBuf[200]; 74c60d0446Sdrh int r2 = sqlite3_errcode(db); 75c60d0446Sdrh sprintf(zBuf, "error code %s (%d) does not match sqlite3_errcode %s (%d)", 76c60d0446Sdrh errorName(rc), rc, errorName(r2), r2); 77c60d0446Sdrh Tcl_ResetResult(interp); 78c60d0446Sdrh Tcl_AppendResult(interp, zBuf, 0); 79c60d0446Sdrh return 1; 80c60d0446Sdrh } 81c60d0446Sdrh return 0; 82c60d0446Sdrh } 83c60d0446Sdrh 84c60d0446Sdrh /* 859bb575fdSdrh ** Decode a pointer to an sqlite3 object. 86b86ccfb2Sdrh */ 879bb575fdSdrh static int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb){ 88fe63d1c9Sdrh *ppDb = (sqlite3*)sqlite3TextToPtr(zA); 89b86ccfb2Sdrh return TCL_OK; 90b86ccfb2Sdrh } 91b86ccfb2Sdrh 92b86ccfb2Sdrh /* 9351e3d8e2Sdanielk1977 ** Decode a pointer to an sqlite3_stmt object. 9451e3d8e2Sdanielk1977 */ 9551e3d8e2Sdanielk1977 static int getStmtPointer( 9651e3d8e2Sdanielk1977 Tcl_Interp *interp, 9751e3d8e2Sdanielk1977 const char *zArg, 9851e3d8e2Sdanielk1977 sqlite3_stmt **ppStmt 9951e3d8e2Sdanielk1977 ){ 100fe63d1c9Sdrh *ppStmt = (sqlite3_stmt*)sqlite3TextToPtr(zArg); 10151e3d8e2Sdanielk1977 return TCL_OK; 10251e3d8e2Sdanielk1977 } 10351e3d8e2Sdanielk1977 10451e3d8e2Sdanielk1977 /* 1059a1d0abeSdanielk1977 ** Decode a pointer to an sqlite3_stmt object. 1069a1d0abeSdanielk1977 */ 1079a1d0abeSdanielk1977 static int getFilePointer( 1089a1d0abeSdanielk1977 Tcl_Interp *interp, 1099a1d0abeSdanielk1977 const char *zArg, 1109a1d0abeSdanielk1977 OsFile **ppFile 1119a1d0abeSdanielk1977 ){ 112fe63d1c9Sdrh *ppFile = (OsFile*)sqlite3TextToPtr(zArg); 1139a1d0abeSdanielk1977 return TCL_OK; 1149a1d0abeSdanielk1977 } 1159a1d0abeSdanielk1977 1169a1d0abeSdanielk1977 /* 1177d8085a8Sdrh ** Generate a text representation of a pointer that can be understood 1187d8085a8Sdrh ** by the getDbPointer and getVmPointer routines above. 1197d8085a8Sdrh ** 1207d8085a8Sdrh ** The problem is, on some machines (Solaris) if you do a printf with 1217d8085a8Sdrh ** "%p" you cannot turn around and do a scanf with the same "%p" and 1227d8085a8Sdrh ** get your pointer back. You have to prepend a "0x" before it will 1237d8085a8Sdrh ** work. Or at least that is what is reported to me (drh). But this 1247d8085a8Sdrh ** behavior varies from machine to machine. The solution used her is 1257d8085a8Sdrh ** to test the string right after it is generated to see if it can be 1267d8085a8Sdrh ** understood by scanf, and if not, try prepending an "0x" to see if 1277d8085a8Sdrh ** that helps. If nothing works, a fatal error is generated. 1287d8085a8Sdrh */ 1297d8085a8Sdrh static int makePointerStr(Tcl_Interp *interp, char *zPtr, void *p){ 130fe63d1c9Sdrh sqlite3_snprintf(100, zPtr, "%p", p); 1317d8085a8Sdrh return TCL_OK; 1327d8085a8Sdrh } 1337d8085a8Sdrh 1347d8085a8Sdrh /* 1356f8a503dSdanielk1977 ** The callback routine for sqlite3_exec_printf(). 136d1bf3512Sdrh */ 137d1bf3512Sdrh static int exec_printf_cb(void *pArg, int argc, char **argv, char **name){ 138d1bf3512Sdrh Tcl_DString *str = (Tcl_DString*)pArg; 139d1bf3512Sdrh int i; 140d1bf3512Sdrh 141d1bf3512Sdrh if( Tcl_DStringLength(str)==0 ){ 142d1bf3512Sdrh for(i=0; i<argc; i++){ 143d1bf3512Sdrh Tcl_DStringAppendElement(str, name[i] ? name[i] : "NULL"); 144d1bf3512Sdrh } 145d1bf3512Sdrh } 146d1bf3512Sdrh for(i=0; i<argc; i++){ 147d1bf3512Sdrh Tcl_DStringAppendElement(str, argv[i] ? argv[i] : "NULL"); 148d1bf3512Sdrh } 149d1bf3512Sdrh return 0; 150d1bf3512Sdrh } 151d1bf3512Sdrh 152d1bf3512Sdrh /* 1536f8a503dSdanielk1977 ** Usage: sqlite3_exec_printf DB FORMAT STRING 154d1bf3512Sdrh ** 1556f8a503dSdanielk1977 ** Invoke the sqlite3_exec_printf() interface using the open database 156d1bf3512Sdrh ** DB. The SQL is the string FORMAT. The format string should contain 157d1bf3512Sdrh ** one %s or %q. STRING is the value inserted into %s or %q. 158d1bf3512Sdrh */ 159d1bf3512Sdrh static int test_exec_printf( 160d1bf3512Sdrh void *NotUsed, 161d1bf3512Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 162d1bf3512Sdrh int argc, /* Number of arguments */ 163d1bf3512Sdrh char **argv /* Text of each argument */ 164d1bf3512Sdrh ){ 1659bb575fdSdrh sqlite3 *db; 166d1bf3512Sdrh Tcl_DString str; 167d1bf3512Sdrh int rc; 168d1bf3512Sdrh char *zErr = 0; 1691211de37Sdrh char *zSql; 170d1bf3512Sdrh char zBuf[30]; 171d1bf3512Sdrh if( argc!=4 ){ 172d1bf3512Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 173d1bf3512Sdrh " DB FORMAT STRING", 0); 174d1bf3512Sdrh return TCL_ERROR; 175d1bf3512Sdrh } 176b86ccfb2Sdrh if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; 177d1bf3512Sdrh Tcl_DStringInit(&str); 1781211de37Sdrh zSql = sqlite3_mprintf(argv[2], argv[3]); 1791211de37Sdrh rc = sqlite3_exec(db, zSql, exec_printf_cb, &str, &zErr); 1801211de37Sdrh sqlite3_free(zSql); 181d1bf3512Sdrh sprintf(zBuf, "%d", rc); 182d1bf3512Sdrh Tcl_AppendElement(interp, zBuf); 183d1bf3512Sdrh Tcl_AppendElement(interp, rc==SQLITE_OK ? Tcl_DStringValue(&str) : zErr); 184d1bf3512Sdrh Tcl_DStringFree(&str); 185d1bf3512Sdrh if( zErr ) free(zErr); 186c60d0446Sdrh if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; 187d1bf3512Sdrh return TCL_OK; 188d1bf3512Sdrh } 189d1bf3512Sdrh 190d1bf3512Sdrh /* 1916f8a503dSdanielk1977 ** Usage: sqlite3_mprintf_z_test SEPARATOR ARG0 ARG1 ... 192d93d8a81Sdrh ** 193d93d8a81Sdrh ** Test the %z format of mprintf(). Use multiple mprintf() calls to 194d93d8a81Sdrh ** concatenate arg0 through argn using separator as the separator. 195d93d8a81Sdrh ** Return the result. 196d93d8a81Sdrh */ 197d93d8a81Sdrh static int test_mprintf_z( 198d93d8a81Sdrh void *NotUsed, 199d93d8a81Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 200d93d8a81Sdrh int argc, /* Number of arguments */ 201d93d8a81Sdrh char **argv /* Text of each argument */ 202d93d8a81Sdrh ){ 203d93d8a81Sdrh char *zResult = 0; 204d93d8a81Sdrh int i; 205d93d8a81Sdrh 206d93d8a81Sdrh for(i=2; i<argc; i++){ 2074adee20fSdanielk1977 zResult = sqlite3MPrintf("%z%s%s", zResult, argv[1], argv[i]); 208d93d8a81Sdrh } 209d93d8a81Sdrh Tcl_AppendResult(interp, zResult, 0); 2105f968436Sdrh sqliteFree(zResult); 211d93d8a81Sdrh return TCL_OK; 212d93d8a81Sdrh } 213d93d8a81Sdrh 214d93d8a81Sdrh /* 2156f8a503dSdanielk1977 ** Usage: sqlite3_get_table_printf DB FORMAT STRING 216d1bf3512Sdrh ** 2176f8a503dSdanielk1977 ** Invoke the sqlite3_get_table_printf() interface using the open database 218d1bf3512Sdrh ** DB. The SQL is the string FORMAT. The format string should contain 219d1bf3512Sdrh ** one %s or %q. STRING is the value inserted into %s or %q. 220d1bf3512Sdrh */ 221d1bf3512Sdrh static int test_get_table_printf( 222d1bf3512Sdrh void *NotUsed, 223d1bf3512Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 224d1bf3512Sdrh int argc, /* Number of arguments */ 225d1bf3512Sdrh char **argv /* Text of each argument */ 226d1bf3512Sdrh ){ 2279bb575fdSdrh sqlite3 *db; 228d1bf3512Sdrh Tcl_DString str; 229d1bf3512Sdrh int rc; 230d1bf3512Sdrh char *zErr = 0; 231d1bf3512Sdrh int nRow, nCol; 232d1bf3512Sdrh char **aResult; 233d1bf3512Sdrh int i; 234d1bf3512Sdrh char zBuf[30]; 2351211de37Sdrh char *zSql; 236d1bf3512Sdrh if( argc!=4 ){ 237d1bf3512Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 238d1bf3512Sdrh " DB FORMAT STRING", 0); 239d1bf3512Sdrh return TCL_ERROR; 240d1bf3512Sdrh } 241b86ccfb2Sdrh if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; 242d1bf3512Sdrh Tcl_DStringInit(&str); 2431211de37Sdrh zSql = sqlite3_mprintf(argv[2],argv[3]); 2441211de37Sdrh rc = sqlite3_get_table(db, zSql, &aResult, &nRow, &nCol, &zErr); 2451211de37Sdrh sqlite3_free(zSql); 246d1bf3512Sdrh sprintf(zBuf, "%d", rc); 247d1bf3512Sdrh Tcl_AppendElement(interp, zBuf); 248d1bf3512Sdrh if( rc==SQLITE_OK ){ 249d1bf3512Sdrh sprintf(zBuf, "%d", nRow); 250d1bf3512Sdrh Tcl_AppendElement(interp, zBuf); 251d1bf3512Sdrh sprintf(zBuf, "%d", nCol); 252d1bf3512Sdrh Tcl_AppendElement(interp, zBuf); 253d1bf3512Sdrh for(i=0; i<(nRow+1)*nCol; i++){ 254d1bf3512Sdrh Tcl_AppendElement(interp, aResult[i] ? aResult[i] : "NULL"); 255d1bf3512Sdrh } 256d1bf3512Sdrh }else{ 257d1bf3512Sdrh Tcl_AppendElement(interp, zErr); 258d1bf3512Sdrh } 2596f8a503dSdanielk1977 sqlite3_free_table(aResult); 260d1bf3512Sdrh if( zErr ) free(zErr); 261c60d0446Sdrh if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; 262d1bf3512Sdrh return TCL_OK; 263d1bf3512Sdrh } 264d1bf3512Sdrh 265af9ff33aSdrh 266af9ff33aSdrh /* 2676f8a503dSdanielk1977 ** Usage: sqlite3_last_insert_rowid DB 268af9ff33aSdrh ** 269af9ff33aSdrh ** Returns the integer ROWID of the most recent insert. 270af9ff33aSdrh */ 271af9ff33aSdrh static int test_last_rowid( 272af9ff33aSdrh void *NotUsed, 273af9ff33aSdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 274af9ff33aSdrh int argc, /* Number of arguments */ 275af9ff33aSdrh char **argv /* Text of each argument */ 276af9ff33aSdrh ){ 2779bb575fdSdrh sqlite3 *db; 278af9ff33aSdrh char zBuf[30]; 279af9ff33aSdrh 280af9ff33aSdrh if( argc!=2 ){ 281af9ff33aSdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " DB\"", 0); 282af9ff33aSdrh return TCL_ERROR; 283af9ff33aSdrh } 284b86ccfb2Sdrh if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; 285c572ef7fSdanielk1977 sprintf(zBuf, "%lld", sqlite3_last_insert_rowid(db)); 286af9ff33aSdrh Tcl_AppendResult(interp, zBuf, 0); 287af9ff33aSdrh return SQLITE_OK; 288af9ff33aSdrh } 289af9ff33aSdrh 290d1bf3512Sdrh /* 29125d6543dSdrh ** Usage: sqlite3_key DB KEY 29225d6543dSdrh ** 29325d6543dSdrh ** Set the codec key. 29425d6543dSdrh */ 29525d6543dSdrh static int test_key( 29625d6543dSdrh void *NotUsed, 29725d6543dSdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 29825d6543dSdrh int argc, /* Number of arguments */ 29925d6543dSdrh char **argv /* Text of each argument */ 30025d6543dSdrh ){ 3019bb575fdSdrh sqlite3 *db; 30225d6543dSdrh const char *zKey; 30325d6543dSdrh int nKey; 30425d6543dSdrh if( argc!=3 ){ 30525d6543dSdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 30625d6543dSdrh " FILENAME\"", 0); 30725d6543dSdrh return TCL_ERROR; 30825d6543dSdrh } 30925d6543dSdrh if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; 31025d6543dSdrh zKey = argv[2]; 31125d6543dSdrh nKey = strlen(zKey); 31225d6543dSdrh #ifdef SQLITE_HAS_CODEC 31325d6543dSdrh sqlite3_key(db, zKey, nKey); 31425d6543dSdrh #endif 31525d6543dSdrh return TCL_OK; 31625d6543dSdrh } 31725d6543dSdrh 31825d6543dSdrh /* 31925d6543dSdrh ** Usage: sqlite3_rekey DB KEY 32025d6543dSdrh ** 32125d6543dSdrh ** Change the codec key. 32225d6543dSdrh */ 32325d6543dSdrh static int test_rekey( 32425d6543dSdrh void *NotUsed, 32525d6543dSdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 32625d6543dSdrh int argc, /* Number of arguments */ 32725d6543dSdrh char **argv /* Text of each argument */ 32825d6543dSdrh ){ 3299bb575fdSdrh sqlite3 *db; 33025d6543dSdrh const char *zKey; 33125d6543dSdrh int nKey; 33225d6543dSdrh if( argc!=3 ){ 33325d6543dSdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 33425d6543dSdrh " FILENAME\"", 0); 33525d6543dSdrh return TCL_ERROR; 33625d6543dSdrh } 33725d6543dSdrh if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; 33825d6543dSdrh zKey = argv[2]; 33925d6543dSdrh nKey = strlen(zKey); 34025d6543dSdrh #ifdef SQLITE_HAS_CODEC 34125d6543dSdrh sqlite3_rekey(db, zKey, nKey); 34225d6543dSdrh #endif 34325d6543dSdrh return TCL_OK; 34425d6543dSdrh } 34525d6543dSdrh 34625d6543dSdrh /* 3476f8a503dSdanielk1977 ** Usage: sqlite3_close DB 348d1bf3512Sdrh ** 3496f8a503dSdanielk1977 ** Closes the database opened by sqlite3_open. 350d1bf3512Sdrh */ 351d1bf3512Sdrh static int sqlite_test_close( 352d1bf3512Sdrh void *NotUsed, 353d1bf3512Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 354d1bf3512Sdrh int argc, /* Number of arguments */ 355d1bf3512Sdrh char **argv /* Text of each argument */ 356d1bf3512Sdrh ){ 3579bb575fdSdrh sqlite3 *db; 35896d81f99Sdanielk1977 int rc; 359d1bf3512Sdrh if( argc!=2 ){ 360d1bf3512Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 361d1bf3512Sdrh " FILENAME\"", 0); 362d1bf3512Sdrh return TCL_ERROR; 363d1bf3512Sdrh } 364b86ccfb2Sdrh if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; 36596d81f99Sdanielk1977 rc = sqlite3_close(db); 366f9d64d2cSdanielk1977 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC); 367d1bf3512Sdrh return TCL_OK; 368d1bf3512Sdrh } 369d1bf3512Sdrh 370d1bf3512Sdrh /* 371c22bd47dSdrh ** Implementation of the x_coalesce() function. 372c22bd47dSdrh ** Return the first argument non-NULL argument. 373c22bd47dSdrh */ 3740ae8b831Sdanielk1977 static void ifnullFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ 375c22bd47dSdrh int i; 376c22bd47dSdrh for(i=0; i<argc; i++){ 3779c054830Sdrh if( SQLITE_NULL!=sqlite3_value_type(argv[i]) ){ 378d8123366Sdanielk1977 sqlite3_result_text(context, sqlite3_value_text(argv[i]), -1, 379d8123366Sdanielk1977 SQLITE_TRANSIENT); 380c22bd47dSdrh break; 381c22bd47dSdrh } 382c22bd47dSdrh } 383c22bd47dSdrh } 384c22bd47dSdrh 385c22bd47dSdrh /* 386d1d9fc33Sdrh ** A structure into which to accumulate text. 387d1d9fc33Sdrh */ 388d1d9fc33Sdrh struct dstr { 389d1d9fc33Sdrh int nAlloc; /* Space allocated */ 390d1d9fc33Sdrh int nUsed; /* Space used */ 391d1d9fc33Sdrh char *z; /* The space */ 392d1d9fc33Sdrh }; 393d1d9fc33Sdrh 394d1d9fc33Sdrh /* 395d1d9fc33Sdrh ** Append text to a dstr 396d1d9fc33Sdrh */ 397d1d9fc33Sdrh static void dstrAppend(struct dstr *p, const char *z, int divider){ 398d1d9fc33Sdrh int n = strlen(z); 399d1d9fc33Sdrh if( p->nUsed + n + 2 > p->nAlloc ){ 400d1d9fc33Sdrh char *zNew; 401d1d9fc33Sdrh p->nAlloc = p->nAlloc*2 + n + 200; 402d1d9fc33Sdrh zNew = sqliteRealloc(p->z, p->nAlloc); 403d1d9fc33Sdrh if( zNew==0 ){ 404d1d9fc33Sdrh sqliteFree(p->z); 405d1d9fc33Sdrh memset(p, 0, sizeof(*p)); 406d1d9fc33Sdrh return; 407d1d9fc33Sdrh } 408d1d9fc33Sdrh p->z = zNew; 409d1d9fc33Sdrh } 410d1d9fc33Sdrh if( divider && p->nUsed>0 ){ 411d1d9fc33Sdrh p->z[p->nUsed++] = divider; 412d1d9fc33Sdrh } 413d1d9fc33Sdrh memcpy(&p->z[p->nUsed], z, n+1); 414d1d9fc33Sdrh p->nUsed += n; 415d1d9fc33Sdrh } 416d1d9fc33Sdrh 417d1d9fc33Sdrh /* 4184adee20fSdanielk1977 ** Invoked for each callback from sqlite3ExecFunc 419d1d9fc33Sdrh */ 420d1d9fc33Sdrh static int execFuncCallback(void *pData, int argc, char **argv, char **NotUsed){ 421d1d9fc33Sdrh struct dstr *p = (struct dstr*)pData; 422d1d9fc33Sdrh int i; 423d1d9fc33Sdrh for(i=0; i<argc; i++){ 424d1d9fc33Sdrh if( argv[i]==0 ){ 425d1d9fc33Sdrh dstrAppend(p, "NULL", ' '); 426d1d9fc33Sdrh }else{ 427d1d9fc33Sdrh dstrAppend(p, argv[i], ' '); 428d1d9fc33Sdrh } 429d1d9fc33Sdrh } 430d1d9fc33Sdrh return 0; 431d1d9fc33Sdrh } 432d1d9fc33Sdrh 433d1d9fc33Sdrh /* 434e35ee196Sdanielk1977 ** Implementation of the x_sqlite_exec() function. This function takes 435c22bd47dSdrh ** a single argument and attempts to execute that argument as SQL code. 4366cbe1f1bSdrh ** This is illegal and should set the SQLITE_MISUSE flag on the database. 437c22bd47dSdrh ** 4386f8a503dSdanielk1977 ** 2004-Jan-07: We have changed this to make it legal to call sqlite3_exec() 439d1d9fc33Sdrh ** from within a function call. 440d1d9fc33Sdrh ** 441c22bd47dSdrh ** This routine simulates the effect of having two threads attempt to 442c22bd47dSdrh ** use the same database at the same time. 443c22bd47dSdrh */ 44451ad0ecdSdanielk1977 static void sqlite3ExecFunc( 4450ae8b831Sdanielk1977 sqlite3_context *context, 44651ad0ecdSdanielk1977 int argc, 44751ad0ecdSdanielk1977 sqlite3_value **argv 44851ad0ecdSdanielk1977 ){ 449d1d9fc33Sdrh struct dstr x; 450d1d9fc33Sdrh memset(&x, 0, sizeof(x)); 4519bb575fdSdrh sqlite3_exec((sqlite3*)sqlite3_user_data(context), 4524f26d6c4Sdrh sqlite3_value_text(argv[0]), 453d1d9fc33Sdrh execFuncCallback, &x, 0); 454d8123366Sdanielk1977 sqlite3_result_text(context, x.z, x.nUsed, SQLITE_TRANSIENT); 455d1d9fc33Sdrh sqliteFree(x.z); 456c22bd47dSdrh } 457c22bd47dSdrh 458c22bd47dSdrh /* 459c22bd47dSdrh ** Usage: sqlite_test_create_function DB 460c22bd47dSdrh ** 4616f8a503dSdanielk1977 ** Call the sqlite3_create_function API on the given database in order 462c22bd47dSdrh ** to create a function named "x_coalesce". This function does the same thing 463c22bd47dSdrh ** as the "coalesce" function. This function also registers an SQL function 464e35ee196Sdanielk1977 ** named "x_sqlite_exec" that invokes sqlite3_exec(). Invoking sqlite3_exec() 465c22bd47dSdrh ** in this way is illegal recursion and should raise an SQLITE_MISUSE error. 466c22bd47dSdrh ** The effect is similar to trying to use the same database connection from 467c22bd47dSdrh ** two threads at the same time. 468c22bd47dSdrh ** 469c22bd47dSdrh ** The original motivation for this routine was to be able to call the 4706f8a503dSdanielk1977 ** sqlite3_create_function function while a query is in progress in order 471c22bd47dSdrh ** to test the SQLITE_MISUSE detection logic. 472c22bd47dSdrh */ 473c2eef3b3Sdrh static int test_create_function( 474c22bd47dSdrh void *NotUsed, 475c22bd47dSdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 476c22bd47dSdrh int argc, /* Number of arguments */ 477c22bd47dSdrh char **argv /* Text of each argument */ 478c22bd47dSdrh ){ 479c60d0446Sdrh int rc; 4809bb575fdSdrh sqlite3 *db; 481312d6b36Sdanielk1977 sqlite3_value *pVal; 4829bb575fdSdrh extern void Md5_Register(sqlite3*); 483312d6b36Sdanielk1977 484c22bd47dSdrh if( argc!=2 ){ 485c22bd47dSdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 486c22bd47dSdrh " FILENAME\"", 0); 487c22bd47dSdrh return TCL_ERROR; 488c22bd47dSdrh } 489b86ccfb2Sdrh if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; 490c60d0446Sdrh rc = sqlite3_create_function(db, "x_coalesce", -1, SQLITE_ANY, 0, 491d8123366Sdanielk1977 ifnullFunc, 0, 0); 492312d6b36Sdanielk1977 493312d6b36Sdanielk1977 /* Use the sqlite3_create_function16() API here. Mainly for fun, but also 494312d6b36Sdanielk1977 ** because it is not tested anywhere else. */ 495c60d0446Sdrh if( rc==SQLITE_OK ){ 496312d6b36Sdanielk1977 pVal = sqlite3ValueNew(); 497312d6b36Sdanielk1977 sqlite3ValueSetStr(pVal, -1, "x_sqlite_exec", SQLITE_UTF8, SQLITE_STATIC); 498c60d0446Sdrh rc = sqlite3_create_function16(db, 499c60d0446Sdrh sqlite3ValueText(pVal, SQLITE_UTF16NATIVE), 500312d6b36Sdanielk1977 1, SQLITE_UTF16, db, sqlite3ExecFunc, 0, 0); 501312d6b36Sdanielk1977 sqlite3ValueFree(pVal); 502c60d0446Sdrh } 503c60d0446Sdrh if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; 504c22bd47dSdrh return TCL_OK; 505c22bd47dSdrh } 506c22bd47dSdrh 507c22bd47dSdrh /* 508c22bd47dSdrh ** Routines to implement the x_count() aggregate function. 509c22bd47dSdrh */ 510c22bd47dSdrh typedef struct CountCtx CountCtx; 511c22bd47dSdrh struct CountCtx { 512c22bd47dSdrh int n; 513c22bd47dSdrh }; 5140ae8b831Sdanielk1977 static void countStep(sqlite3_context *context, int argc, sqlite3_value **argv){ 515c22bd47dSdrh CountCtx *p; 5164f26d6c4Sdrh p = sqlite3_aggregate_context(context, sizeof(*p)); 5179c054830Sdrh if( (argc==0 || SQLITE_NULL!=sqlite3_value_type(argv[0]) ) && p ){ 518c22bd47dSdrh p->n++; 519c22bd47dSdrh } 520c22bd47dSdrh } 5210ae8b831Sdanielk1977 static void countFinalize(sqlite3_context *context){ 522c22bd47dSdrh CountCtx *p; 5234f26d6c4Sdrh p = sqlite3_aggregate_context(context, sizeof(*p)); 524c572ef7fSdanielk1977 sqlite3_result_int(context, p ? p->n : 0); 525c22bd47dSdrh } 526c22bd47dSdrh 527c22bd47dSdrh /* 528c22bd47dSdrh ** Usage: sqlite_test_create_aggregate DB 529c22bd47dSdrh ** 5306f8a503dSdanielk1977 ** Call the sqlite3_create_function API on the given database in order 531c22bd47dSdrh ** to create a function named "x_count". This function does the same thing 532c22bd47dSdrh ** as the "md5sum" function. 533c22bd47dSdrh ** 534c22bd47dSdrh ** The original motivation for this routine was to be able to call the 5356f8a503dSdanielk1977 ** sqlite3_create_aggregate function while a query is in progress in order 536c22bd47dSdrh ** to test the SQLITE_MISUSE detection logic. 537c22bd47dSdrh */ 538c2eef3b3Sdrh static int test_create_aggregate( 539c22bd47dSdrh void *NotUsed, 540c22bd47dSdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 541c22bd47dSdrh int argc, /* Number of arguments */ 542c22bd47dSdrh char **argv /* Text of each argument */ 543c22bd47dSdrh ){ 5449bb575fdSdrh sqlite3 *db; 545c60d0446Sdrh int rc; 546c22bd47dSdrh if( argc!=2 ){ 547c22bd47dSdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 548c22bd47dSdrh " FILENAME\"", 0); 549c22bd47dSdrh return TCL_ERROR; 550c22bd47dSdrh } 551b86ccfb2Sdrh if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; 552c60d0446Sdrh rc = sqlite3_create_function(db, "x_count", 0, SQLITE_UTF8, 0, 0, 553d8123366Sdanielk1977 countStep,countFinalize); 554c60d0446Sdrh if( rc==SQLITE_OK ){ 555f9d64d2cSdanielk1977 sqlite3_create_function(db, "x_count", 1, SQLITE_UTF8, 0, 0, 556d8123366Sdanielk1977 countStep,countFinalize); 557c60d0446Sdrh } 558c60d0446Sdrh if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; 559c22bd47dSdrh return TCL_OK; 560c22bd47dSdrh } 561c22bd47dSdrh 562c22bd47dSdrh 563c22bd47dSdrh 564c22bd47dSdrh /* 5656f8a503dSdanielk1977 ** Usage: sqlite3_mprintf_int FORMAT INTEGER INTEGER INTEGER 566d1bf3512Sdrh ** 567d1bf3512Sdrh ** Call mprintf with three integer arguments 568d1bf3512Sdrh */ 5696f8a503dSdanielk1977 static int sqlite3_mprintf_int( 570d1bf3512Sdrh void *NotUsed, 571d1bf3512Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 572d1bf3512Sdrh int argc, /* Number of arguments */ 573d1bf3512Sdrh char **argv /* Text of each argument */ 574d1bf3512Sdrh ){ 575d1bf3512Sdrh int a[3], i; 576d1bf3512Sdrh char *z; 577d1bf3512Sdrh if( argc!=5 ){ 578d1bf3512Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 579d1bf3512Sdrh " FORMAT INT INT INT\"", 0); 580d1bf3512Sdrh return TCL_ERROR; 581d1bf3512Sdrh } 582d1bf3512Sdrh for(i=2; i<5; i++){ 583d1bf3512Sdrh if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR; 584d1bf3512Sdrh } 5856f8a503dSdanielk1977 z = sqlite3_mprintf(argv[1], a[0], a[1], a[2]); 586d1bf3512Sdrh Tcl_AppendResult(interp, z, 0); 5873f4fedb2Sdrh sqlite3_free(z); 588d1bf3512Sdrh return TCL_OK; 589d1bf3512Sdrh } 590d1bf3512Sdrh 591d1bf3512Sdrh /* 5929d213ef0Sdrh ** If zNum represents an integer that will fit in 64-bits, then set 5939d213ef0Sdrh ** *pValue to that integer and return true. Otherwise return false. 5949d213ef0Sdrh */ 5959d213ef0Sdrh static int sqlite3GetInt64(const char *zNum, i64 *pValue){ 5969d213ef0Sdrh if( sqlite3FitsIn64Bits(zNum) ){ 5979d213ef0Sdrh sqlite3atoi64(zNum, pValue); 5989d213ef0Sdrh return 1; 5999d213ef0Sdrh } 6009d213ef0Sdrh return 0; 6019d213ef0Sdrh } 6029d213ef0Sdrh 6039d213ef0Sdrh /* 604e9707671Sdrh ** Usage: sqlite3_mprintf_int64 FORMAT INTEGER INTEGER INTEGER 605e9707671Sdrh ** 606e9707671Sdrh ** Call mprintf with three 64-bit integer arguments 607e9707671Sdrh */ 608e9707671Sdrh static int sqlite3_mprintf_int64( 609e9707671Sdrh void *NotUsed, 610e9707671Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 611e9707671Sdrh int argc, /* Number of arguments */ 612e9707671Sdrh char **argv /* Text of each argument */ 613e9707671Sdrh ){ 614e9707671Sdrh int i; 615e9707671Sdrh sqlite_int64 a[3]; 616e9707671Sdrh char *z; 617e9707671Sdrh if( argc!=5 ){ 618e9707671Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 619e9707671Sdrh " FORMAT INT INT INT\"", 0); 620e9707671Sdrh return TCL_ERROR; 621e9707671Sdrh } 622e9707671Sdrh for(i=2; i<5; i++){ 623e9707671Sdrh if( !sqlite3GetInt64(argv[i], &a[i-2]) ){ 624e9707671Sdrh Tcl_AppendResult(interp, "argument is not a valid 64-bit integer", 0); 625e9707671Sdrh return TCL_ERROR; 626e9707671Sdrh } 627e9707671Sdrh } 628e9707671Sdrh z = sqlite3_mprintf(argv[1], a[0], a[1], a[2]); 629e9707671Sdrh Tcl_AppendResult(interp, z, 0); 630e9707671Sdrh sqlite3_free(z); 631e9707671Sdrh return TCL_OK; 632e9707671Sdrh } 633e9707671Sdrh 634e9707671Sdrh /* 6356f8a503dSdanielk1977 ** Usage: sqlite3_mprintf_str FORMAT INTEGER INTEGER STRING 636d1bf3512Sdrh ** 637d1bf3512Sdrh ** Call mprintf with two integer arguments and one string argument 638d1bf3512Sdrh */ 6396f8a503dSdanielk1977 static int sqlite3_mprintf_str( 640d1bf3512Sdrh void *NotUsed, 641d1bf3512Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 642d1bf3512Sdrh int argc, /* Number of arguments */ 643d1bf3512Sdrh char **argv /* Text of each argument */ 644d1bf3512Sdrh ){ 645d1bf3512Sdrh int a[3], i; 646d1bf3512Sdrh char *z; 647f220b24fSchw if( argc<4 || argc>5 ){ 648d1bf3512Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 649f220b24fSchw " FORMAT INT INT ?STRING?\"", 0); 650d1bf3512Sdrh return TCL_ERROR; 651d1bf3512Sdrh } 652d1bf3512Sdrh for(i=2; i<4; i++){ 653d1bf3512Sdrh if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR; 654d1bf3512Sdrh } 6556f8a503dSdanielk1977 z = sqlite3_mprintf(argv[1], a[0], a[1], argc>4 ? argv[4] : NULL); 656d1bf3512Sdrh Tcl_AppendResult(interp, z, 0); 6573f4fedb2Sdrh sqlite3_free(z); 658d1bf3512Sdrh return TCL_OK; 659d1bf3512Sdrh } 660d1bf3512Sdrh 661d1bf3512Sdrh /* 6626f8a503dSdanielk1977 ** Usage: sqlite3_mprintf_str FORMAT INTEGER INTEGER DOUBLE 663d1bf3512Sdrh ** 664d1bf3512Sdrh ** Call mprintf with two integer arguments and one double argument 665d1bf3512Sdrh */ 6666f8a503dSdanielk1977 static int sqlite3_mprintf_double( 667d1bf3512Sdrh void *NotUsed, 668d1bf3512Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 669d1bf3512Sdrh int argc, /* Number of arguments */ 670d1bf3512Sdrh char **argv /* Text of each argument */ 671d1bf3512Sdrh ){ 672d1bf3512Sdrh int a[3], i; 673d1bf3512Sdrh double r; 674d1bf3512Sdrh char *z; 675d1bf3512Sdrh if( argc!=5 ){ 676d1bf3512Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 677d1bf3512Sdrh " FORMAT INT INT STRING\"", 0); 678d1bf3512Sdrh return TCL_ERROR; 679d1bf3512Sdrh } 680d1bf3512Sdrh for(i=2; i<4; i++){ 681d1bf3512Sdrh if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR; 682d1bf3512Sdrh } 683d1bf3512Sdrh if( Tcl_GetDouble(interp, argv[4], &r) ) return TCL_ERROR; 6846f8a503dSdanielk1977 z = sqlite3_mprintf(argv[1], a[0], a[1], r); 685d1bf3512Sdrh Tcl_AppendResult(interp, z, 0); 6863f4fedb2Sdrh sqlite3_free(z); 687d1bf3512Sdrh return TCL_OK; 688d1bf3512Sdrh } 689d1bf3512Sdrh 690d1bf3512Sdrh /* 6916f8a503dSdanielk1977 ** Usage: sqlite3_mprintf_str FORMAT DOUBLE DOUBLE 692b621c237Sdrh ** 693b621c237Sdrh ** Call mprintf with a single double argument which is the product of the 694b621c237Sdrh ** two arguments given above. This is used to generate overflow and underflow 695b621c237Sdrh ** doubles to test that they are converted properly. 696b621c237Sdrh */ 6976f8a503dSdanielk1977 static int sqlite3_mprintf_scaled( 698b621c237Sdrh void *NotUsed, 699b621c237Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 700b621c237Sdrh int argc, /* Number of arguments */ 701b621c237Sdrh char **argv /* Text of each argument */ 702b621c237Sdrh ){ 703b621c237Sdrh int i; 704b621c237Sdrh double r[2]; 705b621c237Sdrh char *z; 706b621c237Sdrh if( argc!=4 ){ 707b621c237Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 708b621c237Sdrh " FORMAT DOUBLE DOUBLE\"", 0); 709b621c237Sdrh return TCL_ERROR; 710b621c237Sdrh } 711b621c237Sdrh for(i=2; i<4; i++){ 712b621c237Sdrh if( Tcl_GetDouble(interp, argv[i], &r[i-2]) ) return TCL_ERROR; 713b621c237Sdrh } 7146f8a503dSdanielk1977 z = sqlite3_mprintf(argv[1], r[0]*r[1]); 715b621c237Sdrh Tcl_AppendResult(interp, z, 0); 7163f4fedb2Sdrh sqlite3_free(z); 717b621c237Sdrh return TCL_OK; 718b621c237Sdrh } 719b621c237Sdrh 720b621c237Sdrh /* 721e29b1a05Sdrh ** Usage: sqlite3_mprintf_stronly FORMAT STRING 722e29b1a05Sdrh ** 723e29b1a05Sdrh ** Call mprintf with a single double argument which is the product of the 724e29b1a05Sdrh ** two arguments given above. This is used to generate overflow and underflow 725e29b1a05Sdrh ** doubles to test that they are converted properly. 726e29b1a05Sdrh */ 727e29b1a05Sdrh static int sqlite3_mprintf_stronly( 728e29b1a05Sdrh void *NotUsed, 729e29b1a05Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 730e29b1a05Sdrh int argc, /* Number of arguments */ 731e29b1a05Sdrh char **argv /* Text of each argument */ 732e29b1a05Sdrh ){ 733e29b1a05Sdrh char *z; 734e29b1a05Sdrh if( argc!=3 ){ 735e29b1a05Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 736e29b1a05Sdrh " FORMAT STRING\"", 0); 737e29b1a05Sdrh return TCL_ERROR; 738e29b1a05Sdrh } 739e29b1a05Sdrh z = sqlite3_mprintf(argv[1], argv[2]); 740e29b1a05Sdrh Tcl_AppendResult(interp, z, 0); 741e29b1a05Sdrh sqlite3_free(z); 742e29b1a05Sdrh return TCL_OK; 743e29b1a05Sdrh } 744e29b1a05Sdrh 745e29b1a05Sdrh /* 746daffd0e5Sdrh ** Usage: sqlite_malloc_fail N 747daffd0e5Sdrh ** 748afa4a020Sdrh ** Rig sqliteMalloc() to fail on the N-th call. Turn off this mechanism 7496f8a503dSdanielk1977 ** and reset the sqlite3_malloc_failed variable is N==0. 750daffd0e5Sdrh */ 751faa57accSdrh #ifdef SQLITE_DEBUG 752daffd0e5Sdrh static int sqlite_malloc_fail( 753daffd0e5Sdrh void *NotUsed, 754daffd0e5Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 755daffd0e5Sdrh int argc, /* Number of arguments */ 756daffd0e5Sdrh char **argv /* Text of each argument */ 757daffd0e5Sdrh ){ 758daffd0e5Sdrh int n; 759daffd0e5Sdrh if( argc!=2 ){ 760daffd0e5Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " N\"", 0); 761daffd0e5Sdrh return TCL_ERROR; 762daffd0e5Sdrh } 763daffd0e5Sdrh if( Tcl_GetInt(interp, argv[1], &n) ) return TCL_ERROR; 7646f8a503dSdanielk1977 sqlite3_iMallocFail = n; 7656f8a503dSdanielk1977 sqlite3_malloc_failed = 0; 766daffd0e5Sdrh return TCL_OK; 767daffd0e5Sdrh } 768daffd0e5Sdrh #endif 769daffd0e5Sdrh 770daffd0e5Sdrh /* 771daffd0e5Sdrh ** Usage: sqlite_malloc_stat 772daffd0e5Sdrh ** 773daffd0e5Sdrh ** Return the number of prior calls to sqliteMalloc() and sqliteFree(). 774daffd0e5Sdrh */ 775faa57accSdrh #ifdef SQLITE_DEBUG 776daffd0e5Sdrh static int sqlite_malloc_stat( 777daffd0e5Sdrh void *NotUsed, 778daffd0e5Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 779daffd0e5Sdrh int argc, /* Number of arguments */ 780daffd0e5Sdrh char **argv /* Text of each argument */ 781daffd0e5Sdrh ){ 782daffd0e5Sdrh char zBuf[200]; 7836f8a503dSdanielk1977 sprintf(zBuf, "%d %d %d", sqlite3_nMalloc, sqlite3_nFree, sqlite3_iMallocFail); 784daffd0e5Sdrh Tcl_AppendResult(interp, zBuf, 0); 785daffd0e5Sdrh return TCL_OK; 786daffd0e5Sdrh } 787daffd0e5Sdrh #endif 788daffd0e5Sdrh 789daffd0e5Sdrh /* 79028b4e489Sdrh ** Usage: sqlite_abort 79128b4e489Sdrh ** 79228b4e489Sdrh ** Shutdown the process immediately. This is not a clean shutdown. 79328b4e489Sdrh ** This command is used to test the recoverability of a database in 79428b4e489Sdrh ** the event of a program crash. 79528b4e489Sdrh */ 79628b4e489Sdrh static int sqlite_abort( 79728b4e489Sdrh void *NotUsed, 79828b4e489Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 79928b4e489Sdrh int argc, /* Number of arguments */ 80028b4e489Sdrh char **argv /* Text of each argument */ 80128b4e489Sdrh ){ 80228b4e489Sdrh assert( interp==0 ); /* This will always fail */ 80328b4e489Sdrh return TCL_OK; 80428b4e489Sdrh } 80528b4e489Sdrh 80628b4e489Sdrh /* 8076cbe1f1bSdrh ** The following routine is a user-defined SQL function whose purpose 8086cbe1f1bSdrh ** is to test the sqlite_set_result() API. 8096cbe1f1bSdrh */ 8100ae8b831Sdanielk1977 static void testFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ 8116cbe1f1bSdrh while( argc>=2 ){ 8124f26d6c4Sdrh const char *zArg0 = sqlite3_value_text(argv[0]); 8136d88bad4Sdanielk1977 if( zArg0 ){ 8146d88bad4Sdanielk1977 if( 0==sqlite3StrICmp(zArg0, "int") ){ 8156d88bad4Sdanielk1977 sqlite3_result_int(context, sqlite3_value_int(argv[1])); 8166d88bad4Sdanielk1977 }else if( sqlite3StrICmp(zArg0,"int64")==0 ){ 8176d88bad4Sdanielk1977 sqlite3_result_int64(context, sqlite3_value_int64(argv[1])); 81851ad0ecdSdanielk1977 }else if( sqlite3StrICmp(zArg0,"string")==0 ){ 819d8123366Sdanielk1977 sqlite3_result_text(context, sqlite3_value_text(argv[1]), -1, 820d8123366Sdanielk1977 SQLITE_TRANSIENT); 82151ad0ecdSdanielk1977 }else if( sqlite3StrICmp(zArg0,"double")==0 ){ 8226d88bad4Sdanielk1977 sqlite3_result_double(context, sqlite3_value_double(argv[1])); 8236d88bad4Sdanielk1977 }else if( sqlite3StrICmp(zArg0,"null")==0 ){ 8246d88bad4Sdanielk1977 sqlite3_result_null(context); 8256d88bad4Sdanielk1977 }else if( sqlite3StrICmp(zArg0,"value")==0 ){ 8266d88bad4Sdanielk1977 sqlite3_result_value(context, argv[sqlite3_value_int(argv[1])]); 8276cbe1f1bSdrh }else{ 8286d88bad4Sdanielk1977 goto error_out; 8296d88bad4Sdanielk1977 } 8306d88bad4Sdanielk1977 }else{ 8316d88bad4Sdanielk1977 goto error_out; 8326cbe1f1bSdrh } 8336cbe1f1bSdrh argc -= 2; 8346cbe1f1bSdrh argv += 2; 8356cbe1f1bSdrh } 8366d88bad4Sdanielk1977 return; 8376d88bad4Sdanielk1977 8386d88bad4Sdanielk1977 error_out: 8396d88bad4Sdanielk1977 sqlite3_result_error(context,"first argument should be one of: " 8406d88bad4Sdanielk1977 "int int64 string double null value", -1); 8416cbe1f1bSdrh } 8426cbe1f1bSdrh 8436cbe1f1bSdrh /* 8446cbe1f1bSdrh ** Usage: sqlite_register_test_function DB NAME 8456cbe1f1bSdrh ** 8466cbe1f1bSdrh ** Register the test SQL function on the database DB under the name NAME. 8476cbe1f1bSdrh */ 848c2eef3b3Sdrh static int test_register_func( 8496cbe1f1bSdrh void *NotUsed, 8506cbe1f1bSdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 8516cbe1f1bSdrh int argc, /* Number of arguments */ 8526cbe1f1bSdrh char **argv /* Text of each argument */ 8536cbe1f1bSdrh ){ 8549bb575fdSdrh sqlite3 *db; 8556cbe1f1bSdrh int rc; 8566cbe1f1bSdrh if( argc!=3 ){ 8576cbe1f1bSdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 8586cbe1f1bSdrh " DB FUNCTION-NAME", 0); 8596cbe1f1bSdrh return TCL_ERROR; 8606cbe1f1bSdrh } 861b86ccfb2Sdrh if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; 862f9d64d2cSdanielk1977 rc = sqlite3_create_function(db, argv[2], -1, SQLITE_UTF8, 0, 863d8123366Sdanielk1977 testFunc, 0, 0); 8646cbe1f1bSdrh if( rc!=0 ){ 865f20b21c8Sdanielk1977 Tcl_AppendResult(interp, sqlite3ErrStr(rc), 0); 8666cbe1f1bSdrh return TCL_ERROR; 8676cbe1f1bSdrh } 868c60d0446Sdrh if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; 8696cbe1f1bSdrh return TCL_OK; 8706cbe1f1bSdrh } 8716cbe1f1bSdrh 8726cbe1f1bSdrh /* 873106bb236Sdanielk1977 ** Usage: sqlite3_finalize STMT 874b86ccfb2Sdrh ** 875106bb236Sdanielk1977 ** Finalize a statement handle. 876b86ccfb2Sdrh */ 877b86ccfb2Sdrh static int test_finalize( 878106bb236Sdanielk1977 void * clientData, 879106bb236Sdanielk1977 Tcl_Interp *interp, 880106bb236Sdanielk1977 int objc, 881106bb236Sdanielk1977 Tcl_Obj *CONST objv[] 882b86ccfb2Sdrh ){ 883106bb236Sdanielk1977 sqlite3_stmt *pStmt; 884b86ccfb2Sdrh int rc; 885c60d0446Sdrh sqlite3 *db; 886106bb236Sdanielk1977 887106bb236Sdanielk1977 if( objc!=2 ){ 888106bb236Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 889106bb236Sdanielk1977 Tcl_GetStringFromObj(objv[0], 0), " <STMT>", 0); 890b86ccfb2Sdrh return TCL_ERROR; 891b86ccfb2Sdrh } 892106bb236Sdanielk1977 893106bb236Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 894106bb236Sdanielk1977 895c60d0446Sdrh db = StmtToDb(pStmt); 896fc57d7bfSdanielk1977 rc = sqlite3_finalize(pStmt); 897b77f5dadSdanielk1977 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC); 898c60d0446Sdrh if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; 899106bb236Sdanielk1977 return TCL_OK; 900106bb236Sdanielk1977 } 901106bb236Sdanielk1977 902106bb236Sdanielk1977 /* 903106bb236Sdanielk1977 ** Usage: sqlite3_reset STMT 904106bb236Sdanielk1977 ** 905106bb236Sdanielk1977 ** Finalize a statement handle. 906106bb236Sdanielk1977 */ 907106bb236Sdanielk1977 static int test_reset( 908106bb236Sdanielk1977 void * clientData, 909106bb236Sdanielk1977 Tcl_Interp *interp, 910106bb236Sdanielk1977 int objc, 911106bb236Sdanielk1977 Tcl_Obj *CONST objv[] 912106bb236Sdanielk1977 ){ 913106bb236Sdanielk1977 sqlite3_stmt *pStmt; 914106bb236Sdanielk1977 int rc; 915106bb236Sdanielk1977 916106bb236Sdanielk1977 if( objc!=2 ){ 917106bb236Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 918106bb236Sdanielk1977 Tcl_GetStringFromObj(objv[0], 0), " <STMT>", 0); 919106bb236Sdanielk1977 return TCL_ERROR; 920106bb236Sdanielk1977 } 921106bb236Sdanielk1977 922106bb236Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 923106bb236Sdanielk1977 924fc57d7bfSdanielk1977 rc = sqlite3_reset(pStmt); 925c60d0446Sdrh if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR; 926106bb236Sdanielk1977 if( rc ){ 927b86ccfb2Sdrh return TCL_ERROR; 928b86ccfb2Sdrh } 929b86ccfb2Sdrh return TCL_OK; 930b86ccfb2Sdrh } 931b86ccfb2Sdrh 9325a38705eSdrh /* 933fbcd585fSdanielk1977 ** Usage: sqlite3_changes DB 93450457896Sdrh ** 935fbcd585fSdanielk1977 ** Return the number of changes made to the database by the last SQL 936fbcd585fSdanielk1977 ** execution. 93750457896Sdrh */ 938fbcd585fSdanielk1977 static int test_changes( 939fbcd585fSdanielk1977 void * clientData, 940fbcd585fSdanielk1977 Tcl_Interp *interp, 941fbcd585fSdanielk1977 int objc, 942fbcd585fSdanielk1977 Tcl_Obj *CONST objv[] 943fbcd585fSdanielk1977 ){ 944fbcd585fSdanielk1977 sqlite3 *db; 945fbcd585fSdanielk1977 if( objc!=2 ){ 946fbcd585fSdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 947fbcd585fSdanielk1977 Tcl_GetString(objv[0]), " DB", 0); 948fbcd585fSdanielk1977 return TCL_ERROR; 949fbcd585fSdanielk1977 } 950fbcd585fSdanielk1977 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 951fbcd585fSdanielk1977 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_changes(db))); 952fbcd585fSdanielk1977 return TCL_OK; 953fbcd585fSdanielk1977 } 95450457896Sdrh 95550457896Sdrh /* 9567c972decSdrh ** This is the "static_bind_value" that variables are bound to when 9576f8a503dSdanielk1977 ** the FLAG option of sqlite3_bind is "static" 95850457896Sdrh */ 9597c972decSdrh static char *sqlite_static_bind_value = 0; 9607c972decSdrh 9617c972decSdrh /* 9626f8a503dSdanielk1977 ** Usage: sqlite3_bind VM IDX VALUE FLAGS 9637c972decSdrh ** 9647c972decSdrh ** Sets the value of the IDX-th occurance of "?" in the original SQL 9657c972decSdrh ** string. VALUE is the new value. If FLAGS=="null" then VALUE is 9667c972decSdrh ** ignored and the value is set to NULL. If FLAGS=="static" then 9677c972decSdrh ** the value is set to the value of a static variable named 9687c972decSdrh ** "sqlite_static_bind_value". If FLAGS=="normal" then a copy 9697c972decSdrh ** of the VALUE is made. 9707c972decSdrh */ 9717c972decSdrh static int test_bind( 97250457896Sdrh void *NotUsed, 97350457896Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 97450457896Sdrh int argc, /* Number of arguments */ 97550457896Sdrh char **argv /* Text of each argument */ 97650457896Sdrh ){ 977fc57d7bfSdanielk1977 sqlite3_stmt *pStmt; 97850457896Sdrh int rc; 9797c972decSdrh int idx; 9807c972decSdrh if( argc!=5 ){ 98150457896Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 9827c972decSdrh " VM IDX VALUE (null|static|normal)\"", 0); 98350457896Sdrh return TCL_ERROR; 98450457896Sdrh } 985fc57d7bfSdanielk1977 if( getStmtPointer(interp, argv[1], &pStmt) ) return TCL_ERROR; 9867c972decSdrh if( Tcl_GetInt(interp, argv[2], &idx) ) return TCL_ERROR; 9877c972decSdrh if( strcmp(argv[4],"null")==0 ){ 988fc57d7bfSdanielk1977 rc = sqlite3_bind_null(pStmt, idx); 9897c972decSdrh }else if( strcmp(argv[4],"static")==0 ){ 990fc57d7bfSdanielk1977 rc = sqlite3_bind_text(pStmt, idx, sqlite_static_bind_value, -1, 0); 9917c972decSdrh }else if( strcmp(argv[4],"normal")==0 ){ 992d8123366Sdanielk1977 rc = sqlite3_bind_text(pStmt, idx, argv[3], -1, SQLITE_TRANSIENT); 9937c972decSdrh }else{ 9947c972decSdrh Tcl_AppendResult(interp, "4th argument should be " 9957c972decSdrh "\"null\" or \"static\" or \"normal\"", 0); 9967c972decSdrh return TCL_ERROR; 9977c972decSdrh } 998c60d0446Sdrh if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR; 99950457896Sdrh if( rc ){ 100050457896Sdrh char zBuf[50]; 100150457896Sdrh sprintf(zBuf, "(%d) ", rc); 1002f20b21c8Sdanielk1977 Tcl_AppendResult(interp, zBuf, sqlite3ErrStr(rc), 0); 100350457896Sdrh return TCL_ERROR; 100450457896Sdrh } 100550457896Sdrh return TCL_OK; 100650457896Sdrh } 100750457896Sdrh 10084e6af134Sdanielk1977 10094e6af134Sdanielk1977 /* 10104e6af134Sdanielk1977 ** Usage: add_test_collate <db ptr> <utf8> <utf16le> <utf16be> 10114e6af134Sdanielk1977 ** 10124e6af134Sdanielk1977 ** This function is used to test that SQLite selects the correct collation 10134e6af134Sdanielk1977 ** sequence callback when multiple versions (for different text encodings) 10144e6af134Sdanielk1977 ** are available. 10154e6af134Sdanielk1977 ** 10164e6af134Sdanielk1977 ** Calling this routine registers the collation sequence "test_collate" 10174e6af134Sdanielk1977 ** with database handle <db>. The second argument must be a list of three 10184e6af134Sdanielk1977 ** boolean values. If the first is true, then a version of test_collate is 10194e6af134Sdanielk1977 ** registered for UTF-8, if the second is true, a version is registered for 10204e6af134Sdanielk1977 ** UTF-16le, if the third is true, a UTF-16be version is available. 10214e6af134Sdanielk1977 ** Previous versions of test_collate are deleted. 10224e6af134Sdanielk1977 ** 10234e6af134Sdanielk1977 ** The collation sequence test_collate is implemented by calling the 10244e6af134Sdanielk1977 ** following TCL script: 10254e6af134Sdanielk1977 ** 10264e6af134Sdanielk1977 ** "test_collate <enc> <lhs> <rhs>" 10274e6af134Sdanielk1977 ** 10284e6af134Sdanielk1977 ** The <lhs> and <rhs> are the two values being compared, encoded in UTF-8. 10294e6af134Sdanielk1977 ** The <enc> parameter is the encoding of the collation function that 10304e6af134Sdanielk1977 ** SQLite selected to call. The TCL test script implements the 10314e6af134Sdanielk1977 ** "test_collate" proc. 10324e6af134Sdanielk1977 ** 10334e6af134Sdanielk1977 ** Note that this will only work with one intepreter at a time, as the 10344e6af134Sdanielk1977 ** interp pointer to use when evaluating the TCL script is stored in 10354e6af134Sdanielk1977 ** pTestCollateInterp. 10364e6af134Sdanielk1977 */ 10374e6af134Sdanielk1977 static Tcl_Interp* pTestCollateInterp; 10384e6af134Sdanielk1977 static int test_collate_func( 10394e6af134Sdanielk1977 void *pCtx, 10404e6af134Sdanielk1977 int nA, const void *zA, 10414e6af134Sdanielk1977 int nB, const void *zB 10424e6af134Sdanielk1977 ){ 10434e6af134Sdanielk1977 Tcl_Interp *i = pTestCollateInterp; 10444e6af134Sdanielk1977 int encin = (int)pCtx; 10454e6af134Sdanielk1977 int res; 10464e6af134Sdanielk1977 10474e6af134Sdanielk1977 sqlite3_value *pVal; 10484e6af134Sdanielk1977 Tcl_Obj *pX; 10494e6af134Sdanielk1977 10504e6af134Sdanielk1977 pX = Tcl_NewStringObj("test_collate", -1); 10514e6af134Sdanielk1977 Tcl_IncrRefCount(pX); 10524e6af134Sdanielk1977 10534e6af134Sdanielk1977 switch( encin ){ 10544e6af134Sdanielk1977 case SQLITE_UTF8: 10554e6af134Sdanielk1977 Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-8",-1)); 10564e6af134Sdanielk1977 break; 10574e6af134Sdanielk1977 case SQLITE_UTF16LE: 10584e6af134Sdanielk1977 Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-16LE",-1)); 10594e6af134Sdanielk1977 break; 10604e6af134Sdanielk1977 case SQLITE_UTF16BE: 10614e6af134Sdanielk1977 Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-16BE",-1)); 10624e6af134Sdanielk1977 break; 10634e6af134Sdanielk1977 default: 10644e6af134Sdanielk1977 assert(0); 10654e6af134Sdanielk1977 } 10664e6af134Sdanielk1977 10674e6af134Sdanielk1977 pVal = sqlite3ValueNew(); 1068bfd6cce5Sdanielk1977 sqlite3ValueSetStr(pVal, nA, zA, encin, SQLITE_STATIC); 10694e6af134Sdanielk1977 Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj(sqlite3_value_text(pVal),-1)); 1070bfd6cce5Sdanielk1977 sqlite3ValueSetStr(pVal, nB, zB, encin, SQLITE_STATIC); 10714e6af134Sdanielk1977 Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj(sqlite3_value_text(pVal),-1)); 10724e6af134Sdanielk1977 sqlite3ValueFree(pVal); 10734e6af134Sdanielk1977 10744e6af134Sdanielk1977 Tcl_EvalObjEx(i, pX, 0); 10754e6af134Sdanielk1977 Tcl_DecrRefCount(pX); 10764e6af134Sdanielk1977 Tcl_GetIntFromObj(i, Tcl_GetObjResult(i), &res); 10774e6af134Sdanielk1977 return res; 10784e6af134Sdanielk1977 } 10794e6af134Sdanielk1977 static int test_collate( 10804e6af134Sdanielk1977 void * clientData, 10814e6af134Sdanielk1977 Tcl_Interp *interp, 10824e6af134Sdanielk1977 int objc, 10834e6af134Sdanielk1977 Tcl_Obj *CONST objv[] 10844e6af134Sdanielk1977 ){ 10854e6af134Sdanielk1977 sqlite3 *db; 10864e6af134Sdanielk1977 int val; 1087312d6b36Sdanielk1977 sqlite3_value *pVal; 1088c60d0446Sdrh int rc; 10894e6af134Sdanielk1977 10904e6af134Sdanielk1977 if( objc!=5 ) goto bad_args; 10914e6af134Sdanielk1977 pTestCollateInterp = interp; 10924e6af134Sdanielk1977 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 10934e6af134Sdanielk1977 10944e6af134Sdanielk1977 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[2], &val) ) return TCL_ERROR; 1095c60d0446Sdrh rc = sqlite3_create_collation(db, "test_collate", SQLITE_UTF8, 10964e6af134Sdanielk1977 (void *)SQLITE_UTF8, val?test_collate_func:0); 1097c60d0446Sdrh if( rc==SQLITE_OK ){ 10984e6af134Sdanielk1977 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[3], &val) ) return TCL_ERROR; 1099c60d0446Sdrh rc = sqlite3_create_collation(db, "test_collate", SQLITE_UTF16LE, 11004e6af134Sdanielk1977 (void *)SQLITE_UTF16LE, val?test_collate_func:0); 11014e6af134Sdanielk1977 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[4], &val) ) return TCL_ERROR; 1102312d6b36Sdanielk1977 1103312d6b36Sdanielk1977 pVal = sqlite3ValueNew(); 1104312d6b36Sdanielk1977 sqlite3ValueSetStr(pVal, -1, "test_collate", SQLITE_UTF8, SQLITE_STATIC); 1105312d6b36Sdanielk1977 sqlite3_create_collation16(db, sqlite3ValueText(pVal, SQLITE_UTF16NATIVE), 1106312d6b36Sdanielk1977 SQLITE_UTF16BE, (void *)SQLITE_UTF16BE, val?test_collate_func:0); 1107312d6b36Sdanielk1977 sqlite3ValueFree(pVal); 1108c60d0446Sdrh } 1109c60d0446Sdrh if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; 11104e6af134Sdanielk1977 return TCL_OK; 11114e6af134Sdanielk1977 11124e6af134Sdanielk1977 bad_args: 11134e6af134Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 11144e6af134Sdanielk1977 Tcl_GetStringFromObj(objv[0], 0), " <DB> <utf8> <utf16le> <utf16be>", 0); 11154e6af134Sdanielk1977 return TCL_ERROR; 11164e6af134Sdanielk1977 } 11174e6af134Sdanielk1977 1118312d6b36Sdanielk1977 static void test_collate_needed_cb( 1119312d6b36Sdanielk1977 void *pCtx, 1120312d6b36Sdanielk1977 sqlite3 *db, 1121312d6b36Sdanielk1977 int eTextRep, 1122312d6b36Sdanielk1977 const void *notUsed 1123312d6b36Sdanielk1977 ){ 1124312d6b36Sdanielk1977 int enc = db->enc; 1125312d6b36Sdanielk1977 sqlite3_create_collation( 1126312d6b36Sdanielk1977 db, "test_collate", db->enc, (void *)enc, test_collate_func); 1127312d6b36Sdanielk1977 } 1128312d6b36Sdanielk1977 1129312d6b36Sdanielk1977 /* 1130312d6b36Sdanielk1977 ** Usage: add_test_collate_needed DB 1131312d6b36Sdanielk1977 */ 1132312d6b36Sdanielk1977 static int test_collate_needed( 1133312d6b36Sdanielk1977 void * clientData, 1134312d6b36Sdanielk1977 Tcl_Interp *interp, 1135312d6b36Sdanielk1977 int objc, 1136312d6b36Sdanielk1977 Tcl_Obj *CONST objv[] 1137312d6b36Sdanielk1977 ){ 1138312d6b36Sdanielk1977 sqlite3 *db; 1139c60d0446Sdrh int rc; 1140312d6b36Sdanielk1977 1141312d6b36Sdanielk1977 if( objc!=2 ) goto bad_args; 1142312d6b36Sdanielk1977 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 1143c60d0446Sdrh rc = sqlite3_collation_needed16(db, 0, test_collate_needed_cb); 1144c60d0446Sdrh if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; 1145312d6b36Sdanielk1977 return TCL_OK; 1146312d6b36Sdanielk1977 1147312d6b36Sdanielk1977 bad_args: 1148312d6b36Sdanielk1977 Tcl_WrongNumArgs(interp, 1, objv, "DB"); 1149312d6b36Sdanielk1977 return TCL_ERROR; 1150312d6b36Sdanielk1977 } 1151312d6b36Sdanielk1977 1152c8e9a2dfSdanielk1977 /* 1153c8e9a2dfSdanielk1977 ** Usage: add_test_function <db ptr> <utf8> <utf16le> <utf16be> 1154c8e9a2dfSdanielk1977 ** 1155c8e9a2dfSdanielk1977 ** This function is used to test that SQLite selects the correct user 1156c8e9a2dfSdanielk1977 ** function callback when multiple versions (for different text encodings) 1157c8e9a2dfSdanielk1977 ** are available. 1158c8e9a2dfSdanielk1977 ** 1159c8e9a2dfSdanielk1977 ** Calling this routine registers up to three versions of the user function 1160c8e9a2dfSdanielk1977 ** "test_function" with database handle <db>. If the second argument is 1161c8e9a2dfSdanielk1977 ** true, then a version of test_function is registered for UTF-8, if the 1162c8e9a2dfSdanielk1977 ** third is true, a version is registered for UTF-16le, if the fourth is 1163c8e9a2dfSdanielk1977 ** true, a UTF-16be version is available. Previous versions of 1164c8e9a2dfSdanielk1977 ** test_function are deleted. 1165c8e9a2dfSdanielk1977 ** 1166c8e9a2dfSdanielk1977 ** The user function is implemented by calling the following TCL script: 1167c8e9a2dfSdanielk1977 ** 1168c8e9a2dfSdanielk1977 ** "test_function <enc> <arg>" 1169c8e9a2dfSdanielk1977 ** 1170c8e9a2dfSdanielk1977 ** Where <enc> is one of UTF-8, UTF-16LE or UTF16BE, and <arg> is the 1171c8e9a2dfSdanielk1977 ** single argument passed to the SQL function. The value returned by 1172c8e9a2dfSdanielk1977 ** the TCL script is used as the return value of the SQL function. It 1173c8e9a2dfSdanielk1977 ** is passed to SQLite using UTF-16BE for a UTF-8 test_function(), UTF-8 1174c8e9a2dfSdanielk1977 ** for a UTF-16LE test_function(), and UTF-16LE for an implementation that 1175c8e9a2dfSdanielk1977 ** prefers UTF-16BE. 1176c8e9a2dfSdanielk1977 */ 1177c8e9a2dfSdanielk1977 static void test_function_utf8( 1178c8e9a2dfSdanielk1977 sqlite3_context *pCtx, 1179c8e9a2dfSdanielk1977 int nArg, 1180c8e9a2dfSdanielk1977 sqlite3_value **argv 1181c8e9a2dfSdanielk1977 ){ 1182c8e9a2dfSdanielk1977 Tcl_Interp *interp; 1183c8e9a2dfSdanielk1977 Tcl_Obj *pX; 1184c8e9a2dfSdanielk1977 sqlite3_value *pVal; 1185c8e9a2dfSdanielk1977 interp = (Tcl_Interp *)sqlite3_user_data(pCtx); 1186c8e9a2dfSdanielk1977 pX = Tcl_NewStringObj("test_function", -1); 1187c8e9a2dfSdanielk1977 Tcl_IncrRefCount(pX); 1188c8e9a2dfSdanielk1977 Tcl_ListObjAppendElement(interp, pX, Tcl_NewStringObj("UTF-8", -1)); 1189c8e9a2dfSdanielk1977 Tcl_ListObjAppendElement(interp, pX, 1190c8e9a2dfSdanielk1977 Tcl_NewStringObj(sqlite3_value_text(argv[0]), -1)); 1191c8e9a2dfSdanielk1977 Tcl_EvalObjEx(interp, pX, 0); 1192c8e9a2dfSdanielk1977 Tcl_DecrRefCount(pX); 1193c8e9a2dfSdanielk1977 sqlite3_result_text(pCtx, Tcl_GetStringResult(interp), -1, SQLITE_TRANSIENT); 1194c8e9a2dfSdanielk1977 pVal = sqlite3ValueNew(); 1195c8e9a2dfSdanielk1977 sqlite3ValueSetStr(pVal, -1, Tcl_GetStringResult(interp), 1196c8e9a2dfSdanielk1977 SQLITE_UTF8, SQLITE_STATIC); 1197c8e9a2dfSdanielk1977 sqlite3_result_text16be(pCtx, sqlite3_value_text16be(pVal), 1198c8e9a2dfSdanielk1977 -1, SQLITE_TRANSIENT); 1199c8e9a2dfSdanielk1977 sqlite3ValueFree(pVal); 1200c8e9a2dfSdanielk1977 } 1201c8e9a2dfSdanielk1977 static void test_function_utf16le( 1202c8e9a2dfSdanielk1977 sqlite3_context *pCtx, 1203c8e9a2dfSdanielk1977 int nArg, 1204c8e9a2dfSdanielk1977 sqlite3_value **argv 1205c8e9a2dfSdanielk1977 ){ 1206c8e9a2dfSdanielk1977 Tcl_Interp *interp; 1207c8e9a2dfSdanielk1977 Tcl_Obj *pX; 1208c8e9a2dfSdanielk1977 sqlite3_value *pVal; 1209c8e9a2dfSdanielk1977 interp = (Tcl_Interp *)sqlite3_user_data(pCtx); 1210c8e9a2dfSdanielk1977 pX = Tcl_NewStringObj("test_function", -1); 1211c8e9a2dfSdanielk1977 Tcl_IncrRefCount(pX); 1212c8e9a2dfSdanielk1977 Tcl_ListObjAppendElement(interp, pX, Tcl_NewStringObj("UTF-16LE", -1)); 1213c8e9a2dfSdanielk1977 Tcl_ListObjAppendElement(interp, pX, 1214c8e9a2dfSdanielk1977 Tcl_NewStringObj(sqlite3_value_text(argv[0]), -1)); 1215c8e9a2dfSdanielk1977 Tcl_EvalObjEx(interp, pX, 0); 1216c8e9a2dfSdanielk1977 Tcl_DecrRefCount(pX); 1217c8e9a2dfSdanielk1977 pVal = sqlite3ValueNew(); 1218c8e9a2dfSdanielk1977 sqlite3ValueSetStr(pVal, -1, Tcl_GetStringResult(interp), 1219c8e9a2dfSdanielk1977 SQLITE_UTF8, SQLITE_STATIC); 1220c8e9a2dfSdanielk1977 sqlite3_result_text(pCtx,sqlite3_value_text(pVal),-1,SQLITE_TRANSIENT); 1221c8e9a2dfSdanielk1977 sqlite3ValueFree(pVal); 1222c8e9a2dfSdanielk1977 } 1223c8e9a2dfSdanielk1977 static void test_function_utf16be( 1224c8e9a2dfSdanielk1977 sqlite3_context *pCtx, 1225c8e9a2dfSdanielk1977 int nArg, 1226c8e9a2dfSdanielk1977 sqlite3_value **argv 1227c8e9a2dfSdanielk1977 ){ 1228c8e9a2dfSdanielk1977 Tcl_Interp *interp; 1229c8e9a2dfSdanielk1977 Tcl_Obj *pX; 1230c8e9a2dfSdanielk1977 sqlite3_value *pVal; 1231c8e9a2dfSdanielk1977 interp = (Tcl_Interp *)sqlite3_user_data(pCtx); 1232c8e9a2dfSdanielk1977 pX = Tcl_NewStringObj("test_function", -1); 1233c8e9a2dfSdanielk1977 Tcl_IncrRefCount(pX); 1234c8e9a2dfSdanielk1977 Tcl_ListObjAppendElement(interp, pX, Tcl_NewStringObj("UTF-16BE", -1)); 1235c8e9a2dfSdanielk1977 Tcl_ListObjAppendElement(interp, pX, 1236c8e9a2dfSdanielk1977 Tcl_NewStringObj(sqlite3_value_text(argv[0]), -1)); 1237c8e9a2dfSdanielk1977 Tcl_EvalObjEx(interp, pX, 0); 1238c8e9a2dfSdanielk1977 Tcl_DecrRefCount(pX); 1239c8e9a2dfSdanielk1977 pVal = sqlite3ValueNew(); 1240c8e9a2dfSdanielk1977 sqlite3ValueSetStr(pVal, -1, Tcl_GetStringResult(interp), 1241c8e9a2dfSdanielk1977 SQLITE_UTF8, SQLITE_STATIC); 1242c8e9a2dfSdanielk1977 sqlite3_result_text16le(pCtx, sqlite3_value_text16le(pVal), 1243c8e9a2dfSdanielk1977 -1, SQLITE_TRANSIENT); 1244c8e9a2dfSdanielk1977 sqlite3ValueFree(pVal); 1245c8e9a2dfSdanielk1977 } 1246c8e9a2dfSdanielk1977 static int test_function( 1247c8e9a2dfSdanielk1977 void * clientData, 1248c8e9a2dfSdanielk1977 Tcl_Interp *interp, 1249c8e9a2dfSdanielk1977 int objc, 1250c8e9a2dfSdanielk1977 Tcl_Obj *CONST objv[] 1251c8e9a2dfSdanielk1977 ){ 1252c8e9a2dfSdanielk1977 sqlite3 *db; 1253c8e9a2dfSdanielk1977 int val; 1254c8e9a2dfSdanielk1977 1255c8e9a2dfSdanielk1977 if( objc!=5 ) goto bad_args; 1256c8e9a2dfSdanielk1977 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 1257c8e9a2dfSdanielk1977 1258c8e9a2dfSdanielk1977 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[2], &val) ) return TCL_ERROR; 1259c8e9a2dfSdanielk1977 if( val ){ 1260c8e9a2dfSdanielk1977 sqlite3_create_function(db, "test_function", 1, SQLITE_UTF8, 1261c8e9a2dfSdanielk1977 interp, test_function_utf8, 0, 0); 1262c8e9a2dfSdanielk1977 } 1263c8e9a2dfSdanielk1977 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[3], &val) ) return TCL_ERROR; 1264c8e9a2dfSdanielk1977 if( val ){ 1265c8e9a2dfSdanielk1977 sqlite3_create_function(db, "test_function", 1, SQLITE_UTF16LE, 1266c8e9a2dfSdanielk1977 interp, test_function_utf16le, 0, 0); 1267c8e9a2dfSdanielk1977 } 1268c8e9a2dfSdanielk1977 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[4], &val) ) return TCL_ERROR; 1269c8e9a2dfSdanielk1977 if( val ){ 1270c8e9a2dfSdanielk1977 sqlite3_create_function(db, "test_function", 1, SQLITE_UTF16BE, 1271c8e9a2dfSdanielk1977 interp, test_function_utf16be, 0, 0); 1272c8e9a2dfSdanielk1977 } 1273c8e9a2dfSdanielk1977 1274c8e9a2dfSdanielk1977 return TCL_OK; 1275c8e9a2dfSdanielk1977 bad_args: 1276c8e9a2dfSdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 1277c8e9a2dfSdanielk1977 Tcl_GetStringFromObj(objv[0], 0), " <DB> <utf8> <utf16le> <utf16be>", 0); 1278c8e9a2dfSdanielk1977 return TCL_ERROR; 1279c8e9a2dfSdanielk1977 } 1280c8e9a2dfSdanielk1977 1281312d6b36Sdanielk1977 /* 1282312d6b36Sdanielk1977 ** Usage: test_errstr <err code> 1283312d6b36Sdanielk1977 ** 1284312d6b36Sdanielk1977 ** Test that the english language string equivalents for sqlite error codes 1285312d6b36Sdanielk1977 ** are sane. The parameter is an integer representing an sqlite error code. 1286312d6b36Sdanielk1977 ** The result is a list of two elements, the string representation of the 1287312d6b36Sdanielk1977 ** error code and the english language explanation. 1288312d6b36Sdanielk1977 */ 1289312d6b36Sdanielk1977 static int test_errstr( 1290312d6b36Sdanielk1977 void * clientData, 1291312d6b36Sdanielk1977 Tcl_Interp *interp, 1292312d6b36Sdanielk1977 int objc, 1293312d6b36Sdanielk1977 Tcl_Obj *CONST objv[] 1294312d6b36Sdanielk1977 ){ 1295312d6b36Sdanielk1977 char *zCode; 1296312d6b36Sdanielk1977 int i; 1297312d6b36Sdanielk1977 if( objc!=1 ){ 1298312d6b36Sdanielk1977 Tcl_WrongNumArgs(interp, 1, objv, "<error code>"); 1299312d6b36Sdanielk1977 } 1300312d6b36Sdanielk1977 1301312d6b36Sdanielk1977 zCode = Tcl_GetString(objv[1]); 1302312d6b36Sdanielk1977 for(i=0; i<200; i++){ 1303312d6b36Sdanielk1977 if( 0==strcmp(errorName(i), zCode) ) break; 1304312d6b36Sdanielk1977 } 1305312d6b36Sdanielk1977 Tcl_SetResult(interp, (char *)sqlite3ErrStr(i), 0); 1306312d6b36Sdanielk1977 return TCL_OK; 1307312d6b36Sdanielk1977 } 1308312d6b36Sdanielk1977 1309c8e9a2dfSdanielk1977 static int sqlite3_crashparams( 13108a6c550dSdanielk1977 void * clientData, 13118a6c550dSdanielk1977 Tcl_Interp *interp, 13128a6c550dSdanielk1977 int objc, 13138a6c550dSdanielk1977 Tcl_Obj *CONST objv[] 13148a6c550dSdanielk1977 ){ 13158a6c550dSdanielk1977 #ifdef OS_TEST 1316c8e9a2dfSdanielk1977 int delay; 1317c8e9a2dfSdanielk1977 if( objc!=3 ) goto bad_args; 1318c8e9a2dfSdanielk1977 if( Tcl_GetIntFromObj(interp, objv[1], &delay) ) return TCL_ERROR; 1319c8e9a2dfSdanielk1977 sqlite3SetCrashParams(delay, Tcl_GetString(objv[2])); 13208a6c550dSdanielk1977 #endif 13218a6c550dSdanielk1977 return TCL_OK; 13228a6c550dSdanielk1977 1323241db313Sdrh #ifdef OS_TEST 13248a6c550dSdanielk1977 bad_args: 13258a6c550dSdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 1326c8e9a2dfSdanielk1977 Tcl_GetStringFromObj(objv[0], 0), "<delay> <filename>", 0); 13278a6c550dSdanielk1977 return TCL_ERROR; 1328241db313Sdrh #endif 13298a6c550dSdanielk1977 } 13308a6c550dSdanielk1977 13318a6c550dSdanielk1977 133250457896Sdrh /* 133399ee3600Sdrh ** Usage: breakpoint 133499ee3600Sdrh ** 133599ee3600Sdrh ** This routine exists for one purpose - to provide a place to put a 133699ee3600Sdrh ** breakpoint with GDB that can be triggered using TCL code. The use 133799ee3600Sdrh ** for this is when a particular test fails on (say) the 1485th iteration. 133899ee3600Sdrh ** In the TCL test script, we can add code like this: 133999ee3600Sdrh ** 134099ee3600Sdrh ** if {$i==1485} breakpoint 134199ee3600Sdrh ** 134299ee3600Sdrh ** Then run testfixture in the debugger and wait for the breakpoint to 134399ee3600Sdrh ** fire. Then additional breakpoints can be set to trace down the bug. 134499ee3600Sdrh */ 134599ee3600Sdrh static int test_breakpoint( 134699ee3600Sdrh void *NotUsed, 134799ee3600Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 134899ee3600Sdrh int argc, /* Number of arguments */ 134999ee3600Sdrh char **argv /* Text of each argument */ 135099ee3600Sdrh ){ 135199ee3600Sdrh return TCL_OK; /* Do nothing */ 135299ee3600Sdrh } 135399ee3600Sdrh 1354241db313Sdrh /* 1355241db313Sdrh ** Usage: sqlite3_bind_int STMT N VALUE 1356241db313Sdrh ** 1357241db313Sdrh ** Test the sqlite3_bind_int interface. STMT is a prepared statement. 1358241db313Sdrh ** N is the index of a wildcard in the prepared statement. This command 1359241db313Sdrh ** binds a 32-bit integer VALUE to that wildcard. 1360241db313Sdrh */ 1361241db313Sdrh static int test_bind_int( 136251e3d8e2Sdanielk1977 void * clientData, 136351e3d8e2Sdanielk1977 Tcl_Interp *interp, 136451e3d8e2Sdanielk1977 int objc, 136551e3d8e2Sdanielk1977 Tcl_Obj *CONST objv[] 136651e3d8e2Sdanielk1977 ){ 136751e3d8e2Sdanielk1977 sqlite3_stmt *pStmt; 136851e3d8e2Sdanielk1977 int idx; 136951e3d8e2Sdanielk1977 int value; 137051e3d8e2Sdanielk1977 int rc; 137151e3d8e2Sdanielk1977 137251e3d8e2Sdanielk1977 if( objc!=4 ){ 137351e3d8e2Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 1374241db313Sdrh Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE", 0); 137551e3d8e2Sdanielk1977 return TCL_ERROR; 137651e3d8e2Sdanielk1977 } 137751e3d8e2Sdanielk1977 137851e3d8e2Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 137951e3d8e2Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; 138051e3d8e2Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[3], &value) ) return TCL_ERROR; 138151e3d8e2Sdanielk1977 1382c572ef7fSdanielk1977 rc = sqlite3_bind_int(pStmt, idx, value); 1383c60d0446Sdrh if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR; 138451e3d8e2Sdanielk1977 if( rc!=SQLITE_OK ){ 138551e3d8e2Sdanielk1977 return TCL_ERROR; 138651e3d8e2Sdanielk1977 } 138751e3d8e2Sdanielk1977 138851e3d8e2Sdanielk1977 return TCL_OK; 138951e3d8e2Sdanielk1977 } 139051e3d8e2Sdanielk1977 1391241db313Sdrh 1392241db313Sdrh /* 1393241db313Sdrh ** Usage: sqlite3_bind_int64 STMT N VALUE 1394241db313Sdrh ** 1395241db313Sdrh ** Test the sqlite3_bind_int64 interface. STMT is a prepared statement. 1396241db313Sdrh ** N is the index of a wildcard in the prepared statement. This command 1397241db313Sdrh ** binds a 64-bit integer VALUE to that wildcard. 1398241db313Sdrh */ 139951e3d8e2Sdanielk1977 static int test_bind_int64( 140051e3d8e2Sdanielk1977 void * clientData, 140151e3d8e2Sdanielk1977 Tcl_Interp *interp, 140251e3d8e2Sdanielk1977 int objc, 140351e3d8e2Sdanielk1977 Tcl_Obj *CONST objv[] 140451e3d8e2Sdanielk1977 ){ 140551e3d8e2Sdanielk1977 sqlite3_stmt *pStmt; 140651e3d8e2Sdanielk1977 int idx; 140751e3d8e2Sdanielk1977 i64 value; 140851e3d8e2Sdanielk1977 int rc; 140951e3d8e2Sdanielk1977 141051e3d8e2Sdanielk1977 if( objc!=4 ){ 141151e3d8e2Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 1412241db313Sdrh Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE", 0); 141351e3d8e2Sdanielk1977 return TCL_ERROR; 141451e3d8e2Sdanielk1977 } 141551e3d8e2Sdanielk1977 141651e3d8e2Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 141751e3d8e2Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; 141851e3d8e2Sdanielk1977 if( Tcl_GetWideIntFromObj(interp, objv[3], &value) ) return TCL_ERROR; 141951e3d8e2Sdanielk1977 142051e3d8e2Sdanielk1977 rc = sqlite3_bind_int64(pStmt, idx, value); 1421c60d0446Sdrh if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR; 142251e3d8e2Sdanielk1977 if( rc!=SQLITE_OK ){ 142351e3d8e2Sdanielk1977 return TCL_ERROR; 142451e3d8e2Sdanielk1977 } 142551e3d8e2Sdanielk1977 142651e3d8e2Sdanielk1977 return TCL_OK; 142751e3d8e2Sdanielk1977 } 142851e3d8e2Sdanielk1977 1429241db313Sdrh 1430241db313Sdrh /* 1431241db313Sdrh ** Usage: sqlite3_bind_double STMT N VALUE 1432241db313Sdrh ** 1433241db313Sdrh ** Test the sqlite3_bind_double interface. STMT is a prepared statement. 1434241db313Sdrh ** N is the index of a wildcard in the prepared statement. This command 1435241db313Sdrh ** binds a 64-bit integer VALUE to that wildcard. 1436241db313Sdrh */ 143751e3d8e2Sdanielk1977 static int test_bind_double( 143851e3d8e2Sdanielk1977 void * clientData, 143951e3d8e2Sdanielk1977 Tcl_Interp *interp, 144051e3d8e2Sdanielk1977 int objc, 144151e3d8e2Sdanielk1977 Tcl_Obj *CONST objv[] 144251e3d8e2Sdanielk1977 ){ 144351e3d8e2Sdanielk1977 sqlite3_stmt *pStmt; 144451e3d8e2Sdanielk1977 int idx; 144551e3d8e2Sdanielk1977 double value; 144651e3d8e2Sdanielk1977 int rc; 144751e3d8e2Sdanielk1977 144851e3d8e2Sdanielk1977 if( objc!=4 ){ 144951e3d8e2Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 1450241db313Sdrh Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE", 0); 145151e3d8e2Sdanielk1977 return TCL_ERROR; 145251e3d8e2Sdanielk1977 } 145351e3d8e2Sdanielk1977 145451e3d8e2Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 145551e3d8e2Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; 145651e3d8e2Sdanielk1977 if( Tcl_GetDoubleFromObj(interp, objv[3], &value) ) return TCL_ERROR; 145751e3d8e2Sdanielk1977 145851e3d8e2Sdanielk1977 rc = sqlite3_bind_double(pStmt, idx, value); 1459c60d0446Sdrh if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR; 146051e3d8e2Sdanielk1977 if( rc!=SQLITE_OK ){ 146151e3d8e2Sdanielk1977 return TCL_ERROR; 146251e3d8e2Sdanielk1977 } 146351e3d8e2Sdanielk1977 146451e3d8e2Sdanielk1977 return TCL_OK; 146551e3d8e2Sdanielk1977 } 146651e3d8e2Sdanielk1977 1467241db313Sdrh /* 1468241db313Sdrh ** Usage: sqlite3_bind_null STMT N 1469241db313Sdrh ** 1470241db313Sdrh ** Test the sqlite3_bind_null interface. STMT is a prepared statement. 1471241db313Sdrh ** N is the index of a wildcard in the prepared statement. This command 1472241db313Sdrh ** binds a NULL to the wildcard. 1473241db313Sdrh */ 147451e3d8e2Sdanielk1977 static int test_bind_null( 147551e3d8e2Sdanielk1977 void * clientData, 147651e3d8e2Sdanielk1977 Tcl_Interp *interp, 147751e3d8e2Sdanielk1977 int objc, 147851e3d8e2Sdanielk1977 Tcl_Obj *CONST objv[] 147951e3d8e2Sdanielk1977 ){ 148051e3d8e2Sdanielk1977 sqlite3_stmt *pStmt; 148151e3d8e2Sdanielk1977 int idx; 148251e3d8e2Sdanielk1977 int rc; 148351e3d8e2Sdanielk1977 148451e3d8e2Sdanielk1977 if( objc!=3 ){ 148551e3d8e2Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 1486241db313Sdrh Tcl_GetStringFromObj(objv[0], 0), " STMT N", 0); 148751e3d8e2Sdanielk1977 return TCL_ERROR; 148851e3d8e2Sdanielk1977 } 148951e3d8e2Sdanielk1977 149051e3d8e2Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 149151e3d8e2Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; 149251e3d8e2Sdanielk1977 149351e3d8e2Sdanielk1977 rc = sqlite3_bind_null(pStmt, idx); 1494c60d0446Sdrh if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR; 149551e3d8e2Sdanielk1977 if( rc!=SQLITE_OK ){ 149651e3d8e2Sdanielk1977 return TCL_ERROR; 149751e3d8e2Sdanielk1977 } 149851e3d8e2Sdanielk1977 149951e3d8e2Sdanielk1977 return TCL_OK; 150051e3d8e2Sdanielk1977 } 150151e3d8e2Sdanielk1977 1502241db313Sdrh /* 1503241db313Sdrh ** Usage: sqlite3_bind_text STMT N STRING BYTES 1504241db313Sdrh ** 1505241db313Sdrh ** Test the sqlite3_bind_text interface. STMT is a prepared statement. 1506241db313Sdrh ** N is the index of a wildcard in the prepared statement. This command 1507241db313Sdrh ** binds a UTF-8 string STRING to the wildcard. The string is BYTES bytes 1508241db313Sdrh ** long. 1509241db313Sdrh */ 151051e3d8e2Sdanielk1977 static int test_bind_text( 151151e3d8e2Sdanielk1977 void * clientData, 151251e3d8e2Sdanielk1977 Tcl_Interp *interp, 151351e3d8e2Sdanielk1977 int objc, 151451e3d8e2Sdanielk1977 Tcl_Obj *CONST objv[] 151551e3d8e2Sdanielk1977 ){ 151651e3d8e2Sdanielk1977 sqlite3_stmt *pStmt; 151751e3d8e2Sdanielk1977 int idx; 151851e3d8e2Sdanielk1977 int bytes; 151951e3d8e2Sdanielk1977 char *value; 152051e3d8e2Sdanielk1977 int rc; 152151e3d8e2Sdanielk1977 152251e3d8e2Sdanielk1977 if( objc!=5 ){ 152351e3d8e2Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 1524241db313Sdrh Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE BYTES", 0); 152551e3d8e2Sdanielk1977 return TCL_ERROR; 152651e3d8e2Sdanielk1977 } 152751e3d8e2Sdanielk1977 152851e3d8e2Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 152951e3d8e2Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; 153051e3d8e2Sdanielk1977 value = Tcl_GetString(objv[3]); 153151e3d8e2Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[4], &bytes) ) return TCL_ERROR; 153251e3d8e2Sdanielk1977 1533d8123366Sdanielk1977 rc = sqlite3_bind_text(pStmt, idx, value, bytes, SQLITE_TRANSIENT); 1534c60d0446Sdrh if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR; 153551e3d8e2Sdanielk1977 if( rc!=SQLITE_OK ){ 153651e3d8e2Sdanielk1977 return TCL_ERROR; 153751e3d8e2Sdanielk1977 } 153851e3d8e2Sdanielk1977 153951e3d8e2Sdanielk1977 return TCL_OK; 154051e3d8e2Sdanielk1977 } 154151e3d8e2Sdanielk1977 1542241db313Sdrh /* 1543241db313Sdrh ** Usage: sqlite3_bind_text16 STMT N STRING BYTES 1544241db313Sdrh ** 1545241db313Sdrh ** Test the sqlite3_bind_text16 interface. STMT is a prepared statement. 1546241db313Sdrh ** N is the index of a wildcard in the prepared statement. This command 1547241db313Sdrh ** binds a UTF-16 string STRING to the wildcard. The string is BYTES bytes 1548241db313Sdrh ** long. 1549241db313Sdrh */ 155051e3d8e2Sdanielk1977 static int test_bind_text16( 155151e3d8e2Sdanielk1977 void * clientData, 155251e3d8e2Sdanielk1977 Tcl_Interp *interp, 155351e3d8e2Sdanielk1977 int objc, 155451e3d8e2Sdanielk1977 Tcl_Obj *CONST objv[] 155551e3d8e2Sdanielk1977 ){ 155651e3d8e2Sdanielk1977 sqlite3_stmt *pStmt; 155751e3d8e2Sdanielk1977 int idx; 155851e3d8e2Sdanielk1977 int bytes; 155951e3d8e2Sdanielk1977 char *value; 156051e3d8e2Sdanielk1977 int rc; 156151e3d8e2Sdanielk1977 156251e3d8e2Sdanielk1977 if( objc!=5 ){ 156351e3d8e2Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 1564241db313Sdrh Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE BYTES", 0); 156551e3d8e2Sdanielk1977 return TCL_ERROR; 156651e3d8e2Sdanielk1977 } 156751e3d8e2Sdanielk1977 156851e3d8e2Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 156951e3d8e2Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; 157051e3d8e2Sdanielk1977 value = Tcl_GetByteArrayFromObj(objv[3], 0); 157151e3d8e2Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[4], &bytes) ) return TCL_ERROR; 157251e3d8e2Sdanielk1977 1573d8123366Sdanielk1977 rc = sqlite3_bind_text16(pStmt, idx, (void *)value, bytes, SQLITE_TRANSIENT); 1574c60d0446Sdrh if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR; 157551e3d8e2Sdanielk1977 if( rc!=SQLITE_OK ){ 157651e3d8e2Sdanielk1977 return TCL_ERROR; 157751e3d8e2Sdanielk1977 } 157851e3d8e2Sdanielk1977 157951e3d8e2Sdanielk1977 return TCL_OK; 158051e3d8e2Sdanielk1977 } 158151e3d8e2Sdanielk1977 1582241db313Sdrh /* 1583241db313Sdrh ** Usage: sqlite3_bind_blob STMT N DATA BYTES 1584241db313Sdrh ** 1585241db313Sdrh ** Test the sqlite3_bind_blob interface. STMT is a prepared statement. 1586241db313Sdrh ** N is the index of a wildcard in the prepared statement. This command 1587241db313Sdrh ** binds a BLOB to the wildcard. The BLOB is BYTES bytes in size. 1588241db313Sdrh */ 158951e3d8e2Sdanielk1977 static int test_bind_blob( 159051e3d8e2Sdanielk1977 void * clientData, 159151e3d8e2Sdanielk1977 Tcl_Interp *interp, 159251e3d8e2Sdanielk1977 int objc, 159351e3d8e2Sdanielk1977 Tcl_Obj *CONST objv[] 159451e3d8e2Sdanielk1977 ){ 159551e3d8e2Sdanielk1977 sqlite3_stmt *pStmt; 159651e3d8e2Sdanielk1977 int idx; 159751e3d8e2Sdanielk1977 int bytes; 159851e3d8e2Sdanielk1977 char *value; 159951e3d8e2Sdanielk1977 int rc; 160051e3d8e2Sdanielk1977 160151e3d8e2Sdanielk1977 if( objc!=5 ){ 160251e3d8e2Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 1603241db313Sdrh Tcl_GetStringFromObj(objv[0], 0), " STMT N DATA BYTES", 0); 160451e3d8e2Sdanielk1977 return TCL_ERROR; 160551e3d8e2Sdanielk1977 } 160651e3d8e2Sdanielk1977 160751e3d8e2Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 160851e3d8e2Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; 160951e3d8e2Sdanielk1977 value = Tcl_GetString(objv[3]); 161049e4643eSdanielk1977 if( Tcl_GetIntFromObj(interp, objv[4], &bytes) ) return TCL_ERROR; 161151e3d8e2Sdanielk1977 1612d8123366Sdanielk1977 rc = sqlite3_bind_blob(pStmt, idx, value, bytes, SQLITE_TRANSIENT); 1613c60d0446Sdrh if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR; 161451e3d8e2Sdanielk1977 if( rc!=SQLITE_OK ){ 161551e3d8e2Sdanielk1977 return TCL_ERROR; 161651e3d8e2Sdanielk1977 } 161751e3d8e2Sdanielk1977 161851e3d8e2Sdanielk1977 return TCL_OK; 161951e3d8e2Sdanielk1977 } 162051e3d8e2Sdanielk1977 162199ee3600Sdrh /* 162275f6a032Sdrh ** Usage: sqlite3_bind_parameter_count STMT 162375f6a032Sdrh ** 162475f6a032Sdrh ** Return the number of wildcards in the given statement. 162575f6a032Sdrh */ 162675f6a032Sdrh static int test_bind_parameter_count( 162775f6a032Sdrh void * clientData, 162875f6a032Sdrh Tcl_Interp *interp, 162975f6a032Sdrh int objc, 163075f6a032Sdrh Tcl_Obj *CONST objv[] 163175f6a032Sdrh ){ 163275f6a032Sdrh sqlite3_stmt *pStmt; 163375f6a032Sdrh 163475f6a032Sdrh if( objc!=2 ){ 163575f6a032Sdrh Tcl_WrongNumArgs(interp, 1, objv, "STMT"); 163675f6a032Sdrh return TCL_ERROR; 163775f6a032Sdrh } 163875f6a032Sdrh if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 163975f6a032Sdrh Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_bind_parameter_count(pStmt))); 164075f6a032Sdrh return TCL_OK; 164175f6a032Sdrh } 164275f6a032Sdrh 164375f6a032Sdrh /* 1644895d7472Sdrh ** Usage: sqlite3_bind_parameter_name STMT N 1645895d7472Sdrh ** 1646895d7472Sdrh ** Return the name of the Nth wildcard. The first wildcard is 1. 1647895d7472Sdrh ** An empty string is returned if N is out of range or if the wildcard 1648895d7472Sdrh ** is nameless. 1649895d7472Sdrh */ 1650895d7472Sdrh static int test_bind_parameter_name( 1651895d7472Sdrh void * clientData, 1652895d7472Sdrh Tcl_Interp *interp, 1653895d7472Sdrh int objc, 1654895d7472Sdrh Tcl_Obj *CONST objv[] 1655895d7472Sdrh ){ 1656895d7472Sdrh sqlite3_stmt *pStmt; 1657895d7472Sdrh int i; 1658895d7472Sdrh 1659895d7472Sdrh if( objc!=3 ){ 1660895d7472Sdrh Tcl_WrongNumArgs(interp, 1, objv, "STMT N"); 1661895d7472Sdrh return TCL_ERROR; 1662895d7472Sdrh } 1663895d7472Sdrh if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 1664895d7472Sdrh if( Tcl_GetIntFromObj(interp, objv[2], &i) ) return TCL_ERROR; 1665895d7472Sdrh Tcl_SetObjResult(interp, 1666895d7472Sdrh Tcl_NewStringObj(sqlite3_bind_parameter_name(pStmt,i),-1) 1667895d7472Sdrh ); 1668895d7472Sdrh return TCL_OK; 1669895d7472Sdrh } 1670895d7472Sdrh 1671895d7472Sdrh /* 1672fa6bc000Sdrh ** Usage: sqlite3_bind_parameter_index STMT NAME 1673fa6bc000Sdrh ** 1674fa6bc000Sdrh ** Return the index of the wildcard called NAME. Return 0 if there is 1675fa6bc000Sdrh ** no such wildcard. 1676fa6bc000Sdrh */ 1677fa6bc000Sdrh static int test_bind_parameter_index( 1678fa6bc000Sdrh void * clientData, 1679fa6bc000Sdrh Tcl_Interp *interp, 1680fa6bc000Sdrh int objc, 1681fa6bc000Sdrh Tcl_Obj *CONST objv[] 1682fa6bc000Sdrh ){ 1683fa6bc000Sdrh sqlite3_stmt *pStmt; 1684fa6bc000Sdrh 1685fa6bc000Sdrh if( objc!=3 ){ 1686fa6bc000Sdrh Tcl_WrongNumArgs(interp, 1, objv, "STMT NAME"); 1687fa6bc000Sdrh return TCL_ERROR; 1688fa6bc000Sdrh } 1689fa6bc000Sdrh if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 1690fa6bc000Sdrh Tcl_SetObjResult(interp, 1691fa6bc000Sdrh Tcl_NewIntObj( 1692fa6bc000Sdrh sqlite3_bind_parameter_index(pStmt,Tcl_GetString(objv[2])) 1693fa6bc000Sdrh ) 1694fa6bc000Sdrh ); 1695fa6bc000Sdrh return TCL_OK; 1696fa6bc000Sdrh } 1697fa6bc000Sdrh 1698fa6bc000Sdrh /* 16996622cce3Sdanielk1977 ** Usage: sqlite3_errcode DB 17006622cce3Sdanielk1977 ** 17016622cce3Sdanielk1977 ** Return the string representation of the most recent sqlite3_* API 17026622cce3Sdanielk1977 ** error code. e.g. "SQLITE_ERROR". 17036622cce3Sdanielk1977 */ 17046622cce3Sdanielk1977 static int test_errcode( 17056622cce3Sdanielk1977 void * clientData, 17066622cce3Sdanielk1977 Tcl_Interp *interp, 17076622cce3Sdanielk1977 int objc, 17086622cce3Sdanielk1977 Tcl_Obj *CONST objv[] 17096622cce3Sdanielk1977 ){ 17106622cce3Sdanielk1977 sqlite3 *db; 17116622cce3Sdanielk1977 17126622cce3Sdanielk1977 if( objc!=2 ){ 17136622cce3Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 17146622cce3Sdanielk1977 Tcl_GetString(objv[0]), " DB", 0); 17156622cce3Sdanielk1977 return TCL_ERROR; 17166622cce3Sdanielk1977 } 17176622cce3Sdanielk1977 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 17186622cce3Sdanielk1977 Tcl_SetResult(interp, (char *)errorName(sqlite3_errcode(db)), 0); 17196622cce3Sdanielk1977 return TCL_OK; 17206622cce3Sdanielk1977 } 17216622cce3Sdanielk1977 17226622cce3Sdanielk1977 /* 17236622cce3Sdanielk1977 ** Usage: test_errmsg DB 17246622cce3Sdanielk1977 ** 17256622cce3Sdanielk1977 ** Returns the UTF-8 representation of the error message string for the 17266622cce3Sdanielk1977 ** most recent sqlite3_* API call. 17276622cce3Sdanielk1977 */ 17286622cce3Sdanielk1977 static int test_errmsg( 17296622cce3Sdanielk1977 void * clientData, 17306622cce3Sdanielk1977 Tcl_Interp *interp, 17316622cce3Sdanielk1977 int objc, 17326622cce3Sdanielk1977 Tcl_Obj *CONST objv[] 17336622cce3Sdanielk1977 ){ 17349bb575fdSdrh sqlite3 *db; 17356622cce3Sdanielk1977 const char *zErr; 17366622cce3Sdanielk1977 17376622cce3Sdanielk1977 if( objc!=2 ){ 17386622cce3Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 17396622cce3Sdanielk1977 Tcl_GetString(objv[0]), " DB", 0); 17406622cce3Sdanielk1977 return TCL_ERROR; 17416622cce3Sdanielk1977 } 17426622cce3Sdanielk1977 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 17436622cce3Sdanielk1977 17446622cce3Sdanielk1977 zErr = sqlite3_errmsg(db); 17456622cce3Sdanielk1977 Tcl_SetObjResult(interp, Tcl_NewStringObj(zErr, -1)); 17466622cce3Sdanielk1977 return TCL_OK; 17476622cce3Sdanielk1977 } 17486622cce3Sdanielk1977 17496622cce3Sdanielk1977 /* 17506622cce3Sdanielk1977 ** Usage: test_errmsg16 DB 17516622cce3Sdanielk1977 ** 17526622cce3Sdanielk1977 ** Returns the UTF-16 representation of the error message string for the 17536622cce3Sdanielk1977 ** most recent sqlite3_* API call. This is a byte array object at the TCL 17546622cce3Sdanielk1977 ** level, and it includes the 0x00 0x00 terminator bytes at the end of the 17556622cce3Sdanielk1977 ** UTF-16 string. 17566622cce3Sdanielk1977 */ 17576622cce3Sdanielk1977 static int test_errmsg16( 17586622cce3Sdanielk1977 void * clientData, 17596622cce3Sdanielk1977 Tcl_Interp *interp, 17606622cce3Sdanielk1977 int objc, 17616622cce3Sdanielk1977 Tcl_Obj *CONST objv[] 17626622cce3Sdanielk1977 ){ 17639bb575fdSdrh sqlite3 *db; 17646622cce3Sdanielk1977 const void *zErr; 17656622cce3Sdanielk1977 int bytes; 17666622cce3Sdanielk1977 17676622cce3Sdanielk1977 if( objc!=2 ){ 17686622cce3Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 17696622cce3Sdanielk1977 Tcl_GetString(objv[0]), " DB", 0); 17706622cce3Sdanielk1977 return TCL_ERROR; 17716622cce3Sdanielk1977 } 17726622cce3Sdanielk1977 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 17736622cce3Sdanielk1977 17746622cce3Sdanielk1977 zErr = sqlite3_errmsg16(db); 17756622cce3Sdanielk1977 bytes = sqlite3utf16ByteLen(zErr, -1); 17766622cce3Sdanielk1977 Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(zErr, bytes)); 17776622cce3Sdanielk1977 return TCL_OK; 17786622cce3Sdanielk1977 } 17796622cce3Sdanielk1977 17806622cce3Sdanielk1977 /* 17816622cce3Sdanielk1977 ** Usage: sqlite3_prepare DB sql bytes tailvar 17826622cce3Sdanielk1977 ** 17836622cce3Sdanielk1977 ** Compile up to <bytes> bytes of the supplied SQL string <sql> using 17846622cce3Sdanielk1977 ** database handle <DB>. The parameter <tailval> is the name of a global 17856622cce3Sdanielk1977 ** variable that is set to the unused portion of <sql> (if any). A 17866622cce3Sdanielk1977 ** STMT handle is returned. 17876622cce3Sdanielk1977 */ 17886622cce3Sdanielk1977 static int test_prepare( 17896622cce3Sdanielk1977 void * clientData, 17906622cce3Sdanielk1977 Tcl_Interp *interp, 17916622cce3Sdanielk1977 int objc, 17926622cce3Sdanielk1977 Tcl_Obj *CONST objv[] 17936622cce3Sdanielk1977 ){ 17946622cce3Sdanielk1977 sqlite3 *db; 17956622cce3Sdanielk1977 const char *zSql; 17966622cce3Sdanielk1977 int bytes; 17976622cce3Sdanielk1977 const char *zTail = 0; 17986622cce3Sdanielk1977 sqlite3_stmt *pStmt = 0; 17996622cce3Sdanielk1977 char zBuf[50]; 18004ad1713cSdanielk1977 int rc; 18016622cce3Sdanielk1977 18026622cce3Sdanielk1977 if( objc!=5 ){ 18036622cce3Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 18046622cce3Sdanielk1977 Tcl_GetString(objv[0]), " DB sql bytes tailvar", 0); 18056622cce3Sdanielk1977 return TCL_ERROR; 18066622cce3Sdanielk1977 } 18076622cce3Sdanielk1977 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 18086622cce3Sdanielk1977 zSql = Tcl_GetString(objv[2]); 18096622cce3Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR; 18106622cce3Sdanielk1977 18114ad1713cSdanielk1977 rc = sqlite3_prepare(db, zSql, bytes, &pStmt, &zTail); 1812c60d0446Sdrh if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; 18136622cce3Sdanielk1977 if( zTail ){ 18146622cce3Sdanielk1977 if( bytes>=0 ){ 18156622cce3Sdanielk1977 bytes = bytes - (zTail-zSql); 18166622cce3Sdanielk1977 } 18176622cce3Sdanielk1977 Tcl_ObjSetVar2(interp, objv[4], 0, Tcl_NewStringObj(zTail, bytes), 0); 18186622cce3Sdanielk1977 } 18194ad1713cSdanielk1977 if( rc!=SQLITE_OK ){ 18204ad1713cSdanielk1977 assert( pStmt==0 ); 18214ad1713cSdanielk1977 sprintf(zBuf, "(%d) ", rc); 18224ad1713cSdanielk1977 Tcl_AppendResult(interp, zBuf, sqlite3_errmsg(db), 0); 18234ad1713cSdanielk1977 return TCL_ERROR; 18244ad1713cSdanielk1977 } 18256622cce3Sdanielk1977 18264ad1713cSdanielk1977 if( pStmt ){ 18276622cce3Sdanielk1977 if( makePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR; 18286622cce3Sdanielk1977 Tcl_AppendResult(interp, zBuf, 0); 18294ad1713cSdanielk1977 } 18306622cce3Sdanielk1977 return TCL_OK; 18316622cce3Sdanielk1977 } 18326622cce3Sdanielk1977 18336622cce3Sdanielk1977 /* 18346622cce3Sdanielk1977 ** Usage: sqlite3_prepare DB sql bytes tailvar 18356622cce3Sdanielk1977 ** 18366622cce3Sdanielk1977 ** Compile up to <bytes> bytes of the supplied SQL string <sql> using 18376622cce3Sdanielk1977 ** database handle <DB>. The parameter <tailval> is the name of a global 18386622cce3Sdanielk1977 ** variable that is set to the unused portion of <sql> (if any). A 18396622cce3Sdanielk1977 ** STMT handle is returned. 18406622cce3Sdanielk1977 */ 18416622cce3Sdanielk1977 static int test_prepare16( 18426622cce3Sdanielk1977 void * clientData, 18436622cce3Sdanielk1977 Tcl_Interp *interp, 18446622cce3Sdanielk1977 int objc, 18456622cce3Sdanielk1977 Tcl_Obj *CONST objv[] 18466622cce3Sdanielk1977 ){ 18476622cce3Sdanielk1977 sqlite3 *db; 18486622cce3Sdanielk1977 const void *zSql; 18496622cce3Sdanielk1977 const void *zTail = 0; 18506622cce3Sdanielk1977 Tcl_Obj *pTail = 0; 18516622cce3Sdanielk1977 sqlite3_stmt *pStmt = 0; 18526622cce3Sdanielk1977 char zBuf[50]; 1853c60d0446Sdrh int rc; 18546622cce3Sdanielk1977 int bytes; /* The integer specified as arg 3 */ 18556622cce3Sdanielk1977 int objlen; /* The byte-array length of arg 2 */ 18566622cce3Sdanielk1977 18576622cce3Sdanielk1977 if( objc!=5 ){ 18586622cce3Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 18596622cce3Sdanielk1977 Tcl_GetString(objv[0]), " DB sql bytes tailvar", 0); 18606622cce3Sdanielk1977 return TCL_ERROR; 18616622cce3Sdanielk1977 } 18626622cce3Sdanielk1977 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 18636622cce3Sdanielk1977 zSql = Tcl_GetByteArrayFromObj(objv[2], &objlen); 18646622cce3Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR; 18656622cce3Sdanielk1977 1866c60d0446Sdrh rc = sqlite3_prepare16(db, zSql, bytes, &pStmt, &zTail); 1867c60d0446Sdrh if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; 1868c60d0446Sdrh if( rc ){ 18696622cce3Sdanielk1977 return TCL_ERROR; 18706622cce3Sdanielk1977 } 18716622cce3Sdanielk1977 18726622cce3Sdanielk1977 if( zTail ){ 18736622cce3Sdanielk1977 objlen = objlen - ((u8 *)zTail-(u8 *)zSql); 18746622cce3Sdanielk1977 }else{ 18756622cce3Sdanielk1977 objlen = 0; 18766622cce3Sdanielk1977 } 18776622cce3Sdanielk1977 pTail = Tcl_NewByteArrayObj((u8 *)zTail, objlen); 18786622cce3Sdanielk1977 Tcl_IncrRefCount(pTail); 18796622cce3Sdanielk1977 Tcl_ObjSetVar2(interp, objv[4], 0, pTail, 0); 18804ad1713cSdanielk1977 Tcl_DecrRefCount(pTail); 18816622cce3Sdanielk1977 18824ad1713cSdanielk1977 if( pStmt ){ 18836622cce3Sdanielk1977 if( makePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR; 18844ad1713cSdanielk1977 } 18856622cce3Sdanielk1977 Tcl_AppendResult(interp, zBuf, 0); 18866622cce3Sdanielk1977 return TCL_OK; 18876622cce3Sdanielk1977 } 18886622cce3Sdanielk1977 18894ad1713cSdanielk1977 /* 18904ad1713cSdanielk1977 ** Usage: sqlite3_open filename ?options-list? 18914ad1713cSdanielk1977 */ 18924ad1713cSdanielk1977 static int test_open( 18934ad1713cSdanielk1977 void * clientData, 18944ad1713cSdanielk1977 Tcl_Interp *interp, 18954ad1713cSdanielk1977 int objc, 18964ad1713cSdanielk1977 Tcl_Obj *CONST objv[] 18974ad1713cSdanielk1977 ){ 18984ad1713cSdanielk1977 const char *zFilename; 18994ad1713cSdanielk1977 sqlite3 *db; 19004ad1713cSdanielk1977 int rc; 19014ad1713cSdanielk1977 char zBuf[100]; 19024ad1713cSdanielk1977 19034ad1713cSdanielk1977 if( objc!=3 && objc!=2 ){ 19044ad1713cSdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 19054ad1713cSdanielk1977 Tcl_GetString(objv[0]), " filename options-list", 0); 19064ad1713cSdanielk1977 return TCL_ERROR; 19074ad1713cSdanielk1977 } 19084ad1713cSdanielk1977 19094ad1713cSdanielk1977 zFilename = Tcl_GetString(objv[1]); 19104f057f90Sdanielk1977 rc = sqlite3_open(zFilename, &db); 19114ad1713cSdanielk1977 19124ad1713cSdanielk1977 if( makePointerStr(interp, zBuf, db) ) return TCL_ERROR; 19134ad1713cSdanielk1977 Tcl_AppendResult(interp, zBuf, 0); 19144ad1713cSdanielk1977 return TCL_OK; 19154ad1713cSdanielk1977 } 19164ad1713cSdanielk1977 19174ad1713cSdanielk1977 /* 19184ad1713cSdanielk1977 ** Usage: sqlite3_open16 filename options 19194ad1713cSdanielk1977 */ 19204ad1713cSdanielk1977 static int test_open16( 19214ad1713cSdanielk1977 void * clientData, 19224ad1713cSdanielk1977 Tcl_Interp *interp, 19234ad1713cSdanielk1977 int objc, 19244ad1713cSdanielk1977 Tcl_Obj *CONST objv[] 19254ad1713cSdanielk1977 ){ 19264ad1713cSdanielk1977 const void *zFilename; 19274ad1713cSdanielk1977 sqlite3 *db; 19284ad1713cSdanielk1977 int rc; 19294ad1713cSdanielk1977 char zBuf[100]; 19304ad1713cSdanielk1977 19314ad1713cSdanielk1977 if( objc!=3 ){ 19324ad1713cSdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 19334ad1713cSdanielk1977 Tcl_GetString(objv[0]), " filename options-list", 0); 19344ad1713cSdanielk1977 return TCL_ERROR; 19354ad1713cSdanielk1977 } 19364ad1713cSdanielk1977 19374ad1713cSdanielk1977 zFilename = Tcl_GetByteArrayFromObj(objv[1], 0); 19384f057f90Sdanielk1977 rc = sqlite3_open16(zFilename, &db); 19394ad1713cSdanielk1977 19404ad1713cSdanielk1977 if( makePointerStr(interp, zBuf, db) ) return TCL_ERROR; 19414ad1713cSdanielk1977 Tcl_AppendResult(interp, zBuf, 0); 19424ad1713cSdanielk1977 return TCL_OK; 19434ad1713cSdanielk1977 } 1944d3d39e93Sdrh 1945d3d39e93Sdrh /* 1946bc6ada41Sdanielk1977 ** Usage: sqlite3_complete16 <UTF-16 string> 1947bc6ada41Sdanielk1977 ** 1948bc6ada41Sdanielk1977 ** Return 1 if the supplied argument is a complete SQL statement, or zero 1949bc6ada41Sdanielk1977 ** otherwise. 1950bc6ada41Sdanielk1977 */ 1951bc6ada41Sdanielk1977 static int test_complete16( 1952bc6ada41Sdanielk1977 void * clientData, 1953bc6ada41Sdanielk1977 Tcl_Interp *interp, 1954bc6ada41Sdanielk1977 int objc, 1955bc6ada41Sdanielk1977 Tcl_Obj *CONST objv[] 1956bc6ada41Sdanielk1977 ){ 1957bc6ada41Sdanielk1977 char *zBuf; 1958bc6ada41Sdanielk1977 1959bc6ada41Sdanielk1977 if( objc!=2 ){ 1960bc6ada41Sdanielk1977 Tcl_WrongNumArgs(interp, 1, objv, "<utf-16 sql>"); 1961bc6ada41Sdanielk1977 return TCL_ERROR; 1962bc6ada41Sdanielk1977 } 1963bc6ada41Sdanielk1977 1964bc6ada41Sdanielk1977 zBuf = Tcl_GetByteArrayFromObj(objv[1], 0); 1965bc6ada41Sdanielk1977 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_complete16(zBuf))); 1966bc6ada41Sdanielk1977 return TCL_OK; 1967bc6ada41Sdanielk1977 } 1968bc6ada41Sdanielk1977 1969bc6ada41Sdanielk1977 /* 1970106bb236Sdanielk1977 ** Usage: sqlite3_step STMT 1971106bb236Sdanielk1977 ** 1972106bb236Sdanielk1977 ** Advance the statement to the next row. 1973106bb236Sdanielk1977 */ 197417240fd9Sdanielk1977 static int test_step( 1975106bb236Sdanielk1977 void * clientData, 1976106bb236Sdanielk1977 Tcl_Interp *interp, 1977106bb236Sdanielk1977 int objc, 1978106bb236Sdanielk1977 Tcl_Obj *CONST objv[] 1979106bb236Sdanielk1977 ){ 1980106bb236Sdanielk1977 sqlite3_stmt *pStmt; 1981106bb236Sdanielk1977 int rc; 1982106bb236Sdanielk1977 1983e1cd9874Sdanielk1977 if( objc!=2 ){ 1984106bb236Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 1985106bb236Sdanielk1977 Tcl_GetString(objv[0]), " STMT", 0); 1986106bb236Sdanielk1977 return TCL_ERROR; 1987106bb236Sdanielk1977 } 1988106bb236Sdanielk1977 1989106bb236Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 199017240fd9Sdanielk1977 rc = sqlite3_step(pStmt); 1991106bb236Sdanielk1977 1992fbcd585fSdanielk1977 /* if( rc!=SQLITE_DONE && rc!=SQLITE_ROW ) return TCL_ERROR; */ 19936590493dSdanielk1977 Tcl_SetResult(interp, (char *)errorName(rc), 0); 1994e1cd9874Sdanielk1977 return TCL_OK; 1995e1cd9874Sdanielk1977 } 1996e1cd9874Sdanielk1977 1997e1cd9874Sdanielk1977 /* 199817240fd9Sdanielk1977 ** Usage: sqlite3_column_count STMT 199917240fd9Sdanielk1977 ** 200017240fd9Sdanielk1977 ** Return the number of columns returned by the sql statement STMT. 200117240fd9Sdanielk1977 */ 200217240fd9Sdanielk1977 static int test_column_count( 200317240fd9Sdanielk1977 void * clientData, 200417240fd9Sdanielk1977 Tcl_Interp *interp, 200517240fd9Sdanielk1977 int objc, 200617240fd9Sdanielk1977 Tcl_Obj *CONST objv[] 200717240fd9Sdanielk1977 ){ 200817240fd9Sdanielk1977 sqlite3_stmt *pStmt; 200917240fd9Sdanielk1977 201017240fd9Sdanielk1977 if( objc!=2 ){ 201117240fd9Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 201217240fd9Sdanielk1977 Tcl_GetString(objv[0]), " STMT column", 0); 201317240fd9Sdanielk1977 return TCL_ERROR; 201417240fd9Sdanielk1977 } 201517240fd9Sdanielk1977 201617240fd9Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 201717240fd9Sdanielk1977 201817240fd9Sdanielk1977 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_column_count(pStmt))); 201917240fd9Sdanielk1977 return TCL_OK; 202017240fd9Sdanielk1977 } 202117240fd9Sdanielk1977 202217240fd9Sdanielk1977 /* 20233cf86063Sdanielk1977 ** Usage: sqlite3_column_type STMT column 20243cf86063Sdanielk1977 ** 20253cf86063Sdanielk1977 ** Return the type of the data in column 'column' of the current row. 20263cf86063Sdanielk1977 */ 20273cf86063Sdanielk1977 static int test_column_type( 20283cf86063Sdanielk1977 void * clientData, 20293cf86063Sdanielk1977 Tcl_Interp *interp, 20303cf86063Sdanielk1977 int objc, 20313cf86063Sdanielk1977 Tcl_Obj *CONST objv[] 20323cf86063Sdanielk1977 ){ 20333cf86063Sdanielk1977 sqlite3_stmt *pStmt; 20343cf86063Sdanielk1977 int col; 20353cf86063Sdanielk1977 int tp; 20363cf86063Sdanielk1977 20373cf86063Sdanielk1977 if( objc!=3 ){ 20383cf86063Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 20393cf86063Sdanielk1977 Tcl_GetString(objv[0]), " STMT column", 0); 20403cf86063Sdanielk1977 return TCL_ERROR; 20413cf86063Sdanielk1977 } 20423cf86063Sdanielk1977 20433cf86063Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 20443cf86063Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; 20453cf86063Sdanielk1977 20463cf86063Sdanielk1977 tp = sqlite3_column_type(pStmt, col); 20473cf86063Sdanielk1977 switch( tp ){ 20489c054830Sdrh case SQLITE_INTEGER: 20493cf86063Sdanielk1977 Tcl_SetResult(interp, "INTEGER", TCL_STATIC); 20503cf86063Sdanielk1977 break; 20519c054830Sdrh case SQLITE_NULL: 20523cf86063Sdanielk1977 Tcl_SetResult(interp, "NULL", TCL_STATIC); 20533cf86063Sdanielk1977 break; 20549c054830Sdrh case SQLITE_FLOAT: 20553cf86063Sdanielk1977 Tcl_SetResult(interp, "FLOAT", TCL_STATIC); 20563cf86063Sdanielk1977 break; 20579c054830Sdrh case SQLITE_TEXT: 20583cf86063Sdanielk1977 Tcl_SetResult(interp, "TEXT", TCL_STATIC); 20593cf86063Sdanielk1977 break; 20609c054830Sdrh case SQLITE_BLOB: 20613cf86063Sdanielk1977 Tcl_SetResult(interp, "BLOB", TCL_STATIC); 20623cf86063Sdanielk1977 break; 20633cf86063Sdanielk1977 default: 20643cf86063Sdanielk1977 assert(0); 20653cf86063Sdanielk1977 } 20663cf86063Sdanielk1977 20673cf86063Sdanielk1977 return TCL_OK; 20683cf86063Sdanielk1977 } 20693cf86063Sdanielk1977 20703cf86063Sdanielk1977 /* 207104f2e68dSdanielk1977 ** Usage: sqlite3_column_int64 STMT column 20723cf86063Sdanielk1977 ** 20733cf86063Sdanielk1977 ** Return the data in column 'column' of the current row cast as an 207404f2e68dSdanielk1977 ** wide (64-bit) integer. 20753cf86063Sdanielk1977 */ 207604f2e68dSdanielk1977 static int test_column_int64( 20773cf86063Sdanielk1977 void * clientData, 20783cf86063Sdanielk1977 Tcl_Interp *interp, 20793cf86063Sdanielk1977 int objc, 20803cf86063Sdanielk1977 Tcl_Obj *CONST objv[] 20813cf86063Sdanielk1977 ){ 20823cf86063Sdanielk1977 sqlite3_stmt *pStmt; 20833cf86063Sdanielk1977 int col; 208404f2e68dSdanielk1977 i64 iVal; 20853cf86063Sdanielk1977 20863cf86063Sdanielk1977 if( objc!=3 ){ 20873cf86063Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 20883cf86063Sdanielk1977 Tcl_GetString(objv[0]), " STMT column", 0); 20893cf86063Sdanielk1977 return TCL_ERROR; 20903cf86063Sdanielk1977 } 20913cf86063Sdanielk1977 20923cf86063Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 20933cf86063Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; 20943cf86063Sdanielk1977 209504f2e68dSdanielk1977 iVal = sqlite3_column_int64(pStmt, col); 209604f2e68dSdanielk1977 Tcl_SetObjResult(interp, Tcl_NewWideIntObj(iVal)); 209704f2e68dSdanielk1977 return TCL_OK; 209804f2e68dSdanielk1977 } 209904f2e68dSdanielk1977 210004f2e68dSdanielk1977 /* 2101ea61b2c4Sdanielk1977 ** Usage: sqlite3_column_blob STMT column 2102ea61b2c4Sdanielk1977 */ 2103ea61b2c4Sdanielk1977 static int test_column_blob( 2104ea61b2c4Sdanielk1977 void * clientData, 2105ea61b2c4Sdanielk1977 Tcl_Interp *interp, 2106ea61b2c4Sdanielk1977 int objc, 2107ea61b2c4Sdanielk1977 Tcl_Obj *CONST objv[] 2108ea61b2c4Sdanielk1977 ){ 2109ea61b2c4Sdanielk1977 sqlite3_stmt *pStmt; 2110ea61b2c4Sdanielk1977 int col; 2111ea61b2c4Sdanielk1977 2112ea61b2c4Sdanielk1977 int len; 2113c572ef7fSdanielk1977 const void *pBlob; 2114ea61b2c4Sdanielk1977 2115ea61b2c4Sdanielk1977 if( objc!=3 ){ 2116ea61b2c4Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 2117ea61b2c4Sdanielk1977 Tcl_GetString(objv[0]), " STMT column", 0); 2118ea61b2c4Sdanielk1977 return TCL_ERROR; 2119ea61b2c4Sdanielk1977 } 2120ea61b2c4Sdanielk1977 2121ea61b2c4Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 2122ea61b2c4Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; 2123ea61b2c4Sdanielk1977 2124ea61b2c4Sdanielk1977 pBlob = sqlite3_column_blob(pStmt, col); 2125ea61b2c4Sdanielk1977 len = sqlite3_column_bytes(pStmt, col); 2126ea61b2c4Sdanielk1977 Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(pBlob, len)); 2127ea61b2c4Sdanielk1977 return TCL_OK; 2128ea61b2c4Sdanielk1977 } 2129ea61b2c4Sdanielk1977 2130ea61b2c4Sdanielk1977 /* 213104f2e68dSdanielk1977 ** Usage: sqlite3_column_double STMT column 213204f2e68dSdanielk1977 ** 213304f2e68dSdanielk1977 ** Return the data in column 'column' of the current row cast as a double. 213404f2e68dSdanielk1977 */ 213504f2e68dSdanielk1977 static int test_column_double( 213604f2e68dSdanielk1977 void * clientData, 213704f2e68dSdanielk1977 Tcl_Interp *interp, 213804f2e68dSdanielk1977 int objc, 213904f2e68dSdanielk1977 Tcl_Obj *CONST objv[] 214004f2e68dSdanielk1977 ){ 214104f2e68dSdanielk1977 sqlite3_stmt *pStmt; 214204f2e68dSdanielk1977 int col; 214304f2e68dSdanielk1977 double rVal; 214404f2e68dSdanielk1977 214504f2e68dSdanielk1977 if( objc!=3 ){ 214604f2e68dSdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 214704f2e68dSdanielk1977 Tcl_GetString(objv[0]), " STMT column", 0); 214804f2e68dSdanielk1977 return TCL_ERROR; 214904f2e68dSdanielk1977 } 215004f2e68dSdanielk1977 215104f2e68dSdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 215204f2e68dSdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; 215304f2e68dSdanielk1977 215404f2e68dSdanielk1977 rVal = sqlite3_column_double(pStmt, col); 2155c572ef7fSdanielk1977 Tcl_SetObjResult(interp, Tcl_NewDoubleObj(rVal)); 21563cf86063Sdanielk1977 return TCL_OK; 21573cf86063Sdanielk1977 } 21583cf86063Sdanielk1977 21593cf86063Sdanielk1977 /* 216017240fd9Sdanielk1977 ** Usage: sqlite3_data_count STMT 216117240fd9Sdanielk1977 ** 216217240fd9Sdanielk1977 ** Return the number of columns returned by the sql statement STMT. 216317240fd9Sdanielk1977 */ 216417240fd9Sdanielk1977 static int test_data_count( 216517240fd9Sdanielk1977 void * clientData, 216617240fd9Sdanielk1977 Tcl_Interp *interp, 216717240fd9Sdanielk1977 int objc, 216817240fd9Sdanielk1977 Tcl_Obj *CONST objv[] 216917240fd9Sdanielk1977 ){ 217017240fd9Sdanielk1977 sqlite3_stmt *pStmt; 217117240fd9Sdanielk1977 217217240fd9Sdanielk1977 if( objc!=2 ){ 217317240fd9Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 217417240fd9Sdanielk1977 Tcl_GetString(objv[0]), " STMT column", 0); 217517240fd9Sdanielk1977 return TCL_ERROR; 217617240fd9Sdanielk1977 } 217717240fd9Sdanielk1977 217817240fd9Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 217917240fd9Sdanielk1977 218017240fd9Sdanielk1977 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_data_count(pStmt))); 218117240fd9Sdanielk1977 return TCL_OK; 218217240fd9Sdanielk1977 } 218317240fd9Sdanielk1977 218417240fd9Sdanielk1977 /* 218504f2e68dSdanielk1977 ** Usage: sqlite3_column_text STMT column 218604f2e68dSdanielk1977 ** 218704f2e68dSdanielk1977 ** Usage: sqlite3_column_decltype STMT column 218804f2e68dSdanielk1977 ** 218904f2e68dSdanielk1977 ** Usage: sqlite3_column_name STMT column 219004f2e68dSdanielk1977 */ 219104f2e68dSdanielk1977 static int test_stmt_utf8( 2192241db313Sdrh void * clientData, /* Pointer to SQLite API function to be invoke */ 219304f2e68dSdanielk1977 Tcl_Interp *interp, 219404f2e68dSdanielk1977 int objc, 219504f2e68dSdanielk1977 Tcl_Obj *CONST objv[] 219604f2e68dSdanielk1977 ){ 219704f2e68dSdanielk1977 sqlite3_stmt *pStmt; 219804f2e68dSdanielk1977 int col; 2199c572ef7fSdanielk1977 const char *(*xFunc)(sqlite3_stmt*, int) = clientData; 2200f93bbbeaSdanielk1977 const char *zRet; 220104f2e68dSdanielk1977 220204f2e68dSdanielk1977 if( objc!=3 ){ 220304f2e68dSdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 220404f2e68dSdanielk1977 Tcl_GetString(objv[0]), " STMT column", 0); 220504f2e68dSdanielk1977 return TCL_ERROR; 220604f2e68dSdanielk1977 } 220704f2e68dSdanielk1977 220804f2e68dSdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 220904f2e68dSdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; 2210f93bbbeaSdanielk1977 zRet = xFunc(pStmt, col); 2211f93bbbeaSdanielk1977 if( zRet ){ 2212f93bbbeaSdanielk1977 Tcl_SetResult(interp, (char *)zRet, 0); 2213f93bbbeaSdanielk1977 } 221404f2e68dSdanielk1977 return TCL_OK; 221504f2e68dSdanielk1977 } 221604f2e68dSdanielk1977 221704f2e68dSdanielk1977 /* 221804f2e68dSdanielk1977 ** Usage: sqlite3_column_text STMT column 221904f2e68dSdanielk1977 ** 222004f2e68dSdanielk1977 ** Usage: sqlite3_column_decltype STMT column 222104f2e68dSdanielk1977 ** 222204f2e68dSdanielk1977 ** Usage: sqlite3_column_name STMT column 222304f2e68dSdanielk1977 */ 222404f2e68dSdanielk1977 static int test_stmt_utf16( 2225241db313Sdrh void * clientData, /* Pointer to SQLite API function to be invoked */ 222604f2e68dSdanielk1977 Tcl_Interp *interp, 222704f2e68dSdanielk1977 int objc, 222804f2e68dSdanielk1977 Tcl_Obj *CONST objv[] 222904f2e68dSdanielk1977 ){ 223004f2e68dSdanielk1977 sqlite3_stmt *pStmt; 223104f2e68dSdanielk1977 int col; 223204f2e68dSdanielk1977 Tcl_Obj *pRet; 223304f2e68dSdanielk1977 const void *zName16; 2234c572ef7fSdanielk1977 const void *(*xFunc)(sqlite3_stmt*, int) = clientData; 223504f2e68dSdanielk1977 223604f2e68dSdanielk1977 if( objc!=3 ){ 223704f2e68dSdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 223804f2e68dSdanielk1977 Tcl_GetString(objv[0]), " STMT column", 0); 223904f2e68dSdanielk1977 return TCL_ERROR; 224004f2e68dSdanielk1977 } 224104f2e68dSdanielk1977 224204f2e68dSdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 224304f2e68dSdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; 224404f2e68dSdanielk1977 224504f2e68dSdanielk1977 zName16 = xFunc(pStmt, col); 2246f93bbbeaSdanielk1977 if( zName16 ){ 224704f2e68dSdanielk1977 pRet = Tcl_NewByteArrayObj(zName16, sqlite3utf16ByteLen(zName16, -1)+2); 224804f2e68dSdanielk1977 Tcl_SetObjResult(interp, pRet); 2249f93bbbeaSdanielk1977 } 225004f2e68dSdanielk1977 225104f2e68dSdanielk1977 return TCL_OK; 225204f2e68dSdanielk1977 } 225304f2e68dSdanielk1977 225404f2e68dSdanielk1977 /* 225504f2e68dSdanielk1977 ** Usage: sqlite3_column_int STMT column 225604f2e68dSdanielk1977 ** 225704f2e68dSdanielk1977 ** Usage: sqlite3_column_bytes STMT column 225804f2e68dSdanielk1977 ** 225904f2e68dSdanielk1977 ** Usage: sqlite3_column_bytes16 STMT column 226004f2e68dSdanielk1977 ** 226104f2e68dSdanielk1977 */ 226204f2e68dSdanielk1977 static int test_stmt_int( 2263241db313Sdrh void * clientData, /* Pointer to SQLite API function to be invoked */ 226404f2e68dSdanielk1977 Tcl_Interp *interp, 226504f2e68dSdanielk1977 int objc, 226604f2e68dSdanielk1977 Tcl_Obj *CONST objv[] 226704f2e68dSdanielk1977 ){ 226804f2e68dSdanielk1977 sqlite3_stmt *pStmt; 226904f2e68dSdanielk1977 int col; 2270c572ef7fSdanielk1977 int (*xFunc)(sqlite3_stmt*, int) = clientData; 227104f2e68dSdanielk1977 227204f2e68dSdanielk1977 if( objc!=3 ){ 227304f2e68dSdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 227404f2e68dSdanielk1977 Tcl_GetString(objv[0]), " STMT column", 0); 227504f2e68dSdanielk1977 return TCL_ERROR; 227604f2e68dSdanielk1977 } 227704f2e68dSdanielk1977 227804f2e68dSdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 227904f2e68dSdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; 228004f2e68dSdanielk1977 228104f2e68dSdanielk1977 Tcl_SetObjResult(interp, Tcl_NewIntObj(xFunc(pStmt, col))); 228204f2e68dSdanielk1977 return TCL_OK; 228304f2e68dSdanielk1977 } 228404f2e68dSdanielk1977 22859a1d0abeSdanielk1977 /* 22869a1d0abeSdanielk1977 ** Usage: sqlite3OsOpenReadWrite <filename> 22879a1d0abeSdanielk1977 */ 22889a1d0abeSdanielk1977 static int test_sqlite3OsOpenReadWrite( 22899a1d0abeSdanielk1977 void * clientData, 22909a1d0abeSdanielk1977 Tcl_Interp *interp, 22919a1d0abeSdanielk1977 int objc, 22929a1d0abeSdanielk1977 Tcl_Obj *CONST objv[] 22939a1d0abeSdanielk1977 ){ 22949a1d0abeSdanielk1977 OsFile * pFile; 22959a1d0abeSdanielk1977 int rc; 22969a1d0abeSdanielk1977 int dummy; 22979a1d0abeSdanielk1977 char zBuf[100]; 229804f2e68dSdanielk1977 22999a1d0abeSdanielk1977 if( objc!=2 ){ 23009a1d0abeSdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 23019a1d0abeSdanielk1977 Tcl_GetString(objv[0]), " filename", 0); 23029a1d0abeSdanielk1977 return TCL_ERROR; 23039a1d0abeSdanielk1977 } 23049a1d0abeSdanielk1977 23059a1d0abeSdanielk1977 pFile = sqliteMalloc(sizeof(OsFile)); 23069a1d0abeSdanielk1977 rc = sqlite3OsOpenReadWrite(Tcl_GetString(objv[1]), pFile, &dummy); 23079a1d0abeSdanielk1977 if( rc!=SQLITE_OK ){ 23089a1d0abeSdanielk1977 sqliteFree(pFile); 23099a1d0abeSdanielk1977 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC); 23109a1d0abeSdanielk1977 return TCL_ERROR; 23119a1d0abeSdanielk1977 } 23129a1d0abeSdanielk1977 makePointerStr(interp, zBuf, pFile); 23139a1d0abeSdanielk1977 Tcl_SetResult(interp, zBuf, 0); 23149a1d0abeSdanielk1977 return TCL_ERROR; 23159a1d0abeSdanielk1977 } 23169a1d0abeSdanielk1977 23179a1d0abeSdanielk1977 /* 23189a1d0abeSdanielk1977 ** Usage: sqlite3OsClose <file handle> 23199a1d0abeSdanielk1977 */ 23209a1d0abeSdanielk1977 static int test_sqlite3OsClose( 23219a1d0abeSdanielk1977 void * clientData, 23229a1d0abeSdanielk1977 Tcl_Interp *interp, 23239a1d0abeSdanielk1977 int objc, 23249a1d0abeSdanielk1977 Tcl_Obj *CONST objv[] 23259a1d0abeSdanielk1977 ){ 23269a1d0abeSdanielk1977 OsFile * pFile; 23279a1d0abeSdanielk1977 int rc; 23289a1d0abeSdanielk1977 23299a1d0abeSdanielk1977 if( objc!=2 ){ 23309a1d0abeSdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 23319a1d0abeSdanielk1977 Tcl_GetString(objv[0]), " filehandle", 0); 23329a1d0abeSdanielk1977 return TCL_ERROR; 23339a1d0abeSdanielk1977 } 23349a1d0abeSdanielk1977 23359a1d0abeSdanielk1977 if( getFilePointer(interp, Tcl_GetString(objv[1]), &pFile) ){ 23369a1d0abeSdanielk1977 return TCL_ERROR; 23379a1d0abeSdanielk1977 } 23389a1d0abeSdanielk1977 rc = sqlite3OsClose(pFile); 23399a1d0abeSdanielk1977 if( rc!=SQLITE_OK ){ 23409a1d0abeSdanielk1977 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC); 23419a1d0abeSdanielk1977 return TCL_ERROR; 23429a1d0abeSdanielk1977 } 23439a1d0abeSdanielk1977 sqliteFree(pFile); 23449a1d0abeSdanielk1977 return TCL_OK; 23459a1d0abeSdanielk1977 } 23469a1d0abeSdanielk1977 23479a1d0abeSdanielk1977 /* 23489a1d0abeSdanielk1977 ** Usage: sqlite3OsLock <file handle> <locktype> 23499a1d0abeSdanielk1977 */ 23509a1d0abeSdanielk1977 static int test_sqlite3OsLock( 23519a1d0abeSdanielk1977 void * clientData, 23529a1d0abeSdanielk1977 Tcl_Interp *interp, 23539a1d0abeSdanielk1977 int objc, 23549a1d0abeSdanielk1977 Tcl_Obj *CONST objv[] 23559a1d0abeSdanielk1977 ){ 23569a1d0abeSdanielk1977 OsFile * pFile; 23579a1d0abeSdanielk1977 int rc; 23589a1d0abeSdanielk1977 23599a1d0abeSdanielk1977 if( objc!=3 ){ 23609a1d0abeSdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 23619a1d0abeSdanielk1977 Tcl_GetString(objv[0]), 23629a1d0abeSdanielk1977 " filehandle (SHARED|RESERVED|PENDING|EXCLUSIVE)", 0); 23639a1d0abeSdanielk1977 return TCL_ERROR; 23649a1d0abeSdanielk1977 } 23659a1d0abeSdanielk1977 23669a1d0abeSdanielk1977 if( getFilePointer(interp, Tcl_GetString(objv[1]), &pFile) ){ 23679a1d0abeSdanielk1977 return TCL_ERROR; 23689a1d0abeSdanielk1977 } 23699a1d0abeSdanielk1977 23709a1d0abeSdanielk1977 if( 0==strcmp("SHARED", Tcl_GetString(objv[2])) ){ 23719a1d0abeSdanielk1977 rc = sqlite3OsLock(pFile, SHARED_LOCK); 23729a1d0abeSdanielk1977 } 23739a1d0abeSdanielk1977 else if( 0==strcmp("RESERVED", Tcl_GetString(objv[2])) ){ 23749a1d0abeSdanielk1977 rc = sqlite3OsLock(pFile, RESERVED_LOCK); 23759a1d0abeSdanielk1977 } 23769a1d0abeSdanielk1977 else if( 0==strcmp("PENDING", Tcl_GetString(objv[2])) ){ 23779a1d0abeSdanielk1977 rc = sqlite3OsLock(pFile, PENDING_LOCK); 23789a1d0abeSdanielk1977 } 23799a1d0abeSdanielk1977 else if( 0==strcmp("EXCLUSIVE", Tcl_GetString(objv[2])) ){ 23809a1d0abeSdanielk1977 rc = sqlite3OsLock(pFile, EXCLUSIVE_LOCK); 23819a1d0abeSdanielk1977 }else{ 23829a1d0abeSdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 23839a1d0abeSdanielk1977 Tcl_GetString(objv[0]), 23849a1d0abeSdanielk1977 " filehandle (SHARED|RESERVED|PENDING|EXCLUSIVE)", 0); 23859a1d0abeSdanielk1977 return TCL_ERROR; 23869a1d0abeSdanielk1977 } 23879a1d0abeSdanielk1977 23889a1d0abeSdanielk1977 if( rc!=SQLITE_OK ){ 23899a1d0abeSdanielk1977 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC); 23909a1d0abeSdanielk1977 return TCL_ERROR; 23919a1d0abeSdanielk1977 } 23929a1d0abeSdanielk1977 return TCL_OK; 23939a1d0abeSdanielk1977 } 23949a1d0abeSdanielk1977 23959a1d0abeSdanielk1977 /* 23969a1d0abeSdanielk1977 ** Usage: sqlite3OsUnlock <file handle> 23979a1d0abeSdanielk1977 */ 23989a1d0abeSdanielk1977 static int test_sqlite3OsUnlock( 23999a1d0abeSdanielk1977 void * clientData, 24009a1d0abeSdanielk1977 Tcl_Interp *interp, 24019a1d0abeSdanielk1977 int objc, 24029a1d0abeSdanielk1977 Tcl_Obj *CONST objv[] 24039a1d0abeSdanielk1977 ){ 24049a1d0abeSdanielk1977 OsFile * pFile; 24059a1d0abeSdanielk1977 int rc; 24069a1d0abeSdanielk1977 24079a1d0abeSdanielk1977 if( objc!=2 ){ 24089a1d0abeSdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 24099a1d0abeSdanielk1977 Tcl_GetString(objv[0]), " filehandle", 0); 24109a1d0abeSdanielk1977 return TCL_ERROR; 24119a1d0abeSdanielk1977 } 24129a1d0abeSdanielk1977 24139a1d0abeSdanielk1977 if( getFilePointer(interp, Tcl_GetString(objv[1]), &pFile) ){ 24149a1d0abeSdanielk1977 return TCL_ERROR; 24159a1d0abeSdanielk1977 } 2416a6abd041Sdrh rc = sqlite3OsUnlock(pFile, NO_LOCK); 24179a1d0abeSdanielk1977 if( rc!=SQLITE_OK ){ 24189a1d0abeSdanielk1977 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC); 24199a1d0abeSdanielk1977 return TCL_ERROR; 24209a1d0abeSdanielk1977 } 24219a1d0abeSdanielk1977 return TCL_OK; 24229a1d0abeSdanielk1977 } 2423d3d39e93Sdrh 2424ab3f9feaSdrh /* 2425ab3f9feaSdrh ** Usage: sqlite3OsTempFileName 2426ab3f9feaSdrh */ 2427ab3f9feaSdrh static int test_sqlite3OsTempFileName( 2428ab3f9feaSdrh void * clientData, 2429ab3f9feaSdrh Tcl_Interp *interp, 2430ab3f9feaSdrh int objc, 2431ab3f9feaSdrh Tcl_Obj *CONST objv[] 2432ab3f9feaSdrh ){ 2433ab3f9feaSdrh char zFile[SQLITE_TEMPNAME_SIZE]; 2434ab3f9feaSdrh int rc; 2435ab3f9feaSdrh 2436ab3f9feaSdrh rc = sqlite3OsTempFileName(zFile); 2437ab3f9feaSdrh if( rc!=SQLITE_OK ){ 2438ab3f9feaSdrh Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC); 2439ab3f9feaSdrh return TCL_ERROR; 2440ab3f9feaSdrh } 2441ab3f9feaSdrh Tcl_AppendResult(interp, zFile, 0); 2442ab3f9feaSdrh return TCL_OK; 2443ab3f9feaSdrh } 2444d8123366Sdanielk1977 24456622cce3Sdanielk1977 /* 244692febd92Sdrh ** Usage: tcl_variable_type VARIABLENAME 244792febd92Sdrh ** 244892febd92Sdrh ** Return the name of the internal representation for the 244992febd92Sdrh ** value of the given variable. 245092febd92Sdrh */ 245192febd92Sdrh static int tcl_variable_type( 245292febd92Sdrh void * clientData, 245392febd92Sdrh Tcl_Interp *interp, 245492febd92Sdrh int objc, 245592febd92Sdrh Tcl_Obj *CONST objv[] 245692febd92Sdrh ){ 245792febd92Sdrh Tcl_Obj *pVar; 245892febd92Sdrh if( objc!=2 ){ 245992febd92Sdrh Tcl_WrongNumArgs(interp, 1, objv, "VARIABLE"); 246092febd92Sdrh return TCL_ERROR; 246192febd92Sdrh } 246292febd92Sdrh pVar = Tcl_GetVar2Ex(interp, Tcl_GetString(objv[1]), 0, TCL_LEAVE_ERR_MSG); 246392febd92Sdrh if( pVar==0 ) return TCL_ERROR; 246492febd92Sdrh if( pVar->typePtr ){ 246592febd92Sdrh Tcl_SetObjResult(interp, Tcl_NewStringObj(pVar->typePtr->name, -1)); 246692febd92Sdrh } 246792febd92Sdrh return TCL_OK; 246892febd92Sdrh } 246992febd92Sdrh 247092febd92Sdrh /* 2471*27d258a3Sdrh ** This routine sets entries in the global ::sqlite_options() array variable 2472*27d258a3Sdrh ** according to the compile-time configuration of the database. Test 2473*27d258a3Sdrh ** procedures use this to determine when tests should be omitted. 2474*27d258a3Sdrh */ 2475*27d258a3Sdrh static void set_options(Tcl_Interp *interp){ 2476*27d258a3Sdrh #ifdef SQLITE_OMIT_AUTHORIZATION 2477*27d258a3Sdrh Tcl_SetVar2(interp, "sqlite_options", "auth", "0", TCL_GLOBAL_ONLY); 2478*27d258a3Sdrh #else 2479*27d258a3Sdrh Tcl_SetVar2(interp, "sqlite_options", "auth", "1", TCL_GLOBAL_ONLY); 2480*27d258a3Sdrh #endif 2481*27d258a3Sdrh #ifdef SQLITE_OMIT_VACUUM 2482*27d258a3Sdrh Tcl_SetVar2(interp, "sqlite_options", "vacuum", "0", TCL_GLOBAL_ONLY); 2483*27d258a3Sdrh #else 2484*27d258a3Sdrh Tcl_SetVar2(interp, "sqlite_options", "vacuum", "1", TCL_GLOBAL_ONLY); 2485*27d258a3Sdrh #endif 2486*27d258a3Sdrh #ifdef SQLITE_OMIT_PROGRESS_CALLBACK 2487*27d258a3Sdrh Tcl_SetVar2(interp, "sqlite_options", "progress", "0", TCL_GLOBAL_ONLY); 2488*27d258a3Sdrh #else 2489*27d258a3Sdrh Tcl_SetVar2(interp, "sqlite_options", "progress", "1", TCL_GLOBAL_ONLY); 2490*27d258a3Sdrh #endif 2491*27d258a3Sdrh #ifdef SQLITE_OMIT_DATETIME_FUNCS 2492*27d258a3Sdrh Tcl_SetVar2(interp, "sqlite_options", "datetime", "0", TCL_GLOBAL_ONLY); 2493*27d258a3Sdrh #else 2494*27d258a3Sdrh Tcl_SetVar2(interp, "sqlite_options", "datatime", "1", TCL_GLOBAL_ONLY); 2495*27d258a3Sdrh #endif 2496*27d258a3Sdrh #if defined(THREADSAFE) && THREADSAFE 2497*27d258a3Sdrh Tcl_SetVar2(interp, "sqlite_options", "threadsafe", "1", TCL_GLOBAL_ONLY); 2498*27d258a3Sdrh #else 2499*27d258a3Sdrh Tcl_SetVar2(interp, "sqlite_options", "threadsafe", "0", TCL_GLOBAL_ONLY); 2500*27d258a3Sdrh #endif 2501*27d258a3Sdrh #ifdef SQLITE_OMIT_COMPOUND_SELECT 2502*27d258a3Sdrh Tcl_SetVar2(interp, "sqlite_options", "compound", "0", TCL_GLOBAL_ONLY); 2503*27d258a3Sdrh #else 2504*27d258a3Sdrh Tcl_SetVar2(interp, "sqlite_options", "compound", "1", TCL_GLOBAL_ONLY); 2505*27d258a3Sdrh #endif 2506*27d258a3Sdrh #ifdef SQLITE_OMIT_TRIGGER 2507*27d258a3Sdrh Tcl_SetVar2(interp, "sqlite_options", "trigger", "0", TCL_GLOBAL_ONLY); 2508*27d258a3Sdrh #else 2509*27d258a3Sdrh Tcl_SetVar2(interp, "sqlite_options", "trigger", "1", TCL_GLOBAL_ONLY); 2510*27d258a3Sdrh #endif 2511*27d258a3Sdrh #ifdef SQLITE_OMIT_VIEW 2512*27d258a3Sdrh Tcl_SetVar2(interp, "sqlite_options", "view", "0", TCL_GLOBAL_ONLY); 2513*27d258a3Sdrh #else 2514*27d258a3Sdrh Tcl_SetVar2(interp, "sqlite_options", "view", "1", TCL_GLOBAL_ONLY); 2515*27d258a3Sdrh #endif 2516*27d258a3Sdrh #ifdef SQLITE_OMIT_INTEGRITY_CHECK 2517*27d258a3Sdrh Tcl_SetVar2(interp, "sqlite_options", "integrityck", "0", TCL_GLOBAL_ONLY); 2518*27d258a3Sdrh #else 2519*27d258a3Sdrh Tcl_SetVar2(interp, "sqlite_options", "integrityck", "1", TCL_GLOBAL_ONLY); 2520*27d258a3Sdrh #endif 2521*27d258a3Sdrh #ifdef SQLITE_OMIT_FOREIGN_KEY 2522*27d258a3Sdrh Tcl_SetVar2(interp, "sqlite_options", "foreignkey", "0", TCL_GLOBAL_ONLY); 2523*27d258a3Sdrh #else 2524*27d258a3Sdrh Tcl_SetVar2(interp, "sqlite_options", "foreignkey", "1", TCL_GLOBAL_ONLY); 2525*27d258a3Sdrh #endif 2526*27d258a3Sdrh #ifdef SQLITE_OMIT_CONFLICT_CLAUSE 2527*27d258a3Sdrh Tcl_SetVar2(interp, "sqlite_options", "conflict", "0", TCL_GLOBAL_ONLY); 2528*27d258a3Sdrh #else 2529*27d258a3Sdrh Tcl_SetVar2(interp, "sqlite_options", "conflict", "1", TCL_GLOBAL_ONLY); 2530*27d258a3Sdrh #endif 2531*27d258a3Sdrh } 2532*27d258a3Sdrh 2533*27d258a3Sdrh /* 2534d1bf3512Sdrh ** Register commands with the TCL interpreter. 2535d1bf3512Sdrh */ 2536d1bf3512Sdrh int Sqlitetest1_Init(Tcl_Interp *interp){ 25376f8a503dSdanielk1977 extern int sqlite3_search_count; 25386f8a503dSdanielk1977 extern int sqlite3_interrupt_count; 25396f8a503dSdanielk1977 extern int sqlite3_open_file_count; 25406f8a503dSdanielk1977 extern int sqlite3_current_time; 2541c2eef3b3Sdrh static struct { 2542c2eef3b3Sdrh char *zName; 2543c2eef3b3Sdrh Tcl_CmdProc *xProc; 2544c2eef3b3Sdrh } aCmd[] = { 25456f8a503dSdanielk1977 { "sqlite3_mprintf_int", (Tcl_CmdProc*)sqlite3_mprintf_int }, 2546e9707671Sdrh { "sqlite3_mprintf_int64", (Tcl_CmdProc*)sqlite3_mprintf_int64 }, 25476f8a503dSdanielk1977 { "sqlite3_mprintf_str", (Tcl_CmdProc*)sqlite3_mprintf_str }, 2548e29b1a05Sdrh { "sqlite3_mprintf_stronly", (Tcl_CmdProc*)sqlite3_mprintf_stronly}, 25496f8a503dSdanielk1977 { "sqlite3_mprintf_double", (Tcl_CmdProc*)sqlite3_mprintf_double }, 25506f8a503dSdanielk1977 { "sqlite3_mprintf_scaled", (Tcl_CmdProc*)sqlite3_mprintf_scaled }, 25516f8a503dSdanielk1977 { "sqlite3_mprintf_z_test", (Tcl_CmdProc*)test_mprintf_z }, 25526f8a503dSdanielk1977 { "sqlite3_last_insert_rowid", (Tcl_CmdProc*)test_last_rowid }, 25536f8a503dSdanielk1977 { "sqlite3_exec_printf", (Tcl_CmdProc*)test_exec_printf }, 25546f8a503dSdanielk1977 { "sqlite3_get_table_printf", (Tcl_CmdProc*)test_get_table_printf }, 25556f8a503dSdanielk1977 { "sqlite3_close", (Tcl_CmdProc*)sqlite_test_close }, 25566f8a503dSdanielk1977 { "sqlite3_create_function", (Tcl_CmdProc*)test_create_function }, 25576f8a503dSdanielk1977 { "sqlite3_create_aggregate", (Tcl_CmdProc*)test_create_aggregate }, 2558c2eef3b3Sdrh { "sqlite_register_test_function", (Tcl_CmdProc*)test_register_func }, 2559c2eef3b3Sdrh { "sqlite_abort", (Tcl_CmdProc*)sqlite_abort }, 2560faa57accSdrh #ifdef SQLITE_DEBUG 2561c2eef3b3Sdrh { "sqlite_malloc_fail", (Tcl_CmdProc*)sqlite_malloc_fail }, 2562c2eef3b3Sdrh { "sqlite_malloc_stat", (Tcl_CmdProc*)sqlite_malloc_stat }, 2563c2eef3b3Sdrh #endif 256496fc5fe6Sdanielk1977 { "sqlite_bind", (Tcl_CmdProc*)test_bind }, 256599ee3600Sdrh { "breakpoint", (Tcl_CmdProc*)test_breakpoint }, 256625d6543dSdrh { "sqlite3_key", (Tcl_CmdProc*)test_key }, 256725d6543dSdrh { "sqlite3_rekey", (Tcl_CmdProc*)test_rekey }, 2568c2eef3b3Sdrh }; 256951e3d8e2Sdanielk1977 static struct { 257051e3d8e2Sdanielk1977 char *zName; 257151e3d8e2Sdanielk1977 Tcl_ObjCmdProc *xProc; 257204f2e68dSdanielk1977 void *clientData; 257351e3d8e2Sdanielk1977 } aObjCmd[] = { 2574241db313Sdrh { "sqlite3_bind_int", test_bind_int, 0 }, 257504f2e68dSdanielk1977 { "sqlite3_bind_int64", test_bind_int64, 0 }, 257604f2e68dSdanielk1977 { "sqlite3_bind_double", test_bind_double, 0 }, 257704f2e68dSdanielk1977 { "sqlite3_bind_null", test_bind_null ,0 }, 257804f2e68dSdanielk1977 { "sqlite3_bind_text", test_bind_text ,0 }, 257904f2e68dSdanielk1977 { "sqlite3_bind_text16", test_bind_text16 ,0 }, 258004f2e68dSdanielk1977 { "sqlite3_bind_blob", test_bind_blob ,0 }, 258175f6a032Sdrh { "sqlite3_bind_parameter_count", test_bind_parameter_count, 0}, 2582895d7472Sdrh { "sqlite3_bind_parameter_name", test_bind_parameter_name, 0}, 2583fa6bc000Sdrh { "sqlite3_bind_parameter_index", test_bind_parameter_index, 0}, 258404f2e68dSdanielk1977 { "sqlite3_errcode", test_errcode ,0 }, 258504f2e68dSdanielk1977 { "sqlite3_errmsg", test_errmsg ,0 }, 258604f2e68dSdanielk1977 { "sqlite3_errmsg16", test_errmsg16 ,0 }, 258704f2e68dSdanielk1977 { "sqlite3_open", test_open ,0 }, 258804f2e68dSdanielk1977 { "sqlite3_open16", test_open16 ,0 }, 2589bc6ada41Sdanielk1977 { "sqlite3_complete16", test_complete16 ,0 }, 259004f2e68dSdanielk1977 259104f2e68dSdanielk1977 { "sqlite3_prepare", test_prepare ,0 }, 259204f2e68dSdanielk1977 { "sqlite3_prepare16", test_prepare16 ,0 }, 259304f2e68dSdanielk1977 { "sqlite3_finalize", test_finalize ,0 }, 259404f2e68dSdanielk1977 { "sqlite3_reset", test_reset ,0 }, 2595fbcd585fSdanielk1977 { "sqlite3_changes", test_changes ,0 }, 259604f2e68dSdanielk1977 { "sqlite3_step", test_step ,0 }, 259704f2e68dSdanielk1977 259804f2e68dSdanielk1977 /* sqlite3_column_*() API */ 259904f2e68dSdanielk1977 { "sqlite3_column_count", test_column_count ,0 }, 260004f2e68dSdanielk1977 { "sqlite3_data_count", test_data_count ,0 }, 260104f2e68dSdanielk1977 { "sqlite3_column_type", test_column_type ,0 }, 2602ea61b2c4Sdanielk1977 { "sqlite3_column_blob", test_column_blob ,0 }, 260304f2e68dSdanielk1977 { "sqlite3_column_double", test_column_double ,0 }, 260404f2e68dSdanielk1977 { "sqlite3_column_int64", test_column_int64 ,0 }, 260504f2e68dSdanielk1977 { "sqlite3_column_int", test_stmt_int, sqlite3_column_int }, 260604f2e68dSdanielk1977 { "sqlite3_column_bytes", test_stmt_int, sqlite3_column_bytes }, 260704f2e68dSdanielk1977 { "sqlite3_column_bytes16", test_stmt_int, sqlite3_column_bytes16 }, 260804f2e68dSdanielk1977 { "sqlite3_column_text", test_stmt_utf8, sqlite3_column_text }, 260904f2e68dSdanielk1977 { "sqlite3_column_decltype", test_stmt_utf8, sqlite3_column_decltype }, 261004f2e68dSdanielk1977 { "sqlite3_column_name", test_stmt_utf8, sqlite3_column_name }, 261104f2e68dSdanielk1977 { "sqlite3_column_text16", test_stmt_utf16, sqlite3_column_text16 }, 261204f2e68dSdanielk1977 { "sqlite3_column_decltype16", test_stmt_utf16, sqlite3_column_decltype16}, 261304f2e68dSdanielk1977 { "sqlite3_column_name16", test_stmt_utf16, sqlite3_column_name16 }, 261404f2e68dSdanielk1977 26159a1d0abeSdanielk1977 /* Functions from os.h */ 26169a1d0abeSdanielk1977 { "sqlite3OsOpenReadWrite",test_sqlite3OsOpenReadWrite, 0 }, 26179a1d0abeSdanielk1977 { "sqlite3OsClose", test_sqlite3OsClose, 0 }, 26189a1d0abeSdanielk1977 { "sqlite3OsLock", test_sqlite3OsLock, 0 }, 2619ab3f9feaSdrh { "sqlite3OsTempFileName", test_sqlite3OsTempFileName, 0 }, 2620312d6b36Sdanielk1977 2621312d6b36Sdanielk1977 /* Custom test interfaces */ 26229a1d0abeSdanielk1977 { "sqlite3OsUnlock", test_sqlite3OsUnlock, 0 }, 26234e6af134Sdanielk1977 { "add_test_collate", test_collate, 0 }, 2624312d6b36Sdanielk1977 { "add_test_collate_needed", test_collate_needed, 0 }, 2625c8e9a2dfSdanielk1977 { "add_test_function", test_function, 0 }, 2626c8e9a2dfSdanielk1977 { "sqlite3_crashparams", sqlite3_crashparams, 0 }, 2627312d6b36Sdanielk1977 { "sqlite3_test_errstr", test_errstr, 0 }, 262892febd92Sdrh { "tcl_variable_type", tcl_variable_type, 0 }, 262951e3d8e2Sdanielk1977 }; 2630c2eef3b3Sdrh int i; 26312ac3ee97Sdrh extern int sqlite3_os_trace; 2632c2eef3b3Sdrh 2633c2eef3b3Sdrh for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){ 2634c2eef3b3Sdrh Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0); 2635c2eef3b3Sdrh } 263651e3d8e2Sdanielk1977 for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){ 2637c572ef7fSdanielk1977 Tcl_CreateObjCommand(interp, aObjCmd[i].zName, 2638c572ef7fSdanielk1977 aObjCmd[i].xProc, aObjCmd[i].clientData, 0); 263951e3d8e2Sdanielk1977 } 26406490bebdSdanielk1977 Tcl_LinkVar(interp, "sqlite_search_count", 26416f8a503dSdanielk1977 (char*)&sqlite3_search_count, TCL_LINK_INT); 26426490bebdSdanielk1977 Tcl_LinkVar(interp, "sqlite_interrupt_count", 26436f8a503dSdanielk1977 (char*)&sqlite3_interrupt_count, TCL_LINK_INT); 26446490bebdSdanielk1977 Tcl_LinkVar(interp, "sqlite_open_file_count", 26456f8a503dSdanielk1977 (char*)&sqlite3_open_file_count, TCL_LINK_INT); 26466490bebdSdanielk1977 Tcl_LinkVar(interp, "sqlite_current_time", 26476f8a503dSdanielk1977 (char*)&sqlite3_current_time, TCL_LINK_INT); 26482ac3ee97Sdrh Tcl_LinkVar(interp, "sqlite_os_trace", 26492ac3ee97Sdrh (char*)&sqlite3_os_trace, TCL_LINK_INT); 26507c972decSdrh Tcl_LinkVar(interp, "sqlite_static_bind_value", 26517c972decSdrh (char*)&sqlite_static_bind_value, TCL_LINK_STRING); 2652ab3f9feaSdrh Tcl_LinkVar(interp, "sqlite_temp_directory", 2653effd02bcSdrh (char*)&sqlite3_temp_directory, TCL_LINK_STRING); 2654*27d258a3Sdrh set_options(interp); 2655d1bf3512Sdrh return TCL_OK; 2656d1bf3512Sdrh } 2657