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*faa57accSdrh ** $Id: test1.c,v 1.73 2004/06/09 14:01:51 drh Exp $ 17d1bf3512Sdrh */ 18d1bf3512Sdrh #include "sqliteInt.h" 19d1bf3512Sdrh #include "tcl.h" 2094e92032Sdrh #include "os.h" 21d1bf3512Sdrh #include <stdlib.h> 22d1bf3512Sdrh #include <string.h> 23d1bf3512Sdrh 2494e92032Sdrh #if OS_WIN 2594e92032Sdrh # define PTR_FMT "%x" 2694e92032Sdrh #else 2794e92032Sdrh # define PTR_FMT "%p" 2894e92032Sdrh #endif 2994e92032Sdrh 30c572ef7fSdanielk1977 int sqlite3_exec_printf( 31c572ef7fSdanielk1977 sqlite *db, /* An open database */ 32c572ef7fSdanielk1977 const char *sqlFormat, /* printf-style format string for the SQL */ 33c572ef7fSdanielk1977 sqlite_callback xCallback, /* Callback function */ 34c572ef7fSdanielk1977 void *pArg, /* 1st argument to callback function */ 35c572ef7fSdanielk1977 char **errmsg, /* Error msg written here */ 36c572ef7fSdanielk1977 ... /* Arguments to the format string. */ 37c572ef7fSdanielk1977 ); 38c572ef7fSdanielk1977 int sqlite3_exec_printf( 39c572ef7fSdanielk1977 sqlite *db, /* An open database */ 40c572ef7fSdanielk1977 const char *sqlFormat, /* printf-style format string for the SQL */ 41c572ef7fSdanielk1977 sqlite_callback xCallback, /* Callback function */ 42c572ef7fSdanielk1977 void *pArg, /* 1st argument to callback function */ 43c572ef7fSdanielk1977 char **errmsg, /* Error msg written here */ 44c572ef7fSdanielk1977 ... /* Arguments to the format string. */ 45c572ef7fSdanielk1977 ); 46c572ef7fSdanielk1977 int sqlite3_get_table_printf( 47c572ef7fSdanielk1977 sqlite *db, /* An open database */ 48c572ef7fSdanielk1977 const char *sqlFormat, /* printf-style format string for the SQL */ 49c572ef7fSdanielk1977 char ***resultp, /* Result written to a char *[] that this points to */ 50c572ef7fSdanielk1977 int *nrow, /* Number of result rows written here */ 51c572ef7fSdanielk1977 int *ncol, /* Number of result columns written here */ 52c572ef7fSdanielk1977 char **errmsg, /* Error msg written here */ 53c572ef7fSdanielk1977 ... /* Arguments to the format string */ 54c572ef7fSdanielk1977 ); 55c572ef7fSdanielk1977 566622cce3Sdanielk1977 static const char * errorName(int rc){ 576622cce3Sdanielk1977 const char *zName = 0; 586622cce3Sdanielk1977 switch( rc ){ 596622cce3Sdanielk1977 case SQLITE_OK: zName = "SQLITE_OK"; break; 606622cce3Sdanielk1977 case SQLITE_ERROR: zName = "SQLITE_ERROR"; break; 616622cce3Sdanielk1977 case SQLITE_INTERNAL: zName = "SQLITE_INTERNAL"; break; 626622cce3Sdanielk1977 case SQLITE_PERM: zName = "SQLITE_PERM"; break; 636622cce3Sdanielk1977 case SQLITE_ABORT: zName = "SQLITE_ABORT"; break; 646622cce3Sdanielk1977 case SQLITE_BUSY: zName = "SQLITE_BUSY"; break; 656622cce3Sdanielk1977 case SQLITE_LOCKED: zName = "SQLITE_LOCKED"; break; 666622cce3Sdanielk1977 case SQLITE_NOMEM: zName = "SQLITE_NOMEM"; break; 676622cce3Sdanielk1977 case SQLITE_READONLY: zName = "SQLITE_READONLY"; break; 686622cce3Sdanielk1977 case SQLITE_INTERRUPT: zName = "SQLITE_INTERRUPT"; break; 696622cce3Sdanielk1977 case SQLITE_IOERR: zName = "SQLITE_IOERR"; break; 706622cce3Sdanielk1977 case SQLITE_CORRUPT: zName = "SQLITE_CORRUPT"; break; 716622cce3Sdanielk1977 case SQLITE_NOTFOUND: zName = "SQLITE_NOTFOUND"; break; 726622cce3Sdanielk1977 case SQLITE_FULL: zName = "SQLITE_FULL"; break; 736622cce3Sdanielk1977 case SQLITE_CANTOPEN: zName = "SQLITE_CANTOPEN"; break; 746622cce3Sdanielk1977 case SQLITE_PROTOCOL: zName = "SQLITE_PROTOCOL"; break; 756622cce3Sdanielk1977 case SQLITE_EMPTY: zName = "SQLITE_EMPTY"; break; 766622cce3Sdanielk1977 case SQLITE_SCHEMA: zName = "SQLITE_SCHEMA"; break; 776622cce3Sdanielk1977 case SQLITE_TOOBIG: zName = "SQLITE_TOOBIG"; break; 786622cce3Sdanielk1977 case SQLITE_CONSTRAINT: zName = "SQLITE_CONSTRAINT"; break; 796622cce3Sdanielk1977 case SQLITE_MISMATCH: zName = "SQLITE_MISMATCH"; break; 806622cce3Sdanielk1977 case SQLITE_MISUSE: zName = "SQLITE_MISUSE"; break; 816622cce3Sdanielk1977 case SQLITE_NOLFS: zName = "SQLITE_NOLFS"; break; 826622cce3Sdanielk1977 case SQLITE_AUTH: zName = "SQLITE_AUTH"; break; 836622cce3Sdanielk1977 case SQLITE_FORMAT: zName = "SQLITE_FORMAT"; break; 846622cce3Sdanielk1977 case SQLITE_RANGE: zName = "SQLITE_RANGE"; break; 856622cce3Sdanielk1977 case SQLITE_ROW: zName = "SQLITE_ROW"; break; 866622cce3Sdanielk1977 case SQLITE_DONE: zName = "SQLITE_DONE"; break; 876622cce3Sdanielk1977 default: zName = "SQLITE_Unknown"; break; 886622cce3Sdanielk1977 } 896622cce3Sdanielk1977 return zName; 906622cce3Sdanielk1977 } 916622cce3Sdanielk1977 92d1bf3512Sdrh /* 93b86ccfb2Sdrh ** Decode a pointer to an sqlite object. 94b86ccfb2Sdrh */ 9590f405e3Sdrh static int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite **ppDb){ 9690f405e3Sdrh if( sscanf(zA, PTR_FMT, (void**)ppDb)!=1 && 9790f405e3Sdrh (zA[0]!='0' || zA[1]!='x' || sscanf(&zA[2], PTR_FMT, (void**)ppDb)!=1) 9890f405e3Sdrh ){ 9990f405e3Sdrh Tcl_AppendResult(interp, "\"", zA, "\" is not a valid pointer value", 0); 100b86ccfb2Sdrh return TCL_ERROR; 101b86ccfb2Sdrh } 102b86ccfb2Sdrh return TCL_OK; 103b86ccfb2Sdrh } 104b86ccfb2Sdrh 105b86ccfb2Sdrh /* 10651e3d8e2Sdanielk1977 ** Decode a pointer to an sqlite3_stmt object. 10751e3d8e2Sdanielk1977 */ 10851e3d8e2Sdanielk1977 static int getStmtPointer( 10951e3d8e2Sdanielk1977 Tcl_Interp *interp, 11051e3d8e2Sdanielk1977 const char *zArg, 11151e3d8e2Sdanielk1977 sqlite3_stmt **ppStmt 11251e3d8e2Sdanielk1977 ){ 11351e3d8e2Sdanielk1977 if( sscanf(zArg, PTR_FMT, (void**)ppStmt)!=1 ){ 11451e3d8e2Sdanielk1977 Tcl_AppendResult(interp, "\"", zArg, "\" is not a valid pointer value", 0); 11551e3d8e2Sdanielk1977 return TCL_ERROR; 11651e3d8e2Sdanielk1977 } 11751e3d8e2Sdanielk1977 return TCL_OK; 11851e3d8e2Sdanielk1977 } 11951e3d8e2Sdanielk1977 12051e3d8e2Sdanielk1977 /* 1219a1d0abeSdanielk1977 ** Decode a pointer to an sqlite3_stmt object. 1229a1d0abeSdanielk1977 */ 1239a1d0abeSdanielk1977 static int getFilePointer( 1249a1d0abeSdanielk1977 Tcl_Interp *interp, 1259a1d0abeSdanielk1977 const char *zArg, 1269a1d0abeSdanielk1977 OsFile **ppFile 1279a1d0abeSdanielk1977 ){ 1289a1d0abeSdanielk1977 if( sscanf(zArg, PTR_FMT, (void**)ppFile)!=1 ){ 1299a1d0abeSdanielk1977 Tcl_AppendResult(interp, "\"", zArg, "\" is not a valid pointer value", 0); 1309a1d0abeSdanielk1977 return TCL_ERROR; 1319a1d0abeSdanielk1977 } 1329a1d0abeSdanielk1977 return TCL_OK; 1339a1d0abeSdanielk1977 } 1349a1d0abeSdanielk1977 1359a1d0abeSdanielk1977 /* 1367d8085a8Sdrh ** Generate a text representation of a pointer that can be understood 1377d8085a8Sdrh ** by the getDbPointer and getVmPointer routines above. 1387d8085a8Sdrh ** 1397d8085a8Sdrh ** The problem is, on some machines (Solaris) if you do a printf with 1407d8085a8Sdrh ** "%p" you cannot turn around and do a scanf with the same "%p" and 1417d8085a8Sdrh ** get your pointer back. You have to prepend a "0x" before it will 1427d8085a8Sdrh ** work. Or at least that is what is reported to me (drh). But this 1437d8085a8Sdrh ** behavior varies from machine to machine. The solution used her is 1447d8085a8Sdrh ** to test the string right after it is generated to see if it can be 1457d8085a8Sdrh ** understood by scanf, and if not, try prepending an "0x" to see if 1467d8085a8Sdrh ** that helps. If nothing works, a fatal error is generated. 1477d8085a8Sdrh */ 1487d8085a8Sdrh static int makePointerStr(Tcl_Interp *interp, char *zPtr, void *p){ 1497d8085a8Sdrh void *p2; 1507d8085a8Sdrh sprintf(zPtr, PTR_FMT, p); 1517d8085a8Sdrh if( sscanf(zPtr, PTR_FMT, &p2)!=1 || p2!=p ){ 1527d8085a8Sdrh sprintf(zPtr, "0x" PTR_FMT, p); 1537d8085a8Sdrh if( sscanf(zPtr, PTR_FMT, &p2)!=1 || p2!=p ){ 1547d8085a8Sdrh Tcl_AppendResult(interp, "unable to convert a pointer to a string " 1557d8085a8Sdrh "in the file " __FILE__ " in function makePointerStr(). Please " 1567d8085a8Sdrh "report this problem to the SQLite mailing list or as a new but " 1577d8085a8Sdrh "report. Please provide detailed information about how you compiled " 1587d8085a8Sdrh "SQLite and what computer you are running on.", 0); 1597d8085a8Sdrh return TCL_ERROR; 1607d8085a8Sdrh } 1617d8085a8Sdrh } 1627d8085a8Sdrh return TCL_OK; 1637d8085a8Sdrh } 1647d8085a8Sdrh 1657d8085a8Sdrh /* 1666f8a503dSdanielk1977 ** The callback routine for sqlite3_exec_printf(). 167d1bf3512Sdrh */ 168d1bf3512Sdrh static int exec_printf_cb(void *pArg, int argc, char **argv, char **name){ 169d1bf3512Sdrh Tcl_DString *str = (Tcl_DString*)pArg; 170d1bf3512Sdrh int i; 171d1bf3512Sdrh 172d1bf3512Sdrh if( Tcl_DStringLength(str)==0 ){ 173d1bf3512Sdrh for(i=0; i<argc; i++){ 174d1bf3512Sdrh Tcl_DStringAppendElement(str, name[i] ? name[i] : "NULL"); 175d1bf3512Sdrh } 176d1bf3512Sdrh } 177d1bf3512Sdrh for(i=0; i<argc; i++){ 178d1bf3512Sdrh Tcl_DStringAppendElement(str, argv[i] ? argv[i] : "NULL"); 179d1bf3512Sdrh } 180d1bf3512Sdrh return 0; 181d1bf3512Sdrh } 182d1bf3512Sdrh 183d1bf3512Sdrh /* 1846f8a503dSdanielk1977 ** Usage: sqlite3_exec_printf DB FORMAT STRING 185d1bf3512Sdrh ** 1866f8a503dSdanielk1977 ** Invoke the sqlite3_exec_printf() interface using the open database 187d1bf3512Sdrh ** DB. The SQL is the string FORMAT. The format string should contain 188d1bf3512Sdrh ** one %s or %q. STRING is the value inserted into %s or %q. 189d1bf3512Sdrh */ 190d1bf3512Sdrh static int test_exec_printf( 191d1bf3512Sdrh void *NotUsed, 192d1bf3512Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 193d1bf3512Sdrh int argc, /* Number of arguments */ 194d1bf3512Sdrh char **argv /* Text of each argument */ 195d1bf3512Sdrh ){ 196d1bf3512Sdrh sqlite *db; 197d1bf3512Sdrh Tcl_DString str; 198d1bf3512Sdrh int rc; 199d1bf3512Sdrh char *zErr = 0; 200d1bf3512Sdrh char zBuf[30]; 201d1bf3512Sdrh if( argc!=4 ){ 202d1bf3512Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 203d1bf3512Sdrh " DB FORMAT STRING", 0); 204d1bf3512Sdrh return TCL_ERROR; 205d1bf3512Sdrh } 206b86ccfb2Sdrh if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; 207d1bf3512Sdrh Tcl_DStringInit(&str); 2086f8a503dSdanielk1977 rc = sqlite3_exec_printf(db, argv[2], exec_printf_cb, &str, &zErr, argv[3]); 209d1bf3512Sdrh sprintf(zBuf, "%d", rc); 210d1bf3512Sdrh Tcl_AppendElement(interp, zBuf); 211d1bf3512Sdrh Tcl_AppendElement(interp, rc==SQLITE_OK ? Tcl_DStringValue(&str) : zErr); 212d1bf3512Sdrh Tcl_DStringFree(&str); 213d1bf3512Sdrh if( zErr ) free(zErr); 214d1bf3512Sdrh return TCL_OK; 215d1bf3512Sdrh } 216d1bf3512Sdrh 217d1bf3512Sdrh /* 2186f8a503dSdanielk1977 ** Usage: sqlite3_mprintf_z_test SEPARATOR ARG0 ARG1 ... 219d93d8a81Sdrh ** 220d93d8a81Sdrh ** Test the %z format of mprintf(). Use multiple mprintf() calls to 221d93d8a81Sdrh ** concatenate arg0 through argn using separator as the separator. 222d93d8a81Sdrh ** Return the result. 223d93d8a81Sdrh */ 224d93d8a81Sdrh static int test_mprintf_z( 225d93d8a81Sdrh void *NotUsed, 226d93d8a81Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 227d93d8a81Sdrh int argc, /* Number of arguments */ 228d93d8a81Sdrh char **argv /* Text of each argument */ 229d93d8a81Sdrh ){ 230d93d8a81Sdrh char *zResult = 0; 231d93d8a81Sdrh int i; 232d93d8a81Sdrh 233d93d8a81Sdrh for(i=2; i<argc; i++){ 2344adee20fSdanielk1977 zResult = sqlite3MPrintf("%z%s%s", zResult, argv[1], argv[i]); 235d93d8a81Sdrh } 236d93d8a81Sdrh Tcl_AppendResult(interp, zResult, 0); 2375f968436Sdrh sqliteFree(zResult); 238d93d8a81Sdrh return TCL_OK; 239d93d8a81Sdrh } 240d93d8a81Sdrh 241d93d8a81Sdrh /* 2426f8a503dSdanielk1977 ** Usage: sqlite3_get_table_printf DB FORMAT STRING 243d1bf3512Sdrh ** 2446f8a503dSdanielk1977 ** Invoke the sqlite3_get_table_printf() interface using the open database 245d1bf3512Sdrh ** DB. The SQL is the string FORMAT. The format string should contain 246d1bf3512Sdrh ** one %s or %q. STRING is the value inserted into %s or %q. 247d1bf3512Sdrh */ 248d1bf3512Sdrh static int test_get_table_printf( 249d1bf3512Sdrh void *NotUsed, 250d1bf3512Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 251d1bf3512Sdrh int argc, /* Number of arguments */ 252d1bf3512Sdrh char **argv /* Text of each argument */ 253d1bf3512Sdrh ){ 254d1bf3512Sdrh sqlite *db; 255d1bf3512Sdrh Tcl_DString str; 256d1bf3512Sdrh int rc; 257d1bf3512Sdrh char *zErr = 0; 258d1bf3512Sdrh int nRow, nCol; 259d1bf3512Sdrh char **aResult; 260d1bf3512Sdrh int i; 261d1bf3512Sdrh char zBuf[30]; 262d1bf3512Sdrh if( argc!=4 ){ 263d1bf3512Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 264d1bf3512Sdrh " DB FORMAT STRING", 0); 265d1bf3512Sdrh return TCL_ERROR; 266d1bf3512Sdrh } 267b86ccfb2Sdrh if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; 268d1bf3512Sdrh Tcl_DStringInit(&str); 2696f8a503dSdanielk1977 rc = sqlite3_get_table_printf(db, argv[2], &aResult, &nRow, &nCol, 270d1bf3512Sdrh &zErr, argv[3]); 271d1bf3512Sdrh sprintf(zBuf, "%d", rc); 272d1bf3512Sdrh Tcl_AppendElement(interp, zBuf); 273d1bf3512Sdrh if( rc==SQLITE_OK ){ 274d1bf3512Sdrh sprintf(zBuf, "%d", nRow); 275d1bf3512Sdrh Tcl_AppendElement(interp, zBuf); 276d1bf3512Sdrh sprintf(zBuf, "%d", nCol); 277d1bf3512Sdrh Tcl_AppendElement(interp, zBuf); 278d1bf3512Sdrh for(i=0; i<(nRow+1)*nCol; i++){ 279d1bf3512Sdrh Tcl_AppendElement(interp, aResult[i] ? aResult[i] : "NULL"); 280d1bf3512Sdrh } 281d1bf3512Sdrh }else{ 282d1bf3512Sdrh Tcl_AppendElement(interp, zErr); 283d1bf3512Sdrh } 2846f8a503dSdanielk1977 sqlite3_free_table(aResult); 285d1bf3512Sdrh if( zErr ) free(zErr); 286d1bf3512Sdrh return TCL_OK; 287d1bf3512Sdrh } 288d1bf3512Sdrh 289af9ff33aSdrh 290af9ff33aSdrh /* 2916f8a503dSdanielk1977 ** Usage: sqlite3_last_insert_rowid DB 292af9ff33aSdrh ** 293af9ff33aSdrh ** Returns the integer ROWID of the most recent insert. 294af9ff33aSdrh */ 295af9ff33aSdrh static int test_last_rowid( 296af9ff33aSdrh void *NotUsed, 297af9ff33aSdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 298af9ff33aSdrh int argc, /* Number of arguments */ 299af9ff33aSdrh char **argv /* Text of each argument */ 300af9ff33aSdrh ){ 301af9ff33aSdrh sqlite *db; 302af9ff33aSdrh char zBuf[30]; 303af9ff33aSdrh 304af9ff33aSdrh if( argc!=2 ){ 305af9ff33aSdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " DB\"", 0); 306af9ff33aSdrh return TCL_ERROR; 307af9ff33aSdrh } 308b86ccfb2Sdrh if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; 309c572ef7fSdanielk1977 sprintf(zBuf, "%lld", sqlite3_last_insert_rowid(db)); 310af9ff33aSdrh Tcl_AppendResult(interp, zBuf, 0); 311af9ff33aSdrh return SQLITE_OK; 312af9ff33aSdrh } 313af9ff33aSdrh 314d1bf3512Sdrh /* 3156f8a503dSdanielk1977 ** Usage: sqlite3_close DB 316d1bf3512Sdrh ** 3176f8a503dSdanielk1977 ** Closes the database opened by sqlite3_open. 318d1bf3512Sdrh */ 319d1bf3512Sdrh static int sqlite_test_close( 320d1bf3512Sdrh void *NotUsed, 321d1bf3512Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 322d1bf3512Sdrh int argc, /* Number of arguments */ 323d1bf3512Sdrh char **argv /* Text of each argument */ 324d1bf3512Sdrh ){ 325d1bf3512Sdrh sqlite *db; 326d1bf3512Sdrh if( argc!=2 ){ 327d1bf3512Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 328d1bf3512Sdrh " FILENAME\"", 0); 329d1bf3512Sdrh return TCL_ERROR; 330d1bf3512Sdrh } 331b86ccfb2Sdrh if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; 3326f8a503dSdanielk1977 sqlite3_close(db); 333d1bf3512Sdrh return TCL_OK; 334d1bf3512Sdrh } 335d1bf3512Sdrh 336d1bf3512Sdrh /* 337c22bd47dSdrh ** Implementation of the x_coalesce() function. 338c22bd47dSdrh ** Return the first argument non-NULL argument. 339c22bd47dSdrh */ 3400ae8b831Sdanielk1977 static void ifnullFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ 341c22bd47dSdrh int i; 342c22bd47dSdrh for(i=0; i<argc; i++){ 3439c054830Sdrh if( SQLITE_NULL!=sqlite3_value_type(argv[i]) ){ 3444f26d6c4Sdrh sqlite3_result_text(context, sqlite3_value_text(argv[i]), -1, 1); 345c22bd47dSdrh break; 346c22bd47dSdrh } 347c22bd47dSdrh } 348c22bd47dSdrh } 349c22bd47dSdrh 350c22bd47dSdrh /* 351d1d9fc33Sdrh ** A structure into which to accumulate text. 352d1d9fc33Sdrh */ 353d1d9fc33Sdrh struct dstr { 354d1d9fc33Sdrh int nAlloc; /* Space allocated */ 355d1d9fc33Sdrh int nUsed; /* Space used */ 356d1d9fc33Sdrh char *z; /* The space */ 357d1d9fc33Sdrh }; 358d1d9fc33Sdrh 359d1d9fc33Sdrh /* 360d1d9fc33Sdrh ** Append text to a dstr 361d1d9fc33Sdrh */ 362d1d9fc33Sdrh static void dstrAppend(struct dstr *p, const char *z, int divider){ 363d1d9fc33Sdrh int n = strlen(z); 364d1d9fc33Sdrh if( p->nUsed + n + 2 > p->nAlloc ){ 365d1d9fc33Sdrh char *zNew; 366d1d9fc33Sdrh p->nAlloc = p->nAlloc*2 + n + 200; 367d1d9fc33Sdrh zNew = sqliteRealloc(p->z, p->nAlloc); 368d1d9fc33Sdrh if( zNew==0 ){ 369d1d9fc33Sdrh sqliteFree(p->z); 370d1d9fc33Sdrh memset(p, 0, sizeof(*p)); 371d1d9fc33Sdrh return; 372d1d9fc33Sdrh } 373d1d9fc33Sdrh p->z = zNew; 374d1d9fc33Sdrh } 375d1d9fc33Sdrh if( divider && p->nUsed>0 ){ 376d1d9fc33Sdrh p->z[p->nUsed++] = divider; 377d1d9fc33Sdrh } 378d1d9fc33Sdrh memcpy(&p->z[p->nUsed], z, n+1); 379d1d9fc33Sdrh p->nUsed += n; 380d1d9fc33Sdrh } 381d1d9fc33Sdrh 382d1d9fc33Sdrh /* 3834adee20fSdanielk1977 ** Invoked for each callback from sqlite3ExecFunc 384d1d9fc33Sdrh */ 385d1d9fc33Sdrh static int execFuncCallback(void *pData, int argc, char **argv, char **NotUsed){ 386d1d9fc33Sdrh struct dstr *p = (struct dstr*)pData; 387d1d9fc33Sdrh int i; 388d1d9fc33Sdrh for(i=0; i<argc; i++){ 389d1d9fc33Sdrh if( argv[i]==0 ){ 390d1d9fc33Sdrh dstrAppend(p, "NULL", ' '); 391d1d9fc33Sdrh }else{ 392d1d9fc33Sdrh dstrAppend(p, argv[i], ' '); 393d1d9fc33Sdrh } 394d1d9fc33Sdrh } 395d1d9fc33Sdrh return 0; 396d1d9fc33Sdrh } 397d1d9fc33Sdrh 398d1d9fc33Sdrh /* 3996f8a503dSdanielk1977 ** Implementation of the x_sqlite3_exec() function. This function takes 400c22bd47dSdrh ** a single argument and attempts to execute that argument as SQL code. 4016cbe1f1bSdrh ** This is illegal and should set the SQLITE_MISUSE flag on the database. 402c22bd47dSdrh ** 4036f8a503dSdanielk1977 ** 2004-Jan-07: We have changed this to make it legal to call sqlite3_exec() 404d1d9fc33Sdrh ** from within a function call. 405d1d9fc33Sdrh ** 406c22bd47dSdrh ** This routine simulates the effect of having two threads attempt to 407c22bd47dSdrh ** use the same database at the same time. 408c22bd47dSdrh */ 40951ad0ecdSdanielk1977 static void sqlite3ExecFunc( 4100ae8b831Sdanielk1977 sqlite3_context *context, 41151ad0ecdSdanielk1977 int argc, 41251ad0ecdSdanielk1977 sqlite3_value **argv 41351ad0ecdSdanielk1977 ){ 414d1d9fc33Sdrh struct dstr x; 415d1d9fc33Sdrh memset(&x, 0, sizeof(x)); 41651ad0ecdSdanielk1977 sqlite3_exec((sqlite*)sqlite3_user_data(context), 4174f26d6c4Sdrh sqlite3_value_text(argv[0]), 418d1d9fc33Sdrh execFuncCallback, &x, 0); 4197e18c259Sdanielk1977 sqlite3_result_text(context, x.z, x.nUsed, 1); 420d1d9fc33Sdrh sqliteFree(x.z); 421c22bd47dSdrh } 422c22bd47dSdrh 423c22bd47dSdrh /* 424c22bd47dSdrh ** Usage: sqlite_test_create_function DB 425c22bd47dSdrh ** 4266f8a503dSdanielk1977 ** Call the sqlite3_create_function API on the given database in order 427c22bd47dSdrh ** to create a function named "x_coalesce". This function does the same thing 428c22bd47dSdrh ** as the "coalesce" function. This function also registers an SQL function 4296f8a503dSdanielk1977 ** named "x_sqlite3_exec" that invokes sqlite3_exec(). Invoking sqlite3_exec() 430c22bd47dSdrh ** in this way is illegal recursion and should raise an SQLITE_MISUSE error. 431c22bd47dSdrh ** The effect is similar to trying to use the same database connection from 432c22bd47dSdrh ** two threads at the same time. 433c22bd47dSdrh ** 434c22bd47dSdrh ** The original motivation for this routine was to be able to call the 4356f8a503dSdanielk1977 ** sqlite3_create_function function while a query is in progress in order 436c22bd47dSdrh ** to test the SQLITE_MISUSE detection logic. 437c22bd47dSdrh */ 438c2eef3b3Sdrh static int test_create_function( 439c22bd47dSdrh void *NotUsed, 440c22bd47dSdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 441c22bd47dSdrh int argc, /* Number of arguments */ 442c22bd47dSdrh char **argv /* Text of each argument */ 443c22bd47dSdrh ){ 444c22bd47dSdrh sqlite *db; 445c22bd47dSdrh extern void Md5_Register(sqlite*); 446c22bd47dSdrh if( argc!=2 ){ 447c22bd47dSdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 448c22bd47dSdrh " FILENAME\"", 0); 449c22bd47dSdrh return TCL_ERROR; 450c22bd47dSdrh } 451b86ccfb2Sdrh if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; 4526590493dSdanielk1977 sqlite3_create_function(db, "x_coalesce", -1, 0, 0, 0, ifnullFunc, 0, 0); 4536590493dSdanielk1977 sqlite3_create_function(db, "x_sqlite3_exec", 1, 0, 0, db, 4546590493dSdanielk1977 sqlite3ExecFunc, 0, 0); 455c22bd47dSdrh return TCL_OK; 456c22bd47dSdrh } 457c22bd47dSdrh 458c22bd47dSdrh /* 459c22bd47dSdrh ** Routines to implement the x_count() aggregate function. 460c22bd47dSdrh */ 461c22bd47dSdrh typedef struct CountCtx CountCtx; 462c22bd47dSdrh struct CountCtx { 463c22bd47dSdrh int n; 464c22bd47dSdrh }; 4650ae8b831Sdanielk1977 static void countStep(sqlite3_context *context, int argc, sqlite3_value **argv){ 466c22bd47dSdrh CountCtx *p; 4674f26d6c4Sdrh p = sqlite3_aggregate_context(context, sizeof(*p)); 4689c054830Sdrh if( (argc==0 || SQLITE_NULL!=sqlite3_value_type(argv[0]) ) && p ){ 469c22bd47dSdrh p->n++; 470c22bd47dSdrh } 471c22bd47dSdrh } 4720ae8b831Sdanielk1977 static void countFinalize(sqlite3_context *context){ 473c22bd47dSdrh CountCtx *p; 4744f26d6c4Sdrh p = sqlite3_aggregate_context(context, sizeof(*p)); 475c572ef7fSdanielk1977 sqlite3_result_int(context, p ? p->n : 0); 476c22bd47dSdrh } 477c22bd47dSdrh 478c22bd47dSdrh /* 479c22bd47dSdrh ** Usage: sqlite_test_create_aggregate DB 480c22bd47dSdrh ** 4816f8a503dSdanielk1977 ** Call the sqlite3_create_function API on the given database in order 482c22bd47dSdrh ** to create a function named "x_count". This function does the same thing 483c22bd47dSdrh ** as the "md5sum" function. 484c22bd47dSdrh ** 485c22bd47dSdrh ** The original motivation for this routine was to be able to call the 4866f8a503dSdanielk1977 ** sqlite3_create_aggregate function while a query is in progress in order 487c22bd47dSdrh ** to test the SQLITE_MISUSE detection logic. 488c22bd47dSdrh */ 489c2eef3b3Sdrh static int test_create_aggregate( 490c22bd47dSdrh void *NotUsed, 491c22bd47dSdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 492c22bd47dSdrh int argc, /* Number of arguments */ 493c22bd47dSdrh char **argv /* Text of each argument */ 494c22bd47dSdrh ){ 495c22bd47dSdrh sqlite *db; 496c22bd47dSdrh if( argc!=2 ){ 497c22bd47dSdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 498c22bd47dSdrh " FILENAME\"", 0); 499c22bd47dSdrh return TCL_ERROR; 500c22bd47dSdrh } 501b86ccfb2Sdrh if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; 5026590493dSdanielk1977 sqlite3_create_function(db, "x_count", 0, 0, 0, 0, 0,countStep,countFinalize); 5036590493dSdanielk1977 sqlite3_create_function(db, "x_count", 1, 0, 0, 0, 0,countStep,countFinalize); 504c22bd47dSdrh return TCL_OK; 505c22bd47dSdrh } 506c22bd47dSdrh 507c22bd47dSdrh 508c22bd47dSdrh 509c22bd47dSdrh /* 5106f8a503dSdanielk1977 ** Usage: sqlite3_mprintf_int FORMAT INTEGER INTEGER INTEGER 511d1bf3512Sdrh ** 512d1bf3512Sdrh ** Call mprintf with three integer arguments 513d1bf3512Sdrh */ 5146f8a503dSdanielk1977 static int sqlite3_mprintf_int( 515d1bf3512Sdrh void *NotUsed, 516d1bf3512Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 517d1bf3512Sdrh int argc, /* Number of arguments */ 518d1bf3512Sdrh char **argv /* Text of each argument */ 519d1bf3512Sdrh ){ 520d1bf3512Sdrh int a[3], i; 521d1bf3512Sdrh char *z; 522d1bf3512Sdrh if( argc!=5 ){ 523d1bf3512Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 524d1bf3512Sdrh " FORMAT INT INT INT\"", 0); 525d1bf3512Sdrh return TCL_ERROR; 526d1bf3512Sdrh } 527d1bf3512Sdrh for(i=2; i<5; i++){ 528d1bf3512Sdrh if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR; 529d1bf3512Sdrh } 5306f8a503dSdanielk1977 z = sqlite3_mprintf(argv[1], a[0], a[1], a[2]); 531d1bf3512Sdrh Tcl_AppendResult(interp, z, 0); 5323f4fedb2Sdrh sqlite3_free(z); 533d1bf3512Sdrh return TCL_OK; 534d1bf3512Sdrh } 535d1bf3512Sdrh 536d1bf3512Sdrh /* 5376f8a503dSdanielk1977 ** Usage: sqlite3_mprintf_str FORMAT INTEGER INTEGER STRING 538d1bf3512Sdrh ** 539d1bf3512Sdrh ** Call mprintf with two integer arguments and one string argument 540d1bf3512Sdrh */ 5416f8a503dSdanielk1977 static int sqlite3_mprintf_str( 542d1bf3512Sdrh void *NotUsed, 543d1bf3512Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 544d1bf3512Sdrh int argc, /* Number of arguments */ 545d1bf3512Sdrh char **argv /* Text of each argument */ 546d1bf3512Sdrh ){ 547d1bf3512Sdrh int a[3], i; 548d1bf3512Sdrh char *z; 549f220b24fSchw if( argc<4 || argc>5 ){ 550d1bf3512Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 551f220b24fSchw " FORMAT INT INT ?STRING?\"", 0); 552d1bf3512Sdrh return TCL_ERROR; 553d1bf3512Sdrh } 554d1bf3512Sdrh for(i=2; i<4; i++){ 555d1bf3512Sdrh if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR; 556d1bf3512Sdrh } 5576f8a503dSdanielk1977 z = sqlite3_mprintf(argv[1], a[0], a[1], argc>4 ? argv[4] : NULL); 558d1bf3512Sdrh Tcl_AppendResult(interp, z, 0); 5593f4fedb2Sdrh sqlite3_free(z); 560d1bf3512Sdrh return TCL_OK; 561d1bf3512Sdrh } 562d1bf3512Sdrh 563d1bf3512Sdrh /* 5646f8a503dSdanielk1977 ** Usage: sqlite3_mprintf_str FORMAT INTEGER INTEGER DOUBLE 565d1bf3512Sdrh ** 566d1bf3512Sdrh ** Call mprintf with two integer arguments and one double argument 567d1bf3512Sdrh */ 5686f8a503dSdanielk1977 static int sqlite3_mprintf_double( 569d1bf3512Sdrh void *NotUsed, 570d1bf3512Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 571d1bf3512Sdrh int argc, /* Number of arguments */ 572d1bf3512Sdrh char **argv /* Text of each argument */ 573d1bf3512Sdrh ){ 574d1bf3512Sdrh int a[3], i; 575d1bf3512Sdrh double r; 576d1bf3512Sdrh char *z; 577d1bf3512Sdrh if( argc!=5 ){ 578d1bf3512Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 579d1bf3512Sdrh " FORMAT INT INT STRING\"", 0); 580d1bf3512Sdrh return TCL_ERROR; 581d1bf3512Sdrh } 582d1bf3512Sdrh for(i=2; i<4; i++){ 583d1bf3512Sdrh if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR; 584d1bf3512Sdrh } 585d1bf3512Sdrh if( Tcl_GetDouble(interp, argv[4], &r) ) return TCL_ERROR; 5866f8a503dSdanielk1977 z = sqlite3_mprintf(argv[1], a[0], a[1], r); 587d1bf3512Sdrh Tcl_AppendResult(interp, z, 0); 5883f4fedb2Sdrh sqlite3_free(z); 589d1bf3512Sdrh return TCL_OK; 590d1bf3512Sdrh } 591d1bf3512Sdrh 592d1bf3512Sdrh /* 5936f8a503dSdanielk1977 ** Usage: sqlite3_mprintf_str FORMAT DOUBLE DOUBLE 594b621c237Sdrh ** 595b621c237Sdrh ** Call mprintf with a single double argument which is the product of the 596b621c237Sdrh ** two arguments given above. This is used to generate overflow and underflow 597b621c237Sdrh ** doubles to test that they are converted properly. 598b621c237Sdrh */ 5996f8a503dSdanielk1977 static int sqlite3_mprintf_scaled( 600b621c237Sdrh void *NotUsed, 601b621c237Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 602b621c237Sdrh int argc, /* Number of arguments */ 603b621c237Sdrh char **argv /* Text of each argument */ 604b621c237Sdrh ){ 605b621c237Sdrh int i; 606b621c237Sdrh double r[2]; 607b621c237Sdrh char *z; 608b621c237Sdrh if( argc!=4 ){ 609b621c237Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 610b621c237Sdrh " FORMAT DOUBLE DOUBLE\"", 0); 611b621c237Sdrh return TCL_ERROR; 612b621c237Sdrh } 613b621c237Sdrh for(i=2; i<4; i++){ 614b621c237Sdrh if( Tcl_GetDouble(interp, argv[i], &r[i-2]) ) return TCL_ERROR; 615b621c237Sdrh } 6166f8a503dSdanielk1977 z = sqlite3_mprintf(argv[1], r[0]*r[1]); 617b621c237Sdrh Tcl_AppendResult(interp, z, 0); 6183f4fedb2Sdrh sqlite3_free(z); 619b621c237Sdrh return TCL_OK; 620b621c237Sdrh } 621b621c237Sdrh 622b621c237Sdrh /* 623daffd0e5Sdrh ** Usage: sqlite_malloc_fail N 624daffd0e5Sdrh ** 625afa4a020Sdrh ** Rig sqliteMalloc() to fail on the N-th call. Turn off this mechanism 6266f8a503dSdanielk1977 ** and reset the sqlite3_malloc_failed variable is N==0. 627daffd0e5Sdrh */ 628*faa57accSdrh #ifdef SQLITE_DEBUG 629daffd0e5Sdrh static int sqlite_malloc_fail( 630daffd0e5Sdrh void *NotUsed, 631daffd0e5Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 632daffd0e5Sdrh int argc, /* Number of arguments */ 633daffd0e5Sdrh char **argv /* Text of each argument */ 634daffd0e5Sdrh ){ 635daffd0e5Sdrh int n; 636daffd0e5Sdrh if( argc!=2 ){ 637daffd0e5Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " N\"", 0); 638daffd0e5Sdrh return TCL_ERROR; 639daffd0e5Sdrh } 640daffd0e5Sdrh if( Tcl_GetInt(interp, argv[1], &n) ) return TCL_ERROR; 6416f8a503dSdanielk1977 sqlite3_iMallocFail = n; 6426f8a503dSdanielk1977 sqlite3_malloc_failed = 0; 643daffd0e5Sdrh return TCL_OK; 644daffd0e5Sdrh } 645daffd0e5Sdrh #endif 646daffd0e5Sdrh 647daffd0e5Sdrh /* 648daffd0e5Sdrh ** Usage: sqlite_malloc_stat 649daffd0e5Sdrh ** 650daffd0e5Sdrh ** Return the number of prior calls to sqliteMalloc() and sqliteFree(). 651daffd0e5Sdrh */ 652*faa57accSdrh #ifdef SQLITE_DEBUG 653daffd0e5Sdrh static int sqlite_malloc_stat( 654daffd0e5Sdrh void *NotUsed, 655daffd0e5Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 656daffd0e5Sdrh int argc, /* Number of arguments */ 657daffd0e5Sdrh char **argv /* Text of each argument */ 658daffd0e5Sdrh ){ 659daffd0e5Sdrh char zBuf[200]; 6606f8a503dSdanielk1977 sprintf(zBuf, "%d %d %d", sqlite3_nMalloc, sqlite3_nFree, sqlite3_iMallocFail); 661daffd0e5Sdrh Tcl_AppendResult(interp, zBuf, 0); 662daffd0e5Sdrh return TCL_OK; 663daffd0e5Sdrh } 664daffd0e5Sdrh #endif 665daffd0e5Sdrh 666daffd0e5Sdrh /* 66728b4e489Sdrh ** Usage: sqlite_abort 66828b4e489Sdrh ** 66928b4e489Sdrh ** Shutdown the process immediately. This is not a clean shutdown. 67028b4e489Sdrh ** This command is used to test the recoverability of a database in 67128b4e489Sdrh ** the event of a program crash. 67228b4e489Sdrh */ 67328b4e489Sdrh static int sqlite_abort( 67428b4e489Sdrh void *NotUsed, 67528b4e489Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 67628b4e489Sdrh int argc, /* Number of arguments */ 67728b4e489Sdrh char **argv /* Text of each argument */ 67828b4e489Sdrh ){ 67928b4e489Sdrh assert( interp==0 ); /* This will always fail */ 68028b4e489Sdrh return TCL_OK; 68128b4e489Sdrh } 68228b4e489Sdrh 68328b4e489Sdrh /* 6846cbe1f1bSdrh ** The following routine is a user-defined SQL function whose purpose 6856cbe1f1bSdrh ** is to test the sqlite_set_result() API. 6866cbe1f1bSdrh */ 6870ae8b831Sdanielk1977 static void testFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ 6886cbe1f1bSdrh while( argc>=2 ){ 6894f26d6c4Sdrh const char *zArg0 = sqlite3_value_text(argv[0]); 6906d88bad4Sdanielk1977 if( zArg0 ){ 6916d88bad4Sdanielk1977 if( 0==sqlite3StrICmp(zArg0, "int") ){ 6926d88bad4Sdanielk1977 sqlite3_result_int(context, sqlite3_value_int(argv[1])); 6936d88bad4Sdanielk1977 }else if( sqlite3StrICmp(zArg0,"int64")==0 ){ 6946d88bad4Sdanielk1977 sqlite3_result_int64(context, sqlite3_value_int64(argv[1])); 69551ad0ecdSdanielk1977 }else if( sqlite3StrICmp(zArg0,"string")==0 ){ 6966d88bad4Sdanielk1977 sqlite3_result_text(context, sqlite3_value_text(argv[1]), -1, 1); 69751ad0ecdSdanielk1977 }else if( sqlite3StrICmp(zArg0,"double")==0 ){ 6986d88bad4Sdanielk1977 sqlite3_result_double(context, sqlite3_value_double(argv[1])); 6996d88bad4Sdanielk1977 }else if( sqlite3StrICmp(zArg0,"null")==0 ){ 7006d88bad4Sdanielk1977 sqlite3_result_null(context); 7016d88bad4Sdanielk1977 }else if( sqlite3StrICmp(zArg0,"value")==0 ){ 7026d88bad4Sdanielk1977 sqlite3_result_value(context, argv[sqlite3_value_int(argv[1])]); 7036cbe1f1bSdrh }else{ 7046d88bad4Sdanielk1977 goto error_out; 7056d88bad4Sdanielk1977 } 7066d88bad4Sdanielk1977 }else{ 7076d88bad4Sdanielk1977 goto error_out; 7086cbe1f1bSdrh } 7096cbe1f1bSdrh argc -= 2; 7106cbe1f1bSdrh argv += 2; 7116cbe1f1bSdrh } 7126d88bad4Sdanielk1977 return; 7136d88bad4Sdanielk1977 7146d88bad4Sdanielk1977 error_out: 7156d88bad4Sdanielk1977 sqlite3_result_error(context,"first argument should be one of: " 7166d88bad4Sdanielk1977 "int int64 string double null value", -1); 7176cbe1f1bSdrh } 7186cbe1f1bSdrh 7196cbe1f1bSdrh /* 7206cbe1f1bSdrh ** Usage: sqlite_register_test_function DB NAME 7216cbe1f1bSdrh ** 7226cbe1f1bSdrh ** Register the test SQL function on the database DB under the name NAME. 7236cbe1f1bSdrh */ 724c2eef3b3Sdrh static int test_register_func( 7256cbe1f1bSdrh void *NotUsed, 7266cbe1f1bSdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 7276cbe1f1bSdrh int argc, /* Number of arguments */ 7286cbe1f1bSdrh char **argv /* Text of each argument */ 7296cbe1f1bSdrh ){ 7306cbe1f1bSdrh sqlite *db; 7316cbe1f1bSdrh int rc; 7326cbe1f1bSdrh if( argc!=3 ){ 7336cbe1f1bSdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 7346cbe1f1bSdrh " DB FUNCTION-NAME", 0); 7356cbe1f1bSdrh return TCL_ERROR; 7366cbe1f1bSdrh } 737b86ccfb2Sdrh if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; 7386590493dSdanielk1977 rc = sqlite3_create_function(db, argv[2], -1, 0, 0, 0, testFunc, 0, 0); 7396cbe1f1bSdrh if( rc!=0 ){ 740f20b21c8Sdanielk1977 Tcl_AppendResult(interp, sqlite3ErrStr(rc), 0); 7416cbe1f1bSdrh return TCL_ERROR; 7426cbe1f1bSdrh } 7436cbe1f1bSdrh return TCL_OK; 7446cbe1f1bSdrh } 7456cbe1f1bSdrh 7466cbe1f1bSdrh /* 747106bb236Sdanielk1977 ** Usage: sqlite3_finalize STMT 748b86ccfb2Sdrh ** 749106bb236Sdanielk1977 ** Finalize a statement handle. 750b86ccfb2Sdrh */ 751b86ccfb2Sdrh static int test_finalize( 752106bb236Sdanielk1977 void * clientData, 753106bb236Sdanielk1977 Tcl_Interp *interp, 754106bb236Sdanielk1977 int objc, 755106bb236Sdanielk1977 Tcl_Obj *CONST objv[] 756b86ccfb2Sdrh ){ 757106bb236Sdanielk1977 sqlite3_stmt *pStmt; 758b86ccfb2Sdrh int rc; 759106bb236Sdanielk1977 760106bb236Sdanielk1977 if( objc!=2 ){ 761106bb236Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 762106bb236Sdanielk1977 Tcl_GetStringFromObj(objv[0], 0), " <STMT>", 0); 763b86ccfb2Sdrh return TCL_ERROR; 764b86ccfb2Sdrh } 765106bb236Sdanielk1977 766106bb236Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 767106bb236Sdanielk1977 768fc57d7bfSdanielk1977 rc = sqlite3_finalize(pStmt); 769b77f5dadSdanielk1977 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC); 770b86ccfb2Sdrh if( rc ){ 771106bb236Sdanielk1977 return TCL_ERROR; 772106bb236Sdanielk1977 } 773106bb236Sdanielk1977 return TCL_OK; 774106bb236Sdanielk1977 } 775106bb236Sdanielk1977 776106bb236Sdanielk1977 /* 777106bb236Sdanielk1977 ** Usage: sqlite3_reset STMT 778106bb236Sdanielk1977 ** 779106bb236Sdanielk1977 ** Finalize a statement handle. 780106bb236Sdanielk1977 */ 781106bb236Sdanielk1977 static int test_reset( 782106bb236Sdanielk1977 void * clientData, 783106bb236Sdanielk1977 Tcl_Interp *interp, 784106bb236Sdanielk1977 int objc, 785106bb236Sdanielk1977 Tcl_Obj *CONST objv[] 786106bb236Sdanielk1977 ){ 787106bb236Sdanielk1977 sqlite3_stmt *pStmt; 788106bb236Sdanielk1977 int rc; 789106bb236Sdanielk1977 790106bb236Sdanielk1977 if( objc!=2 ){ 791106bb236Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 792106bb236Sdanielk1977 Tcl_GetStringFromObj(objv[0], 0), " <STMT>", 0); 793106bb236Sdanielk1977 return TCL_ERROR; 794106bb236Sdanielk1977 } 795106bb236Sdanielk1977 796106bb236Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 797106bb236Sdanielk1977 798fc57d7bfSdanielk1977 rc = sqlite3_reset(pStmt); 799106bb236Sdanielk1977 if( rc ){ 800b86ccfb2Sdrh return TCL_ERROR; 801b86ccfb2Sdrh } 802b86ccfb2Sdrh return TCL_OK; 803b86ccfb2Sdrh } 804b86ccfb2Sdrh 8055a38705eSdrh /* 8066f8a503dSdanielk1977 ** Usage: sqlite3_reset VM 80750457896Sdrh ** 80850457896Sdrh ** Reset a virtual machine and prepare it to be run again. 80950457896Sdrh */ 81050457896Sdrh 81150457896Sdrh /* 8127c972decSdrh ** This is the "static_bind_value" that variables are bound to when 8136f8a503dSdanielk1977 ** the FLAG option of sqlite3_bind is "static" 81450457896Sdrh */ 8157c972decSdrh static char *sqlite_static_bind_value = 0; 8167c972decSdrh 8177c972decSdrh /* 8186f8a503dSdanielk1977 ** Usage: sqlite3_bind VM IDX VALUE FLAGS 8197c972decSdrh ** 8207c972decSdrh ** Sets the value of the IDX-th occurance of "?" in the original SQL 8217c972decSdrh ** string. VALUE is the new value. If FLAGS=="null" then VALUE is 8227c972decSdrh ** ignored and the value is set to NULL. If FLAGS=="static" then 8237c972decSdrh ** the value is set to the value of a static variable named 8247c972decSdrh ** "sqlite_static_bind_value". If FLAGS=="normal" then a copy 8257c972decSdrh ** of the VALUE is made. 8267c972decSdrh */ 8277c972decSdrh static int test_bind( 82850457896Sdrh void *NotUsed, 82950457896Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 83050457896Sdrh int argc, /* Number of arguments */ 83150457896Sdrh char **argv /* Text of each argument */ 83250457896Sdrh ){ 833fc57d7bfSdanielk1977 sqlite3_stmt *pStmt; 83450457896Sdrh int rc; 8357c972decSdrh int idx; 8367c972decSdrh if( argc!=5 ){ 83750457896Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 8387c972decSdrh " VM IDX VALUE (null|static|normal)\"", 0); 83950457896Sdrh return TCL_ERROR; 84050457896Sdrh } 841fc57d7bfSdanielk1977 if( getStmtPointer(interp, argv[1], &pStmt) ) return TCL_ERROR; 8427c972decSdrh if( Tcl_GetInt(interp, argv[2], &idx) ) return TCL_ERROR; 8437c972decSdrh if( strcmp(argv[4],"null")==0 ){ 844fc57d7bfSdanielk1977 rc = sqlite3_bind_null(pStmt, idx); 8457c972decSdrh }else if( strcmp(argv[4],"static")==0 ){ 846fc57d7bfSdanielk1977 rc = sqlite3_bind_text(pStmt, idx, sqlite_static_bind_value, -1, 0); 8477c972decSdrh }else if( strcmp(argv[4],"normal")==0 ){ 848fc57d7bfSdanielk1977 rc = sqlite3_bind_text(pStmt, idx, argv[3], -1, 1); 8497c972decSdrh }else{ 8507c972decSdrh Tcl_AppendResult(interp, "4th argument should be " 8517c972decSdrh "\"null\" or \"static\" or \"normal\"", 0); 8527c972decSdrh return TCL_ERROR; 8537c972decSdrh } 85450457896Sdrh if( rc ){ 85550457896Sdrh char zBuf[50]; 85650457896Sdrh sprintf(zBuf, "(%d) ", rc); 857f20b21c8Sdanielk1977 Tcl_AppendResult(interp, zBuf, sqlite3ErrStr(rc), 0); 85850457896Sdrh return TCL_ERROR; 85950457896Sdrh } 86050457896Sdrh return TCL_OK; 86150457896Sdrh } 86250457896Sdrh 86350457896Sdrh /* 86499ee3600Sdrh ** Usage: breakpoint 86599ee3600Sdrh ** 86699ee3600Sdrh ** This routine exists for one purpose - to provide a place to put a 86799ee3600Sdrh ** breakpoint with GDB that can be triggered using TCL code. The use 86899ee3600Sdrh ** for this is when a particular test fails on (say) the 1485th iteration. 86999ee3600Sdrh ** In the TCL test script, we can add code like this: 87099ee3600Sdrh ** 87199ee3600Sdrh ** if {$i==1485} breakpoint 87299ee3600Sdrh ** 87399ee3600Sdrh ** Then run testfixture in the debugger and wait for the breakpoint to 87499ee3600Sdrh ** fire. Then additional breakpoints can be set to trace down the bug. 87599ee3600Sdrh */ 87699ee3600Sdrh static int test_breakpoint( 87799ee3600Sdrh void *NotUsed, 87899ee3600Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 87999ee3600Sdrh int argc, /* Number of arguments */ 88099ee3600Sdrh char **argv /* Text of each argument */ 88199ee3600Sdrh ){ 88299ee3600Sdrh return TCL_OK; /* Do nothing */ 88399ee3600Sdrh } 88499ee3600Sdrh 88551e3d8e2Sdanielk1977 static int test_bind_int32( 88651e3d8e2Sdanielk1977 void * clientData, 88751e3d8e2Sdanielk1977 Tcl_Interp *interp, 88851e3d8e2Sdanielk1977 int objc, 88951e3d8e2Sdanielk1977 Tcl_Obj *CONST objv[] 89051e3d8e2Sdanielk1977 ){ 89151e3d8e2Sdanielk1977 sqlite3_stmt *pStmt; 89251e3d8e2Sdanielk1977 int idx; 89351e3d8e2Sdanielk1977 int value; 89451e3d8e2Sdanielk1977 int rc; 89551e3d8e2Sdanielk1977 89651e3d8e2Sdanielk1977 if( objc!=4 ){ 89751e3d8e2Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 89851e3d8e2Sdanielk1977 Tcl_GetStringFromObj(objv[0], 0), " <STMT> <param no.> <value>", 0); 89951e3d8e2Sdanielk1977 return TCL_ERROR; 90051e3d8e2Sdanielk1977 } 90151e3d8e2Sdanielk1977 90251e3d8e2Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 90351e3d8e2Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; 90451e3d8e2Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[3], &value) ) return TCL_ERROR; 90551e3d8e2Sdanielk1977 906c572ef7fSdanielk1977 rc = sqlite3_bind_int(pStmt, idx, value); 90751e3d8e2Sdanielk1977 if( rc!=SQLITE_OK ){ 90851e3d8e2Sdanielk1977 return TCL_ERROR; 90951e3d8e2Sdanielk1977 } 91051e3d8e2Sdanielk1977 91151e3d8e2Sdanielk1977 return TCL_OK; 91251e3d8e2Sdanielk1977 } 91351e3d8e2Sdanielk1977 91451e3d8e2Sdanielk1977 static int test_bind_int64( 91551e3d8e2Sdanielk1977 void * clientData, 91651e3d8e2Sdanielk1977 Tcl_Interp *interp, 91751e3d8e2Sdanielk1977 int objc, 91851e3d8e2Sdanielk1977 Tcl_Obj *CONST objv[] 91951e3d8e2Sdanielk1977 ){ 92051e3d8e2Sdanielk1977 sqlite3_stmt *pStmt; 92151e3d8e2Sdanielk1977 int idx; 92251e3d8e2Sdanielk1977 i64 value; 92351e3d8e2Sdanielk1977 int rc; 92451e3d8e2Sdanielk1977 92551e3d8e2Sdanielk1977 if( objc!=4 ){ 92651e3d8e2Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 92751e3d8e2Sdanielk1977 Tcl_GetStringFromObj(objv[0], 0), " <STMT> <param no.> <value>", 0); 92851e3d8e2Sdanielk1977 return TCL_ERROR; 92951e3d8e2Sdanielk1977 } 93051e3d8e2Sdanielk1977 93151e3d8e2Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 93251e3d8e2Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; 93351e3d8e2Sdanielk1977 if( Tcl_GetWideIntFromObj(interp, objv[3], &value) ) return TCL_ERROR; 93451e3d8e2Sdanielk1977 93551e3d8e2Sdanielk1977 rc = sqlite3_bind_int64(pStmt, idx, value); 93651e3d8e2Sdanielk1977 if( rc!=SQLITE_OK ){ 93751e3d8e2Sdanielk1977 return TCL_ERROR; 93851e3d8e2Sdanielk1977 } 93951e3d8e2Sdanielk1977 94051e3d8e2Sdanielk1977 return TCL_OK; 94151e3d8e2Sdanielk1977 } 94251e3d8e2Sdanielk1977 94351e3d8e2Sdanielk1977 static int test_bind_double( 94451e3d8e2Sdanielk1977 void * clientData, 94551e3d8e2Sdanielk1977 Tcl_Interp *interp, 94651e3d8e2Sdanielk1977 int objc, 94751e3d8e2Sdanielk1977 Tcl_Obj *CONST objv[] 94851e3d8e2Sdanielk1977 ){ 94951e3d8e2Sdanielk1977 sqlite3_stmt *pStmt; 95051e3d8e2Sdanielk1977 int idx; 95151e3d8e2Sdanielk1977 double value; 95251e3d8e2Sdanielk1977 int rc; 95351e3d8e2Sdanielk1977 95451e3d8e2Sdanielk1977 if( objc!=4 ){ 95551e3d8e2Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 95651e3d8e2Sdanielk1977 Tcl_GetStringFromObj(objv[0], 0), " <STMT> <param no.> <value>", 0); 95751e3d8e2Sdanielk1977 return TCL_ERROR; 95851e3d8e2Sdanielk1977 } 95951e3d8e2Sdanielk1977 96051e3d8e2Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 96151e3d8e2Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; 96251e3d8e2Sdanielk1977 if( Tcl_GetDoubleFromObj(interp, objv[3], &value) ) return TCL_ERROR; 96351e3d8e2Sdanielk1977 96451e3d8e2Sdanielk1977 rc = sqlite3_bind_double(pStmt, idx, value); 96551e3d8e2Sdanielk1977 if( rc!=SQLITE_OK ){ 96651e3d8e2Sdanielk1977 return TCL_ERROR; 96751e3d8e2Sdanielk1977 } 96851e3d8e2Sdanielk1977 96951e3d8e2Sdanielk1977 return TCL_OK; 97051e3d8e2Sdanielk1977 } 97151e3d8e2Sdanielk1977 97251e3d8e2Sdanielk1977 static int test_bind_null( 97351e3d8e2Sdanielk1977 void * clientData, 97451e3d8e2Sdanielk1977 Tcl_Interp *interp, 97551e3d8e2Sdanielk1977 int objc, 97651e3d8e2Sdanielk1977 Tcl_Obj *CONST objv[] 97751e3d8e2Sdanielk1977 ){ 97851e3d8e2Sdanielk1977 sqlite3_stmt *pStmt; 97951e3d8e2Sdanielk1977 int idx; 98051e3d8e2Sdanielk1977 int rc; 98151e3d8e2Sdanielk1977 98251e3d8e2Sdanielk1977 if( objc!=3 ){ 98351e3d8e2Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 98451e3d8e2Sdanielk1977 Tcl_GetStringFromObj(objv[0], 0), " <STMT> <param no.>", 0); 98551e3d8e2Sdanielk1977 return TCL_ERROR; 98651e3d8e2Sdanielk1977 } 98751e3d8e2Sdanielk1977 98851e3d8e2Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 98951e3d8e2Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; 99051e3d8e2Sdanielk1977 99151e3d8e2Sdanielk1977 rc = sqlite3_bind_null(pStmt, idx); 99251e3d8e2Sdanielk1977 if( rc!=SQLITE_OK ){ 99351e3d8e2Sdanielk1977 return TCL_ERROR; 99451e3d8e2Sdanielk1977 } 99551e3d8e2Sdanielk1977 99651e3d8e2Sdanielk1977 return TCL_OK; 99751e3d8e2Sdanielk1977 } 99851e3d8e2Sdanielk1977 99951e3d8e2Sdanielk1977 static int test_bind_text( 100051e3d8e2Sdanielk1977 void * clientData, 100151e3d8e2Sdanielk1977 Tcl_Interp *interp, 100251e3d8e2Sdanielk1977 int objc, 100351e3d8e2Sdanielk1977 Tcl_Obj *CONST objv[] 100451e3d8e2Sdanielk1977 ){ 100551e3d8e2Sdanielk1977 sqlite3_stmt *pStmt; 100651e3d8e2Sdanielk1977 int idx; 100751e3d8e2Sdanielk1977 int bytes; 100851e3d8e2Sdanielk1977 char *value; 100951e3d8e2Sdanielk1977 int rc; 101051e3d8e2Sdanielk1977 101151e3d8e2Sdanielk1977 if( objc!=5 ){ 101251e3d8e2Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 101351e3d8e2Sdanielk1977 Tcl_GetStringFromObj(objv[0], 0), " <STMT> <param no.> <value>" 101451e3d8e2Sdanielk1977 " <bytes>", 0); 101551e3d8e2Sdanielk1977 return TCL_ERROR; 101651e3d8e2Sdanielk1977 } 101751e3d8e2Sdanielk1977 101851e3d8e2Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 101951e3d8e2Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; 102051e3d8e2Sdanielk1977 value = Tcl_GetString(objv[3]); 102151e3d8e2Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[4], &bytes) ) return TCL_ERROR; 102251e3d8e2Sdanielk1977 102351e3d8e2Sdanielk1977 rc = sqlite3_bind_text(pStmt, idx, value, bytes, 1); 102451e3d8e2Sdanielk1977 if( rc!=SQLITE_OK ){ 102551e3d8e2Sdanielk1977 return TCL_ERROR; 102651e3d8e2Sdanielk1977 } 102751e3d8e2Sdanielk1977 102851e3d8e2Sdanielk1977 return TCL_OK; 102951e3d8e2Sdanielk1977 } 103051e3d8e2Sdanielk1977 103151e3d8e2Sdanielk1977 static int test_bind_text16( 103251e3d8e2Sdanielk1977 void * clientData, 103351e3d8e2Sdanielk1977 Tcl_Interp *interp, 103451e3d8e2Sdanielk1977 int objc, 103551e3d8e2Sdanielk1977 Tcl_Obj *CONST objv[] 103651e3d8e2Sdanielk1977 ){ 103751e3d8e2Sdanielk1977 sqlite3_stmt *pStmt; 103851e3d8e2Sdanielk1977 int idx; 103951e3d8e2Sdanielk1977 int bytes; 104051e3d8e2Sdanielk1977 char *value; 104151e3d8e2Sdanielk1977 int rc; 104251e3d8e2Sdanielk1977 104351e3d8e2Sdanielk1977 if( objc!=5 ){ 104451e3d8e2Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 104551e3d8e2Sdanielk1977 Tcl_GetStringFromObj(objv[0], 0), " <STMT> <param no.> <value>" 104651e3d8e2Sdanielk1977 " <bytes>", 0); 104751e3d8e2Sdanielk1977 return TCL_ERROR; 104851e3d8e2Sdanielk1977 } 104951e3d8e2Sdanielk1977 105051e3d8e2Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 105151e3d8e2Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; 105251e3d8e2Sdanielk1977 value = Tcl_GetByteArrayFromObj(objv[3], 0); 105351e3d8e2Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[4], &bytes) ) return TCL_ERROR; 105451e3d8e2Sdanielk1977 105551e3d8e2Sdanielk1977 rc = sqlite3_bind_text16(pStmt, idx, (void *)value, bytes, 1); 105651e3d8e2Sdanielk1977 if( rc!=SQLITE_OK ){ 105751e3d8e2Sdanielk1977 return TCL_ERROR; 105851e3d8e2Sdanielk1977 } 105951e3d8e2Sdanielk1977 106051e3d8e2Sdanielk1977 return TCL_OK; 106151e3d8e2Sdanielk1977 } 106251e3d8e2Sdanielk1977 106351e3d8e2Sdanielk1977 static int test_bind_blob( 106451e3d8e2Sdanielk1977 void * clientData, 106551e3d8e2Sdanielk1977 Tcl_Interp *interp, 106651e3d8e2Sdanielk1977 int objc, 106751e3d8e2Sdanielk1977 Tcl_Obj *CONST objv[] 106851e3d8e2Sdanielk1977 ){ 106951e3d8e2Sdanielk1977 sqlite3_stmt *pStmt; 107051e3d8e2Sdanielk1977 int idx; 107151e3d8e2Sdanielk1977 int bytes; 107251e3d8e2Sdanielk1977 char *value; 107351e3d8e2Sdanielk1977 int rc; 107451e3d8e2Sdanielk1977 107551e3d8e2Sdanielk1977 if( objc!=5 ){ 107651e3d8e2Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 107751e3d8e2Sdanielk1977 Tcl_GetStringFromObj(objv[0], 0), " <STMT> <param no.> <value>" 107851e3d8e2Sdanielk1977 " <bytes>", 0); 107951e3d8e2Sdanielk1977 return TCL_ERROR; 108051e3d8e2Sdanielk1977 } 108151e3d8e2Sdanielk1977 108251e3d8e2Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 108351e3d8e2Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; 108451e3d8e2Sdanielk1977 value = Tcl_GetString(objv[3]); 108549e4643eSdanielk1977 if( Tcl_GetIntFromObj(interp, objv[4], &bytes) ) return TCL_ERROR; 108651e3d8e2Sdanielk1977 108751e3d8e2Sdanielk1977 rc = sqlite3_bind_blob(pStmt, idx, value, bytes, 1); 108851e3d8e2Sdanielk1977 if( rc!=SQLITE_OK ){ 108951e3d8e2Sdanielk1977 return TCL_ERROR; 109051e3d8e2Sdanielk1977 } 109151e3d8e2Sdanielk1977 109251e3d8e2Sdanielk1977 return TCL_OK; 109351e3d8e2Sdanielk1977 } 109451e3d8e2Sdanielk1977 109599ee3600Sdrh /* 10966622cce3Sdanielk1977 ** Usage: sqlite3_errcode DB 10976622cce3Sdanielk1977 ** 10986622cce3Sdanielk1977 ** Return the string representation of the most recent sqlite3_* API 10996622cce3Sdanielk1977 ** error code. e.g. "SQLITE_ERROR". 11006622cce3Sdanielk1977 */ 11016622cce3Sdanielk1977 static int test_errcode( 11026622cce3Sdanielk1977 void * clientData, 11036622cce3Sdanielk1977 Tcl_Interp *interp, 11046622cce3Sdanielk1977 int objc, 11056622cce3Sdanielk1977 Tcl_Obj *CONST objv[] 11066622cce3Sdanielk1977 ){ 11076622cce3Sdanielk1977 sqlite3 *db; 11086622cce3Sdanielk1977 11096622cce3Sdanielk1977 if( objc!=2 ){ 11106622cce3Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 11116622cce3Sdanielk1977 Tcl_GetString(objv[0]), " DB", 0); 11126622cce3Sdanielk1977 return TCL_ERROR; 11136622cce3Sdanielk1977 } 11146622cce3Sdanielk1977 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 11156622cce3Sdanielk1977 Tcl_SetResult(interp, (char *)errorName(sqlite3_errcode(db)), 0); 11166622cce3Sdanielk1977 return TCL_OK; 11176622cce3Sdanielk1977 } 11186622cce3Sdanielk1977 11196622cce3Sdanielk1977 /* 11206622cce3Sdanielk1977 ** Usage: test_errmsg DB 11216622cce3Sdanielk1977 ** 11226622cce3Sdanielk1977 ** Returns the UTF-8 representation of the error message string for the 11236622cce3Sdanielk1977 ** most recent sqlite3_* API call. 11246622cce3Sdanielk1977 */ 11256622cce3Sdanielk1977 static int test_errmsg( 11266622cce3Sdanielk1977 void * clientData, 11276622cce3Sdanielk1977 Tcl_Interp *interp, 11286622cce3Sdanielk1977 int objc, 11296622cce3Sdanielk1977 Tcl_Obj *CONST objv[] 11306622cce3Sdanielk1977 ){ 11316622cce3Sdanielk1977 sqlite *db; 11326622cce3Sdanielk1977 const char *zErr; 11336622cce3Sdanielk1977 11346622cce3Sdanielk1977 if( objc!=2 ){ 11356622cce3Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 11366622cce3Sdanielk1977 Tcl_GetString(objv[0]), " DB", 0); 11376622cce3Sdanielk1977 return TCL_ERROR; 11386622cce3Sdanielk1977 } 11396622cce3Sdanielk1977 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 11406622cce3Sdanielk1977 11416622cce3Sdanielk1977 zErr = sqlite3_errmsg(db); 11426622cce3Sdanielk1977 Tcl_SetObjResult(interp, Tcl_NewStringObj(zErr, -1)); 11436622cce3Sdanielk1977 return TCL_OK; 11446622cce3Sdanielk1977 } 11456622cce3Sdanielk1977 11466622cce3Sdanielk1977 /* 11476622cce3Sdanielk1977 ** Usage: test_errmsg16 DB 11486622cce3Sdanielk1977 ** 11496622cce3Sdanielk1977 ** Returns the UTF-16 representation of the error message string for the 11506622cce3Sdanielk1977 ** most recent sqlite3_* API call. This is a byte array object at the TCL 11516622cce3Sdanielk1977 ** level, and it includes the 0x00 0x00 terminator bytes at the end of the 11526622cce3Sdanielk1977 ** UTF-16 string. 11536622cce3Sdanielk1977 */ 11546622cce3Sdanielk1977 static int test_errmsg16( 11556622cce3Sdanielk1977 void * clientData, 11566622cce3Sdanielk1977 Tcl_Interp *interp, 11576622cce3Sdanielk1977 int objc, 11586622cce3Sdanielk1977 Tcl_Obj *CONST objv[] 11596622cce3Sdanielk1977 ){ 11606622cce3Sdanielk1977 sqlite *db; 11616622cce3Sdanielk1977 const void *zErr; 11626622cce3Sdanielk1977 int bytes; 11636622cce3Sdanielk1977 11646622cce3Sdanielk1977 if( objc!=2 ){ 11656622cce3Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 11666622cce3Sdanielk1977 Tcl_GetString(objv[0]), " DB", 0); 11676622cce3Sdanielk1977 return TCL_ERROR; 11686622cce3Sdanielk1977 } 11696622cce3Sdanielk1977 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 11706622cce3Sdanielk1977 11716622cce3Sdanielk1977 zErr = sqlite3_errmsg16(db); 11726622cce3Sdanielk1977 bytes = sqlite3utf16ByteLen(zErr, -1); 11736622cce3Sdanielk1977 Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(zErr, bytes)); 11746622cce3Sdanielk1977 return TCL_OK; 11756622cce3Sdanielk1977 } 11766622cce3Sdanielk1977 11776622cce3Sdanielk1977 /* 11786622cce3Sdanielk1977 ** Usage: sqlite3_prepare DB sql bytes tailvar 11796622cce3Sdanielk1977 ** 11806622cce3Sdanielk1977 ** Compile up to <bytes> bytes of the supplied SQL string <sql> using 11816622cce3Sdanielk1977 ** database handle <DB>. The parameter <tailval> is the name of a global 11826622cce3Sdanielk1977 ** variable that is set to the unused portion of <sql> (if any). A 11836622cce3Sdanielk1977 ** STMT handle is returned. 11846622cce3Sdanielk1977 */ 11856622cce3Sdanielk1977 static int test_prepare( 11866622cce3Sdanielk1977 void * clientData, 11876622cce3Sdanielk1977 Tcl_Interp *interp, 11886622cce3Sdanielk1977 int objc, 11896622cce3Sdanielk1977 Tcl_Obj *CONST objv[] 11906622cce3Sdanielk1977 ){ 11916622cce3Sdanielk1977 sqlite3 *db; 11926622cce3Sdanielk1977 const char *zSql; 11936622cce3Sdanielk1977 int bytes; 11946622cce3Sdanielk1977 const char *zTail = 0; 11956622cce3Sdanielk1977 sqlite3_stmt *pStmt = 0; 11966622cce3Sdanielk1977 char zBuf[50]; 11974ad1713cSdanielk1977 int rc; 11986622cce3Sdanielk1977 11996622cce3Sdanielk1977 if( objc!=5 ){ 12006622cce3Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 12016622cce3Sdanielk1977 Tcl_GetString(objv[0]), " DB sql bytes tailvar", 0); 12026622cce3Sdanielk1977 return TCL_ERROR; 12036622cce3Sdanielk1977 } 12046622cce3Sdanielk1977 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 12056622cce3Sdanielk1977 zSql = Tcl_GetString(objv[2]); 12066622cce3Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR; 12076622cce3Sdanielk1977 12084ad1713cSdanielk1977 rc = sqlite3_prepare(db, zSql, bytes, &pStmt, &zTail); 12096622cce3Sdanielk1977 if( zTail ){ 12106622cce3Sdanielk1977 if( bytes>=0 ){ 12116622cce3Sdanielk1977 bytes = bytes - (zTail-zSql); 12126622cce3Sdanielk1977 } 12136622cce3Sdanielk1977 Tcl_ObjSetVar2(interp, objv[4], 0, Tcl_NewStringObj(zTail, bytes), 0); 12146622cce3Sdanielk1977 } 12154ad1713cSdanielk1977 if( rc!=SQLITE_OK ){ 12164ad1713cSdanielk1977 assert( pStmt==0 ); 12174ad1713cSdanielk1977 sprintf(zBuf, "(%d) ", rc); 12184ad1713cSdanielk1977 Tcl_AppendResult(interp, zBuf, sqlite3_errmsg(db), 0); 12194ad1713cSdanielk1977 return TCL_ERROR; 12204ad1713cSdanielk1977 } 12216622cce3Sdanielk1977 12224ad1713cSdanielk1977 if( pStmt ){ 12236622cce3Sdanielk1977 if( makePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR; 12246622cce3Sdanielk1977 Tcl_AppendResult(interp, zBuf, 0); 12254ad1713cSdanielk1977 } 12266622cce3Sdanielk1977 return TCL_OK; 12276622cce3Sdanielk1977 } 12286622cce3Sdanielk1977 12296622cce3Sdanielk1977 /* 12306622cce3Sdanielk1977 ** Usage: sqlite3_prepare DB sql bytes tailvar 12316622cce3Sdanielk1977 ** 12326622cce3Sdanielk1977 ** Compile up to <bytes> bytes of the supplied SQL string <sql> using 12336622cce3Sdanielk1977 ** database handle <DB>. The parameter <tailval> is the name of a global 12346622cce3Sdanielk1977 ** variable that is set to the unused portion of <sql> (if any). A 12356622cce3Sdanielk1977 ** STMT handle is returned. 12366622cce3Sdanielk1977 */ 12376622cce3Sdanielk1977 static int test_prepare16( 12386622cce3Sdanielk1977 void * clientData, 12396622cce3Sdanielk1977 Tcl_Interp *interp, 12406622cce3Sdanielk1977 int objc, 12416622cce3Sdanielk1977 Tcl_Obj *CONST objv[] 12426622cce3Sdanielk1977 ){ 12436622cce3Sdanielk1977 sqlite3 *db; 12446622cce3Sdanielk1977 const void *zSql; 12456622cce3Sdanielk1977 const void *zTail = 0; 12466622cce3Sdanielk1977 Tcl_Obj *pTail = 0; 12476622cce3Sdanielk1977 sqlite3_stmt *pStmt = 0; 12486622cce3Sdanielk1977 char zBuf[50]; 12496622cce3Sdanielk1977 int bytes; /* The integer specified as arg 3 */ 12506622cce3Sdanielk1977 int objlen; /* The byte-array length of arg 2 */ 12516622cce3Sdanielk1977 12526622cce3Sdanielk1977 if( objc!=5 ){ 12536622cce3Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 12546622cce3Sdanielk1977 Tcl_GetString(objv[0]), " DB sql bytes tailvar", 0); 12556622cce3Sdanielk1977 return TCL_ERROR; 12566622cce3Sdanielk1977 } 12576622cce3Sdanielk1977 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 12586622cce3Sdanielk1977 zSql = Tcl_GetByteArrayFromObj(objv[2], &objlen); 12596622cce3Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR; 12606622cce3Sdanielk1977 12616622cce3Sdanielk1977 if( SQLITE_OK!=sqlite3_prepare16(db, zSql, bytes, &pStmt, &zTail) ){ 12626622cce3Sdanielk1977 return TCL_ERROR; 12636622cce3Sdanielk1977 } 12646622cce3Sdanielk1977 12656622cce3Sdanielk1977 if( zTail ){ 12666622cce3Sdanielk1977 objlen = objlen - ((u8 *)zTail-(u8 *)zSql); 12676622cce3Sdanielk1977 }else{ 12686622cce3Sdanielk1977 objlen = 0; 12696622cce3Sdanielk1977 } 12706622cce3Sdanielk1977 pTail = Tcl_NewByteArrayObj((u8 *)zTail, objlen); 12716622cce3Sdanielk1977 Tcl_IncrRefCount(pTail); 12726622cce3Sdanielk1977 Tcl_ObjSetVar2(interp, objv[4], 0, pTail, 0); 12734ad1713cSdanielk1977 Tcl_DecrRefCount(pTail); 12746622cce3Sdanielk1977 12754ad1713cSdanielk1977 if( pStmt ){ 12766622cce3Sdanielk1977 if( makePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR; 12774ad1713cSdanielk1977 } 12786622cce3Sdanielk1977 Tcl_AppendResult(interp, zBuf, 0); 12796622cce3Sdanielk1977 return TCL_OK; 12806622cce3Sdanielk1977 } 12816622cce3Sdanielk1977 12824ad1713cSdanielk1977 /* 12834ad1713cSdanielk1977 ** Usage: sqlite3_open filename ?options-list? 12844ad1713cSdanielk1977 */ 12854ad1713cSdanielk1977 static int test_open( 12864ad1713cSdanielk1977 void * clientData, 12874ad1713cSdanielk1977 Tcl_Interp *interp, 12884ad1713cSdanielk1977 int objc, 12894ad1713cSdanielk1977 Tcl_Obj *CONST objv[] 12904ad1713cSdanielk1977 ){ 12914ad1713cSdanielk1977 const char *zFilename; 12924ad1713cSdanielk1977 sqlite3 *db; 12934ad1713cSdanielk1977 int rc; 12944ad1713cSdanielk1977 char zBuf[100]; 12954ad1713cSdanielk1977 12964ad1713cSdanielk1977 if( objc!=3 && objc!=2 ){ 12974ad1713cSdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 12984ad1713cSdanielk1977 Tcl_GetString(objv[0]), " filename options-list", 0); 12994ad1713cSdanielk1977 return TCL_ERROR; 13004ad1713cSdanielk1977 } 13014ad1713cSdanielk1977 13024ad1713cSdanielk1977 zFilename = Tcl_GetString(objv[1]); 13034f057f90Sdanielk1977 rc = sqlite3_open(zFilename, &db); 13044ad1713cSdanielk1977 13054ad1713cSdanielk1977 if( makePointerStr(interp, zBuf, db) ) return TCL_ERROR; 13064ad1713cSdanielk1977 Tcl_AppendResult(interp, zBuf, 0); 13074ad1713cSdanielk1977 return TCL_OK; 13084ad1713cSdanielk1977 } 13094ad1713cSdanielk1977 13104ad1713cSdanielk1977 /* 13114ad1713cSdanielk1977 ** Usage: sqlite3_open16 filename options 13124ad1713cSdanielk1977 */ 13134ad1713cSdanielk1977 static int test_open16( 13144ad1713cSdanielk1977 void * clientData, 13154ad1713cSdanielk1977 Tcl_Interp *interp, 13164ad1713cSdanielk1977 int objc, 13174ad1713cSdanielk1977 Tcl_Obj *CONST objv[] 13184ad1713cSdanielk1977 ){ 13194ad1713cSdanielk1977 const void *zFilename; 13204ad1713cSdanielk1977 sqlite3 *db; 13214ad1713cSdanielk1977 int rc; 13224ad1713cSdanielk1977 char zBuf[100]; 13234ad1713cSdanielk1977 13244ad1713cSdanielk1977 if( objc!=3 ){ 13254ad1713cSdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 13264ad1713cSdanielk1977 Tcl_GetString(objv[0]), " filename options-list", 0); 13274ad1713cSdanielk1977 return TCL_ERROR; 13284ad1713cSdanielk1977 } 13294ad1713cSdanielk1977 13304ad1713cSdanielk1977 zFilename = Tcl_GetByteArrayFromObj(objv[1], 0); 13314f057f90Sdanielk1977 rc = sqlite3_open16(zFilename, &db); 13324ad1713cSdanielk1977 13334ad1713cSdanielk1977 if( makePointerStr(interp, zBuf, db) ) return TCL_ERROR; 13344ad1713cSdanielk1977 Tcl_AppendResult(interp, zBuf, 0); 13354ad1713cSdanielk1977 return TCL_OK; 13364ad1713cSdanielk1977 } 1337d3d39e93Sdrh 1338d3d39e93Sdrh /* 1339106bb236Sdanielk1977 ** Usage: sqlite3_step STMT 1340106bb236Sdanielk1977 ** 1341106bb236Sdanielk1977 ** Advance the statement to the next row. 1342106bb236Sdanielk1977 */ 134317240fd9Sdanielk1977 static int test_step( 1344106bb236Sdanielk1977 void * clientData, 1345106bb236Sdanielk1977 Tcl_Interp *interp, 1346106bb236Sdanielk1977 int objc, 1347106bb236Sdanielk1977 Tcl_Obj *CONST objv[] 1348106bb236Sdanielk1977 ){ 1349106bb236Sdanielk1977 sqlite3_stmt *pStmt; 1350106bb236Sdanielk1977 int rc; 1351106bb236Sdanielk1977 1352e1cd9874Sdanielk1977 if( objc!=2 ){ 1353106bb236Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 1354106bb236Sdanielk1977 Tcl_GetString(objv[0]), " STMT", 0); 1355106bb236Sdanielk1977 return TCL_ERROR; 1356106bb236Sdanielk1977 } 1357106bb236Sdanielk1977 1358106bb236Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 135917240fd9Sdanielk1977 rc = sqlite3_step(pStmt); 1360106bb236Sdanielk1977 1361e1cd9874Sdanielk1977 if( rc!=SQLITE_DONE && rc!=SQLITE_ROW ) return TCL_ERROR; 13626590493dSdanielk1977 Tcl_SetResult(interp, (char *)errorName(rc), 0); 1363e1cd9874Sdanielk1977 return TCL_OK; 1364e1cd9874Sdanielk1977 } 1365e1cd9874Sdanielk1977 1366e1cd9874Sdanielk1977 /* 136717240fd9Sdanielk1977 ** Usage: sqlite3_column_count STMT 136817240fd9Sdanielk1977 ** 136917240fd9Sdanielk1977 ** Return the number of columns returned by the sql statement STMT. 137017240fd9Sdanielk1977 */ 137117240fd9Sdanielk1977 static int test_column_count( 137217240fd9Sdanielk1977 void * clientData, 137317240fd9Sdanielk1977 Tcl_Interp *interp, 137417240fd9Sdanielk1977 int objc, 137517240fd9Sdanielk1977 Tcl_Obj *CONST objv[] 137617240fd9Sdanielk1977 ){ 137717240fd9Sdanielk1977 sqlite3_stmt *pStmt; 137817240fd9Sdanielk1977 137917240fd9Sdanielk1977 if( objc!=2 ){ 138017240fd9Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 138117240fd9Sdanielk1977 Tcl_GetString(objv[0]), " STMT column", 0); 138217240fd9Sdanielk1977 return TCL_ERROR; 138317240fd9Sdanielk1977 } 138417240fd9Sdanielk1977 138517240fd9Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 138617240fd9Sdanielk1977 138717240fd9Sdanielk1977 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_column_count(pStmt))); 138817240fd9Sdanielk1977 return TCL_OK; 138917240fd9Sdanielk1977 } 139017240fd9Sdanielk1977 139117240fd9Sdanielk1977 /* 13923cf86063Sdanielk1977 ** Usage: sqlite3_column_type STMT column 13933cf86063Sdanielk1977 ** 13943cf86063Sdanielk1977 ** Return the type of the data in column 'column' of the current row. 13953cf86063Sdanielk1977 */ 13963cf86063Sdanielk1977 static int test_column_type( 13973cf86063Sdanielk1977 void * clientData, 13983cf86063Sdanielk1977 Tcl_Interp *interp, 13993cf86063Sdanielk1977 int objc, 14003cf86063Sdanielk1977 Tcl_Obj *CONST objv[] 14013cf86063Sdanielk1977 ){ 14023cf86063Sdanielk1977 sqlite3_stmt *pStmt; 14033cf86063Sdanielk1977 int col; 14043cf86063Sdanielk1977 int tp; 14053cf86063Sdanielk1977 14063cf86063Sdanielk1977 if( objc!=3 ){ 14073cf86063Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 14083cf86063Sdanielk1977 Tcl_GetString(objv[0]), " STMT column", 0); 14093cf86063Sdanielk1977 return TCL_ERROR; 14103cf86063Sdanielk1977 } 14113cf86063Sdanielk1977 14123cf86063Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 14133cf86063Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; 14143cf86063Sdanielk1977 14153cf86063Sdanielk1977 tp = sqlite3_column_type(pStmt, col); 14163cf86063Sdanielk1977 switch( tp ){ 14179c054830Sdrh case SQLITE_INTEGER: 14183cf86063Sdanielk1977 Tcl_SetResult(interp, "INTEGER", TCL_STATIC); 14193cf86063Sdanielk1977 break; 14209c054830Sdrh case SQLITE_NULL: 14213cf86063Sdanielk1977 Tcl_SetResult(interp, "NULL", TCL_STATIC); 14223cf86063Sdanielk1977 break; 14239c054830Sdrh case SQLITE_FLOAT: 14243cf86063Sdanielk1977 Tcl_SetResult(interp, "FLOAT", TCL_STATIC); 14253cf86063Sdanielk1977 break; 14269c054830Sdrh case SQLITE_TEXT: 14273cf86063Sdanielk1977 Tcl_SetResult(interp, "TEXT", TCL_STATIC); 14283cf86063Sdanielk1977 break; 14299c054830Sdrh case SQLITE_BLOB: 14303cf86063Sdanielk1977 Tcl_SetResult(interp, "BLOB", TCL_STATIC); 14313cf86063Sdanielk1977 break; 14323cf86063Sdanielk1977 default: 14333cf86063Sdanielk1977 assert(0); 14343cf86063Sdanielk1977 } 14353cf86063Sdanielk1977 14363cf86063Sdanielk1977 return TCL_OK; 14373cf86063Sdanielk1977 } 14383cf86063Sdanielk1977 14393cf86063Sdanielk1977 /* 144004f2e68dSdanielk1977 ** Usage: sqlite3_column_int64 STMT column 14413cf86063Sdanielk1977 ** 14423cf86063Sdanielk1977 ** Return the data in column 'column' of the current row cast as an 144304f2e68dSdanielk1977 ** wide (64-bit) integer. 14443cf86063Sdanielk1977 */ 144504f2e68dSdanielk1977 static int test_column_int64( 14463cf86063Sdanielk1977 void * clientData, 14473cf86063Sdanielk1977 Tcl_Interp *interp, 14483cf86063Sdanielk1977 int objc, 14493cf86063Sdanielk1977 Tcl_Obj *CONST objv[] 14503cf86063Sdanielk1977 ){ 14513cf86063Sdanielk1977 sqlite3_stmt *pStmt; 14523cf86063Sdanielk1977 int col; 145304f2e68dSdanielk1977 i64 iVal; 14543cf86063Sdanielk1977 14553cf86063Sdanielk1977 if( objc!=3 ){ 14563cf86063Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 14573cf86063Sdanielk1977 Tcl_GetString(objv[0]), " STMT column", 0); 14583cf86063Sdanielk1977 return TCL_ERROR; 14593cf86063Sdanielk1977 } 14603cf86063Sdanielk1977 14613cf86063Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 14623cf86063Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; 14633cf86063Sdanielk1977 146404f2e68dSdanielk1977 iVal = sqlite3_column_int64(pStmt, col); 146504f2e68dSdanielk1977 Tcl_SetObjResult(interp, Tcl_NewWideIntObj(iVal)); 146604f2e68dSdanielk1977 return TCL_OK; 146704f2e68dSdanielk1977 } 146804f2e68dSdanielk1977 146904f2e68dSdanielk1977 /* 1470ea61b2c4Sdanielk1977 ** Usage: sqlite3_column_blob STMT column 1471ea61b2c4Sdanielk1977 */ 1472ea61b2c4Sdanielk1977 static int test_column_blob( 1473ea61b2c4Sdanielk1977 void * clientData, 1474ea61b2c4Sdanielk1977 Tcl_Interp *interp, 1475ea61b2c4Sdanielk1977 int objc, 1476ea61b2c4Sdanielk1977 Tcl_Obj *CONST objv[] 1477ea61b2c4Sdanielk1977 ){ 1478ea61b2c4Sdanielk1977 sqlite3_stmt *pStmt; 1479ea61b2c4Sdanielk1977 int col; 1480ea61b2c4Sdanielk1977 1481ea61b2c4Sdanielk1977 int len; 1482c572ef7fSdanielk1977 const void *pBlob; 1483ea61b2c4Sdanielk1977 1484ea61b2c4Sdanielk1977 if( objc!=3 ){ 1485ea61b2c4Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 1486ea61b2c4Sdanielk1977 Tcl_GetString(objv[0]), " STMT column", 0); 1487ea61b2c4Sdanielk1977 return TCL_ERROR; 1488ea61b2c4Sdanielk1977 } 1489ea61b2c4Sdanielk1977 1490ea61b2c4Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 1491ea61b2c4Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; 1492ea61b2c4Sdanielk1977 1493ea61b2c4Sdanielk1977 pBlob = sqlite3_column_blob(pStmt, col); 1494ea61b2c4Sdanielk1977 len = sqlite3_column_bytes(pStmt, col); 1495ea61b2c4Sdanielk1977 Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(pBlob, len)); 1496ea61b2c4Sdanielk1977 return TCL_OK; 1497ea61b2c4Sdanielk1977 } 1498ea61b2c4Sdanielk1977 1499ea61b2c4Sdanielk1977 /* 150004f2e68dSdanielk1977 ** Usage: sqlite3_column_double STMT column 150104f2e68dSdanielk1977 ** 150204f2e68dSdanielk1977 ** Return the data in column 'column' of the current row cast as a double. 150304f2e68dSdanielk1977 */ 150404f2e68dSdanielk1977 static int test_column_double( 150504f2e68dSdanielk1977 void * clientData, 150604f2e68dSdanielk1977 Tcl_Interp *interp, 150704f2e68dSdanielk1977 int objc, 150804f2e68dSdanielk1977 Tcl_Obj *CONST objv[] 150904f2e68dSdanielk1977 ){ 151004f2e68dSdanielk1977 sqlite3_stmt *pStmt; 151104f2e68dSdanielk1977 int col; 151204f2e68dSdanielk1977 double rVal; 151304f2e68dSdanielk1977 151404f2e68dSdanielk1977 if( objc!=3 ){ 151504f2e68dSdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 151604f2e68dSdanielk1977 Tcl_GetString(objv[0]), " STMT column", 0); 151704f2e68dSdanielk1977 return TCL_ERROR; 151804f2e68dSdanielk1977 } 151904f2e68dSdanielk1977 152004f2e68dSdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 152104f2e68dSdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; 152204f2e68dSdanielk1977 152304f2e68dSdanielk1977 rVal = sqlite3_column_double(pStmt, col); 1524c572ef7fSdanielk1977 Tcl_SetObjResult(interp, Tcl_NewDoubleObj(rVal)); 15253cf86063Sdanielk1977 return TCL_OK; 15263cf86063Sdanielk1977 } 15273cf86063Sdanielk1977 15283cf86063Sdanielk1977 /* 152917240fd9Sdanielk1977 ** Usage: sqlite3_data_count STMT 153017240fd9Sdanielk1977 ** 153117240fd9Sdanielk1977 ** Return the number of columns returned by the sql statement STMT. 153217240fd9Sdanielk1977 */ 153317240fd9Sdanielk1977 static int test_data_count( 153417240fd9Sdanielk1977 void * clientData, 153517240fd9Sdanielk1977 Tcl_Interp *interp, 153617240fd9Sdanielk1977 int objc, 153717240fd9Sdanielk1977 Tcl_Obj *CONST objv[] 153817240fd9Sdanielk1977 ){ 153917240fd9Sdanielk1977 sqlite3_stmt *pStmt; 154017240fd9Sdanielk1977 154117240fd9Sdanielk1977 if( objc!=2 ){ 154217240fd9Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 154317240fd9Sdanielk1977 Tcl_GetString(objv[0]), " STMT column", 0); 154417240fd9Sdanielk1977 return TCL_ERROR; 154517240fd9Sdanielk1977 } 154617240fd9Sdanielk1977 154717240fd9Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 154817240fd9Sdanielk1977 154917240fd9Sdanielk1977 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_data_count(pStmt))); 155017240fd9Sdanielk1977 return TCL_OK; 155117240fd9Sdanielk1977 } 155217240fd9Sdanielk1977 155317240fd9Sdanielk1977 /* 155404f2e68dSdanielk1977 ** Usage: sqlite3_column_text STMT column 155504f2e68dSdanielk1977 ** 155604f2e68dSdanielk1977 ** Usage: sqlite3_column_decltype STMT column 155704f2e68dSdanielk1977 ** 155804f2e68dSdanielk1977 ** Usage: sqlite3_column_name STMT column 155904f2e68dSdanielk1977 */ 156004f2e68dSdanielk1977 static int test_stmt_utf8( 156104f2e68dSdanielk1977 void * clientData, 156204f2e68dSdanielk1977 Tcl_Interp *interp, 156304f2e68dSdanielk1977 int objc, 156404f2e68dSdanielk1977 Tcl_Obj *CONST objv[] 156504f2e68dSdanielk1977 ){ 156604f2e68dSdanielk1977 sqlite3_stmt *pStmt; 156704f2e68dSdanielk1977 int col; 1568c572ef7fSdanielk1977 const char *(*xFunc)(sqlite3_stmt*, int) = clientData; 1569f93bbbeaSdanielk1977 const char *zRet; 157004f2e68dSdanielk1977 157104f2e68dSdanielk1977 if( objc!=3 ){ 157204f2e68dSdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 157304f2e68dSdanielk1977 Tcl_GetString(objv[0]), " STMT column", 0); 157404f2e68dSdanielk1977 return TCL_ERROR; 157504f2e68dSdanielk1977 } 157604f2e68dSdanielk1977 157704f2e68dSdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 157804f2e68dSdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; 1579f93bbbeaSdanielk1977 zRet = xFunc(pStmt, col); 1580f93bbbeaSdanielk1977 if( zRet ){ 1581f93bbbeaSdanielk1977 Tcl_SetResult(interp, (char *)zRet, 0); 1582f93bbbeaSdanielk1977 } 158304f2e68dSdanielk1977 return TCL_OK; 158404f2e68dSdanielk1977 } 158504f2e68dSdanielk1977 158604f2e68dSdanielk1977 /* 158704f2e68dSdanielk1977 ** Usage: sqlite3_column_text STMT column 158804f2e68dSdanielk1977 ** 158904f2e68dSdanielk1977 ** Usage: sqlite3_column_decltype STMT column 159004f2e68dSdanielk1977 ** 159104f2e68dSdanielk1977 ** Usage: sqlite3_column_name STMT column 159204f2e68dSdanielk1977 */ 159304f2e68dSdanielk1977 static int test_stmt_utf16( 159404f2e68dSdanielk1977 void * clientData, 159504f2e68dSdanielk1977 Tcl_Interp *interp, 159604f2e68dSdanielk1977 int objc, 159704f2e68dSdanielk1977 Tcl_Obj *CONST objv[] 159804f2e68dSdanielk1977 ){ 159904f2e68dSdanielk1977 sqlite3_stmt *pStmt; 160004f2e68dSdanielk1977 int col; 160104f2e68dSdanielk1977 Tcl_Obj *pRet; 160204f2e68dSdanielk1977 const void *zName16; 1603c572ef7fSdanielk1977 const void *(*xFunc)(sqlite3_stmt*, int) = clientData; 160404f2e68dSdanielk1977 160504f2e68dSdanielk1977 if( objc!=3 ){ 160604f2e68dSdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 160704f2e68dSdanielk1977 Tcl_GetString(objv[0]), " STMT column", 0); 160804f2e68dSdanielk1977 return TCL_ERROR; 160904f2e68dSdanielk1977 } 161004f2e68dSdanielk1977 161104f2e68dSdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 161204f2e68dSdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; 161304f2e68dSdanielk1977 161404f2e68dSdanielk1977 zName16 = xFunc(pStmt, col); 1615f93bbbeaSdanielk1977 if( zName16 ){ 161604f2e68dSdanielk1977 pRet = Tcl_NewByteArrayObj(zName16, sqlite3utf16ByteLen(zName16, -1)+2); 161704f2e68dSdanielk1977 Tcl_SetObjResult(interp, pRet); 1618f93bbbeaSdanielk1977 } 161904f2e68dSdanielk1977 162004f2e68dSdanielk1977 return TCL_OK; 162104f2e68dSdanielk1977 } 162204f2e68dSdanielk1977 162304f2e68dSdanielk1977 /* 162404f2e68dSdanielk1977 ** Usage: sqlite3_column_int STMT column 162504f2e68dSdanielk1977 ** 162604f2e68dSdanielk1977 ** Usage: sqlite3_column_bytes STMT column 162704f2e68dSdanielk1977 ** 162804f2e68dSdanielk1977 ** Usage: sqlite3_column_bytes16 STMT column 162904f2e68dSdanielk1977 ** 163004f2e68dSdanielk1977 */ 163104f2e68dSdanielk1977 static int test_stmt_int( 163204f2e68dSdanielk1977 void * clientData, 163304f2e68dSdanielk1977 Tcl_Interp *interp, 163404f2e68dSdanielk1977 int objc, 163504f2e68dSdanielk1977 Tcl_Obj *CONST objv[] 163604f2e68dSdanielk1977 ){ 163704f2e68dSdanielk1977 sqlite3_stmt *pStmt; 163804f2e68dSdanielk1977 int col; 1639c572ef7fSdanielk1977 int (*xFunc)(sqlite3_stmt*, int) = clientData; 164004f2e68dSdanielk1977 164104f2e68dSdanielk1977 if( objc!=3 ){ 164204f2e68dSdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 164304f2e68dSdanielk1977 Tcl_GetString(objv[0]), " STMT column", 0); 164404f2e68dSdanielk1977 return TCL_ERROR; 164504f2e68dSdanielk1977 } 164604f2e68dSdanielk1977 164704f2e68dSdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 164804f2e68dSdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; 164904f2e68dSdanielk1977 165004f2e68dSdanielk1977 Tcl_SetObjResult(interp, Tcl_NewIntObj(xFunc(pStmt, col))); 165104f2e68dSdanielk1977 return TCL_OK; 165204f2e68dSdanielk1977 } 165304f2e68dSdanielk1977 16549a1d0abeSdanielk1977 /* 16559a1d0abeSdanielk1977 ** Usage: sqlite3OsOpenReadWrite <filename> 16569a1d0abeSdanielk1977 */ 16579a1d0abeSdanielk1977 static int test_sqlite3OsOpenReadWrite( 16589a1d0abeSdanielk1977 void * clientData, 16599a1d0abeSdanielk1977 Tcl_Interp *interp, 16609a1d0abeSdanielk1977 int objc, 16619a1d0abeSdanielk1977 Tcl_Obj *CONST objv[] 16629a1d0abeSdanielk1977 ){ 16639a1d0abeSdanielk1977 OsFile * pFile; 16649a1d0abeSdanielk1977 int rc; 16659a1d0abeSdanielk1977 int dummy; 16669a1d0abeSdanielk1977 char zBuf[100]; 166704f2e68dSdanielk1977 16689a1d0abeSdanielk1977 if( objc!=2 ){ 16699a1d0abeSdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 16709a1d0abeSdanielk1977 Tcl_GetString(objv[0]), " filename", 0); 16719a1d0abeSdanielk1977 return TCL_ERROR; 16729a1d0abeSdanielk1977 } 16739a1d0abeSdanielk1977 16749a1d0abeSdanielk1977 pFile = sqliteMalloc(sizeof(OsFile)); 16759a1d0abeSdanielk1977 rc = sqlite3OsOpenReadWrite(Tcl_GetString(objv[1]), pFile, &dummy); 16769a1d0abeSdanielk1977 if( rc!=SQLITE_OK ){ 16779a1d0abeSdanielk1977 sqliteFree(pFile); 16789a1d0abeSdanielk1977 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC); 16799a1d0abeSdanielk1977 return TCL_ERROR; 16809a1d0abeSdanielk1977 } 16819a1d0abeSdanielk1977 makePointerStr(interp, zBuf, pFile); 16829a1d0abeSdanielk1977 Tcl_SetResult(interp, zBuf, 0); 16839a1d0abeSdanielk1977 return TCL_ERROR; 16849a1d0abeSdanielk1977 } 16859a1d0abeSdanielk1977 16869a1d0abeSdanielk1977 /* 16879a1d0abeSdanielk1977 ** Usage: sqlite3OsClose <file handle> 16889a1d0abeSdanielk1977 */ 16899a1d0abeSdanielk1977 static int test_sqlite3OsClose( 16909a1d0abeSdanielk1977 void * clientData, 16919a1d0abeSdanielk1977 Tcl_Interp *interp, 16929a1d0abeSdanielk1977 int objc, 16939a1d0abeSdanielk1977 Tcl_Obj *CONST objv[] 16949a1d0abeSdanielk1977 ){ 16959a1d0abeSdanielk1977 OsFile * pFile; 16969a1d0abeSdanielk1977 int rc; 16979a1d0abeSdanielk1977 16989a1d0abeSdanielk1977 if( objc!=2 ){ 16999a1d0abeSdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 17009a1d0abeSdanielk1977 Tcl_GetString(objv[0]), " filehandle", 0); 17019a1d0abeSdanielk1977 return TCL_ERROR; 17029a1d0abeSdanielk1977 } 17039a1d0abeSdanielk1977 17049a1d0abeSdanielk1977 if( getFilePointer(interp, Tcl_GetString(objv[1]), &pFile) ){ 17059a1d0abeSdanielk1977 return TCL_ERROR; 17069a1d0abeSdanielk1977 } 17079a1d0abeSdanielk1977 rc = sqlite3OsClose(pFile); 17089a1d0abeSdanielk1977 if( rc!=SQLITE_OK ){ 17099a1d0abeSdanielk1977 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC); 17109a1d0abeSdanielk1977 return TCL_ERROR; 17119a1d0abeSdanielk1977 } 17129a1d0abeSdanielk1977 sqliteFree(pFile); 17139a1d0abeSdanielk1977 return TCL_OK; 17149a1d0abeSdanielk1977 } 17159a1d0abeSdanielk1977 17169a1d0abeSdanielk1977 /* 17179a1d0abeSdanielk1977 ** Usage: sqlite3OsLock <file handle> <locktype> 17189a1d0abeSdanielk1977 */ 17199a1d0abeSdanielk1977 static int test_sqlite3OsLock( 17209a1d0abeSdanielk1977 void * clientData, 17219a1d0abeSdanielk1977 Tcl_Interp *interp, 17229a1d0abeSdanielk1977 int objc, 17239a1d0abeSdanielk1977 Tcl_Obj *CONST objv[] 17249a1d0abeSdanielk1977 ){ 17259a1d0abeSdanielk1977 OsFile * pFile; 17269a1d0abeSdanielk1977 int rc; 17279a1d0abeSdanielk1977 17289a1d0abeSdanielk1977 if( objc!=3 ){ 17299a1d0abeSdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 17309a1d0abeSdanielk1977 Tcl_GetString(objv[0]), 17319a1d0abeSdanielk1977 " filehandle (SHARED|RESERVED|PENDING|EXCLUSIVE)", 0); 17329a1d0abeSdanielk1977 return TCL_ERROR; 17339a1d0abeSdanielk1977 } 17349a1d0abeSdanielk1977 17359a1d0abeSdanielk1977 if( getFilePointer(interp, Tcl_GetString(objv[1]), &pFile) ){ 17369a1d0abeSdanielk1977 return TCL_ERROR; 17379a1d0abeSdanielk1977 } 17389a1d0abeSdanielk1977 17399a1d0abeSdanielk1977 if( 0==strcmp("SHARED", Tcl_GetString(objv[2])) ){ 17409a1d0abeSdanielk1977 rc = sqlite3OsLock(pFile, SHARED_LOCK); 17419a1d0abeSdanielk1977 } 17429a1d0abeSdanielk1977 else if( 0==strcmp("RESERVED", Tcl_GetString(objv[2])) ){ 17439a1d0abeSdanielk1977 rc = sqlite3OsLock(pFile, RESERVED_LOCK); 17449a1d0abeSdanielk1977 } 17459a1d0abeSdanielk1977 else if( 0==strcmp("PENDING", Tcl_GetString(objv[2])) ){ 17469a1d0abeSdanielk1977 rc = sqlite3OsLock(pFile, PENDING_LOCK); 17479a1d0abeSdanielk1977 } 17489a1d0abeSdanielk1977 else if( 0==strcmp("EXCLUSIVE", Tcl_GetString(objv[2])) ){ 17499a1d0abeSdanielk1977 rc = sqlite3OsLock(pFile, EXCLUSIVE_LOCK); 17509a1d0abeSdanielk1977 }else{ 17519a1d0abeSdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 17529a1d0abeSdanielk1977 Tcl_GetString(objv[0]), 17539a1d0abeSdanielk1977 " filehandle (SHARED|RESERVED|PENDING|EXCLUSIVE)", 0); 17549a1d0abeSdanielk1977 return TCL_ERROR; 17559a1d0abeSdanielk1977 } 17569a1d0abeSdanielk1977 17579a1d0abeSdanielk1977 if( rc!=SQLITE_OK ){ 17589a1d0abeSdanielk1977 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC); 17599a1d0abeSdanielk1977 return TCL_ERROR; 17609a1d0abeSdanielk1977 } 17619a1d0abeSdanielk1977 return TCL_OK; 17629a1d0abeSdanielk1977 } 17639a1d0abeSdanielk1977 17649a1d0abeSdanielk1977 /* 17659a1d0abeSdanielk1977 ** Usage: sqlite3OsUnlock <file handle> 17669a1d0abeSdanielk1977 */ 17679a1d0abeSdanielk1977 static int test_sqlite3OsUnlock( 17689a1d0abeSdanielk1977 void * clientData, 17699a1d0abeSdanielk1977 Tcl_Interp *interp, 17709a1d0abeSdanielk1977 int objc, 17719a1d0abeSdanielk1977 Tcl_Obj *CONST objv[] 17729a1d0abeSdanielk1977 ){ 17739a1d0abeSdanielk1977 OsFile * pFile; 17749a1d0abeSdanielk1977 int rc; 17759a1d0abeSdanielk1977 17769a1d0abeSdanielk1977 if( objc!=2 ){ 17779a1d0abeSdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 17789a1d0abeSdanielk1977 Tcl_GetString(objv[0]), " filehandle", 0); 17799a1d0abeSdanielk1977 return TCL_ERROR; 17809a1d0abeSdanielk1977 } 17819a1d0abeSdanielk1977 17829a1d0abeSdanielk1977 if( getFilePointer(interp, Tcl_GetString(objv[1]), &pFile) ){ 17839a1d0abeSdanielk1977 return TCL_ERROR; 17849a1d0abeSdanielk1977 } 17859a1d0abeSdanielk1977 rc = sqlite3OsUnlock(pFile); 17869a1d0abeSdanielk1977 if( rc!=SQLITE_OK ){ 17879a1d0abeSdanielk1977 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC); 17889a1d0abeSdanielk1977 return TCL_ERROR; 17899a1d0abeSdanielk1977 } 17909a1d0abeSdanielk1977 return TCL_OK; 17919a1d0abeSdanielk1977 } 1792d3d39e93Sdrh 17936622cce3Sdanielk1977 /* 1794d1bf3512Sdrh ** Register commands with the TCL interpreter. 1795d1bf3512Sdrh */ 1796d1bf3512Sdrh int Sqlitetest1_Init(Tcl_Interp *interp){ 17976f8a503dSdanielk1977 extern int sqlite3_search_count; 17986f8a503dSdanielk1977 extern int sqlite3_interrupt_count; 17996f8a503dSdanielk1977 extern int sqlite3_open_file_count; 18006f8a503dSdanielk1977 extern int sqlite3_current_time; 1801c2eef3b3Sdrh static struct { 1802c2eef3b3Sdrh char *zName; 1803c2eef3b3Sdrh Tcl_CmdProc *xProc; 1804c2eef3b3Sdrh } aCmd[] = { 18056f8a503dSdanielk1977 { "sqlite3_mprintf_int", (Tcl_CmdProc*)sqlite3_mprintf_int }, 18066f8a503dSdanielk1977 { "sqlite3_mprintf_str", (Tcl_CmdProc*)sqlite3_mprintf_str }, 18076f8a503dSdanielk1977 { "sqlite3_mprintf_double", (Tcl_CmdProc*)sqlite3_mprintf_double }, 18086f8a503dSdanielk1977 { "sqlite3_mprintf_scaled", (Tcl_CmdProc*)sqlite3_mprintf_scaled }, 18096f8a503dSdanielk1977 { "sqlite3_mprintf_z_test", (Tcl_CmdProc*)test_mprintf_z }, 18106f8a503dSdanielk1977 { "sqlite3_last_insert_rowid", (Tcl_CmdProc*)test_last_rowid }, 18116f8a503dSdanielk1977 { "sqlite3_exec_printf", (Tcl_CmdProc*)test_exec_printf }, 18126f8a503dSdanielk1977 { "sqlite3_get_table_printf", (Tcl_CmdProc*)test_get_table_printf }, 18136f8a503dSdanielk1977 { "sqlite3_close", (Tcl_CmdProc*)sqlite_test_close }, 18146f8a503dSdanielk1977 { "sqlite3_create_function", (Tcl_CmdProc*)test_create_function }, 18156f8a503dSdanielk1977 { "sqlite3_create_aggregate", (Tcl_CmdProc*)test_create_aggregate }, 1816c2eef3b3Sdrh { "sqlite_register_test_function", (Tcl_CmdProc*)test_register_func }, 1817c2eef3b3Sdrh { "sqlite_abort", (Tcl_CmdProc*)sqlite_abort }, 1818*faa57accSdrh #ifdef SQLITE_DEBUG 1819c2eef3b3Sdrh { "sqlite_malloc_fail", (Tcl_CmdProc*)sqlite_malloc_fail }, 1820c2eef3b3Sdrh { "sqlite_malloc_stat", (Tcl_CmdProc*)sqlite_malloc_stat }, 1821c2eef3b3Sdrh #endif 182296fc5fe6Sdanielk1977 { "sqlite_bind", (Tcl_CmdProc*)test_bind }, 182399ee3600Sdrh { "breakpoint", (Tcl_CmdProc*)test_breakpoint }, 1824c2eef3b3Sdrh }; 182551e3d8e2Sdanielk1977 static struct { 182651e3d8e2Sdanielk1977 char *zName; 182751e3d8e2Sdanielk1977 Tcl_ObjCmdProc *xProc; 182804f2e68dSdanielk1977 void *clientData; 182951e3d8e2Sdanielk1977 } aObjCmd[] = { 183004f2e68dSdanielk1977 { "sqlite3_bind_int32", test_bind_int32, 0 }, 183104f2e68dSdanielk1977 { "sqlite3_bind_int64", test_bind_int64 , 0 }, 183204f2e68dSdanielk1977 { "sqlite3_bind_double", test_bind_double, 0 }, 183304f2e68dSdanielk1977 { "sqlite3_bind_null", test_bind_null ,0 }, 183404f2e68dSdanielk1977 { "sqlite3_bind_text", test_bind_text ,0 }, 183504f2e68dSdanielk1977 { "sqlite3_bind_text16", test_bind_text16 ,0 }, 183604f2e68dSdanielk1977 { "sqlite3_bind_blob", test_bind_blob ,0 }, 183704f2e68dSdanielk1977 { "sqlite3_errcode", test_errcode ,0 }, 183804f2e68dSdanielk1977 { "sqlite3_errmsg", test_errmsg ,0 }, 183904f2e68dSdanielk1977 { "sqlite3_errmsg16", test_errmsg16 ,0 }, 184004f2e68dSdanielk1977 { "sqlite3_open", test_open ,0 }, 184104f2e68dSdanielk1977 { "sqlite3_open16", test_open16 ,0 }, 184204f2e68dSdanielk1977 184304f2e68dSdanielk1977 { "sqlite3_prepare", test_prepare ,0 }, 184404f2e68dSdanielk1977 { "sqlite3_prepare16", test_prepare16 ,0 }, 184504f2e68dSdanielk1977 { "sqlite3_finalize", test_finalize ,0 }, 184604f2e68dSdanielk1977 { "sqlite3_reset", test_reset ,0 }, 184704f2e68dSdanielk1977 { "sqlite3_step", test_step,0 }, 184804f2e68dSdanielk1977 184904f2e68dSdanielk1977 /* sqlite3_column_*() API */ 185004f2e68dSdanielk1977 { "sqlite3_column_count", test_column_count ,0 }, 185104f2e68dSdanielk1977 { "sqlite3_data_count", test_data_count ,0 }, 185204f2e68dSdanielk1977 { "sqlite3_column_type", test_column_type ,0 }, 1853ea61b2c4Sdanielk1977 { "sqlite3_column_blob", test_column_blob ,0 }, 185404f2e68dSdanielk1977 { "sqlite3_column_double", test_column_double ,0 }, 185504f2e68dSdanielk1977 { "sqlite3_column_int64", test_column_int64 ,0 }, 185604f2e68dSdanielk1977 { "sqlite3_column_int", test_stmt_int ,sqlite3_column_int }, 185704f2e68dSdanielk1977 { "sqlite3_column_bytes", test_stmt_int ,sqlite3_column_bytes }, 185804f2e68dSdanielk1977 { "sqlite3_column_bytes16", test_stmt_int ,sqlite3_column_bytes16 }, 185904f2e68dSdanielk1977 { "sqlite3_column_text", test_stmt_utf8, sqlite3_column_text}, 186004f2e68dSdanielk1977 { "sqlite3_column_decltype", test_stmt_utf8, sqlite3_column_decltype}, 186104f2e68dSdanielk1977 { "sqlite3_column_name", test_stmt_utf8, sqlite3_column_name}, 186204f2e68dSdanielk1977 { "sqlite3_column_text16", test_stmt_utf16, sqlite3_column_text16}, 186304f2e68dSdanielk1977 { "sqlite3_column_decltype16", test_stmt_utf16,sqlite3_column_decltype16}, 186404f2e68dSdanielk1977 { "sqlite3_column_name16", test_stmt_utf16, sqlite3_column_name16}, 186504f2e68dSdanielk1977 18669a1d0abeSdanielk1977 /* Functions from os.h */ 18679a1d0abeSdanielk1977 { "sqlite3OsOpenReadWrite",test_sqlite3OsOpenReadWrite, 0 }, 18689a1d0abeSdanielk1977 { "sqlite3OsClose", test_sqlite3OsClose, 0 }, 18699a1d0abeSdanielk1977 { "sqlite3OsLock", test_sqlite3OsLock, 0 }, 18709a1d0abeSdanielk1977 { "sqlite3OsUnlock", test_sqlite3OsUnlock, 0 }, 18719a1d0abeSdanielk1977 187251e3d8e2Sdanielk1977 }; 1873c2eef3b3Sdrh int i; 18742ac3ee97Sdrh extern int sqlite3_os_trace; 1875c2eef3b3Sdrh 1876c2eef3b3Sdrh for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){ 1877c2eef3b3Sdrh Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0); 1878c2eef3b3Sdrh } 187951e3d8e2Sdanielk1977 for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){ 1880c572ef7fSdanielk1977 Tcl_CreateObjCommand(interp, aObjCmd[i].zName, 1881c572ef7fSdanielk1977 aObjCmd[i].xProc, aObjCmd[i].clientData, 0); 188251e3d8e2Sdanielk1977 } 18836490bebdSdanielk1977 Tcl_LinkVar(interp, "sqlite_search_count", 18846f8a503dSdanielk1977 (char*)&sqlite3_search_count, TCL_LINK_INT); 18856490bebdSdanielk1977 Tcl_LinkVar(interp, "sqlite_interrupt_count", 18866f8a503dSdanielk1977 (char*)&sqlite3_interrupt_count, TCL_LINK_INT); 18876490bebdSdanielk1977 Tcl_LinkVar(interp, "sqlite_open_file_count", 18886f8a503dSdanielk1977 (char*)&sqlite3_open_file_count, TCL_LINK_INT); 18896490bebdSdanielk1977 Tcl_LinkVar(interp, "sqlite_current_time", 18906f8a503dSdanielk1977 (char*)&sqlite3_current_time, TCL_LINK_INT); 18912ac3ee97Sdrh Tcl_LinkVar(interp, "sqlite_os_trace", 18922ac3ee97Sdrh (char*)&sqlite3_os_trace, TCL_LINK_INT); 18937c972decSdrh Tcl_LinkVar(interp, "sqlite_static_bind_value", 18947c972decSdrh (char*)&sqlite_static_bind_value, TCL_LINK_STRING); 1895d1bf3512Sdrh return TCL_OK; 1896d1bf3512Sdrh } 1897