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*bfd6cce5Sdanielk1977 ** $Id: test1.c,v 1.78 2004/06/18 04:24:55 danielk1977 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]) ){ 344d8123366Sdanielk1977 sqlite3_result_text(context, sqlite3_value_text(argv[i]), -1, 345d8123366Sdanielk1977 SQLITE_TRANSIENT); 346c22bd47dSdrh break; 347c22bd47dSdrh } 348c22bd47dSdrh } 349c22bd47dSdrh } 350c22bd47dSdrh 351c22bd47dSdrh /* 352d1d9fc33Sdrh ** A structure into which to accumulate text. 353d1d9fc33Sdrh */ 354d1d9fc33Sdrh struct dstr { 355d1d9fc33Sdrh int nAlloc; /* Space allocated */ 356d1d9fc33Sdrh int nUsed; /* Space used */ 357d1d9fc33Sdrh char *z; /* The space */ 358d1d9fc33Sdrh }; 359d1d9fc33Sdrh 360d1d9fc33Sdrh /* 361d1d9fc33Sdrh ** Append text to a dstr 362d1d9fc33Sdrh */ 363d1d9fc33Sdrh static void dstrAppend(struct dstr *p, const char *z, int divider){ 364d1d9fc33Sdrh int n = strlen(z); 365d1d9fc33Sdrh if( p->nUsed + n + 2 > p->nAlloc ){ 366d1d9fc33Sdrh char *zNew; 367d1d9fc33Sdrh p->nAlloc = p->nAlloc*2 + n + 200; 368d1d9fc33Sdrh zNew = sqliteRealloc(p->z, p->nAlloc); 369d1d9fc33Sdrh if( zNew==0 ){ 370d1d9fc33Sdrh sqliteFree(p->z); 371d1d9fc33Sdrh memset(p, 0, sizeof(*p)); 372d1d9fc33Sdrh return; 373d1d9fc33Sdrh } 374d1d9fc33Sdrh p->z = zNew; 375d1d9fc33Sdrh } 376d1d9fc33Sdrh if( divider && p->nUsed>0 ){ 377d1d9fc33Sdrh p->z[p->nUsed++] = divider; 378d1d9fc33Sdrh } 379d1d9fc33Sdrh memcpy(&p->z[p->nUsed], z, n+1); 380d1d9fc33Sdrh p->nUsed += n; 381d1d9fc33Sdrh } 382d1d9fc33Sdrh 383d1d9fc33Sdrh /* 3844adee20fSdanielk1977 ** Invoked for each callback from sqlite3ExecFunc 385d1d9fc33Sdrh */ 386d1d9fc33Sdrh static int execFuncCallback(void *pData, int argc, char **argv, char **NotUsed){ 387d1d9fc33Sdrh struct dstr *p = (struct dstr*)pData; 388d1d9fc33Sdrh int i; 389d1d9fc33Sdrh for(i=0; i<argc; i++){ 390d1d9fc33Sdrh if( argv[i]==0 ){ 391d1d9fc33Sdrh dstrAppend(p, "NULL", ' '); 392d1d9fc33Sdrh }else{ 393d1d9fc33Sdrh dstrAppend(p, argv[i], ' '); 394d1d9fc33Sdrh } 395d1d9fc33Sdrh } 396d1d9fc33Sdrh return 0; 397d1d9fc33Sdrh } 398d1d9fc33Sdrh 399d1d9fc33Sdrh /* 4006f8a503dSdanielk1977 ** Implementation of the x_sqlite3_exec() function. This function takes 401c22bd47dSdrh ** a single argument and attempts to execute that argument as SQL code. 4026cbe1f1bSdrh ** This is illegal and should set the SQLITE_MISUSE flag on the database. 403c22bd47dSdrh ** 4046f8a503dSdanielk1977 ** 2004-Jan-07: We have changed this to make it legal to call sqlite3_exec() 405d1d9fc33Sdrh ** from within a function call. 406d1d9fc33Sdrh ** 407c22bd47dSdrh ** This routine simulates the effect of having two threads attempt to 408c22bd47dSdrh ** use the same database at the same time. 409c22bd47dSdrh */ 41051ad0ecdSdanielk1977 static void sqlite3ExecFunc( 4110ae8b831Sdanielk1977 sqlite3_context *context, 41251ad0ecdSdanielk1977 int argc, 41351ad0ecdSdanielk1977 sqlite3_value **argv 41451ad0ecdSdanielk1977 ){ 415d1d9fc33Sdrh struct dstr x; 416d1d9fc33Sdrh memset(&x, 0, sizeof(x)); 41751ad0ecdSdanielk1977 sqlite3_exec((sqlite*)sqlite3_user_data(context), 4184f26d6c4Sdrh sqlite3_value_text(argv[0]), 419d1d9fc33Sdrh execFuncCallback, &x, 0); 420d8123366Sdanielk1977 sqlite3_result_text(context, x.z, x.nUsed, SQLITE_TRANSIENT); 421d1d9fc33Sdrh sqliteFree(x.z); 422c22bd47dSdrh } 423c22bd47dSdrh 424c22bd47dSdrh /* 425c22bd47dSdrh ** Usage: sqlite_test_create_function DB 426c22bd47dSdrh ** 4276f8a503dSdanielk1977 ** Call the sqlite3_create_function API on the given database in order 428c22bd47dSdrh ** to create a function named "x_coalesce". This function does the same thing 429c22bd47dSdrh ** as the "coalesce" function. This function also registers an SQL function 4306f8a503dSdanielk1977 ** named "x_sqlite3_exec" that invokes sqlite3_exec(). Invoking sqlite3_exec() 431c22bd47dSdrh ** in this way is illegal recursion and should raise an SQLITE_MISUSE error. 432c22bd47dSdrh ** The effect is similar to trying to use the same database connection from 433c22bd47dSdrh ** two threads at the same time. 434c22bd47dSdrh ** 435c22bd47dSdrh ** The original motivation for this routine was to be able to call the 4366f8a503dSdanielk1977 ** sqlite3_create_function function while a query is in progress in order 437c22bd47dSdrh ** to test the SQLITE_MISUSE detection logic. 438c22bd47dSdrh */ 439c2eef3b3Sdrh static int test_create_function( 440c22bd47dSdrh void *NotUsed, 441c22bd47dSdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 442c22bd47dSdrh int argc, /* Number of arguments */ 443c22bd47dSdrh char **argv /* Text of each argument */ 444c22bd47dSdrh ){ 445c22bd47dSdrh sqlite *db; 446c22bd47dSdrh extern void Md5_Register(sqlite*); 447c22bd47dSdrh if( argc!=2 ){ 448c22bd47dSdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 449c22bd47dSdrh " FILENAME\"", 0); 450c22bd47dSdrh return TCL_ERROR; 451c22bd47dSdrh } 452b86ccfb2Sdrh if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; 453d8123366Sdanielk1977 sqlite3_create_function(db, "x_coalesce", -1, SQLITE_UTF8, 0, 0, 454d8123366Sdanielk1977 ifnullFunc, 0, 0); 455d8123366Sdanielk1977 sqlite3_create_function(db, "x_sqlite3_exec", 1, SQLITE_UTF8, 0, db, 4566590493dSdanielk1977 sqlite3ExecFunc, 0, 0); 457c22bd47dSdrh return TCL_OK; 458c22bd47dSdrh } 459c22bd47dSdrh 460c22bd47dSdrh /* 461c22bd47dSdrh ** Routines to implement the x_count() aggregate function. 462c22bd47dSdrh */ 463c22bd47dSdrh typedef struct CountCtx CountCtx; 464c22bd47dSdrh struct CountCtx { 465c22bd47dSdrh int n; 466c22bd47dSdrh }; 4670ae8b831Sdanielk1977 static void countStep(sqlite3_context *context, int argc, sqlite3_value **argv){ 468c22bd47dSdrh CountCtx *p; 4694f26d6c4Sdrh p = sqlite3_aggregate_context(context, sizeof(*p)); 4709c054830Sdrh if( (argc==0 || SQLITE_NULL!=sqlite3_value_type(argv[0]) ) && p ){ 471c22bd47dSdrh p->n++; 472c22bd47dSdrh } 473c22bd47dSdrh } 4740ae8b831Sdanielk1977 static void countFinalize(sqlite3_context *context){ 475c22bd47dSdrh CountCtx *p; 4764f26d6c4Sdrh p = sqlite3_aggregate_context(context, sizeof(*p)); 477c572ef7fSdanielk1977 sqlite3_result_int(context, p ? p->n : 0); 478c22bd47dSdrh } 479c22bd47dSdrh 480c22bd47dSdrh /* 481c22bd47dSdrh ** Usage: sqlite_test_create_aggregate DB 482c22bd47dSdrh ** 4836f8a503dSdanielk1977 ** Call the sqlite3_create_function API on the given database in order 484c22bd47dSdrh ** to create a function named "x_count". This function does the same thing 485c22bd47dSdrh ** as the "md5sum" function. 486c22bd47dSdrh ** 487c22bd47dSdrh ** The original motivation for this routine was to be able to call the 4886f8a503dSdanielk1977 ** sqlite3_create_aggregate function while a query is in progress in order 489c22bd47dSdrh ** to test the SQLITE_MISUSE detection logic. 490c22bd47dSdrh */ 491c2eef3b3Sdrh static int test_create_aggregate( 492c22bd47dSdrh void *NotUsed, 493c22bd47dSdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 494c22bd47dSdrh int argc, /* Number of arguments */ 495c22bd47dSdrh char **argv /* Text of each argument */ 496c22bd47dSdrh ){ 497c22bd47dSdrh sqlite *db; 498c22bd47dSdrh if( argc!=2 ){ 499c22bd47dSdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 500c22bd47dSdrh " FILENAME\"", 0); 501c22bd47dSdrh return TCL_ERROR; 502c22bd47dSdrh } 503b86ccfb2Sdrh if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; 504d8123366Sdanielk1977 sqlite3_create_function(db, "x_count", 0, SQLITE_UTF8, 0, 0, 0, 505d8123366Sdanielk1977 countStep,countFinalize); 506d8123366Sdanielk1977 sqlite3_create_function(db, "x_count", 1, SQLITE_UTF8, 0, 0, 0, 507d8123366Sdanielk1977 countStep,countFinalize); 508c22bd47dSdrh return TCL_OK; 509c22bd47dSdrh } 510c22bd47dSdrh 511c22bd47dSdrh 512c22bd47dSdrh 513c22bd47dSdrh /* 5146f8a503dSdanielk1977 ** Usage: sqlite3_mprintf_int FORMAT INTEGER INTEGER INTEGER 515d1bf3512Sdrh ** 516d1bf3512Sdrh ** Call mprintf with three integer arguments 517d1bf3512Sdrh */ 5186f8a503dSdanielk1977 static int sqlite3_mprintf_int( 519d1bf3512Sdrh void *NotUsed, 520d1bf3512Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 521d1bf3512Sdrh int argc, /* Number of arguments */ 522d1bf3512Sdrh char **argv /* Text of each argument */ 523d1bf3512Sdrh ){ 524d1bf3512Sdrh int a[3], i; 525d1bf3512Sdrh char *z; 526d1bf3512Sdrh if( argc!=5 ){ 527d1bf3512Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 528d1bf3512Sdrh " FORMAT INT INT INT\"", 0); 529d1bf3512Sdrh return TCL_ERROR; 530d1bf3512Sdrh } 531d1bf3512Sdrh for(i=2; i<5; i++){ 532d1bf3512Sdrh if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR; 533d1bf3512Sdrh } 5346f8a503dSdanielk1977 z = sqlite3_mprintf(argv[1], a[0], a[1], a[2]); 535d1bf3512Sdrh Tcl_AppendResult(interp, z, 0); 5363f4fedb2Sdrh sqlite3_free(z); 537d1bf3512Sdrh return TCL_OK; 538d1bf3512Sdrh } 539d1bf3512Sdrh 540d1bf3512Sdrh /* 5416f8a503dSdanielk1977 ** Usage: sqlite3_mprintf_str FORMAT INTEGER INTEGER STRING 542d1bf3512Sdrh ** 543d1bf3512Sdrh ** Call mprintf with two integer arguments and one string argument 544d1bf3512Sdrh */ 5456f8a503dSdanielk1977 static int sqlite3_mprintf_str( 546d1bf3512Sdrh void *NotUsed, 547d1bf3512Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 548d1bf3512Sdrh int argc, /* Number of arguments */ 549d1bf3512Sdrh char **argv /* Text of each argument */ 550d1bf3512Sdrh ){ 551d1bf3512Sdrh int a[3], i; 552d1bf3512Sdrh char *z; 553f220b24fSchw if( argc<4 || argc>5 ){ 554d1bf3512Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 555f220b24fSchw " FORMAT INT INT ?STRING?\"", 0); 556d1bf3512Sdrh return TCL_ERROR; 557d1bf3512Sdrh } 558d1bf3512Sdrh for(i=2; i<4; i++){ 559d1bf3512Sdrh if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR; 560d1bf3512Sdrh } 5616f8a503dSdanielk1977 z = sqlite3_mprintf(argv[1], a[0], a[1], argc>4 ? argv[4] : NULL); 562d1bf3512Sdrh Tcl_AppendResult(interp, z, 0); 5633f4fedb2Sdrh sqlite3_free(z); 564d1bf3512Sdrh return TCL_OK; 565d1bf3512Sdrh } 566d1bf3512Sdrh 567d1bf3512Sdrh /* 5686f8a503dSdanielk1977 ** Usage: sqlite3_mprintf_str FORMAT INTEGER INTEGER DOUBLE 569d1bf3512Sdrh ** 570d1bf3512Sdrh ** Call mprintf with two integer arguments and one double argument 571d1bf3512Sdrh */ 5726f8a503dSdanielk1977 static int sqlite3_mprintf_double( 573d1bf3512Sdrh void *NotUsed, 574d1bf3512Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 575d1bf3512Sdrh int argc, /* Number of arguments */ 576d1bf3512Sdrh char **argv /* Text of each argument */ 577d1bf3512Sdrh ){ 578d1bf3512Sdrh int a[3], i; 579d1bf3512Sdrh double r; 580d1bf3512Sdrh char *z; 581d1bf3512Sdrh if( argc!=5 ){ 582d1bf3512Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 583d1bf3512Sdrh " FORMAT INT INT STRING\"", 0); 584d1bf3512Sdrh return TCL_ERROR; 585d1bf3512Sdrh } 586d1bf3512Sdrh for(i=2; i<4; i++){ 587d1bf3512Sdrh if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR; 588d1bf3512Sdrh } 589d1bf3512Sdrh if( Tcl_GetDouble(interp, argv[4], &r) ) return TCL_ERROR; 5906f8a503dSdanielk1977 z = sqlite3_mprintf(argv[1], a[0], a[1], r); 591d1bf3512Sdrh Tcl_AppendResult(interp, z, 0); 5923f4fedb2Sdrh sqlite3_free(z); 593d1bf3512Sdrh return TCL_OK; 594d1bf3512Sdrh } 595d1bf3512Sdrh 596d1bf3512Sdrh /* 5976f8a503dSdanielk1977 ** Usage: sqlite3_mprintf_str FORMAT DOUBLE DOUBLE 598b621c237Sdrh ** 599b621c237Sdrh ** Call mprintf with a single double argument which is the product of the 600b621c237Sdrh ** two arguments given above. This is used to generate overflow and underflow 601b621c237Sdrh ** doubles to test that they are converted properly. 602b621c237Sdrh */ 6036f8a503dSdanielk1977 static int sqlite3_mprintf_scaled( 604b621c237Sdrh void *NotUsed, 605b621c237Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 606b621c237Sdrh int argc, /* Number of arguments */ 607b621c237Sdrh char **argv /* Text of each argument */ 608b621c237Sdrh ){ 609b621c237Sdrh int i; 610b621c237Sdrh double r[2]; 611b621c237Sdrh char *z; 612b621c237Sdrh if( argc!=4 ){ 613b621c237Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 614b621c237Sdrh " FORMAT DOUBLE DOUBLE\"", 0); 615b621c237Sdrh return TCL_ERROR; 616b621c237Sdrh } 617b621c237Sdrh for(i=2; i<4; i++){ 618b621c237Sdrh if( Tcl_GetDouble(interp, argv[i], &r[i-2]) ) return TCL_ERROR; 619b621c237Sdrh } 6206f8a503dSdanielk1977 z = sqlite3_mprintf(argv[1], r[0]*r[1]); 621b621c237Sdrh Tcl_AppendResult(interp, z, 0); 6223f4fedb2Sdrh sqlite3_free(z); 623b621c237Sdrh return TCL_OK; 624b621c237Sdrh } 625b621c237Sdrh 626b621c237Sdrh /* 627daffd0e5Sdrh ** Usage: sqlite_malloc_fail N 628daffd0e5Sdrh ** 629afa4a020Sdrh ** Rig sqliteMalloc() to fail on the N-th call. Turn off this mechanism 6306f8a503dSdanielk1977 ** and reset the sqlite3_malloc_failed variable is N==0. 631daffd0e5Sdrh */ 632faa57accSdrh #ifdef SQLITE_DEBUG 633daffd0e5Sdrh static int sqlite_malloc_fail( 634daffd0e5Sdrh void *NotUsed, 635daffd0e5Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 636daffd0e5Sdrh int argc, /* Number of arguments */ 637daffd0e5Sdrh char **argv /* Text of each argument */ 638daffd0e5Sdrh ){ 639daffd0e5Sdrh int n; 640daffd0e5Sdrh if( argc!=2 ){ 641daffd0e5Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " N\"", 0); 642daffd0e5Sdrh return TCL_ERROR; 643daffd0e5Sdrh } 644daffd0e5Sdrh if( Tcl_GetInt(interp, argv[1], &n) ) return TCL_ERROR; 6456f8a503dSdanielk1977 sqlite3_iMallocFail = n; 6466f8a503dSdanielk1977 sqlite3_malloc_failed = 0; 647daffd0e5Sdrh return TCL_OK; 648daffd0e5Sdrh } 649daffd0e5Sdrh #endif 650daffd0e5Sdrh 651daffd0e5Sdrh /* 652daffd0e5Sdrh ** Usage: sqlite_malloc_stat 653daffd0e5Sdrh ** 654daffd0e5Sdrh ** Return the number of prior calls to sqliteMalloc() and sqliteFree(). 655daffd0e5Sdrh */ 656faa57accSdrh #ifdef SQLITE_DEBUG 657daffd0e5Sdrh static int sqlite_malloc_stat( 658daffd0e5Sdrh void *NotUsed, 659daffd0e5Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 660daffd0e5Sdrh int argc, /* Number of arguments */ 661daffd0e5Sdrh char **argv /* Text of each argument */ 662daffd0e5Sdrh ){ 663daffd0e5Sdrh char zBuf[200]; 6646f8a503dSdanielk1977 sprintf(zBuf, "%d %d %d", sqlite3_nMalloc, sqlite3_nFree, sqlite3_iMallocFail); 665daffd0e5Sdrh Tcl_AppendResult(interp, zBuf, 0); 666daffd0e5Sdrh return TCL_OK; 667daffd0e5Sdrh } 668daffd0e5Sdrh #endif 669daffd0e5Sdrh 670daffd0e5Sdrh /* 67128b4e489Sdrh ** Usage: sqlite_abort 67228b4e489Sdrh ** 67328b4e489Sdrh ** Shutdown the process immediately. This is not a clean shutdown. 67428b4e489Sdrh ** This command is used to test the recoverability of a database in 67528b4e489Sdrh ** the event of a program crash. 67628b4e489Sdrh */ 67728b4e489Sdrh static int sqlite_abort( 67828b4e489Sdrh void *NotUsed, 67928b4e489Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 68028b4e489Sdrh int argc, /* Number of arguments */ 68128b4e489Sdrh char **argv /* Text of each argument */ 68228b4e489Sdrh ){ 68328b4e489Sdrh assert( interp==0 ); /* This will always fail */ 68428b4e489Sdrh return TCL_OK; 68528b4e489Sdrh } 68628b4e489Sdrh 68728b4e489Sdrh /* 6886cbe1f1bSdrh ** The following routine is a user-defined SQL function whose purpose 6896cbe1f1bSdrh ** is to test the sqlite_set_result() API. 6906cbe1f1bSdrh */ 6910ae8b831Sdanielk1977 static void testFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ 6926cbe1f1bSdrh while( argc>=2 ){ 6934f26d6c4Sdrh const char *zArg0 = sqlite3_value_text(argv[0]); 6946d88bad4Sdanielk1977 if( zArg0 ){ 6956d88bad4Sdanielk1977 if( 0==sqlite3StrICmp(zArg0, "int") ){ 6966d88bad4Sdanielk1977 sqlite3_result_int(context, sqlite3_value_int(argv[1])); 6976d88bad4Sdanielk1977 }else if( sqlite3StrICmp(zArg0,"int64")==0 ){ 6986d88bad4Sdanielk1977 sqlite3_result_int64(context, sqlite3_value_int64(argv[1])); 69951ad0ecdSdanielk1977 }else if( sqlite3StrICmp(zArg0,"string")==0 ){ 700d8123366Sdanielk1977 sqlite3_result_text(context, sqlite3_value_text(argv[1]), -1, 701d8123366Sdanielk1977 SQLITE_TRANSIENT); 70251ad0ecdSdanielk1977 }else if( sqlite3StrICmp(zArg0,"double")==0 ){ 7036d88bad4Sdanielk1977 sqlite3_result_double(context, sqlite3_value_double(argv[1])); 7046d88bad4Sdanielk1977 }else if( sqlite3StrICmp(zArg0,"null")==0 ){ 7056d88bad4Sdanielk1977 sqlite3_result_null(context); 7066d88bad4Sdanielk1977 }else if( sqlite3StrICmp(zArg0,"value")==0 ){ 7076d88bad4Sdanielk1977 sqlite3_result_value(context, argv[sqlite3_value_int(argv[1])]); 7086cbe1f1bSdrh }else{ 7096d88bad4Sdanielk1977 goto error_out; 7106d88bad4Sdanielk1977 } 7116d88bad4Sdanielk1977 }else{ 7126d88bad4Sdanielk1977 goto error_out; 7136cbe1f1bSdrh } 7146cbe1f1bSdrh argc -= 2; 7156cbe1f1bSdrh argv += 2; 7166cbe1f1bSdrh } 7176d88bad4Sdanielk1977 return; 7186d88bad4Sdanielk1977 7196d88bad4Sdanielk1977 error_out: 7206d88bad4Sdanielk1977 sqlite3_result_error(context,"first argument should be one of: " 7216d88bad4Sdanielk1977 "int int64 string double null value", -1); 7226cbe1f1bSdrh } 7236cbe1f1bSdrh 7246cbe1f1bSdrh /* 7256cbe1f1bSdrh ** Usage: sqlite_register_test_function DB NAME 7266cbe1f1bSdrh ** 7276cbe1f1bSdrh ** Register the test SQL function on the database DB under the name NAME. 7286cbe1f1bSdrh */ 729c2eef3b3Sdrh static int test_register_func( 7306cbe1f1bSdrh void *NotUsed, 7316cbe1f1bSdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 7326cbe1f1bSdrh int argc, /* Number of arguments */ 7336cbe1f1bSdrh char **argv /* Text of each argument */ 7346cbe1f1bSdrh ){ 7356cbe1f1bSdrh sqlite *db; 7366cbe1f1bSdrh int rc; 7376cbe1f1bSdrh if( argc!=3 ){ 7386cbe1f1bSdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 7396cbe1f1bSdrh " DB FUNCTION-NAME", 0); 7406cbe1f1bSdrh return TCL_ERROR; 7416cbe1f1bSdrh } 742b86ccfb2Sdrh if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; 743d8123366Sdanielk1977 rc = sqlite3_create_function(db, argv[2], -1, SQLITE_UTF8, 0, 0, 744d8123366Sdanielk1977 testFunc, 0, 0); 7456cbe1f1bSdrh if( rc!=0 ){ 746f20b21c8Sdanielk1977 Tcl_AppendResult(interp, sqlite3ErrStr(rc), 0); 7476cbe1f1bSdrh return TCL_ERROR; 7486cbe1f1bSdrh } 7496cbe1f1bSdrh return TCL_OK; 7506cbe1f1bSdrh } 7516cbe1f1bSdrh 7526cbe1f1bSdrh /* 753106bb236Sdanielk1977 ** Usage: sqlite3_finalize STMT 754b86ccfb2Sdrh ** 755106bb236Sdanielk1977 ** Finalize a statement handle. 756b86ccfb2Sdrh */ 757b86ccfb2Sdrh static int test_finalize( 758106bb236Sdanielk1977 void * clientData, 759106bb236Sdanielk1977 Tcl_Interp *interp, 760106bb236Sdanielk1977 int objc, 761106bb236Sdanielk1977 Tcl_Obj *CONST objv[] 762b86ccfb2Sdrh ){ 763106bb236Sdanielk1977 sqlite3_stmt *pStmt; 764b86ccfb2Sdrh int rc; 765106bb236Sdanielk1977 766106bb236Sdanielk1977 if( objc!=2 ){ 767106bb236Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 768106bb236Sdanielk1977 Tcl_GetStringFromObj(objv[0], 0), " <STMT>", 0); 769b86ccfb2Sdrh return TCL_ERROR; 770b86ccfb2Sdrh } 771106bb236Sdanielk1977 772106bb236Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 773106bb236Sdanielk1977 774fc57d7bfSdanielk1977 rc = sqlite3_finalize(pStmt); 775b77f5dadSdanielk1977 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC); 776106bb236Sdanielk1977 return TCL_OK; 777106bb236Sdanielk1977 } 778106bb236Sdanielk1977 779106bb236Sdanielk1977 /* 780106bb236Sdanielk1977 ** Usage: sqlite3_reset STMT 781106bb236Sdanielk1977 ** 782106bb236Sdanielk1977 ** Finalize a statement handle. 783106bb236Sdanielk1977 */ 784106bb236Sdanielk1977 static int test_reset( 785106bb236Sdanielk1977 void * clientData, 786106bb236Sdanielk1977 Tcl_Interp *interp, 787106bb236Sdanielk1977 int objc, 788106bb236Sdanielk1977 Tcl_Obj *CONST objv[] 789106bb236Sdanielk1977 ){ 790106bb236Sdanielk1977 sqlite3_stmt *pStmt; 791106bb236Sdanielk1977 int rc; 792106bb236Sdanielk1977 793106bb236Sdanielk1977 if( objc!=2 ){ 794106bb236Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 795106bb236Sdanielk1977 Tcl_GetStringFromObj(objv[0], 0), " <STMT>", 0); 796106bb236Sdanielk1977 return TCL_ERROR; 797106bb236Sdanielk1977 } 798106bb236Sdanielk1977 799106bb236Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 800106bb236Sdanielk1977 801fc57d7bfSdanielk1977 rc = sqlite3_reset(pStmt); 802106bb236Sdanielk1977 if( rc ){ 803b86ccfb2Sdrh return TCL_ERROR; 804b86ccfb2Sdrh } 805b86ccfb2Sdrh return TCL_OK; 806b86ccfb2Sdrh } 807b86ccfb2Sdrh 8085a38705eSdrh /* 809fbcd585fSdanielk1977 ** Usage: sqlite3_changes DB 81050457896Sdrh ** 811fbcd585fSdanielk1977 ** Return the number of changes made to the database by the last SQL 812fbcd585fSdanielk1977 ** execution. 81350457896Sdrh */ 814fbcd585fSdanielk1977 static int test_changes( 815fbcd585fSdanielk1977 void * clientData, 816fbcd585fSdanielk1977 Tcl_Interp *interp, 817fbcd585fSdanielk1977 int objc, 818fbcd585fSdanielk1977 Tcl_Obj *CONST objv[] 819fbcd585fSdanielk1977 ){ 820fbcd585fSdanielk1977 sqlite3 *db; 821fbcd585fSdanielk1977 if( objc!=2 ){ 822fbcd585fSdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 823fbcd585fSdanielk1977 Tcl_GetString(objv[0]), " DB", 0); 824fbcd585fSdanielk1977 return TCL_ERROR; 825fbcd585fSdanielk1977 } 826fbcd585fSdanielk1977 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 827fbcd585fSdanielk1977 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_changes(db))); 828fbcd585fSdanielk1977 return TCL_OK; 829fbcd585fSdanielk1977 } 83050457896Sdrh 83150457896Sdrh /* 8327c972decSdrh ** This is the "static_bind_value" that variables are bound to when 8336f8a503dSdanielk1977 ** the FLAG option of sqlite3_bind is "static" 83450457896Sdrh */ 8357c972decSdrh static char *sqlite_static_bind_value = 0; 8367c972decSdrh 8377c972decSdrh /* 8386f8a503dSdanielk1977 ** Usage: sqlite3_bind VM IDX VALUE FLAGS 8397c972decSdrh ** 8407c972decSdrh ** Sets the value of the IDX-th occurance of "?" in the original SQL 8417c972decSdrh ** string. VALUE is the new value. If FLAGS=="null" then VALUE is 8427c972decSdrh ** ignored and the value is set to NULL. If FLAGS=="static" then 8437c972decSdrh ** the value is set to the value of a static variable named 8447c972decSdrh ** "sqlite_static_bind_value". If FLAGS=="normal" then a copy 8457c972decSdrh ** of the VALUE is made. 8467c972decSdrh */ 8477c972decSdrh static int test_bind( 84850457896Sdrh void *NotUsed, 84950457896Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 85050457896Sdrh int argc, /* Number of arguments */ 85150457896Sdrh char **argv /* Text of each argument */ 85250457896Sdrh ){ 853fc57d7bfSdanielk1977 sqlite3_stmt *pStmt; 85450457896Sdrh int rc; 8557c972decSdrh int idx; 8567c972decSdrh if( argc!=5 ){ 85750457896Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 8587c972decSdrh " VM IDX VALUE (null|static|normal)\"", 0); 85950457896Sdrh return TCL_ERROR; 86050457896Sdrh } 861fc57d7bfSdanielk1977 if( getStmtPointer(interp, argv[1], &pStmt) ) return TCL_ERROR; 8627c972decSdrh if( Tcl_GetInt(interp, argv[2], &idx) ) return TCL_ERROR; 8637c972decSdrh if( strcmp(argv[4],"null")==0 ){ 864fc57d7bfSdanielk1977 rc = sqlite3_bind_null(pStmt, idx); 8657c972decSdrh }else if( strcmp(argv[4],"static")==0 ){ 866fc57d7bfSdanielk1977 rc = sqlite3_bind_text(pStmt, idx, sqlite_static_bind_value, -1, 0); 8677c972decSdrh }else if( strcmp(argv[4],"normal")==0 ){ 868d8123366Sdanielk1977 rc = sqlite3_bind_text(pStmt, idx, argv[3], -1, SQLITE_TRANSIENT); 8697c972decSdrh }else{ 8707c972decSdrh Tcl_AppendResult(interp, "4th argument should be " 8717c972decSdrh "\"null\" or \"static\" or \"normal\"", 0); 8727c972decSdrh return TCL_ERROR; 8737c972decSdrh } 87450457896Sdrh if( rc ){ 87550457896Sdrh char zBuf[50]; 87650457896Sdrh sprintf(zBuf, "(%d) ", rc); 877f20b21c8Sdanielk1977 Tcl_AppendResult(interp, zBuf, sqlite3ErrStr(rc), 0); 87850457896Sdrh return TCL_ERROR; 87950457896Sdrh } 88050457896Sdrh return TCL_OK; 88150457896Sdrh } 88250457896Sdrh 8834e6af134Sdanielk1977 8844e6af134Sdanielk1977 /* 8854e6af134Sdanielk1977 ** Usage: add_test_collate <db ptr> <utf8> <utf16le> <utf16be> 8864e6af134Sdanielk1977 ** 8874e6af134Sdanielk1977 ** This function is used to test that SQLite selects the correct collation 8884e6af134Sdanielk1977 ** sequence callback when multiple versions (for different text encodings) 8894e6af134Sdanielk1977 ** are available. 8904e6af134Sdanielk1977 ** 8914e6af134Sdanielk1977 ** Calling this routine registers the collation sequence "test_collate" 8924e6af134Sdanielk1977 ** with database handle <db>. The second argument must be a list of three 8934e6af134Sdanielk1977 ** boolean values. If the first is true, then a version of test_collate is 8944e6af134Sdanielk1977 ** registered for UTF-8, if the second is true, a version is registered for 8954e6af134Sdanielk1977 ** UTF-16le, if the third is true, a UTF-16be version is available. 8964e6af134Sdanielk1977 ** Previous versions of test_collate are deleted. 8974e6af134Sdanielk1977 ** 8984e6af134Sdanielk1977 ** The collation sequence test_collate is implemented by calling the 8994e6af134Sdanielk1977 ** following TCL script: 9004e6af134Sdanielk1977 ** 9014e6af134Sdanielk1977 ** "test_collate <enc> <lhs> <rhs>" 9024e6af134Sdanielk1977 ** 9034e6af134Sdanielk1977 ** The <lhs> and <rhs> are the two values being compared, encoded in UTF-8. 9044e6af134Sdanielk1977 ** The <enc> parameter is the encoding of the collation function that 9054e6af134Sdanielk1977 ** SQLite selected to call. The TCL test script implements the 9064e6af134Sdanielk1977 ** "test_collate" proc. 9074e6af134Sdanielk1977 ** 9084e6af134Sdanielk1977 ** Note that this will only work with one intepreter at a time, as the 9094e6af134Sdanielk1977 ** interp pointer to use when evaluating the TCL script is stored in 9104e6af134Sdanielk1977 ** pTestCollateInterp. 9114e6af134Sdanielk1977 */ 9124e6af134Sdanielk1977 static Tcl_Interp* pTestCollateInterp; 9134e6af134Sdanielk1977 static int test_collate_func( 9144e6af134Sdanielk1977 void *pCtx, 9154e6af134Sdanielk1977 int nA, const void *zA, 9164e6af134Sdanielk1977 int nB, const void *zB 9174e6af134Sdanielk1977 ){ 9184e6af134Sdanielk1977 Tcl_Interp *i = pTestCollateInterp; 9194e6af134Sdanielk1977 int encin = (int)pCtx; 9204e6af134Sdanielk1977 int res; 9214e6af134Sdanielk1977 9224e6af134Sdanielk1977 sqlite3_value *pVal; 9234e6af134Sdanielk1977 Tcl_Obj *pX; 9244e6af134Sdanielk1977 9254e6af134Sdanielk1977 pX = Tcl_NewStringObj("test_collate", -1); 9264e6af134Sdanielk1977 Tcl_IncrRefCount(pX); 9274e6af134Sdanielk1977 9284e6af134Sdanielk1977 switch( encin ){ 9294e6af134Sdanielk1977 case SQLITE_UTF8: 9304e6af134Sdanielk1977 Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-8",-1)); 9314e6af134Sdanielk1977 break; 9324e6af134Sdanielk1977 case SQLITE_UTF16LE: 9334e6af134Sdanielk1977 Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-16LE",-1)); 9344e6af134Sdanielk1977 break; 9354e6af134Sdanielk1977 case SQLITE_UTF16BE: 9364e6af134Sdanielk1977 Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-16BE",-1)); 9374e6af134Sdanielk1977 break; 9384e6af134Sdanielk1977 default: 9394e6af134Sdanielk1977 assert(0); 9404e6af134Sdanielk1977 } 9414e6af134Sdanielk1977 9424e6af134Sdanielk1977 pVal = sqlite3ValueNew(); 943*bfd6cce5Sdanielk1977 sqlite3ValueSetStr(pVal, nA, zA, encin, SQLITE_STATIC); 9444e6af134Sdanielk1977 Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj(sqlite3_value_text(pVal),-1)); 945*bfd6cce5Sdanielk1977 sqlite3ValueSetStr(pVal, nB, zB, encin, SQLITE_STATIC); 9464e6af134Sdanielk1977 Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj(sqlite3_value_text(pVal),-1)); 9474e6af134Sdanielk1977 sqlite3ValueFree(pVal); 9484e6af134Sdanielk1977 9494e6af134Sdanielk1977 Tcl_EvalObjEx(i, pX, 0); 9504e6af134Sdanielk1977 Tcl_DecrRefCount(pX); 9514e6af134Sdanielk1977 Tcl_GetIntFromObj(i, Tcl_GetObjResult(i), &res); 9524e6af134Sdanielk1977 return res; 9534e6af134Sdanielk1977 } 9544e6af134Sdanielk1977 static int test_collate( 9554e6af134Sdanielk1977 void * clientData, 9564e6af134Sdanielk1977 Tcl_Interp *interp, 9574e6af134Sdanielk1977 int objc, 9584e6af134Sdanielk1977 Tcl_Obj *CONST objv[] 9594e6af134Sdanielk1977 ){ 9604e6af134Sdanielk1977 sqlite3 *db; 9614e6af134Sdanielk1977 int val; 9624e6af134Sdanielk1977 9634e6af134Sdanielk1977 if( objc!=5 ) goto bad_args; 9644e6af134Sdanielk1977 pTestCollateInterp = interp; 9654e6af134Sdanielk1977 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 9664e6af134Sdanielk1977 9674e6af134Sdanielk1977 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[2], &val) ) return TCL_ERROR; 9684e6af134Sdanielk1977 sqlite3_create_collation(db, "test_collate", SQLITE_UTF8, 9694e6af134Sdanielk1977 (void *)SQLITE_UTF8, val?test_collate_func:0); 9704e6af134Sdanielk1977 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[3], &val) ) return TCL_ERROR; 9714e6af134Sdanielk1977 sqlite3_create_collation(db, "test_collate", SQLITE_UTF16LE, 9724e6af134Sdanielk1977 (void *)SQLITE_UTF16LE, val?test_collate_func:0); 9734e6af134Sdanielk1977 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[4], &val) ) return TCL_ERROR; 9744e6af134Sdanielk1977 sqlite3_create_collation(db, "test_collate", SQLITE_UTF16BE, 9754e6af134Sdanielk1977 (void *)SQLITE_UTF16BE, val?test_collate_func:0); 9764e6af134Sdanielk1977 9774e6af134Sdanielk1977 return TCL_OK; 9784e6af134Sdanielk1977 9794e6af134Sdanielk1977 bad_args: 9804e6af134Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 9814e6af134Sdanielk1977 Tcl_GetStringFromObj(objv[0], 0), " <DB> <utf8> <utf16le> <utf16be>", 0); 9824e6af134Sdanielk1977 return TCL_ERROR; 9834e6af134Sdanielk1977 } 9844e6af134Sdanielk1977 98550457896Sdrh /* 98699ee3600Sdrh ** Usage: breakpoint 98799ee3600Sdrh ** 98899ee3600Sdrh ** This routine exists for one purpose - to provide a place to put a 98999ee3600Sdrh ** breakpoint with GDB that can be triggered using TCL code. The use 99099ee3600Sdrh ** for this is when a particular test fails on (say) the 1485th iteration. 99199ee3600Sdrh ** In the TCL test script, we can add code like this: 99299ee3600Sdrh ** 99399ee3600Sdrh ** if {$i==1485} breakpoint 99499ee3600Sdrh ** 99599ee3600Sdrh ** Then run testfixture in the debugger and wait for the breakpoint to 99699ee3600Sdrh ** fire. Then additional breakpoints can be set to trace down the bug. 99799ee3600Sdrh */ 99899ee3600Sdrh static int test_breakpoint( 99999ee3600Sdrh void *NotUsed, 100099ee3600Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 100199ee3600Sdrh int argc, /* Number of arguments */ 100299ee3600Sdrh char **argv /* Text of each argument */ 100399ee3600Sdrh ){ 100499ee3600Sdrh return TCL_OK; /* Do nothing */ 100599ee3600Sdrh } 100699ee3600Sdrh 100751e3d8e2Sdanielk1977 static int test_bind_int32( 100851e3d8e2Sdanielk1977 void * clientData, 100951e3d8e2Sdanielk1977 Tcl_Interp *interp, 101051e3d8e2Sdanielk1977 int objc, 101151e3d8e2Sdanielk1977 Tcl_Obj *CONST objv[] 101251e3d8e2Sdanielk1977 ){ 101351e3d8e2Sdanielk1977 sqlite3_stmt *pStmt; 101451e3d8e2Sdanielk1977 int idx; 101551e3d8e2Sdanielk1977 int value; 101651e3d8e2Sdanielk1977 int rc; 101751e3d8e2Sdanielk1977 101851e3d8e2Sdanielk1977 if( objc!=4 ){ 101951e3d8e2Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 102051e3d8e2Sdanielk1977 Tcl_GetStringFromObj(objv[0], 0), " <STMT> <param no.> <value>", 0); 102151e3d8e2Sdanielk1977 return TCL_ERROR; 102251e3d8e2Sdanielk1977 } 102351e3d8e2Sdanielk1977 102451e3d8e2Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 102551e3d8e2Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; 102651e3d8e2Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[3], &value) ) return TCL_ERROR; 102751e3d8e2Sdanielk1977 1028c572ef7fSdanielk1977 rc = sqlite3_bind_int(pStmt, idx, value); 102951e3d8e2Sdanielk1977 if( rc!=SQLITE_OK ){ 103051e3d8e2Sdanielk1977 return TCL_ERROR; 103151e3d8e2Sdanielk1977 } 103251e3d8e2Sdanielk1977 103351e3d8e2Sdanielk1977 return TCL_OK; 103451e3d8e2Sdanielk1977 } 103551e3d8e2Sdanielk1977 103651e3d8e2Sdanielk1977 static int test_bind_int64( 103751e3d8e2Sdanielk1977 void * clientData, 103851e3d8e2Sdanielk1977 Tcl_Interp *interp, 103951e3d8e2Sdanielk1977 int objc, 104051e3d8e2Sdanielk1977 Tcl_Obj *CONST objv[] 104151e3d8e2Sdanielk1977 ){ 104251e3d8e2Sdanielk1977 sqlite3_stmt *pStmt; 104351e3d8e2Sdanielk1977 int idx; 104451e3d8e2Sdanielk1977 i64 value; 104551e3d8e2Sdanielk1977 int rc; 104651e3d8e2Sdanielk1977 104751e3d8e2Sdanielk1977 if( objc!=4 ){ 104851e3d8e2Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 104951e3d8e2Sdanielk1977 Tcl_GetStringFromObj(objv[0], 0), " <STMT> <param no.> <value>", 0); 105051e3d8e2Sdanielk1977 return TCL_ERROR; 105151e3d8e2Sdanielk1977 } 105251e3d8e2Sdanielk1977 105351e3d8e2Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 105451e3d8e2Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; 105551e3d8e2Sdanielk1977 if( Tcl_GetWideIntFromObj(interp, objv[3], &value) ) return TCL_ERROR; 105651e3d8e2Sdanielk1977 105751e3d8e2Sdanielk1977 rc = sqlite3_bind_int64(pStmt, idx, value); 105851e3d8e2Sdanielk1977 if( rc!=SQLITE_OK ){ 105951e3d8e2Sdanielk1977 return TCL_ERROR; 106051e3d8e2Sdanielk1977 } 106151e3d8e2Sdanielk1977 106251e3d8e2Sdanielk1977 return TCL_OK; 106351e3d8e2Sdanielk1977 } 106451e3d8e2Sdanielk1977 106551e3d8e2Sdanielk1977 static int test_bind_double( 106651e3d8e2Sdanielk1977 void * clientData, 106751e3d8e2Sdanielk1977 Tcl_Interp *interp, 106851e3d8e2Sdanielk1977 int objc, 106951e3d8e2Sdanielk1977 Tcl_Obj *CONST objv[] 107051e3d8e2Sdanielk1977 ){ 107151e3d8e2Sdanielk1977 sqlite3_stmt *pStmt; 107251e3d8e2Sdanielk1977 int idx; 107351e3d8e2Sdanielk1977 double value; 107451e3d8e2Sdanielk1977 int rc; 107551e3d8e2Sdanielk1977 107651e3d8e2Sdanielk1977 if( objc!=4 ){ 107751e3d8e2Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 107851e3d8e2Sdanielk1977 Tcl_GetStringFromObj(objv[0], 0), " <STMT> <param no.> <value>", 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 if( Tcl_GetDoubleFromObj(interp, objv[3], &value) ) return TCL_ERROR; 108551e3d8e2Sdanielk1977 108651e3d8e2Sdanielk1977 rc = sqlite3_bind_double(pStmt, idx, value); 108751e3d8e2Sdanielk1977 if( rc!=SQLITE_OK ){ 108851e3d8e2Sdanielk1977 return TCL_ERROR; 108951e3d8e2Sdanielk1977 } 109051e3d8e2Sdanielk1977 109151e3d8e2Sdanielk1977 return TCL_OK; 109251e3d8e2Sdanielk1977 } 109351e3d8e2Sdanielk1977 109451e3d8e2Sdanielk1977 static int test_bind_null( 109551e3d8e2Sdanielk1977 void * clientData, 109651e3d8e2Sdanielk1977 Tcl_Interp *interp, 109751e3d8e2Sdanielk1977 int objc, 109851e3d8e2Sdanielk1977 Tcl_Obj *CONST objv[] 109951e3d8e2Sdanielk1977 ){ 110051e3d8e2Sdanielk1977 sqlite3_stmt *pStmt; 110151e3d8e2Sdanielk1977 int idx; 110251e3d8e2Sdanielk1977 int rc; 110351e3d8e2Sdanielk1977 110451e3d8e2Sdanielk1977 if( objc!=3 ){ 110551e3d8e2Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 110651e3d8e2Sdanielk1977 Tcl_GetStringFromObj(objv[0], 0), " <STMT> <param no.>", 0); 110751e3d8e2Sdanielk1977 return TCL_ERROR; 110851e3d8e2Sdanielk1977 } 110951e3d8e2Sdanielk1977 111051e3d8e2Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 111151e3d8e2Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; 111251e3d8e2Sdanielk1977 111351e3d8e2Sdanielk1977 rc = sqlite3_bind_null(pStmt, idx); 111451e3d8e2Sdanielk1977 if( rc!=SQLITE_OK ){ 111551e3d8e2Sdanielk1977 return TCL_ERROR; 111651e3d8e2Sdanielk1977 } 111751e3d8e2Sdanielk1977 111851e3d8e2Sdanielk1977 return TCL_OK; 111951e3d8e2Sdanielk1977 } 112051e3d8e2Sdanielk1977 112151e3d8e2Sdanielk1977 static int test_bind_text( 112251e3d8e2Sdanielk1977 void * clientData, 112351e3d8e2Sdanielk1977 Tcl_Interp *interp, 112451e3d8e2Sdanielk1977 int objc, 112551e3d8e2Sdanielk1977 Tcl_Obj *CONST objv[] 112651e3d8e2Sdanielk1977 ){ 112751e3d8e2Sdanielk1977 sqlite3_stmt *pStmt; 112851e3d8e2Sdanielk1977 int idx; 112951e3d8e2Sdanielk1977 int bytes; 113051e3d8e2Sdanielk1977 char *value; 113151e3d8e2Sdanielk1977 int rc; 113251e3d8e2Sdanielk1977 113351e3d8e2Sdanielk1977 if( objc!=5 ){ 113451e3d8e2Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 113551e3d8e2Sdanielk1977 Tcl_GetStringFromObj(objv[0], 0), " <STMT> <param no.> <value>" 113651e3d8e2Sdanielk1977 " <bytes>", 0); 113751e3d8e2Sdanielk1977 return TCL_ERROR; 113851e3d8e2Sdanielk1977 } 113951e3d8e2Sdanielk1977 114051e3d8e2Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 114151e3d8e2Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; 114251e3d8e2Sdanielk1977 value = Tcl_GetString(objv[3]); 114351e3d8e2Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[4], &bytes) ) return TCL_ERROR; 114451e3d8e2Sdanielk1977 1145d8123366Sdanielk1977 rc = sqlite3_bind_text(pStmt, idx, value, bytes, SQLITE_TRANSIENT); 114651e3d8e2Sdanielk1977 if( rc!=SQLITE_OK ){ 114751e3d8e2Sdanielk1977 return TCL_ERROR; 114851e3d8e2Sdanielk1977 } 114951e3d8e2Sdanielk1977 115051e3d8e2Sdanielk1977 return TCL_OK; 115151e3d8e2Sdanielk1977 } 115251e3d8e2Sdanielk1977 115351e3d8e2Sdanielk1977 static int test_bind_text16( 115451e3d8e2Sdanielk1977 void * clientData, 115551e3d8e2Sdanielk1977 Tcl_Interp *interp, 115651e3d8e2Sdanielk1977 int objc, 115751e3d8e2Sdanielk1977 Tcl_Obj *CONST objv[] 115851e3d8e2Sdanielk1977 ){ 115951e3d8e2Sdanielk1977 sqlite3_stmt *pStmt; 116051e3d8e2Sdanielk1977 int idx; 116151e3d8e2Sdanielk1977 int bytes; 116251e3d8e2Sdanielk1977 char *value; 116351e3d8e2Sdanielk1977 int rc; 116451e3d8e2Sdanielk1977 116551e3d8e2Sdanielk1977 if( objc!=5 ){ 116651e3d8e2Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 116751e3d8e2Sdanielk1977 Tcl_GetStringFromObj(objv[0], 0), " <STMT> <param no.> <value>" 116851e3d8e2Sdanielk1977 " <bytes>", 0); 116951e3d8e2Sdanielk1977 return TCL_ERROR; 117051e3d8e2Sdanielk1977 } 117151e3d8e2Sdanielk1977 117251e3d8e2Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 117351e3d8e2Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; 117451e3d8e2Sdanielk1977 value = Tcl_GetByteArrayFromObj(objv[3], 0); 117551e3d8e2Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[4], &bytes) ) return TCL_ERROR; 117651e3d8e2Sdanielk1977 1177d8123366Sdanielk1977 rc = sqlite3_bind_text16(pStmt, idx, (void *)value, bytes, SQLITE_TRANSIENT); 117851e3d8e2Sdanielk1977 if( rc!=SQLITE_OK ){ 117951e3d8e2Sdanielk1977 return TCL_ERROR; 118051e3d8e2Sdanielk1977 } 118151e3d8e2Sdanielk1977 118251e3d8e2Sdanielk1977 return TCL_OK; 118351e3d8e2Sdanielk1977 } 118451e3d8e2Sdanielk1977 118551e3d8e2Sdanielk1977 static int test_bind_blob( 118651e3d8e2Sdanielk1977 void * clientData, 118751e3d8e2Sdanielk1977 Tcl_Interp *interp, 118851e3d8e2Sdanielk1977 int objc, 118951e3d8e2Sdanielk1977 Tcl_Obj *CONST objv[] 119051e3d8e2Sdanielk1977 ){ 119151e3d8e2Sdanielk1977 sqlite3_stmt *pStmt; 119251e3d8e2Sdanielk1977 int idx; 119351e3d8e2Sdanielk1977 int bytes; 119451e3d8e2Sdanielk1977 char *value; 119551e3d8e2Sdanielk1977 int rc; 119651e3d8e2Sdanielk1977 119751e3d8e2Sdanielk1977 if( objc!=5 ){ 119851e3d8e2Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 119951e3d8e2Sdanielk1977 Tcl_GetStringFromObj(objv[0], 0), " <STMT> <param no.> <value>" 120051e3d8e2Sdanielk1977 " <bytes>", 0); 120151e3d8e2Sdanielk1977 return TCL_ERROR; 120251e3d8e2Sdanielk1977 } 120351e3d8e2Sdanielk1977 120451e3d8e2Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 120551e3d8e2Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; 120651e3d8e2Sdanielk1977 value = Tcl_GetString(objv[3]); 120749e4643eSdanielk1977 if( Tcl_GetIntFromObj(interp, objv[4], &bytes) ) return TCL_ERROR; 120851e3d8e2Sdanielk1977 1209d8123366Sdanielk1977 rc = sqlite3_bind_blob(pStmt, idx, value, bytes, SQLITE_TRANSIENT); 121051e3d8e2Sdanielk1977 if( rc!=SQLITE_OK ){ 121151e3d8e2Sdanielk1977 return TCL_ERROR; 121251e3d8e2Sdanielk1977 } 121351e3d8e2Sdanielk1977 121451e3d8e2Sdanielk1977 return TCL_OK; 121551e3d8e2Sdanielk1977 } 121651e3d8e2Sdanielk1977 121799ee3600Sdrh /* 12186622cce3Sdanielk1977 ** Usage: sqlite3_errcode DB 12196622cce3Sdanielk1977 ** 12206622cce3Sdanielk1977 ** Return the string representation of the most recent sqlite3_* API 12216622cce3Sdanielk1977 ** error code. e.g. "SQLITE_ERROR". 12226622cce3Sdanielk1977 */ 12236622cce3Sdanielk1977 static int test_errcode( 12246622cce3Sdanielk1977 void * clientData, 12256622cce3Sdanielk1977 Tcl_Interp *interp, 12266622cce3Sdanielk1977 int objc, 12276622cce3Sdanielk1977 Tcl_Obj *CONST objv[] 12286622cce3Sdanielk1977 ){ 12296622cce3Sdanielk1977 sqlite3 *db; 12306622cce3Sdanielk1977 12316622cce3Sdanielk1977 if( objc!=2 ){ 12326622cce3Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 12336622cce3Sdanielk1977 Tcl_GetString(objv[0]), " DB", 0); 12346622cce3Sdanielk1977 return TCL_ERROR; 12356622cce3Sdanielk1977 } 12366622cce3Sdanielk1977 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 12376622cce3Sdanielk1977 Tcl_SetResult(interp, (char *)errorName(sqlite3_errcode(db)), 0); 12386622cce3Sdanielk1977 return TCL_OK; 12396622cce3Sdanielk1977 } 12406622cce3Sdanielk1977 12416622cce3Sdanielk1977 /* 12426622cce3Sdanielk1977 ** Usage: test_errmsg DB 12436622cce3Sdanielk1977 ** 12446622cce3Sdanielk1977 ** Returns the UTF-8 representation of the error message string for the 12456622cce3Sdanielk1977 ** most recent sqlite3_* API call. 12466622cce3Sdanielk1977 */ 12476622cce3Sdanielk1977 static int test_errmsg( 12486622cce3Sdanielk1977 void * clientData, 12496622cce3Sdanielk1977 Tcl_Interp *interp, 12506622cce3Sdanielk1977 int objc, 12516622cce3Sdanielk1977 Tcl_Obj *CONST objv[] 12526622cce3Sdanielk1977 ){ 12536622cce3Sdanielk1977 sqlite *db; 12546622cce3Sdanielk1977 const char *zErr; 12556622cce3Sdanielk1977 12566622cce3Sdanielk1977 if( objc!=2 ){ 12576622cce3Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 12586622cce3Sdanielk1977 Tcl_GetString(objv[0]), " DB", 0); 12596622cce3Sdanielk1977 return TCL_ERROR; 12606622cce3Sdanielk1977 } 12616622cce3Sdanielk1977 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 12626622cce3Sdanielk1977 12636622cce3Sdanielk1977 zErr = sqlite3_errmsg(db); 12646622cce3Sdanielk1977 Tcl_SetObjResult(interp, Tcl_NewStringObj(zErr, -1)); 12656622cce3Sdanielk1977 return TCL_OK; 12666622cce3Sdanielk1977 } 12676622cce3Sdanielk1977 12686622cce3Sdanielk1977 /* 12696622cce3Sdanielk1977 ** Usage: test_errmsg16 DB 12706622cce3Sdanielk1977 ** 12716622cce3Sdanielk1977 ** Returns the UTF-16 representation of the error message string for the 12726622cce3Sdanielk1977 ** most recent sqlite3_* API call. This is a byte array object at the TCL 12736622cce3Sdanielk1977 ** level, and it includes the 0x00 0x00 terminator bytes at the end of the 12746622cce3Sdanielk1977 ** UTF-16 string. 12756622cce3Sdanielk1977 */ 12766622cce3Sdanielk1977 static int test_errmsg16( 12776622cce3Sdanielk1977 void * clientData, 12786622cce3Sdanielk1977 Tcl_Interp *interp, 12796622cce3Sdanielk1977 int objc, 12806622cce3Sdanielk1977 Tcl_Obj *CONST objv[] 12816622cce3Sdanielk1977 ){ 12826622cce3Sdanielk1977 sqlite *db; 12836622cce3Sdanielk1977 const void *zErr; 12846622cce3Sdanielk1977 int bytes; 12856622cce3Sdanielk1977 12866622cce3Sdanielk1977 if( objc!=2 ){ 12876622cce3Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 12886622cce3Sdanielk1977 Tcl_GetString(objv[0]), " DB", 0); 12896622cce3Sdanielk1977 return TCL_ERROR; 12906622cce3Sdanielk1977 } 12916622cce3Sdanielk1977 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 12926622cce3Sdanielk1977 12936622cce3Sdanielk1977 zErr = sqlite3_errmsg16(db); 12946622cce3Sdanielk1977 bytes = sqlite3utf16ByteLen(zErr, -1); 12956622cce3Sdanielk1977 Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(zErr, bytes)); 12966622cce3Sdanielk1977 return TCL_OK; 12976622cce3Sdanielk1977 } 12986622cce3Sdanielk1977 12996622cce3Sdanielk1977 /* 13006622cce3Sdanielk1977 ** Usage: sqlite3_prepare DB sql bytes tailvar 13016622cce3Sdanielk1977 ** 13026622cce3Sdanielk1977 ** Compile up to <bytes> bytes of the supplied SQL string <sql> using 13036622cce3Sdanielk1977 ** database handle <DB>. The parameter <tailval> is the name of a global 13046622cce3Sdanielk1977 ** variable that is set to the unused portion of <sql> (if any). A 13056622cce3Sdanielk1977 ** STMT handle is returned. 13066622cce3Sdanielk1977 */ 13076622cce3Sdanielk1977 static int test_prepare( 13086622cce3Sdanielk1977 void * clientData, 13096622cce3Sdanielk1977 Tcl_Interp *interp, 13106622cce3Sdanielk1977 int objc, 13116622cce3Sdanielk1977 Tcl_Obj *CONST objv[] 13126622cce3Sdanielk1977 ){ 13136622cce3Sdanielk1977 sqlite3 *db; 13146622cce3Sdanielk1977 const char *zSql; 13156622cce3Sdanielk1977 int bytes; 13166622cce3Sdanielk1977 const char *zTail = 0; 13176622cce3Sdanielk1977 sqlite3_stmt *pStmt = 0; 13186622cce3Sdanielk1977 char zBuf[50]; 13194ad1713cSdanielk1977 int rc; 13206622cce3Sdanielk1977 13216622cce3Sdanielk1977 if( objc!=5 ){ 13226622cce3Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 13236622cce3Sdanielk1977 Tcl_GetString(objv[0]), " DB sql bytes tailvar", 0); 13246622cce3Sdanielk1977 return TCL_ERROR; 13256622cce3Sdanielk1977 } 13266622cce3Sdanielk1977 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 13276622cce3Sdanielk1977 zSql = Tcl_GetString(objv[2]); 13286622cce3Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR; 13296622cce3Sdanielk1977 13304ad1713cSdanielk1977 rc = sqlite3_prepare(db, zSql, bytes, &pStmt, &zTail); 13316622cce3Sdanielk1977 if( zTail ){ 13326622cce3Sdanielk1977 if( bytes>=0 ){ 13336622cce3Sdanielk1977 bytes = bytes - (zTail-zSql); 13346622cce3Sdanielk1977 } 13356622cce3Sdanielk1977 Tcl_ObjSetVar2(interp, objv[4], 0, Tcl_NewStringObj(zTail, bytes), 0); 13366622cce3Sdanielk1977 } 13374ad1713cSdanielk1977 if( rc!=SQLITE_OK ){ 13384ad1713cSdanielk1977 assert( pStmt==0 ); 13394ad1713cSdanielk1977 sprintf(zBuf, "(%d) ", rc); 13404ad1713cSdanielk1977 Tcl_AppendResult(interp, zBuf, sqlite3_errmsg(db), 0); 13414ad1713cSdanielk1977 return TCL_ERROR; 13424ad1713cSdanielk1977 } 13436622cce3Sdanielk1977 13444ad1713cSdanielk1977 if( pStmt ){ 13456622cce3Sdanielk1977 if( makePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR; 13466622cce3Sdanielk1977 Tcl_AppendResult(interp, zBuf, 0); 13474ad1713cSdanielk1977 } 13486622cce3Sdanielk1977 return TCL_OK; 13496622cce3Sdanielk1977 } 13506622cce3Sdanielk1977 13516622cce3Sdanielk1977 /* 13526622cce3Sdanielk1977 ** Usage: sqlite3_prepare DB sql bytes tailvar 13536622cce3Sdanielk1977 ** 13546622cce3Sdanielk1977 ** Compile up to <bytes> bytes of the supplied SQL string <sql> using 13556622cce3Sdanielk1977 ** database handle <DB>. The parameter <tailval> is the name of a global 13566622cce3Sdanielk1977 ** variable that is set to the unused portion of <sql> (if any). A 13576622cce3Sdanielk1977 ** STMT handle is returned. 13586622cce3Sdanielk1977 */ 13596622cce3Sdanielk1977 static int test_prepare16( 13606622cce3Sdanielk1977 void * clientData, 13616622cce3Sdanielk1977 Tcl_Interp *interp, 13626622cce3Sdanielk1977 int objc, 13636622cce3Sdanielk1977 Tcl_Obj *CONST objv[] 13646622cce3Sdanielk1977 ){ 13656622cce3Sdanielk1977 sqlite3 *db; 13666622cce3Sdanielk1977 const void *zSql; 13676622cce3Sdanielk1977 const void *zTail = 0; 13686622cce3Sdanielk1977 Tcl_Obj *pTail = 0; 13696622cce3Sdanielk1977 sqlite3_stmt *pStmt = 0; 13706622cce3Sdanielk1977 char zBuf[50]; 13716622cce3Sdanielk1977 int bytes; /* The integer specified as arg 3 */ 13726622cce3Sdanielk1977 int objlen; /* The byte-array length of arg 2 */ 13736622cce3Sdanielk1977 13746622cce3Sdanielk1977 if( objc!=5 ){ 13756622cce3Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 13766622cce3Sdanielk1977 Tcl_GetString(objv[0]), " DB sql bytes tailvar", 0); 13776622cce3Sdanielk1977 return TCL_ERROR; 13786622cce3Sdanielk1977 } 13796622cce3Sdanielk1977 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 13806622cce3Sdanielk1977 zSql = Tcl_GetByteArrayFromObj(objv[2], &objlen); 13816622cce3Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR; 13826622cce3Sdanielk1977 13836622cce3Sdanielk1977 if( SQLITE_OK!=sqlite3_prepare16(db, zSql, bytes, &pStmt, &zTail) ){ 13846622cce3Sdanielk1977 return TCL_ERROR; 13856622cce3Sdanielk1977 } 13866622cce3Sdanielk1977 13876622cce3Sdanielk1977 if( zTail ){ 13886622cce3Sdanielk1977 objlen = objlen - ((u8 *)zTail-(u8 *)zSql); 13896622cce3Sdanielk1977 }else{ 13906622cce3Sdanielk1977 objlen = 0; 13916622cce3Sdanielk1977 } 13926622cce3Sdanielk1977 pTail = Tcl_NewByteArrayObj((u8 *)zTail, objlen); 13936622cce3Sdanielk1977 Tcl_IncrRefCount(pTail); 13946622cce3Sdanielk1977 Tcl_ObjSetVar2(interp, objv[4], 0, pTail, 0); 13954ad1713cSdanielk1977 Tcl_DecrRefCount(pTail); 13966622cce3Sdanielk1977 13974ad1713cSdanielk1977 if( pStmt ){ 13986622cce3Sdanielk1977 if( makePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR; 13994ad1713cSdanielk1977 } 14006622cce3Sdanielk1977 Tcl_AppendResult(interp, zBuf, 0); 14016622cce3Sdanielk1977 return TCL_OK; 14026622cce3Sdanielk1977 } 14036622cce3Sdanielk1977 14044ad1713cSdanielk1977 /* 14054ad1713cSdanielk1977 ** Usage: sqlite3_open filename ?options-list? 14064ad1713cSdanielk1977 */ 14074ad1713cSdanielk1977 static int test_open( 14084ad1713cSdanielk1977 void * clientData, 14094ad1713cSdanielk1977 Tcl_Interp *interp, 14104ad1713cSdanielk1977 int objc, 14114ad1713cSdanielk1977 Tcl_Obj *CONST objv[] 14124ad1713cSdanielk1977 ){ 14134ad1713cSdanielk1977 const char *zFilename; 14144ad1713cSdanielk1977 sqlite3 *db; 14154ad1713cSdanielk1977 int rc; 14164ad1713cSdanielk1977 char zBuf[100]; 14174ad1713cSdanielk1977 14184ad1713cSdanielk1977 if( objc!=3 && objc!=2 ){ 14194ad1713cSdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 14204ad1713cSdanielk1977 Tcl_GetString(objv[0]), " filename options-list", 0); 14214ad1713cSdanielk1977 return TCL_ERROR; 14224ad1713cSdanielk1977 } 14234ad1713cSdanielk1977 14244ad1713cSdanielk1977 zFilename = Tcl_GetString(objv[1]); 14254f057f90Sdanielk1977 rc = sqlite3_open(zFilename, &db); 14264ad1713cSdanielk1977 14274ad1713cSdanielk1977 if( makePointerStr(interp, zBuf, db) ) return TCL_ERROR; 14284ad1713cSdanielk1977 Tcl_AppendResult(interp, zBuf, 0); 14294ad1713cSdanielk1977 return TCL_OK; 14304ad1713cSdanielk1977 } 14314ad1713cSdanielk1977 14324ad1713cSdanielk1977 /* 14334ad1713cSdanielk1977 ** Usage: sqlite3_open16 filename options 14344ad1713cSdanielk1977 */ 14354ad1713cSdanielk1977 static int test_open16( 14364ad1713cSdanielk1977 void * clientData, 14374ad1713cSdanielk1977 Tcl_Interp *interp, 14384ad1713cSdanielk1977 int objc, 14394ad1713cSdanielk1977 Tcl_Obj *CONST objv[] 14404ad1713cSdanielk1977 ){ 14414ad1713cSdanielk1977 const void *zFilename; 14424ad1713cSdanielk1977 sqlite3 *db; 14434ad1713cSdanielk1977 int rc; 14444ad1713cSdanielk1977 char zBuf[100]; 14454ad1713cSdanielk1977 14464ad1713cSdanielk1977 if( objc!=3 ){ 14474ad1713cSdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 14484ad1713cSdanielk1977 Tcl_GetString(objv[0]), " filename options-list", 0); 14494ad1713cSdanielk1977 return TCL_ERROR; 14504ad1713cSdanielk1977 } 14514ad1713cSdanielk1977 14524ad1713cSdanielk1977 zFilename = Tcl_GetByteArrayFromObj(objv[1], 0); 14534f057f90Sdanielk1977 rc = sqlite3_open16(zFilename, &db); 14544ad1713cSdanielk1977 14554ad1713cSdanielk1977 if( makePointerStr(interp, zBuf, db) ) return TCL_ERROR; 14564ad1713cSdanielk1977 Tcl_AppendResult(interp, zBuf, 0); 14574ad1713cSdanielk1977 return TCL_OK; 14584ad1713cSdanielk1977 } 1459d3d39e93Sdrh 1460d3d39e93Sdrh /* 1461106bb236Sdanielk1977 ** Usage: sqlite3_step STMT 1462106bb236Sdanielk1977 ** 1463106bb236Sdanielk1977 ** Advance the statement to the next row. 1464106bb236Sdanielk1977 */ 146517240fd9Sdanielk1977 static int test_step( 1466106bb236Sdanielk1977 void * clientData, 1467106bb236Sdanielk1977 Tcl_Interp *interp, 1468106bb236Sdanielk1977 int objc, 1469106bb236Sdanielk1977 Tcl_Obj *CONST objv[] 1470106bb236Sdanielk1977 ){ 1471106bb236Sdanielk1977 sqlite3_stmt *pStmt; 1472106bb236Sdanielk1977 int rc; 1473106bb236Sdanielk1977 1474e1cd9874Sdanielk1977 if( objc!=2 ){ 1475106bb236Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 1476106bb236Sdanielk1977 Tcl_GetString(objv[0]), " STMT", 0); 1477106bb236Sdanielk1977 return TCL_ERROR; 1478106bb236Sdanielk1977 } 1479106bb236Sdanielk1977 1480106bb236Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 148117240fd9Sdanielk1977 rc = sqlite3_step(pStmt); 1482106bb236Sdanielk1977 1483fbcd585fSdanielk1977 /* if( rc!=SQLITE_DONE && rc!=SQLITE_ROW ) return TCL_ERROR; */ 14846590493dSdanielk1977 Tcl_SetResult(interp, (char *)errorName(rc), 0); 1485e1cd9874Sdanielk1977 return TCL_OK; 1486e1cd9874Sdanielk1977 } 1487e1cd9874Sdanielk1977 1488e1cd9874Sdanielk1977 /* 148917240fd9Sdanielk1977 ** Usage: sqlite3_column_count STMT 149017240fd9Sdanielk1977 ** 149117240fd9Sdanielk1977 ** Return the number of columns returned by the sql statement STMT. 149217240fd9Sdanielk1977 */ 149317240fd9Sdanielk1977 static int test_column_count( 149417240fd9Sdanielk1977 void * clientData, 149517240fd9Sdanielk1977 Tcl_Interp *interp, 149617240fd9Sdanielk1977 int objc, 149717240fd9Sdanielk1977 Tcl_Obj *CONST objv[] 149817240fd9Sdanielk1977 ){ 149917240fd9Sdanielk1977 sqlite3_stmt *pStmt; 150017240fd9Sdanielk1977 150117240fd9Sdanielk1977 if( objc!=2 ){ 150217240fd9Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 150317240fd9Sdanielk1977 Tcl_GetString(objv[0]), " STMT column", 0); 150417240fd9Sdanielk1977 return TCL_ERROR; 150517240fd9Sdanielk1977 } 150617240fd9Sdanielk1977 150717240fd9Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 150817240fd9Sdanielk1977 150917240fd9Sdanielk1977 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_column_count(pStmt))); 151017240fd9Sdanielk1977 return TCL_OK; 151117240fd9Sdanielk1977 } 151217240fd9Sdanielk1977 151317240fd9Sdanielk1977 /* 15143cf86063Sdanielk1977 ** Usage: sqlite3_column_type STMT column 15153cf86063Sdanielk1977 ** 15163cf86063Sdanielk1977 ** Return the type of the data in column 'column' of the current row. 15173cf86063Sdanielk1977 */ 15183cf86063Sdanielk1977 static int test_column_type( 15193cf86063Sdanielk1977 void * clientData, 15203cf86063Sdanielk1977 Tcl_Interp *interp, 15213cf86063Sdanielk1977 int objc, 15223cf86063Sdanielk1977 Tcl_Obj *CONST objv[] 15233cf86063Sdanielk1977 ){ 15243cf86063Sdanielk1977 sqlite3_stmt *pStmt; 15253cf86063Sdanielk1977 int col; 15263cf86063Sdanielk1977 int tp; 15273cf86063Sdanielk1977 15283cf86063Sdanielk1977 if( objc!=3 ){ 15293cf86063Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 15303cf86063Sdanielk1977 Tcl_GetString(objv[0]), " STMT column", 0); 15313cf86063Sdanielk1977 return TCL_ERROR; 15323cf86063Sdanielk1977 } 15333cf86063Sdanielk1977 15343cf86063Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 15353cf86063Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; 15363cf86063Sdanielk1977 15373cf86063Sdanielk1977 tp = sqlite3_column_type(pStmt, col); 15383cf86063Sdanielk1977 switch( tp ){ 15399c054830Sdrh case SQLITE_INTEGER: 15403cf86063Sdanielk1977 Tcl_SetResult(interp, "INTEGER", TCL_STATIC); 15413cf86063Sdanielk1977 break; 15429c054830Sdrh case SQLITE_NULL: 15433cf86063Sdanielk1977 Tcl_SetResult(interp, "NULL", TCL_STATIC); 15443cf86063Sdanielk1977 break; 15459c054830Sdrh case SQLITE_FLOAT: 15463cf86063Sdanielk1977 Tcl_SetResult(interp, "FLOAT", TCL_STATIC); 15473cf86063Sdanielk1977 break; 15489c054830Sdrh case SQLITE_TEXT: 15493cf86063Sdanielk1977 Tcl_SetResult(interp, "TEXT", TCL_STATIC); 15503cf86063Sdanielk1977 break; 15519c054830Sdrh case SQLITE_BLOB: 15523cf86063Sdanielk1977 Tcl_SetResult(interp, "BLOB", TCL_STATIC); 15533cf86063Sdanielk1977 break; 15543cf86063Sdanielk1977 default: 15553cf86063Sdanielk1977 assert(0); 15563cf86063Sdanielk1977 } 15573cf86063Sdanielk1977 15583cf86063Sdanielk1977 return TCL_OK; 15593cf86063Sdanielk1977 } 15603cf86063Sdanielk1977 15613cf86063Sdanielk1977 /* 156204f2e68dSdanielk1977 ** Usage: sqlite3_column_int64 STMT column 15633cf86063Sdanielk1977 ** 15643cf86063Sdanielk1977 ** Return the data in column 'column' of the current row cast as an 156504f2e68dSdanielk1977 ** wide (64-bit) integer. 15663cf86063Sdanielk1977 */ 156704f2e68dSdanielk1977 static int test_column_int64( 15683cf86063Sdanielk1977 void * clientData, 15693cf86063Sdanielk1977 Tcl_Interp *interp, 15703cf86063Sdanielk1977 int objc, 15713cf86063Sdanielk1977 Tcl_Obj *CONST objv[] 15723cf86063Sdanielk1977 ){ 15733cf86063Sdanielk1977 sqlite3_stmt *pStmt; 15743cf86063Sdanielk1977 int col; 157504f2e68dSdanielk1977 i64 iVal; 15763cf86063Sdanielk1977 15773cf86063Sdanielk1977 if( objc!=3 ){ 15783cf86063Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 15793cf86063Sdanielk1977 Tcl_GetString(objv[0]), " STMT column", 0); 15803cf86063Sdanielk1977 return TCL_ERROR; 15813cf86063Sdanielk1977 } 15823cf86063Sdanielk1977 15833cf86063Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 15843cf86063Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; 15853cf86063Sdanielk1977 158604f2e68dSdanielk1977 iVal = sqlite3_column_int64(pStmt, col); 158704f2e68dSdanielk1977 Tcl_SetObjResult(interp, Tcl_NewWideIntObj(iVal)); 158804f2e68dSdanielk1977 return TCL_OK; 158904f2e68dSdanielk1977 } 159004f2e68dSdanielk1977 159104f2e68dSdanielk1977 /* 1592ea61b2c4Sdanielk1977 ** Usage: sqlite3_column_blob STMT column 1593ea61b2c4Sdanielk1977 */ 1594ea61b2c4Sdanielk1977 static int test_column_blob( 1595ea61b2c4Sdanielk1977 void * clientData, 1596ea61b2c4Sdanielk1977 Tcl_Interp *interp, 1597ea61b2c4Sdanielk1977 int objc, 1598ea61b2c4Sdanielk1977 Tcl_Obj *CONST objv[] 1599ea61b2c4Sdanielk1977 ){ 1600ea61b2c4Sdanielk1977 sqlite3_stmt *pStmt; 1601ea61b2c4Sdanielk1977 int col; 1602ea61b2c4Sdanielk1977 1603ea61b2c4Sdanielk1977 int len; 1604c572ef7fSdanielk1977 const void *pBlob; 1605ea61b2c4Sdanielk1977 1606ea61b2c4Sdanielk1977 if( objc!=3 ){ 1607ea61b2c4Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 1608ea61b2c4Sdanielk1977 Tcl_GetString(objv[0]), " STMT column", 0); 1609ea61b2c4Sdanielk1977 return TCL_ERROR; 1610ea61b2c4Sdanielk1977 } 1611ea61b2c4Sdanielk1977 1612ea61b2c4Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 1613ea61b2c4Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; 1614ea61b2c4Sdanielk1977 1615ea61b2c4Sdanielk1977 pBlob = sqlite3_column_blob(pStmt, col); 1616ea61b2c4Sdanielk1977 len = sqlite3_column_bytes(pStmt, col); 1617ea61b2c4Sdanielk1977 Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(pBlob, len)); 1618ea61b2c4Sdanielk1977 return TCL_OK; 1619ea61b2c4Sdanielk1977 } 1620ea61b2c4Sdanielk1977 1621ea61b2c4Sdanielk1977 /* 162204f2e68dSdanielk1977 ** Usage: sqlite3_column_double STMT column 162304f2e68dSdanielk1977 ** 162404f2e68dSdanielk1977 ** Return the data in column 'column' of the current row cast as a double. 162504f2e68dSdanielk1977 */ 162604f2e68dSdanielk1977 static int test_column_double( 162704f2e68dSdanielk1977 void * clientData, 162804f2e68dSdanielk1977 Tcl_Interp *interp, 162904f2e68dSdanielk1977 int objc, 163004f2e68dSdanielk1977 Tcl_Obj *CONST objv[] 163104f2e68dSdanielk1977 ){ 163204f2e68dSdanielk1977 sqlite3_stmt *pStmt; 163304f2e68dSdanielk1977 int col; 163404f2e68dSdanielk1977 double rVal; 163504f2e68dSdanielk1977 163604f2e68dSdanielk1977 if( objc!=3 ){ 163704f2e68dSdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 163804f2e68dSdanielk1977 Tcl_GetString(objv[0]), " STMT column", 0); 163904f2e68dSdanielk1977 return TCL_ERROR; 164004f2e68dSdanielk1977 } 164104f2e68dSdanielk1977 164204f2e68dSdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 164304f2e68dSdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; 164404f2e68dSdanielk1977 164504f2e68dSdanielk1977 rVal = sqlite3_column_double(pStmt, col); 1646c572ef7fSdanielk1977 Tcl_SetObjResult(interp, Tcl_NewDoubleObj(rVal)); 16473cf86063Sdanielk1977 return TCL_OK; 16483cf86063Sdanielk1977 } 16493cf86063Sdanielk1977 16503cf86063Sdanielk1977 /* 165117240fd9Sdanielk1977 ** Usage: sqlite3_data_count STMT 165217240fd9Sdanielk1977 ** 165317240fd9Sdanielk1977 ** Return the number of columns returned by the sql statement STMT. 165417240fd9Sdanielk1977 */ 165517240fd9Sdanielk1977 static int test_data_count( 165617240fd9Sdanielk1977 void * clientData, 165717240fd9Sdanielk1977 Tcl_Interp *interp, 165817240fd9Sdanielk1977 int objc, 165917240fd9Sdanielk1977 Tcl_Obj *CONST objv[] 166017240fd9Sdanielk1977 ){ 166117240fd9Sdanielk1977 sqlite3_stmt *pStmt; 166217240fd9Sdanielk1977 166317240fd9Sdanielk1977 if( objc!=2 ){ 166417240fd9Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 166517240fd9Sdanielk1977 Tcl_GetString(objv[0]), " STMT column", 0); 166617240fd9Sdanielk1977 return TCL_ERROR; 166717240fd9Sdanielk1977 } 166817240fd9Sdanielk1977 166917240fd9Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 167017240fd9Sdanielk1977 167117240fd9Sdanielk1977 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_data_count(pStmt))); 167217240fd9Sdanielk1977 return TCL_OK; 167317240fd9Sdanielk1977 } 167417240fd9Sdanielk1977 167517240fd9Sdanielk1977 /* 167604f2e68dSdanielk1977 ** Usage: sqlite3_column_text STMT column 167704f2e68dSdanielk1977 ** 167804f2e68dSdanielk1977 ** Usage: sqlite3_column_decltype STMT column 167904f2e68dSdanielk1977 ** 168004f2e68dSdanielk1977 ** Usage: sqlite3_column_name STMT column 168104f2e68dSdanielk1977 */ 168204f2e68dSdanielk1977 static int test_stmt_utf8( 168304f2e68dSdanielk1977 void * clientData, 168404f2e68dSdanielk1977 Tcl_Interp *interp, 168504f2e68dSdanielk1977 int objc, 168604f2e68dSdanielk1977 Tcl_Obj *CONST objv[] 168704f2e68dSdanielk1977 ){ 168804f2e68dSdanielk1977 sqlite3_stmt *pStmt; 168904f2e68dSdanielk1977 int col; 1690c572ef7fSdanielk1977 const char *(*xFunc)(sqlite3_stmt*, int) = clientData; 1691f93bbbeaSdanielk1977 const char *zRet; 169204f2e68dSdanielk1977 169304f2e68dSdanielk1977 if( objc!=3 ){ 169404f2e68dSdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 169504f2e68dSdanielk1977 Tcl_GetString(objv[0]), " STMT column", 0); 169604f2e68dSdanielk1977 return TCL_ERROR; 169704f2e68dSdanielk1977 } 169804f2e68dSdanielk1977 169904f2e68dSdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 170004f2e68dSdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; 1701f93bbbeaSdanielk1977 zRet = xFunc(pStmt, col); 1702f93bbbeaSdanielk1977 if( zRet ){ 1703f93bbbeaSdanielk1977 Tcl_SetResult(interp, (char *)zRet, 0); 1704f93bbbeaSdanielk1977 } 170504f2e68dSdanielk1977 return TCL_OK; 170604f2e68dSdanielk1977 } 170704f2e68dSdanielk1977 170804f2e68dSdanielk1977 /* 170904f2e68dSdanielk1977 ** Usage: sqlite3_column_text STMT column 171004f2e68dSdanielk1977 ** 171104f2e68dSdanielk1977 ** Usage: sqlite3_column_decltype STMT column 171204f2e68dSdanielk1977 ** 171304f2e68dSdanielk1977 ** Usage: sqlite3_column_name STMT column 171404f2e68dSdanielk1977 */ 171504f2e68dSdanielk1977 static int test_stmt_utf16( 171604f2e68dSdanielk1977 void * clientData, 171704f2e68dSdanielk1977 Tcl_Interp *interp, 171804f2e68dSdanielk1977 int objc, 171904f2e68dSdanielk1977 Tcl_Obj *CONST objv[] 172004f2e68dSdanielk1977 ){ 172104f2e68dSdanielk1977 sqlite3_stmt *pStmt; 172204f2e68dSdanielk1977 int col; 172304f2e68dSdanielk1977 Tcl_Obj *pRet; 172404f2e68dSdanielk1977 const void *zName16; 1725c572ef7fSdanielk1977 const void *(*xFunc)(sqlite3_stmt*, int) = clientData; 172604f2e68dSdanielk1977 172704f2e68dSdanielk1977 if( objc!=3 ){ 172804f2e68dSdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 172904f2e68dSdanielk1977 Tcl_GetString(objv[0]), " STMT column", 0); 173004f2e68dSdanielk1977 return TCL_ERROR; 173104f2e68dSdanielk1977 } 173204f2e68dSdanielk1977 173304f2e68dSdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 173404f2e68dSdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; 173504f2e68dSdanielk1977 173604f2e68dSdanielk1977 zName16 = xFunc(pStmt, col); 1737f93bbbeaSdanielk1977 if( zName16 ){ 173804f2e68dSdanielk1977 pRet = Tcl_NewByteArrayObj(zName16, sqlite3utf16ByteLen(zName16, -1)+2); 173904f2e68dSdanielk1977 Tcl_SetObjResult(interp, pRet); 1740f93bbbeaSdanielk1977 } 174104f2e68dSdanielk1977 174204f2e68dSdanielk1977 return TCL_OK; 174304f2e68dSdanielk1977 } 174404f2e68dSdanielk1977 174504f2e68dSdanielk1977 /* 174604f2e68dSdanielk1977 ** Usage: sqlite3_column_int STMT column 174704f2e68dSdanielk1977 ** 174804f2e68dSdanielk1977 ** Usage: sqlite3_column_bytes STMT column 174904f2e68dSdanielk1977 ** 175004f2e68dSdanielk1977 ** Usage: sqlite3_column_bytes16 STMT column 175104f2e68dSdanielk1977 ** 175204f2e68dSdanielk1977 */ 175304f2e68dSdanielk1977 static int test_stmt_int( 175404f2e68dSdanielk1977 void * clientData, 175504f2e68dSdanielk1977 Tcl_Interp *interp, 175604f2e68dSdanielk1977 int objc, 175704f2e68dSdanielk1977 Tcl_Obj *CONST objv[] 175804f2e68dSdanielk1977 ){ 175904f2e68dSdanielk1977 sqlite3_stmt *pStmt; 176004f2e68dSdanielk1977 int col; 1761c572ef7fSdanielk1977 int (*xFunc)(sqlite3_stmt*, int) = clientData; 176204f2e68dSdanielk1977 176304f2e68dSdanielk1977 if( objc!=3 ){ 176404f2e68dSdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 176504f2e68dSdanielk1977 Tcl_GetString(objv[0]), " STMT column", 0); 176604f2e68dSdanielk1977 return TCL_ERROR; 176704f2e68dSdanielk1977 } 176804f2e68dSdanielk1977 176904f2e68dSdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 177004f2e68dSdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; 177104f2e68dSdanielk1977 177204f2e68dSdanielk1977 Tcl_SetObjResult(interp, Tcl_NewIntObj(xFunc(pStmt, col))); 177304f2e68dSdanielk1977 return TCL_OK; 177404f2e68dSdanielk1977 } 177504f2e68dSdanielk1977 17769a1d0abeSdanielk1977 /* 17779a1d0abeSdanielk1977 ** Usage: sqlite3OsOpenReadWrite <filename> 17789a1d0abeSdanielk1977 */ 17799a1d0abeSdanielk1977 static int test_sqlite3OsOpenReadWrite( 17809a1d0abeSdanielk1977 void * clientData, 17819a1d0abeSdanielk1977 Tcl_Interp *interp, 17829a1d0abeSdanielk1977 int objc, 17839a1d0abeSdanielk1977 Tcl_Obj *CONST objv[] 17849a1d0abeSdanielk1977 ){ 17859a1d0abeSdanielk1977 OsFile * pFile; 17869a1d0abeSdanielk1977 int rc; 17879a1d0abeSdanielk1977 int dummy; 17889a1d0abeSdanielk1977 char zBuf[100]; 178904f2e68dSdanielk1977 17909a1d0abeSdanielk1977 if( objc!=2 ){ 17919a1d0abeSdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 17929a1d0abeSdanielk1977 Tcl_GetString(objv[0]), " filename", 0); 17939a1d0abeSdanielk1977 return TCL_ERROR; 17949a1d0abeSdanielk1977 } 17959a1d0abeSdanielk1977 17969a1d0abeSdanielk1977 pFile = sqliteMalloc(sizeof(OsFile)); 17979a1d0abeSdanielk1977 rc = sqlite3OsOpenReadWrite(Tcl_GetString(objv[1]), pFile, &dummy); 17989a1d0abeSdanielk1977 if( rc!=SQLITE_OK ){ 17999a1d0abeSdanielk1977 sqliteFree(pFile); 18009a1d0abeSdanielk1977 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC); 18019a1d0abeSdanielk1977 return TCL_ERROR; 18029a1d0abeSdanielk1977 } 18039a1d0abeSdanielk1977 makePointerStr(interp, zBuf, pFile); 18049a1d0abeSdanielk1977 Tcl_SetResult(interp, zBuf, 0); 18059a1d0abeSdanielk1977 return TCL_ERROR; 18069a1d0abeSdanielk1977 } 18079a1d0abeSdanielk1977 18089a1d0abeSdanielk1977 /* 18099a1d0abeSdanielk1977 ** Usage: sqlite3OsClose <file handle> 18109a1d0abeSdanielk1977 */ 18119a1d0abeSdanielk1977 static int test_sqlite3OsClose( 18129a1d0abeSdanielk1977 void * clientData, 18139a1d0abeSdanielk1977 Tcl_Interp *interp, 18149a1d0abeSdanielk1977 int objc, 18159a1d0abeSdanielk1977 Tcl_Obj *CONST objv[] 18169a1d0abeSdanielk1977 ){ 18179a1d0abeSdanielk1977 OsFile * pFile; 18189a1d0abeSdanielk1977 int rc; 18199a1d0abeSdanielk1977 18209a1d0abeSdanielk1977 if( objc!=2 ){ 18219a1d0abeSdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 18229a1d0abeSdanielk1977 Tcl_GetString(objv[0]), " filehandle", 0); 18239a1d0abeSdanielk1977 return TCL_ERROR; 18249a1d0abeSdanielk1977 } 18259a1d0abeSdanielk1977 18269a1d0abeSdanielk1977 if( getFilePointer(interp, Tcl_GetString(objv[1]), &pFile) ){ 18279a1d0abeSdanielk1977 return TCL_ERROR; 18289a1d0abeSdanielk1977 } 18299a1d0abeSdanielk1977 rc = sqlite3OsClose(pFile); 18309a1d0abeSdanielk1977 if( rc!=SQLITE_OK ){ 18319a1d0abeSdanielk1977 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC); 18329a1d0abeSdanielk1977 return TCL_ERROR; 18339a1d0abeSdanielk1977 } 18349a1d0abeSdanielk1977 sqliteFree(pFile); 18359a1d0abeSdanielk1977 return TCL_OK; 18369a1d0abeSdanielk1977 } 18379a1d0abeSdanielk1977 18389a1d0abeSdanielk1977 /* 18399a1d0abeSdanielk1977 ** Usage: sqlite3OsLock <file handle> <locktype> 18409a1d0abeSdanielk1977 */ 18419a1d0abeSdanielk1977 static int test_sqlite3OsLock( 18429a1d0abeSdanielk1977 void * clientData, 18439a1d0abeSdanielk1977 Tcl_Interp *interp, 18449a1d0abeSdanielk1977 int objc, 18459a1d0abeSdanielk1977 Tcl_Obj *CONST objv[] 18469a1d0abeSdanielk1977 ){ 18479a1d0abeSdanielk1977 OsFile * pFile; 18489a1d0abeSdanielk1977 int rc; 18499a1d0abeSdanielk1977 18509a1d0abeSdanielk1977 if( objc!=3 ){ 18519a1d0abeSdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 18529a1d0abeSdanielk1977 Tcl_GetString(objv[0]), 18539a1d0abeSdanielk1977 " filehandle (SHARED|RESERVED|PENDING|EXCLUSIVE)", 0); 18549a1d0abeSdanielk1977 return TCL_ERROR; 18559a1d0abeSdanielk1977 } 18569a1d0abeSdanielk1977 18579a1d0abeSdanielk1977 if( getFilePointer(interp, Tcl_GetString(objv[1]), &pFile) ){ 18589a1d0abeSdanielk1977 return TCL_ERROR; 18599a1d0abeSdanielk1977 } 18609a1d0abeSdanielk1977 18619a1d0abeSdanielk1977 if( 0==strcmp("SHARED", Tcl_GetString(objv[2])) ){ 18629a1d0abeSdanielk1977 rc = sqlite3OsLock(pFile, SHARED_LOCK); 18639a1d0abeSdanielk1977 } 18649a1d0abeSdanielk1977 else if( 0==strcmp("RESERVED", Tcl_GetString(objv[2])) ){ 18659a1d0abeSdanielk1977 rc = sqlite3OsLock(pFile, RESERVED_LOCK); 18669a1d0abeSdanielk1977 } 18679a1d0abeSdanielk1977 else if( 0==strcmp("PENDING", Tcl_GetString(objv[2])) ){ 18689a1d0abeSdanielk1977 rc = sqlite3OsLock(pFile, PENDING_LOCK); 18699a1d0abeSdanielk1977 } 18709a1d0abeSdanielk1977 else if( 0==strcmp("EXCLUSIVE", Tcl_GetString(objv[2])) ){ 18719a1d0abeSdanielk1977 rc = sqlite3OsLock(pFile, EXCLUSIVE_LOCK); 18729a1d0abeSdanielk1977 }else{ 18739a1d0abeSdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 18749a1d0abeSdanielk1977 Tcl_GetString(objv[0]), 18759a1d0abeSdanielk1977 " filehandle (SHARED|RESERVED|PENDING|EXCLUSIVE)", 0); 18769a1d0abeSdanielk1977 return TCL_ERROR; 18779a1d0abeSdanielk1977 } 18789a1d0abeSdanielk1977 18799a1d0abeSdanielk1977 if( rc!=SQLITE_OK ){ 18809a1d0abeSdanielk1977 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC); 18819a1d0abeSdanielk1977 return TCL_ERROR; 18829a1d0abeSdanielk1977 } 18839a1d0abeSdanielk1977 return TCL_OK; 18849a1d0abeSdanielk1977 } 18859a1d0abeSdanielk1977 18869a1d0abeSdanielk1977 /* 18879a1d0abeSdanielk1977 ** Usage: sqlite3OsUnlock <file handle> 18889a1d0abeSdanielk1977 */ 18899a1d0abeSdanielk1977 static int test_sqlite3OsUnlock( 18909a1d0abeSdanielk1977 void * clientData, 18919a1d0abeSdanielk1977 Tcl_Interp *interp, 18929a1d0abeSdanielk1977 int objc, 18939a1d0abeSdanielk1977 Tcl_Obj *CONST objv[] 18949a1d0abeSdanielk1977 ){ 18959a1d0abeSdanielk1977 OsFile * pFile; 18969a1d0abeSdanielk1977 int rc; 18979a1d0abeSdanielk1977 18989a1d0abeSdanielk1977 if( objc!=2 ){ 18999a1d0abeSdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 19009a1d0abeSdanielk1977 Tcl_GetString(objv[0]), " filehandle", 0); 19019a1d0abeSdanielk1977 return TCL_ERROR; 19029a1d0abeSdanielk1977 } 19039a1d0abeSdanielk1977 19049a1d0abeSdanielk1977 if( getFilePointer(interp, Tcl_GetString(objv[1]), &pFile) ){ 19059a1d0abeSdanielk1977 return TCL_ERROR; 19069a1d0abeSdanielk1977 } 1907a6abd041Sdrh rc = sqlite3OsUnlock(pFile, NO_LOCK); 19089a1d0abeSdanielk1977 if( rc!=SQLITE_OK ){ 19099a1d0abeSdanielk1977 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC); 19109a1d0abeSdanielk1977 return TCL_ERROR; 19119a1d0abeSdanielk1977 } 19129a1d0abeSdanielk1977 return TCL_OK; 19139a1d0abeSdanielk1977 } 1914d3d39e93Sdrh 1915d8123366Sdanielk1977 19166622cce3Sdanielk1977 /* 1917d1bf3512Sdrh ** Register commands with the TCL interpreter. 1918d1bf3512Sdrh */ 1919d1bf3512Sdrh int Sqlitetest1_Init(Tcl_Interp *interp){ 19206f8a503dSdanielk1977 extern int sqlite3_search_count; 19216f8a503dSdanielk1977 extern int sqlite3_interrupt_count; 19226f8a503dSdanielk1977 extern int sqlite3_open_file_count; 19236f8a503dSdanielk1977 extern int sqlite3_current_time; 1924c2eef3b3Sdrh static struct { 1925c2eef3b3Sdrh char *zName; 1926c2eef3b3Sdrh Tcl_CmdProc *xProc; 1927c2eef3b3Sdrh } aCmd[] = { 19286f8a503dSdanielk1977 { "sqlite3_mprintf_int", (Tcl_CmdProc*)sqlite3_mprintf_int }, 19296f8a503dSdanielk1977 { "sqlite3_mprintf_str", (Tcl_CmdProc*)sqlite3_mprintf_str }, 19306f8a503dSdanielk1977 { "sqlite3_mprintf_double", (Tcl_CmdProc*)sqlite3_mprintf_double }, 19316f8a503dSdanielk1977 { "sqlite3_mprintf_scaled", (Tcl_CmdProc*)sqlite3_mprintf_scaled }, 19326f8a503dSdanielk1977 { "sqlite3_mprintf_z_test", (Tcl_CmdProc*)test_mprintf_z }, 19336f8a503dSdanielk1977 { "sqlite3_last_insert_rowid", (Tcl_CmdProc*)test_last_rowid }, 19346f8a503dSdanielk1977 { "sqlite3_exec_printf", (Tcl_CmdProc*)test_exec_printf }, 19356f8a503dSdanielk1977 { "sqlite3_get_table_printf", (Tcl_CmdProc*)test_get_table_printf }, 19366f8a503dSdanielk1977 { "sqlite3_close", (Tcl_CmdProc*)sqlite_test_close }, 19376f8a503dSdanielk1977 { "sqlite3_create_function", (Tcl_CmdProc*)test_create_function }, 19386f8a503dSdanielk1977 { "sqlite3_create_aggregate", (Tcl_CmdProc*)test_create_aggregate }, 1939c2eef3b3Sdrh { "sqlite_register_test_function", (Tcl_CmdProc*)test_register_func }, 1940c2eef3b3Sdrh { "sqlite_abort", (Tcl_CmdProc*)sqlite_abort }, 1941faa57accSdrh #ifdef SQLITE_DEBUG 1942c2eef3b3Sdrh { "sqlite_malloc_fail", (Tcl_CmdProc*)sqlite_malloc_fail }, 1943c2eef3b3Sdrh { "sqlite_malloc_stat", (Tcl_CmdProc*)sqlite_malloc_stat }, 1944c2eef3b3Sdrh #endif 194596fc5fe6Sdanielk1977 { "sqlite_bind", (Tcl_CmdProc*)test_bind }, 194699ee3600Sdrh { "breakpoint", (Tcl_CmdProc*)test_breakpoint }, 1947c2eef3b3Sdrh }; 194851e3d8e2Sdanielk1977 static struct { 194951e3d8e2Sdanielk1977 char *zName; 195051e3d8e2Sdanielk1977 Tcl_ObjCmdProc *xProc; 195104f2e68dSdanielk1977 void *clientData; 195251e3d8e2Sdanielk1977 } aObjCmd[] = { 195304f2e68dSdanielk1977 { "sqlite3_bind_int32", test_bind_int32, 0 }, 195404f2e68dSdanielk1977 { "sqlite3_bind_int64", test_bind_int64 , 0 }, 195504f2e68dSdanielk1977 { "sqlite3_bind_double", test_bind_double, 0 }, 195604f2e68dSdanielk1977 { "sqlite3_bind_null", test_bind_null ,0 }, 195704f2e68dSdanielk1977 { "sqlite3_bind_text", test_bind_text ,0 }, 195804f2e68dSdanielk1977 { "sqlite3_bind_text16", test_bind_text16 ,0 }, 195904f2e68dSdanielk1977 { "sqlite3_bind_blob", test_bind_blob ,0 }, 196004f2e68dSdanielk1977 { "sqlite3_errcode", test_errcode ,0 }, 196104f2e68dSdanielk1977 { "sqlite3_errmsg", test_errmsg ,0 }, 196204f2e68dSdanielk1977 { "sqlite3_errmsg16", test_errmsg16 ,0 }, 196304f2e68dSdanielk1977 { "sqlite3_open", test_open ,0 }, 196404f2e68dSdanielk1977 { "sqlite3_open16", test_open16 ,0 }, 196504f2e68dSdanielk1977 196604f2e68dSdanielk1977 { "sqlite3_prepare", test_prepare ,0 }, 196704f2e68dSdanielk1977 { "sqlite3_prepare16", test_prepare16 ,0 }, 196804f2e68dSdanielk1977 { "sqlite3_finalize", test_finalize ,0 }, 196904f2e68dSdanielk1977 { "sqlite3_reset", test_reset ,0 }, 1970fbcd585fSdanielk1977 { "sqlite3_changes", test_changes ,0 }, 197104f2e68dSdanielk1977 { "sqlite3_step", test_step ,0 }, 197204f2e68dSdanielk1977 197304f2e68dSdanielk1977 /* sqlite3_column_*() API */ 197404f2e68dSdanielk1977 { "sqlite3_column_count", test_column_count ,0 }, 197504f2e68dSdanielk1977 { "sqlite3_data_count", test_data_count ,0 }, 197604f2e68dSdanielk1977 { "sqlite3_column_type", test_column_type ,0 }, 1977ea61b2c4Sdanielk1977 { "sqlite3_column_blob", test_column_blob ,0 }, 197804f2e68dSdanielk1977 { "sqlite3_column_double", test_column_double ,0 }, 197904f2e68dSdanielk1977 { "sqlite3_column_int64", test_column_int64 ,0 }, 198004f2e68dSdanielk1977 { "sqlite3_column_int", test_stmt_int ,sqlite3_column_int }, 198104f2e68dSdanielk1977 { "sqlite3_column_bytes", test_stmt_int ,sqlite3_column_bytes }, 198204f2e68dSdanielk1977 { "sqlite3_column_bytes16", test_stmt_int ,sqlite3_column_bytes16 }, 198304f2e68dSdanielk1977 { "sqlite3_column_text", test_stmt_utf8, sqlite3_column_text}, 198404f2e68dSdanielk1977 { "sqlite3_column_decltype", test_stmt_utf8, sqlite3_column_decltype}, 198504f2e68dSdanielk1977 { "sqlite3_column_name", test_stmt_utf8, sqlite3_column_name}, 198604f2e68dSdanielk1977 { "sqlite3_column_text16", test_stmt_utf16, sqlite3_column_text16}, 198704f2e68dSdanielk1977 { "sqlite3_column_decltype16", test_stmt_utf16,sqlite3_column_decltype16}, 198804f2e68dSdanielk1977 { "sqlite3_column_name16", test_stmt_utf16, sqlite3_column_name16}, 198904f2e68dSdanielk1977 19909a1d0abeSdanielk1977 /* Functions from os.h */ 19919a1d0abeSdanielk1977 { "sqlite3OsOpenReadWrite",test_sqlite3OsOpenReadWrite, 0 }, 19929a1d0abeSdanielk1977 { "sqlite3OsClose", test_sqlite3OsClose, 0 }, 19939a1d0abeSdanielk1977 { "sqlite3OsLock", test_sqlite3OsLock, 0 }, 19949a1d0abeSdanielk1977 { "sqlite3OsUnlock", test_sqlite3OsUnlock, 0 }, 19954e6af134Sdanielk1977 { "add_test_collate", test_collate, 0 }, 19969a1d0abeSdanielk1977 199751e3d8e2Sdanielk1977 }; 1998c2eef3b3Sdrh int i; 19992ac3ee97Sdrh extern int sqlite3_os_trace; 2000c2eef3b3Sdrh 2001c2eef3b3Sdrh for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){ 2002c2eef3b3Sdrh Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0); 2003c2eef3b3Sdrh } 200451e3d8e2Sdanielk1977 for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){ 2005c572ef7fSdanielk1977 Tcl_CreateObjCommand(interp, aObjCmd[i].zName, 2006c572ef7fSdanielk1977 aObjCmd[i].xProc, aObjCmd[i].clientData, 0); 200751e3d8e2Sdanielk1977 } 20086490bebdSdanielk1977 Tcl_LinkVar(interp, "sqlite_search_count", 20096f8a503dSdanielk1977 (char*)&sqlite3_search_count, TCL_LINK_INT); 20106490bebdSdanielk1977 Tcl_LinkVar(interp, "sqlite_interrupt_count", 20116f8a503dSdanielk1977 (char*)&sqlite3_interrupt_count, TCL_LINK_INT); 20126490bebdSdanielk1977 Tcl_LinkVar(interp, "sqlite_open_file_count", 20136f8a503dSdanielk1977 (char*)&sqlite3_open_file_count, TCL_LINK_INT); 20146490bebdSdanielk1977 Tcl_LinkVar(interp, "sqlite_current_time", 20156f8a503dSdanielk1977 (char*)&sqlite3_current_time, TCL_LINK_INT); 20162ac3ee97Sdrh Tcl_LinkVar(interp, "sqlite_os_trace", 20172ac3ee97Sdrh (char*)&sqlite3_os_trace, TCL_LINK_INT); 20187c972decSdrh Tcl_LinkVar(interp, "sqlite_static_bind_value", 20197c972decSdrh (char*)&sqlite_static_bind_value, TCL_LINK_STRING); 2020d1bf3512Sdrh return TCL_OK; 2021d1bf3512Sdrh } 2022