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*8a6c550dSdanielk1977 ** $Id: test1.c,v 1.81 2004/06/22 12:18:32 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; 32696d81f99Sdanielk1977 int rc; 327d1bf3512Sdrh if( argc!=2 ){ 328d1bf3512Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 329d1bf3512Sdrh " FILENAME\"", 0); 330d1bf3512Sdrh return TCL_ERROR; 331d1bf3512Sdrh } 332b86ccfb2Sdrh if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; 33396d81f99Sdanielk1977 rc = sqlite3_close(db); 334f9d64d2cSdanielk1977 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC); 335d1bf3512Sdrh return TCL_OK; 336d1bf3512Sdrh } 337d1bf3512Sdrh 338d1bf3512Sdrh /* 339c22bd47dSdrh ** Implementation of the x_coalesce() function. 340c22bd47dSdrh ** Return the first argument non-NULL argument. 341c22bd47dSdrh */ 3420ae8b831Sdanielk1977 static void ifnullFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ 343c22bd47dSdrh int i; 344c22bd47dSdrh for(i=0; i<argc; i++){ 3459c054830Sdrh if( SQLITE_NULL!=sqlite3_value_type(argv[i]) ){ 346d8123366Sdanielk1977 sqlite3_result_text(context, sqlite3_value_text(argv[i]), -1, 347d8123366Sdanielk1977 SQLITE_TRANSIENT); 348c22bd47dSdrh break; 349c22bd47dSdrh } 350c22bd47dSdrh } 351c22bd47dSdrh } 352c22bd47dSdrh 353c22bd47dSdrh /* 354d1d9fc33Sdrh ** A structure into which to accumulate text. 355d1d9fc33Sdrh */ 356d1d9fc33Sdrh struct dstr { 357d1d9fc33Sdrh int nAlloc; /* Space allocated */ 358d1d9fc33Sdrh int nUsed; /* Space used */ 359d1d9fc33Sdrh char *z; /* The space */ 360d1d9fc33Sdrh }; 361d1d9fc33Sdrh 362d1d9fc33Sdrh /* 363d1d9fc33Sdrh ** Append text to a dstr 364d1d9fc33Sdrh */ 365d1d9fc33Sdrh static void dstrAppend(struct dstr *p, const char *z, int divider){ 366d1d9fc33Sdrh int n = strlen(z); 367d1d9fc33Sdrh if( p->nUsed + n + 2 > p->nAlloc ){ 368d1d9fc33Sdrh char *zNew; 369d1d9fc33Sdrh p->nAlloc = p->nAlloc*2 + n + 200; 370d1d9fc33Sdrh zNew = sqliteRealloc(p->z, p->nAlloc); 371d1d9fc33Sdrh if( zNew==0 ){ 372d1d9fc33Sdrh sqliteFree(p->z); 373d1d9fc33Sdrh memset(p, 0, sizeof(*p)); 374d1d9fc33Sdrh return; 375d1d9fc33Sdrh } 376d1d9fc33Sdrh p->z = zNew; 377d1d9fc33Sdrh } 378d1d9fc33Sdrh if( divider && p->nUsed>0 ){ 379d1d9fc33Sdrh p->z[p->nUsed++] = divider; 380d1d9fc33Sdrh } 381d1d9fc33Sdrh memcpy(&p->z[p->nUsed], z, n+1); 382d1d9fc33Sdrh p->nUsed += n; 383d1d9fc33Sdrh } 384d1d9fc33Sdrh 385d1d9fc33Sdrh /* 3864adee20fSdanielk1977 ** Invoked for each callback from sqlite3ExecFunc 387d1d9fc33Sdrh */ 388d1d9fc33Sdrh static int execFuncCallback(void *pData, int argc, char **argv, char **NotUsed){ 389d1d9fc33Sdrh struct dstr *p = (struct dstr*)pData; 390d1d9fc33Sdrh int i; 391d1d9fc33Sdrh for(i=0; i<argc; i++){ 392d1d9fc33Sdrh if( argv[i]==0 ){ 393d1d9fc33Sdrh dstrAppend(p, "NULL", ' '); 394d1d9fc33Sdrh }else{ 395d1d9fc33Sdrh dstrAppend(p, argv[i], ' '); 396d1d9fc33Sdrh } 397d1d9fc33Sdrh } 398d1d9fc33Sdrh return 0; 399d1d9fc33Sdrh } 400d1d9fc33Sdrh 401d1d9fc33Sdrh /* 4026f8a503dSdanielk1977 ** Implementation of the x_sqlite3_exec() function. This function takes 403c22bd47dSdrh ** a single argument and attempts to execute that argument as SQL code. 4046cbe1f1bSdrh ** This is illegal and should set the SQLITE_MISUSE flag on the database. 405c22bd47dSdrh ** 4066f8a503dSdanielk1977 ** 2004-Jan-07: We have changed this to make it legal to call sqlite3_exec() 407d1d9fc33Sdrh ** from within a function call. 408d1d9fc33Sdrh ** 409c22bd47dSdrh ** This routine simulates the effect of having two threads attempt to 410c22bd47dSdrh ** use the same database at the same time. 411c22bd47dSdrh */ 41251ad0ecdSdanielk1977 static void sqlite3ExecFunc( 4130ae8b831Sdanielk1977 sqlite3_context *context, 41451ad0ecdSdanielk1977 int argc, 41551ad0ecdSdanielk1977 sqlite3_value **argv 41651ad0ecdSdanielk1977 ){ 417d1d9fc33Sdrh struct dstr x; 418d1d9fc33Sdrh memset(&x, 0, sizeof(x)); 41951ad0ecdSdanielk1977 sqlite3_exec((sqlite*)sqlite3_user_data(context), 4204f26d6c4Sdrh sqlite3_value_text(argv[0]), 421d1d9fc33Sdrh execFuncCallback, &x, 0); 422d8123366Sdanielk1977 sqlite3_result_text(context, x.z, x.nUsed, SQLITE_TRANSIENT); 423d1d9fc33Sdrh sqliteFree(x.z); 424c22bd47dSdrh } 425c22bd47dSdrh 426c22bd47dSdrh /* 427c22bd47dSdrh ** Usage: sqlite_test_create_function DB 428c22bd47dSdrh ** 4296f8a503dSdanielk1977 ** Call the sqlite3_create_function API on the given database in order 430c22bd47dSdrh ** to create a function named "x_coalesce". This function does the same thing 431c22bd47dSdrh ** as the "coalesce" function. This function also registers an SQL function 4326f8a503dSdanielk1977 ** named "x_sqlite3_exec" that invokes sqlite3_exec(). Invoking sqlite3_exec() 433c22bd47dSdrh ** in this way is illegal recursion and should raise an SQLITE_MISUSE error. 434c22bd47dSdrh ** The effect is similar to trying to use the same database connection from 435c22bd47dSdrh ** two threads at the same time. 436c22bd47dSdrh ** 437c22bd47dSdrh ** The original motivation for this routine was to be able to call the 4386f8a503dSdanielk1977 ** sqlite3_create_function function while a query is in progress in order 439c22bd47dSdrh ** to test the SQLITE_MISUSE detection logic. 440c22bd47dSdrh */ 441c2eef3b3Sdrh static int test_create_function( 442c22bd47dSdrh void *NotUsed, 443c22bd47dSdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 444c22bd47dSdrh int argc, /* Number of arguments */ 445c22bd47dSdrh char **argv /* Text of each argument */ 446c22bd47dSdrh ){ 447c22bd47dSdrh sqlite *db; 448c22bd47dSdrh extern void Md5_Register(sqlite*); 449c22bd47dSdrh if( argc!=2 ){ 450c22bd47dSdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 451c22bd47dSdrh " FILENAME\"", 0); 452c22bd47dSdrh return TCL_ERROR; 453c22bd47dSdrh } 454b86ccfb2Sdrh if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; 455f9d64d2cSdanielk1977 sqlite3_create_function(db, "x_coalesce", -1, SQLITE_UTF8, 0, 456d8123366Sdanielk1977 ifnullFunc, 0, 0); 457f9d64d2cSdanielk1977 sqlite3_create_function(db, "x_sqlite3_exec", 1, SQLITE_UTF8, db, 4586590493dSdanielk1977 sqlite3ExecFunc, 0, 0); 459c22bd47dSdrh return TCL_OK; 460c22bd47dSdrh } 461c22bd47dSdrh 462c22bd47dSdrh /* 463c22bd47dSdrh ** Routines to implement the x_count() aggregate function. 464c22bd47dSdrh */ 465c22bd47dSdrh typedef struct CountCtx CountCtx; 466c22bd47dSdrh struct CountCtx { 467c22bd47dSdrh int n; 468c22bd47dSdrh }; 4690ae8b831Sdanielk1977 static void countStep(sqlite3_context *context, int argc, sqlite3_value **argv){ 470c22bd47dSdrh CountCtx *p; 4714f26d6c4Sdrh p = sqlite3_aggregate_context(context, sizeof(*p)); 4729c054830Sdrh if( (argc==0 || SQLITE_NULL!=sqlite3_value_type(argv[0]) ) && p ){ 473c22bd47dSdrh p->n++; 474c22bd47dSdrh } 475c22bd47dSdrh } 4760ae8b831Sdanielk1977 static void countFinalize(sqlite3_context *context){ 477c22bd47dSdrh CountCtx *p; 4784f26d6c4Sdrh p = sqlite3_aggregate_context(context, sizeof(*p)); 479c572ef7fSdanielk1977 sqlite3_result_int(context, p ? p->n : 0); 480c22bd47dSdrh } 481c22bd47dSdrh 482c22bd47dSdrh /* 483c22bd47dSdrh ** Usage: sqlite_test_create_aggregate DB 484c22bd47dSdrh ** 4856f8a503dSdanielk1977 ** Call the sqlite3_create_function API on the given database in order 486c22bd47dSdrh ** to create a function named "x_count". This function does the same thing 487c22bd47dSdrh ** as the "md5sum" function. 488c22bd47dSdrh ** 489c22bd47dSdrh ** The original motivation for this routine was to be able to call the 4906f8a503dSdanielk1977 ** sqlite3_create_aggregate function while a query is in progress in order 491c22bd47dSdrh ** to test the SQLITE_MISUSE detection logic. 492c22bd47dSdrh */ 493c2eef3b3Sdrh static int test_create_aggregate( 494c22bd47dSdrh void *NotUsed, 495c22bd47dSdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 496c22bd47dSdrh int argc, /* Number of arguments */ 497c22bd47dSdrh char **argv /* Text of each argument */ 498c22bd47dSdrh ){ 499c22bd47dSdrh sqlite *db; 500c22bd47dSdrh if( argc!=2 ){ 501c22bd47dSdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 502c22bd47dSdrh " FILENAME\"", 0); 503c22bd47dSdrh return TCL_ERROR; 504c22bd47dSdrh } 505b86ccfb2Sdrh if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; 506f9d64d2cSdanielk1977 sqlite3_create_function(db, "x_count", 0, SQLITE_UTF8, 0, 0, 507d8123366Sdanielk1977 countStep,countFinalize); 508f9d64d2cSdanielk1977 sqlite3_create_function(db, "x_count", 1, SQLITE_UTF8, 0, 0, 509d8123366Sdanielk1977 countStep,countFinalize); 510c22bd47dSdrh return TCL_OK; 511c22bd47dSdrh } 512c22bd47dSdrh 513c22bd47dSdrh 514c22bd47dSdrh 515c22bd47dSdrh /* 5166f8a503dSdanielk1977 ** Usage: sqlite3_mprintf_int FORMAT INTEGER INTEGER INTEGER 517d1bf3512Sdrh ** 518d1bf3512Sdrh ** Call mprintf with three integer arguments 519d1bf3512Sdrh */ 5206f8a503dSdanielk1977 static int sqlite3_mprintf_int( 521d1bf3512Sdrh void *NotUsed, 522d1bf3512Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 523d1bf3512Sdrh int argc, /* Number of arguments */ 524d1bf3512Sdrh char **argv /* Text of each argument */ 525d1bf3512Sdrh ){ 526d1bf3512Sdrh int a[3], i; 527d1bf3512Sdrh char *z; 528d1bf3512Sdrh if( argc!=5 ){ 529d1bf3512Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 530d1bf3512Sdrh " FORMAT INT INT INT\"", 0); 531d1bf3512Sdrh return TCL_ERROR; 532d1bf3512Sdrh } 533d1bf3512Sdrh for(i=2; i<5; i++){ 534d1bf3512Sdrh if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR; 535d1bf3512Sdrh } 5366f8a503dSdanielk1977 z = sqlite3_mprintf(argv[1], a[0], a[1], a[2]); 537d1bf3512Sdrh Tcl_AppendResult(interp, z, 0); 5383f4fedb2Sdrh sqlite3_free(z); 539d1bf3512Sdrh return TCL_OK; 540d1bf3512Sdrh } 541d1bf3512Sdrh 542d1bf3512Sdrh /* 5436f8a503dSdanielk1977 ** Usage: sqlite3_mprintf_str FORMAT INTEGER INTEGER STRING 544d1bf3512Sdrh ** 545d1bf3512Sdrh ** Call mprintf with two integer arguments and one string argument 546d1bf3512Sdrh */ 5476f8a503dSdanielk1977 static int sqlite3_mprintf_str( 548d1bf3512Sdrh void *NotUsed, 549d1bf3512Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 550d1bf3512Sdrh int argc, /* Number of arguments */ 551d1bf3512Sdrh char **argv /* Text of each argument */ 552d1bf3512Sdrh ){ 553d1bf3512Sdrh int a[3], i; 554d1bf3512Sdrh char *z; 555f220b24fSchw if( argc<4 || argc>5 ){ 556d1bf3512Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 557f220b24fSchw " FORMAT INT INT ?STRING?\"", 0); 558d1bf3512Sdrh return TCL_ERROR; 559d1bf3512Sdrh } 560d1bf3512Sdrh for(i=2; i<4; i++){ 561d1bf3512Sdrh if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR; 562d1bf3512Sdrh } 5636f8a503dSdanielk1977 z = sqlite3_mprintf(argv[1], a[0], a[1], argc>4 ? argv[4] : NULL); 564d1bf3512Sdrh Tcl_AppendResult(interp, z, 0); 5653f4fedb2Sdrh sqlite3_free(z); 566d1bf3512Sdrh return TCL_OK; 567d1bf3512Sdrh } 568d1bf3512Sdrh 569d1bf3512Sdrh /* 5706f8a503dSdanielk1977 ** Usage: sqlite3_mprintf_str FORMAT INTEGER INTEGER DOUBLE 571d1bf3512Sdrh ** 572d1bf3512Sdrh ** Call mprintf with two integer arguments and one double argument 573d1bf3512Sdrh */ 5746f8a503dSdanielk1977 static int sqlite3_mprintf_double( 575d1bf3512Sdrh void *NotUsed, 576d1bf3512Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 577d1bf3512Sdrh int argc, /* Number of arguments */ 578d1bf3512Sdrh char **argv /* Text of each argument */ 579d1bf3512Sdrh ){ 580d1bf3512Sdrh int a[3], i; 581d1bf3512Sdrh double r; 582d1bf3512Sdrh char *z; 583d1bf3512Sdrh if( argc!=5 ){ 584d1bf3512Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 585d1bf3512Sdrh " FORMAT INT INT STRING\"", 0); 586d1bf3512Sdrh return TCL_ERROR; 587d1bf3512Sdrh } 588d1bf3512Sdrh for(i=2; i<4; i++){ 589d1bf3512Sdrh if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR; 590d1bf3512Sdrh } 591d1bf3512Sdrh if( Tcl_GetDouble(interp, argv[4], &r) ) return TCL_ERROR; 5926f8a503dSdanielk1977 z = sqlite3_mprintf(argv[1], a[0], a[1], r); 593d1bf3512Sdrh Tcl_AppendResult(interp, z, 0); 5943f4fedb2Sdrh sqlite3_free(z); 595d1bf3512Sdrh return TCL_OK; 596d1bf3512Sdrh } 597d1bf3512Sdrh 598d1bf3512Sdrh /* 5996f8a503dSdanielk1977 ** Usage: sqlite3_mprintf_str FORMAT DOUBLE DOUBLE 600b621c237Sdrh ** 601b621c237Sdrh ** Call mprintf with a single double argument which is the product of the 602b621c237Sdrh ** two arguments given above. This is used to generate overflow and underflow 603b621c237Sdrh ** doubles to test that they are converted properly. 604b621c237Sdrh */ 6056f8a503dSdanielk1977 static int sqlite3_mprintf_scaled( 606b621c237Sdrh void *NotUsed, 607b621c237Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 608b621c237Sdrh int argc, /* Number of arguments */ 609b621c237Sdrh char **argv /* Text of each argument */ 610b621c237Sdrh ){ 611b621c237Sdrh int i; 612b621c237Sdrh double r[2]; 613b621c237Sdrh char *z; 614b621c237Sdrh if( argc!=4 ){ 615b621c237Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 616b621c237Sdrh " FORMAT DOUBLE DOUBLE\"", 0); 617b621c237Sdrh return TCL_ERROR; 618b621c237Sdrh } 619b621c237Sdrh for(i=2; i<4; i++){ 620b621c237Sdrh if( Tcl_GetDouble(interp, argv[i], &r[i-2]) ) return TCL_ERROR; 621b621c237Sdrh } 6226f8a503dSdanielk1977 z = sqlite3_mprintf(argv[1], r[0]*r[1]); 623b621c237Sdrh Tcl_AppendResult(interp, z, 0); 6243f4fedb2Sdrh sqlite3_free(z); 625b621c237Sdrh return TCL_OK; 626b621c237Sdrh } 627b621c237Sdrh 628b621c237Sdrh /* 629daffd0e5Sdrh ** Usage: sqlite_malloc_fail N 630daffd0e5Sdrh ** 631afa4a020Sdrh ** Rig sqliteMalloc() to fail on the N-th call. Turn off this mechanism 6326f8a503dSdanielk1977 ** and reset the sqlite3_malloc_failed variable is N==0. 633daffd0e5Sdrh */ 634faa57accSdrh #ifdef SQLITE_DEBUG 635daffd0e5Sdrh static int sqlite_malloc_fail( 636daffd0e5Sdrh void *NotUsed, 637daffd0e5Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 638daffd0e5Sdrh int argc, /* Number of arguments */ 639daffd0e5Sdrh char **argv /* Text of each argument */ 640daffd0e5Sdrh ){ 641daffd0e5Sdrh int n; 642daffd0e5Sdrh if( argc!=2 ){ 643daffd0e5Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " N\"", 0); 644daffd0e5Sdrh return TCL_ERROR; 645daffd0e5Sdrh } 646daffd0e5Sdrh if( Tcl_GetInt(interp, argv[1], &n) ) return TCL_ERROR; 6476f8a503dSdanielk1977 sqlite3_iMallocFail = n; 6486f8a503dSdanielk1977 sqlite3_malloc_failed = 0; 649daffd0e5Sdrh return TCL_OK; 650daffd0e5Sdrh } 651daffd0e5Sdrh #endif 652daffd0e5Sdrh 653daffd0e5Sdrh /* 654daffd0e5Sdrh ** Usage: sqlite_malloc_stat 655daffd0e5Sdrh ** 656daffd0e5Sdrh ** Return the number of prior calls to sqliteMalloc() and sqliteFree(). 657daffd0e5Sdrh */ 658faa57accSdrh #ifdef SQLITE_DEBUG 659daffd0e5Sdrh static int sqlite_malloc_stat( 660daffd0e5Sdrh void *NotUsed, 661daffd0e5Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 662daffd0e5Sdrh int argc, /* Number of arguments */ 663daffd0e5Sdrh char **argv /* Text of each argument */ 664daffd0e5Sdrh ){ 665daffd0e5Sdrh char zBuf[200]; 6666f8a503dSdanielk1977 sprintf(zBuf, "%d %d %d", sqlite3_nMalloc, sqlite3_nFree, sqlite3_iMallocFail); 667daffd0e5Sdrh Tcl_AppendResult(interp, zBuf, 0); 668daffd0e5Sdrh return TCL_OK; 669daffd0e5Sdrh } 670daffd0e5Sdrh #endif 671daffd0e5Sdrh 672daffd0e5Sdrh /* 67328b4e489Sdrh ** Usage: sqlite_abort 67428b4e489Sdrh ** 67528b4e489Sdrh ** Shutdown the process immediately. This is not a clean shutdown. 67628b4e489Sdrh ** This command is used to test the recoverability of a database in 67728b4e489Sdrh ** the event of a program crash. 67828b4e489Sdrh */ 67928b4e489Sdrh static int sqlite_abort( 68028b4e489Sdrh void *NotUsed, 68128b4e489Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 68228b4e489Sdrh int argc, /* Number of arguments */ 68328b4e489Sdrh char **argv /* Text of each argument */ 68428b4e489Sdrh ){ 68528b4e489Sdrh assert( interp==0 ); /* This will always fail */ 68628b4e489Sdrh return TCL_OK; 68728b4e489Sdrh } 68828b4e489Sdrh 68928b4e489Sdrh /* 6906cbe1f1bSdrh ** The following routine is a user-defined SQL function whose purpose 6916cbe1f1bSdrh ** is to test the sqlite_set_result() API. 6926cbe1f1bSdrh */ 6930ae8b831Sdanielk1977 static void testFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ 6946cbe1f1bSdrh while( argc>=2 ){ 6954f26d6c4Sdrh const char *zArg0 = sqlite3_value_text(argv[0]); 6966d88bad4Sdanielk1977 if( zArg0 ){ 6976d88bad4Sdanielk1977 if( 0==sqlite3StrICmp(zArg0, "int") ){ 6986d88bad4Sdanielk1977 sqlite3_result_int(context, sqlite3_value_int(argv[1])); 6996d88bad4Sdanielk1977 }else if( sqlite3StrICmp(zArg0,"int64")==0 ){ 7006d88bad4Sdanielk1977 sqlite3_result_int64(context, sqlite3_value_int64(argv[1])); 70151ad0ecdSdanielk1977 }else if( sqlite3StrICmp(zArg0,"string")==0 ){ 702d8123366Sdanielk1977 sqlite3_result_text(context, sqlite3_value_text(argv[1]), -1, 703d8123366Sdanielk1977 SQLITE_TRANSIENT); 70451ad0ecdSdanielk1977 }else if( sqlite3StrICmp(zArg0,"double")==0 ){ 7056d88bad4Sdanielk1977 sqlite3_result_double(context, sqlite3_value_double(argv[1])); 7066d88bad4Sdanielk1977 }else if( sqlite3StrICmp(zArg0,"null")==0 ){ 7076d88bad4Sdanielk1977 sqlite3_result_null(context); 7086d88bad4Sdanielk1977 }else if( sqlite3StrICmp(zArg0,"value")==0 ){ 7096d88bad4Sdanielk1977 sqlite3_result_value(context, argv[sqlite3_value_int(argv[1])]); 7106cbe1f1bSdrh }else{ 7116d88bad4Sdanielk1977 goto error_out; 7126d88bad4Sdanielk1977 } 7136d88bad4Sdanielk1977 }else{ 7146d88bad4Sdanielk1977 goto error_out; 7156cbe1f1bSdrh } 7166cbe1f1bSdrh argc -= 2; 7176cbe1f1bSdrh argv += 2; 7186cbe1f1bSdrh } 7196d88bad4Sdanielk1977 return; 7206d88bad4Sdanielk1977 7216d88bad4Sdanielk1977 error_out: 7226d88bad4Sdanielk1977 sqlite3_result_error(context,"first argument should be one of: " 7236d88bad4Sdanielk1977 "int int64 string double null value", -1); 7246cbe1f1bSdrh } 7256cbe1f1bSdrh 7266cbe1f1bSdrh /* 7276cbe1f1bSdrh ** Usage: sqlite_register_test_function DB NAME 7286cbe1f1bSdrh ** 7296cbe1f1bSdrh ** Register the test SQL function on the database DB under the name NAME. 7306cbe1f1bSdrh */ 731c2eef3b3Sdrh static int test_register_func( 7326cbe1f1bSdrh void *NotUsed, 7336cbe1f1bSdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 7346cbe1f1bSdrh int argc, /* Number of arguments */ 7356cbe1f1bSdrh char **argv /* Text of each argument */ 7366cbe1f1bSdrh ){ 7376cbe1f1bSdrh sqlite *db; 7386cbe1f1bSdrh int rc; 7396cbe1f1bSdrh if( argc!=3 ){ 7406cbe1f1bSdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 7416cbe1f1bSdrh " DB FUNCTION-NAME", 0); 7426cbe1f1bSdrh return TCL_ERROR; 7436cbe1f1bSdrh } 744b86ccfb2Sdrh if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; 745f9d64d2cSdanielk1977 rc = sqlite3_create_function(db, argv[2], -1, SQLITE_UTF8, 0, 746d8123366Sdanielk1977 testFunc, 0, 0); 7476cbe1f1bSdrh if( rc!=0 ){ 748f20b21c8Sdanielk1977 Tcl_AppendResult(interp, sqlite3ErrStr(rc), 0); 7496cbe1f1bSdrh return TCL_ERROR; 7506cbe1f1bSdrh } 7516cbe1f1bSdrh return TCL_OK; 7526cbe1f1bSdrh } 7536cbe1f1bSdrh 7546cbe1f1bSdrh /* 755106bb236Sdanielk1977 ** Usage: sqlite3_finalize STMT 756b86ccfb2Sdrh ** 757106bb236Sdanielk1977 ** Finalize a statement handle. 758b86ccfb2Sdrh */ 759b86ccfb2Sdrh static int test_finalize( 760106bb236Sdanielk1977 void * clientData, 761106bb236Sdanielk1977 Tcl_Interp *interp, 762106bb236Sdanielk1977 int objc, 763106bb236Sdanielk1977 Tcl_Obj *CONST objv[] 764b86ccfb2Sdrh ){ 765106bb236Sdanielk1977 sqlite3_stmt *pStmt; 766b86ccfb2Sdrh int rc; 767106bb236Sdanielk1977 768106bb236Sdanielk1977 if( objc!=2 ){ 769106bb236Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 770106bb236Sdanielk1977 Tcl_GetStringFromObj(objv[0], 0), " <STMT>", 0); 771b86ccfb2Sdrh return TCL_ERROR; 772b86ccfb2Sdrh } 773106bb236Sdanielk1977 774106bb236Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 775106bb236Sdanielk1977 776fc57d7bfSdanielk1977 rc = sqlite3_finalize(pStmt); 777b77f5dadSdanielk1977 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC); 778106bb236Sdanielk1977 return TCL_OK; 779106bb236Sdanielk1977 } 780106bb236Sdanielk1977 781106bb236Sdanielk1977 /* 782106bb236Sdanielk1977 ** Usage: sqlite3_reset STMT 783106bb236Sdanielk1977 ** 784106bb236Sdanielk1977 ** Finalize a statement handle. 785106bb236Sdanielk1977 */ 786106bb236Sdanielk1977 static int test_reset( 787106bb236Sdanielk1977 void * clientData, 788106bb236Sdanielk1977 Tcl_Interp *interp, 789106bb236Sdanielk1977 int objc, 790106bb236Sdanielk1977 Tcl_Obj *CONST objv[] 791106bb236Sdanielk1977 ){ 792106bb236Sdanielk1977 sqlite3_stmt *pStmt; 793106bb236Sdanielk1977 int rc; 794106bb236Sdanielk1977 795106bb236Sdanielk1977 if( objc!=2 ){ 796106bb236Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 797106bb236Sdanielk1977 Tcl_GetStringFromObj(objv[0], 0), " <STMT>", 0); 798106bb236Sdanielk1977 return TCL_ERROR; 799106bb236Sdanielk1977 } 800106bb236Sdanielk1977 801106bb236Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 802106bb236Sdanielk1977 803fc57d7bfSdanielk1977 rc = sqlite3_reset(pStmt); 804106bb236Sdanielk1977 if( rc ){ 805b86ccfb2Sdrh return TCL_ERROR; 806b86ccfb2Sdrh } 807b86ccfb2Sdrh return TCL_OK; 808b86ccfb2Sdrh } 809b86ccfb2Sdrh 8105a38705eSdrh /* 811fbcd585fSdanielk1977 ** Usage: sqlite3_changes DB 81250457896Sdrh ** 813fbcd585fSdanielk1977 ** Return the number of changes made to the database by the last SQL 814fbcd585fSdanielk1977 ** execution. 81550457896Sdrh */ 816fbcd585fSdanielk1977 static int test_changes( 817fbcd585fSdanielk1977 void * clientData, 818fbcd585fSdanielk1977 Tcl_Interp *interp, 819fbcd585fSdanielk1977 int objc, 820fbcd585fSdanielk1977 Tcl_Obj *CONST objv[] 821fbcd585fSdanielk1977 ){ 822fbcd585fSdanielk1977 sqlite3 *db; 823fbcd585fSdanielk1977 if( objc!=2 ){ 824fbcd585fSdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 825fbcd585fSdanielk1977 Tcl_GetString(objv[0]), " DB", 0); 826fbcd585fSdanielk1977 return TCL_ERROR; 827fbcd585fSdanielk1977 } 828fbcd585fSdanielk1977 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 829fbcd585fSdanielk1977 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_changes(db))); 830fbcd585fSdanielk1977 return TCL_OK; 831fbcd585fSdanielk1977 } 83250457896Sdrh 83350457896Sdrh /* 8347c972decSdrh ** This is the "static_bind_value" that variables are bound to when 8356f8a503dSdanielk1977 ** the FLAG option of sqlite3_bind is "static" 83650457896Sdrh */ 8377c972decSdrh static char *sqlite_static_bind_value = 0; 8387c972decSdrh 8397c972decSdrh /* 8406f8a503dSdanielk1977 ** Usage: sqlite3_bind VM IDX VALUE FLAGS 8417c972decSdrh ** 8427c972decSdrh ** Sets the value of the IDX-th occurance of "?" in the original SQL 8437c972decSdrh ** string. VALUE is the new value. If FLAGS=="null" then VALUE is 8447c972decSdrh ** ignored and the value is set to NULL. If FLAGS=="static" then 8457c972decSdrh ** the value is set to the value of a static variable named 8467c972decSdrh ** "sqlite_static_bind_value". If FLAGS=="normal" then a copy 8477c972decSdrh ** of the VALUE is made. 8487c972decSdrh */ 8497c972decSdrh static int test_bind( 85050457896Sdrh void *NotUsed, 85150457896Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 85250457896Sdrh int argc, /* Number of arguments */ 85350457896Sdrh char **argv /* Text of each argument */ 85450457896Sdrh ){ 855fc57d7bfSdanielk1977 sqlite3_stmt *pStmt; 85650457896Sdrh int rc; 8577c972decSdrh int idx; 8587c972decSdrh if( argc!=5 ){ 85950457896Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 8607c972decSdrh " VM IDX VALUE (null|static|normal)\"", 0); 86150457896Sdrh return TCL_ERROR; 86250457896Sdrh } 863fc57d7bfSdanielk1977 if( getStmtPointer(interp, argv[1], &pStmt) ) return TCL_ERROR; 8647c972decSdrh if( Tcl_GetInt(interp, argv[2], &idx) ) return TCL_ERROR; 8657c972decSdrh if( strcmp(argv[4],"null")==0 ){ 866fc57d7bfSdanielk1977 rc = sqlite3_bind_null(pStmt, idx); 8677c972decSdrh }else if( strcmp(argv[4],"static")==0 ){ 868fc57d7bfSdanielk1977 rc = sqlite3_bind_text(pStmt, idx, sqlite_static_bind_value, -1, 0); 8697c972decSdrh }else if( strcmp(argv[4],"normal")==0 ){ 870d8123366Sdanielk1977 rc = sqlite3_bind_text(pStmt, idx, argv[3], -1, SQLITE_TRANSIENT); 8717c972decSdrh }else{ 8727c972decSdrh Tcl_AppendResult(interp, "4th argument should be " 8737c972decSdrh "\"null\" or \"static\" or \"normal\"", 0); 8747c972decSdrh return TCL_ERROR; 8757c972decSdrh } 87650457896Sdrh if( rc ){ 87750457896Sdrh char zBuf[50]; 87850457896Sdrh sprintf(zBuf, "(%d) ", rc); 879f20b21c8Sdanielk1977 Tcl_AppendResult(interp, zBuf, sqlite3ErrStr(rc), 0); 88050457896Sdrh return TCL_ERROR; 88150457896Sdrh } 88250457896Sdrh return TCL_OK; 88350457896Sdrh } 88450457896Sdrh 8854e6af134Sdanielk1977 8864e6af134Sdanielk1977 /* 8874e6af134Sdanielk1977 ** Usage: add_test_collate <db ptr> <utf8> <utf16le> <utf16be> 8884e6af134Sdanielk1977 ** 8894e6af134Sdanielk1977 ** This function is used to test that SQLite selects the correct collation 8904e6af134Sdanielk1977 ** sequence callback when multiple versions (for different text encodings) 8914e6af134Sdanielk1977 ** are available. 8924e6af134Sdanielk1977 ** 8934e6af134Sdanielk1977 ** Calling this routine registers the collation sequence "test_collate" 8944e6af134Sdanielk1977 ** with database handle <db>. The second argument must be a list of three 8954e6af134Sdanielk1977 ** boolean values. If the first is true, then a version of test_collate is 8964e6af134Sdanielk1977 ** registered for UTF-8, if the second is true, a version is registered for 8974e6af134Sdanielk1977 ** UTF-16le, if the third is true, a UTF-16be version is available. 8984e6af134Sdanielk1977 ** Previous versions of test_collate are deleted. 8994e6af134Sdanielk1977 ** 9004e6af134Sdanielk1977 ** The collation sequence test_collate is implemented by calling the 9014e6af134Sdanielk1977 ** following TCL script: 9024e6af134Sdanielk1977 ** 9034e6af134Sdanielk1977 ** "test_collate <enc> <lhs> <rhs>" 9044e6af134Sdanielk1977 ** 9054e6af134Sdanielk1977 ** The <lhs> and <rhs> are the two values being compared, encoded in UTF-8. 9064e6af134Sdanielk1977 ** The <enc> parameter is the encoding of the collation function that 9074e6af134Sdanielk1977 ** SQLite selected to call. The TCL test script implements the 9084e6af134Sdanielk1977 ** "test_collate" proc. 9094e6af134Sdanielk1977 ** 9104e6af134Sdanielk1977 ** Note that this will only work with one intepreter at a time, as the 9114e6af134Sdanielk1977 ** interp pointer to use when evaluating the TCL script is stored in 9124e6af134Sdanielk1977 ** pTestCollateInterp. 9134e6af134Sdanielk1977 */ 9144e6af134Sdanielk1977 static Tcl_Interp* pTestCollateInterp; 9154e6af134Sdanielk1977 static int test_collate_func( 9164e6af134Sdanielk1977 void *pCtx, 9174e6af134Sdanielk1977 int nA, const void *zA, 9184e6af134Sdanielk1977 int nB, const void *zB 9194e6af134Sdanielk1977 ){ 9204e6af134Sdanielk1977 Tcl_Interp *i = pTestCollateInterp; 9214e6af134Sdanielk1977 int encin = (int)pCtx; 9224e6af134Sdanielk1977 int res; 9234e6af134Sdanielk1977 9244e6af134Sdanielk1977 sqlite3_value *pVal; 9254e6af134Sdanielk1977 Tcl_Obj *pX; 9264e6af134Sdanielk1977 9274e6af134Sdanielk1977 pX = Tcl_NewStringObj("test_collate", -1); 9284e6af134Sdanielk1977 Tcl_IncrRefCount(pX); 9294e6af134Sdanielk1977 9304e6af134Sdanielk1977 switch( encin ){ 9314e6af134Sdanielk1977 case SQLITE_UTF8: 9324e6af134Sdanielk1977 Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-8",-1)); 9334e6af134Sdanielk1977 break; 9344e6af134Sdanielk1977 case SQLITE_UTF16LE: 9354e6af134Sdanielk1977 Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-16LE",-1)); 9364e6af134Sdanielk1977 break; 9374e6af134Sdanielk1977 case SQLITE_UTF16BE: 9384e6af134Sdanielk1977 Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-16BE",-1)); 9394e6af134Sdanielk1977 break; 9404e6af134Sdanielk1977 default: 9414e6af134Sdanielk1977 assert(0); 9424e6af134Sdanielk1977 } 9434e6af134Sdanielk1977 9444e6af134Sdanielk1977 pVal = sqlite3ValueNew(); 945bfd6cce5Sdanielk1977 sqlite3ValueSetStr(pVal, nA, zA, encin, SQLITE_STATIC); 9464e6af134Sdanielk1977 Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj(sqlite3_value_text(pVal),-1)); 947bfd6cce5Sdanielk1977 sqlite3ValueSetStr(pVal, nB, zB, encin, SQLITE_STATIC); 9484e6af134Sdanielk1977 Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj(sqlite3_value_text(pVal),-1)); 9494e6af134Sdanielk1977 sqlite3ValueFree(pVal); 9504e6af134Sdanielk1977 9514e6af134Sdanielk1977 Tcl_EvalObjEx(i, pX, 0); 9524e6af134Sdanielk1977 Tcl_DecrRefCount(pX); 9534e6af134Sdanielk1977 Tcl_GetIntFromObj(i, Tcl_GetObjResult(i), &res); 9544e6af134Sdanielk1977 return res; 9554e6af134Sdanielk1977 } 9564e6af134Sdanielk1977 static int test_collate( 9574e6af134Sdanielk1977 void * clientData, 9584e6af134Sdanielk1977 Tcl_Interp *interp, 9594e6af134Sdanielk1977 int objc, 9604e6af134Sdanielk1977 Tcl_Obj *CONST objv[] 9614e6af134Sdanielk1977 ){ 9624e6af134Sdanielk1977 sqlite3 *db; 9634e6af134Sdanielk1977 int val; 9644e6af134Sdanielk1977 9654e6af134Sdanielk1977 if( objc!=5 ) goto bad_args; 9664e6af134Sdanielk1977 pTestCollateInterp = interp; 9674e6af134Sdanielk1977 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 9684e6af134Sdanielk1977 9694e6af134Sdanielk1977 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[2], &val) ) return TCL_ERROR; 9704e6af134Sdanielk1977 sqlite3_create_collation(db, "test_collate", SQLITE_UTF8, 9714e6af134Sdanielk1977 (void *)SQLITE_UTF8, val?test_collate_func:0); 9724e6af134Sdanielk1977 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[3], &val) ) return TCL_ERROR; 9734e6af134Sdanielk1977 sqlite3_create_collation(db, "test_collate", SQLITE_UTF16LE, 9744e6af134Sdanielk1977 (void *)SQLITE_UTF16LE, val?test_collate_func:0); 9754e6af134Sdanielk1977 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[4], &val) ) return TCL_ERROR; 9764e6af134Sdanielk1977 sqlite3_create_collation(db, "test_collate", SQLITE_UTF16BE, 9774e6af134Sdanielk1977 (void *)SQLITE_UTF16BE, val?test_collate_func:0); 9784e6af134Sdanielk1977 9794e6af134Sdanielk1977 return TCL_OK; 9804e6af134Sdanielk1977 9814e6af134Sdanielk1977 bad_args: 9824e6af134Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 9834e6af134Sdanielk1977 Tcl_GetStringFromObj(objv[0], 0), " <DB> <utf8> <utf16le> <utf16be>", 0); 9844e6af134Sdanielk1977 return TCL_ERROR; 9854e6af134Sdanielk1977 } 9864e6af134Sdanielk1977 987*8a6c550dSdanielk1977 static int sqlite3_crashseed( 988*8a6c550dSdanielk1977 void * clientData, 989*8a6c550dSdanielk1977 Tcl_Interp *interp, 990*8a6c550dSdanielk1977 int objc, 991*8a6c550dSdanielk1977 Tcl_Obj *CONST objv[] 992*8a6c550dSdanielk1977 ){ 993*8a6c550dSdanielk1977 #ifdef OS_TEST 994*8a6c550dSdanielk1977 int seed; 995*8a6c550dSdanielk1977 if( objc!=2 ) goto bad_args; 996*8a6c550dSdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &seed) ) return TCL_ERROR; 997*8a6c550dSdanielk1977 sqlite3SetCrashseed(seed); 998*8a6c550dSdanielk1977 #endif 999*8a6c550dSdanielk1977 return TCL_OK; 1000*8a6c550dSdanielk1977 1001*8a6c550dSdanielk1977 bad_args: 1002*8a6c550dSdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 1003*8a6c550dSdanielk1977 Tcl_GetStringFromObj(objv[0], 0), "<seed>", 0); 1004*8a6c550dSdanielk1977 return TCL_ERROR; 1005*8a6c550dSdanielk1977 } 1006*8a6c550dSdanielk1977 1007*8a6c550dSdanielk1977 100850457896Sdrh /* 100999ee3600Sdrh ** Usage: breakpoint 101099ee3600Sdrh ** 101199ee3600Sdrh ** This routine exists for one purpose - to provide a place to put a 101299ee3600Sdrh ** breakpoint with GDB that can be triggered using TCL code. The use 101399ee3600Sdrh ** for this is when a particular test fails on (say) the 1485th iteration. 101499ee3600Sdrh ** In the TCL test script, we can add code like this: 101599ee3600Sdrh ** 101699ee3600Sdrh ** if {$i==1485} breakpoint 101799ee3600Sdrh ** 101899ee3600Sdrh ** Then run testfixture in the debugger and wait for the breakpoint to 101999ee3600Sdrh ** fire. Then additional breakpoints can be set to trace down the bug. 102099ee3600Sdrh */ 102199ee3600Sdrh static int test_breakpoint( 102299ee3600Sdrh void *NotUsed, 102399ee3600Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 102499ee3600Sdrh int argc, /* Number of arguments */ 102599ee3600Sdrh char **argv /* Text of each argument */ 102699ee3600Sdrh ){ 102799ee3600Sdrh return TCL_OK; /* Do nothing */ 102899ee3600Sdrh } 102999ee3600Sdrh 103051e3d8e2Sdanielk1977 static int test_bind_int32( 103151e3d8e2Sdanielk1977 void * clientData, 103251e3d8e2Sdanielk1977 Tcl_Interp *interp, 103351e3d8e2Sdanielk1977 int objc, 103451e3d8e2Sdanielk1977 Tcl_Obj *CONST objv[] 103551e3d8e2Sdanielk1977 ){ 103651e3d8e2Sdanielk1977 sqlite3_stmt *pStmt; 103751e3d8e2Sdanielk1977 int idx; 103851e3d8e2Sdanielk1977 int value; 103951e3d8e2Sdanielk1977 int rc; 104051e3d8e2Sdanielk1977 104151e3d8e2Sdanielk1977 if( objc!=4 ){ 104251e3d8e2Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 104351e3d8e2Sdanielk1977 Tcl_GetStringFromObj(objv[0], 0), " <STMT> <param no.> <value>", 0); 104451e3d8e2Sdanielk1977 return TCL_ERROR; 104551e3d8e2Sdanielk1977 } 104651e3d8e2Sdanielk1977 104751e3d8e2Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 104851e3d8e2Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; 104951e3d8e2Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[3], &value) ) return TCL_ERROR; 105051e3d8e2Sdanielk1977 1051c572ef7fSdanielk1977 rc = sqlite3_bind_int(pStmt, idx, value); 105251e3d8e2Sdanielk1977 if( rc!=SQLITE_OK ){ 105351e3d8e2Sdanielk1977 return TCL_ERROR; 105451e3d8e2Sdanielk1977 } 105551e3d8e2Sdanielk1977 105651e3d8e2Sdanielk1977 return TCL_OK; 105751e3d8e2Sdanielk1977 } 105851e3d8e2Sdanielk1977 105951e3d8e2Sdanielk1977 static int test_bind_int64( 106051e3d8e2Sdanielk1977 void * clientData, 106151e3d8e2Sdanielk1977 Tcl_Interp *interp, 106251e3d8e2Sdanielk1977 int objc, 106351e3d8e2Sdanielk1977 Tcl_Obj *CONST objv[] 106451e3d8e2Sdanielk1977 ){ 106551e3d8e2Sdanielk1977 sqlite3_stmt *pStmt; 106651e3d8e2Sdanielk1977 int idx; 106751e3d8e2Sdanielk1977 i64 value; 106851e3d8e2Sdanielk1977 int rc; 106951e3d8e2Sdanielk1977 107051e3d8e2Sdanielk1977 if( objc!=4 ){ 107151e3d8e2Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 107251e3d8e2Sdanielk1977 Tcl_GetStringFromObj(objv[0], 0), " <STMT> <param no.> <value>", 0); 107351e3d8e2Sdanielk1977 return TCL_ERROR; 107451e3d8e2Sdanielk1977 } 107551e3d8e2Sdanielk1977 107651e3d8e2Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 107751e3d8e2Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; 107851e3d8e2Sdanielk1977 if( Tcl_GetWideIntFromObj(interp, objv[3], &value) ) return TCL_ERROR; 107951e3d8e2Sdanielk1977 108051e3d8e2Sdanielk1977 rc = sqlite3_bind_int64(pStmt, idx, value); 108151e3d8e2Sdanielk1977 if( rc!=SQLITE_OK ){ 108251e3d8e2Sdanielk1977 return TCL_ERROR; 108351e3d8e2Sdanielk1977 } 108451e3d8e2Sdanielk1977 108551e3d8e2Sdanielk1977 return TCL_OK; 108651e3d8e2Sdanielk1977 } 108751e3d8e2Sdanielk1977 108851e3d8e2Sdanielk1977 static int test_bind_double( 108951e3d8e2Sdanielk1977 void * clientData, 109051e3d8e2Sdanielk1977 Tcl_Interp *interp, 109151e3d8e2Sdanielk1977 int objc, 109251e3d8e2Sdanielk1977 Tcl_Obj *CONST objv[] 109351e3d8e2Sdanielk1977 ){ 109451e3d8e2Sdanielk1977 sqlite3_stmt *pStmt; 109551e3d8e2Sdanielk1977 int idx; 109651e3d8e2Sdanielk1977 double value; 109751e3d8e2Sdanielk1977 int rc; 109851e3d8e2Sdanielk1977 109951e3d8e2Sdanielk1977 if( objc!=4 ){ 110051e3d8e2Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 110151e3d8e2Sdanielk1977 Tcl_GetStringFromObj(objv[0], 0), " <STMT> <param no.> <value>", 0); 110251e3d8e2Sdanielk1977 return TCL_ERROR; 110351e3d8e2Sdanielk1977 } 110451e3d8e2Sdanielk1977 110551e3d8e2Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 110651e3d8e2Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; 110751e3d8e2Sdanielk1977 if( Tcl_GetDoubleFromObj(interp, objv[3], &value) ) return TCL_ERROR; 110851e3d8e2Sdanielk1977 110951e3d8e2Sdanielk1977 rc = sqlite3_bind_double(pStmt, idx, value); 111051e3d8e2Sdanielk1977 if( rc!=SQLITE_OK ){ 111151e3d8e2Sdanielk1977 return TCL_ERROR; 111251e3d8e2Sdanielk1977 } 111351e3d8e2Sdanielk1977 111451e3d8e2Sdanielk1977 return TCL_OK; 111551e3d8e2Sdanielk1977 } 111651e3d8e2Sdanielk1977 111751e3d8e2Sdanielk1977 static int test_bind_null( 111851e3d8e2Sdanielk1977 void * clientData, 111951e3d8e2Sdanielk1977 Tcl_Interp *interp, 112051e3d8e2Sdanielk1977 int objc, 112151e3d8e2Sdanielk1977 Tcl_Obj *CONST objv[] 112251e3d8e2Sdanielk1977 ){ 112351e3d8e2Sdanielk1977 sqlite3_stmt *pStmt; 112451e3d8e2Sdanielk1977 int idx; 112551e3d8e2Sdanielk1977 int rc; 112651e3d8e2Sdanielk1977 112751e3d8e2Sdanielk1977 if( objc!=3 ){ 112851e3d8e2Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 112951e3d8e2Sdanielk1977 Tcl_GetStringFromObj(objv[0], 0), " <STMT> <param no.>", 0); 113051e3d8e2Sdanielk1977 return TCL_ERROR; 113151e3d8e2Sdanielk1977 } 113251e3d8e2Sdanielk1977 113351e3d8e2Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 113451e3d8e2Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; 113551e3d8e2Sdanielk1977 113651e3d8e2Sdanielk1977 rc = sqlite3_bind_null(pStmt, idx); 113751e3d8e2Sdanielk1977 if( rc!=SQLITE_OK ){ 113851e3d8e2Sdanielk1977 return TCL_ERROR; 113951e3d8e2Sdanielk1977 } 114051e3d8e2Sdanielk1977 114151e3d8e2Sdanielk1977 return TCL_OK; 114251e3d8e2Sdanielk1977 } 114351e3d8e2Sdanielk1977 114451e3d8e2Sdanielk1977 static int test_bind_text( 114551e3d8e2Sdanielk1977 void * clientData, 114651e3d8e2Sdanielk1977 Tcl_Interp *interp, 114751e3d8e2Sdanielk1977 int objc, 114851e3d8e2Sdanielk1977 Tcl_Obj *CONST objv[] 114951e3d8e2Sdanielk1977 ){ 115051e3d8e2Sdanielk1977 sqlite3_stmt *pStmt; 115151e3d8e2Sdanielk1977 int idx; 115251e3d8e2Sdanielk1977 int bytes; 115351e3d8e2Sdanielk1977 char *value; 115451e3d8e2Sdanielk1977 int rc; 115551e3d8e2Sdanielk1977 115651e3d8e2Sdanielk1977 if( objc!=5 ){ 115751e3d8e2Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 115851e3d8e2Sdanielk1977 Tcl_GetStringFromObj(objv[0], 0), " <STMT> <param no.> <value>" 115951e3d8e2Sdanielk1977 " <bytes>", 0); 116051e3d8e2Sdanielk1977 return TCL_ERROR; 116151e3d8e2Sdanielk1977 } 116251e3d8e2Sdanielk1977 116351e3d8e2Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 116451e3d8e2Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; 116551e3d8e2Sdanielk1977 value = Tcl_GetString(objv[3]); 116651e3d8e2Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[4], &bytes) ) return TCL_ERROR; 116751e3d8e2Sdanielk1977 1168d8123366Sdanielk1977 rc = sqlite3_bind_text(pStmt, idx, value, bytes, SQLITE_TRANSIENT); 116951e3d8e2Sdanielk1977 if( rc!=SQLITE_OK ){ 117051e3d8e2Sdanielk1977 return TCL_ERROR; 117151e3d8e2Sdanielk1977 } 117251e3d8e2Sdanielk1977 117351e3d8e2Sdanielk1977 return TCL_OK; 117451e3d8e2Sdanielk1977 } 117551e3d8e2Sdanielk1977 117651e3d8e2Sdanielk1977 static int test_bind_text16( 117751e3d8e2Sdanielk1977 void * clientData, 117851e3d8e2Sdanielk1977 Tcl_Interp *interp, 117951e3d8e2Sdanielk1977 int objc, 118051e3d8e2Sdanielk1977 Tcl_Obj *CONST objv[] 118151e3d8e2Sdanielk1977 ){ 118251e3d8e2Sdanielk1977 sqlite3_stmt *pStmt; 118351e3d8e2Sdanielk1977 int idx; 118451e3d8e2Sdanielk1977 int bytes; 118551e3d8e2Sdanielk1977 char *value; 118651e3d8e2Sdanielk1977 int rc; 118751e3d8e2Sdanielk1977 118851e3d8e2Sdanielk1977 if( objc!=5 ){ 118951e3d8e2Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 119051e3d8e2Sdanielk1977 Tcl_GetStringFromObj(objv[0], 0), " <STMT> <param no.> <value>" 119151e3d8e2Sdanielk1977 " <bytes>", 0); 119251e3d8e2Sdanielk1977 return TCL_ERROR; 119351e3d8e2Sdanielk1977 } 119451e3d8e2Sdanielk1977 119551e3d8e2Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 119651e3d8e2Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; 119751e3d8e2Sdanielk1977 value = Tcl_GetByteArrayFromObj(objv[3], 0); 119851e3d8e2Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[4], &bytes) ) return TCL_ERROR; 119951e3d8e2Sdanielk1977 1200d8123366Sdanielk1977 rc = sqlite3_bind_text16(pStmt, idx, (void *)value, bytes, SQLITE_TRANSIENT); 120151e3d8e2Sdanielk1977 if( rc!=SQLITE_OK ){ 120251e3d8e2Sdanielk1977 return TCL_ERROR; 120351e3d8e2Sdanielk1977 } 120451e3d8e2Sdanielk1977 120551e3d8e2Sdanielk1977 return TCL_OK; 120651e3d8e2Sdanielk1977 } 120751e3d8e2Sdanielk1977 120851e3d8e2Sdanielk1977 static int test_bind_blob( 120951e3d8e2Sdanielk1977 void * clientData, 121051e3d8e2Sdanielk1977 Tcl_Interp *interp, 121151e3d8e2Sdanielk1977 int objc, 121251e3d8e2Sdanielk1977 Tcl_Obj *CONST objv[] 121351e3d8e2Sdanielk1977 ){ 121451e3d8e2Sdanielk1977 sqlite3_stmt *pStmt; 121551e3d8e2Sdanielk1977 int idx; 121651e3d8e2Sdanielk1977 int bytes; 121751e3d8e2Sdanielk1977 char *value; 121851e3d8e2Sdanielk1977 int rc; 121951e3d8e2Sdanielk1977 122051e3d8e2Sdanielk1977 if( objc!=5 ){ 122151e3d8e2Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 122251e3d8e2Sdanielk1977 Tcl_GetStringFromObj(objv[0], 0), " <STMT> <param no.> <value>" 122351e3d8e2Sdanielk1977 " <bytes>", 0); 122451e3d8e2Sdanielk1977 return TCL_ERROR; 122551e3d8e2Sdanielk1977 } 122651e3d8e2Sdanielk1977 122751e3d8e2Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 122851e3d8e2Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; 122951e3d8e2Sdanielk1977 value = Tcl_GetString(objv[3]); 123049e4643eSdanielk1977 if( Tcl_GetIntFromObj(interp, objv[4], &bytes) ) return TCL_ERROR; 123151e3d8e2Sdanielk1977 1232d8123366Sdanielk1977 rc = sqlite3_bind_blob(pStmt, idx, value, bytes, SQLITE_TRANSIENT); 123351e3d8e2Sdanielk1977 if( rc!=SQLITE_OK ){ 123451e3d8e2Sdanielk1977 return TCL_ERROR; 123551e3d8e2Sdanielk1977 } 123651e3d8e2Sdanielk1977 123751e3d8e2Sdanielk1977 return TCL_OK; 123851e3d8e2Sdanielk1977 } 123951e3d8e2Sdanielk1977 124099ee3600Sdrh /* 12416622cce3Sdanielk1977 ** Usage: sqlite3_errcode DB 12426622cce3Sdanielk1977 ** 12436622cce3Sdanielk1977 ** Return the string representation of the most recent sqlite3_* API 12446622cce3Sdanielk1977 ** error code. e.g. "SQLITE_ERROR". 12456622cce3Sdanielk1977 */ 12466622cce3Sdanielk1977 static int test_errcode( 12476622cce3Sdanielk1977 void * clientData, 12486622cce3Sdanielk1977 Tcl_Interp *interp, 12496622cce3Sdanielk1977 int objc, 12506622cce3Sdanielk1977 Tcl_Obj *CONST objv[] 12516622cce3Sdanielk1977 ){ 12526622cce3Sdanielk1977 sqlite3 *db; 12536622cce3Sdanielk1977 12546622cce3Sdanielk1977 if( objc!=2 ){ 12556622cce3Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 12566622cce3Sdanielk1977 Tcl_GetString(objv[0]), " DB", 0); 12576622cce3Sdanielk1977 return TCL_ERROR; 12586622cce3Sdanielk1977 } 12596622cce3Sdanielk1977 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 12606622cce3Sdanielk1977 Tcl_SetResult(interp, (char *)errorName(sqlite3_errcode(db)), 0); 12616622cce3Sdanielk1977 return TCL_OK; 12626622cce3Sdanielk1977 } 12636622cce3Sdanielk1977 12646622cce3Sdanielk1977 /* 12656622cce3Sdanielk1977 ** Usage: test_errmsg DB 12666622cce3Sdanielk1977 ** 12676622cce3Sdanielk1977 ** Returns the UTF-8 representation of the error message string for the 12686622cce3Sdanielk1977 ** most recent sqlite3_* API call. 12696622cce3Sdanielk1977 */ 12706622cce3Sdanielk1977 static int test_errmsg( 12716622cce3Sdanielk1977 void * clientData, 12726622cce3Sdanielk1977 Tcl_Interp *interp, 12736622cce3Sdanielk1977 int objc, 12746622cce3Sdanielk1977 Tcl_Obj *CONST objv[] 12756622cce3Sdanielk1977 ){ 12766622cce3Sdanielk1977 sqlite *db; 12776622cce3Sdanielk1977 const char *zErr; 12786622cce3Sdanielk1977 12796622cce3Sdanielk1977 if( objc!=2 ){ 12806622cce3Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 12816622cce3Sdanielk1977 Tcl_GetString(objv[0]), " DB", 0); 12826622cce3Sdanielk1977 return TCL_ERROR; 12836622cce3Sdanielk1977 } 12846622cce3Sdanielk1977 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 12856622cce3Sdanielk1977 12866622cce3Sdanielk1977 zErr = sqlite3_errmsg(db); 12876622cce3Sdanielk1977 Tcl_SetObjResult(interp, Tcl_NewStringObj(zErr, -1)); 12886622cce3Sdanielk1977 return TCL_OK; 12896622cce3Sdanielk1977 } 12906622cce3Sdanielk1977 12916622cce3Sdanielk1977 /* 12926622cce3Sdanielk1977 ** Usage: test_errmsg16 DB 12936622cce3Sdanielk1977 ** 12946622cce3Sdanielk1977 ** Returns the UTF-16 representation of the error message string for the 12956622cce3Sdanielk1977 ** most recent sqlite3_* API call. This is a byte array object at the TCL 12966622cce3Sdanielk1977 ** level, and it includes the 0x00 0x00 terminator bytes at the end of the 12976622cce3Sdanielk1977 ** UTF-16 string. 12986622cce3Sdanielk1977 */ 12996622cce3Sdanielk1977 static int test_errmsg16( 13006622cce3Sdanielk1977 void * clientData, 13016622cce3Sdanielk1977 Tcl_Interp *interp, 13026622cce3Sdanielk1977 int objc, 13036622cce3Sdanielk1977 Tcl_Obj *CONST objv[] 13046622cce3Sdanielk1977 ){ 13056622cce3Sdanielk1977 sqlite *db; 13066622cce3Sdanielk1977 const void *zErr; 13076622cce3Sdanielk1977 int bytes; 13086622cce3Sdanielk1977 13096622cce3Sdanielk1977 if( objc!=2 ){ 13106622cce3Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 13116622cce3Sdanielk1977 Tcl_GetString(objv[0]), " DB", 0); 13126622cce3Sdanielk1977 return TCL_ERROR; 13136622cce3Sdanielk1977 } 13146622cce3Sdanielk1977 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 13156622cce3Sdanielk1977 13166622cce3Sdanielk1977 zErr = sqlite3_errmsg16(db); 13176622cce3Sdanielk1977 bytes = sqlite3utf16ByteLen(zErr, -1); 13186622cce3Sdanielk1977 Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(zErr, bytes)); 13196622cce3Sdanielk1977 return TCL_OK; 13206622cce3Sdanielk1977 } 13216622cce3Sdanielk1977 13226622cce3Sdanielk1977 /* 13236622cce3Sdanielk1977 ** Usage: sqlite3_prepare DB sql bytes tailvar 13246622cce3Sdanielk1977 ** 13256622cce3Sdanielk1977 ** Compile up to <bytes> bytes of the supplied SQL string <sql> using 13266622cce3Sdanielk1977 ** database handle <DB>. The parameter <tailval> is the name of a global 13276622cce3Sdanielk1977 ** variable that is set to the unused portion of <sql> (if any). A 13286622cce3Sdanielk1977 ** STMT handle is returned. 13296622cce3Sdanielk1977 */ 13306622cce3Sdanielk1977 static int test_prepare( 13316622cce3Sdanielk1977 void * clientData, 13326622cce3Sdanielk1977 Tcl_Interp *interp, 13336622cce3Sdanielk1977 int objc, 13346622cce3Sdanielk1977 Tcl_Obj *CONST objv[] 13356622cce3Sdanielk1977 ){ 13366622cce3Sdanielk1977 sqlite3 *db; 13376622cce3Sdanielk1977 const char *zSql; 13386622cce3Sdanielk1977 int bytes; 13396622cce3Sdanielk1977 const char *zTail = 0; 13406622cce3Sdanielk1977 sqlite3_stmt *pStmt = 0; 13416622cce3Sdanielk1977 char zBuf[50]; 13424ad1713cSdanielk1977 int rc; 13436622cce3Sdanielk1977 13446622cce3Sdanielk1977 if( objc!=5 ){ 13456622cce3Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 13466622cce3Sdanielk1977 Tcl_GetString(objv[0]), " DB sql bytes tailvar", 0); 13476622cce3Sdanielk1977 return TCL_ERROR; 13486622cce3Sdanielk1977 } 13496622cce3Sdanielk1977 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 13506622cce3Sdanielk1977 zSql = Tcl_GetString(objv[2]); 13516622cce3Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR; 13526622cce3Sdanielk1977 13534ad1713cSdanielk1977 rc = sqlite3_prepare(db, zSql, bytes, &pStmt, &zTail); 13546622cce3Sdanielk1977 if( zTail ){ 13556622cce3Sdanielk1977 if( bytes>=0 ){ 13566622cce3Sdanielk1977 bytes = bytes - (zTail-zSql); 13576622cce3Sdanielk1977 } 13586622cce3Sdanielk1977 Tcl_ObjSetVar2(interp, objv[4], 0, Tcl_NewStringObj(zTail, bytes), 0); 13596622cce3Sdanielk1977 } 13604ad1713cSdanielk1977 if( rc!=SQLITE_OK ){ 13614ad1713cSdanielk1977 assert( pStmt==0 ); 13624ad1713cSdanielk1977 sprintf(zBuf, "(%d) ", rc); 13634ad1713cSdanielk1977 Tcl_AppendResult(interp, zBuf, sqlite3_errmsg(db), 0); 13644ad1713cSdanielk1977 return TCL_ERROR; 13654ad1713cSdanielk1977 } 13666622cce3Sdanielk1977 13674ad1713cSdanielk1977 if( pStmt ){ 13686622cce3Sdanielk1977 if( makePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR; 13696622cce3Sdanielk1977 Tcl_AppendResult(interp, zBuf, 0); 13704ad1713cSdanielk1977 } 13716622cce3Sdanielk1977 return TCL_OK; 13726622cce3Sdanielk1977 } 13736622cce3Sdanielk1977 13746622cce3Sdanielk1977 /* 13756622cce3Sdanielk1977 ** Usage: sqlite3_prepare DB sql bytes tailvar 13766622cce3Sdanielk1977 ** 13776622cce3Sdanielk1977 ** Compile up to <bytes> bytes of the supplied SQL string <sql> using 13786622cce3Sdanielk1977 ** database handle <DB>. The parameter <tailval> is the name of a global 13796622cce3Sdanielk1977 ** variable that is set to the unused portion of <sql> (if any). A 13806622cce3Sdanielk1977 ** STMT handle is returned. 13816622cce3Sdanielk1977 */ 13826622cce3Sdanielk1977 static int test_prepare16( 13836622cce3Sdanielk1977 void * clientData, 13846622cce3Sdanielk1977 Tcl_Interp *interp, 13856622cce3Sdanielk1977 int objc, 13866622cce3Sdanielk1977 Tcl_Obj *CONST objv[] 13876622cce3Sdanielk1977 ){ 13886622cce3Sdanielk1977 sqlite3 *db; 13896622cce3Sdanielk1977 const void *zSql; 13906622cce3Sdanielk1977 const void *zTail = 0; 13916622cce3Sdanielk1977 Tcl_Obj *pTail = 0; 13926622cce3Sdanielk1977 sqlite3_stmt *pStmt = 0; 13936622cce3Sdanielk1977 char zBuf[50]; 13946622cce3Sdanielk1977 int bytes; /* The integer specified as arg 3 */ 13956622cce3Sdanielk1977 int objlen; /* The byte-array length of arg 2 */ 13966622cce3Sdanielk1977 13976622cce3Sdanielk1977 if( objc!=5 ){ 13986622cce3Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 13996622cce3Sdanielk1977 Tcl_GetString(objv[0]), " DB sql bytes tailvar", 0); 14006622cce3Sdanielk1977 return TCL_ERROR; 14016622cce3Sdanielk1977 } 14026622cce3Sdanielk1977 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 14036622cce3Sdanielk1977 zSql = Tcl_GetByteArrayFromObj(objv[2], &objlen); 14046622cce3Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR; 14056622cce3Sdanielk1977 14066622cce3Sdanielk1977 if( SQLITE_OK!=sqlite3_prepare16(db, zSql, bytes, &pStmt, &zTail) ){ 14076622cce3Sdanielk1977 return TCL_ERROR; 14086622cce3Sdanielk1977 } 14096622cce3Sdanielk1977 14106622cce3Sdanielk1977 if( zTail ){ 14116622cce3Sdanielk1977 objlen = objlen - ((u8 *)zTail-(u8 *)zSql); 14126622cce3Sdanielk1977 }else{ 14136622cce3Sdanielk1977 objlen = 0; 14146622cce3Sdanielk1977 } 14156622cce3Sdanielk1977 pTail = Tcl_NewByteArrayObj((u8 *)zTail, objlen); 14166622cce3Sdanielk1977 Tcl_IncrRefCount(pTail); 14176622cce3Sdanielk1977 Tcl_ObjSetVar2(interp, objv[4], 0, pTail, 0); 14184ad1713cSdanielk1977 Tcl_DecrRefCount(pTail); 14196622cce3Sdanielk1977 14204ad1713cSdanielk1977 if( pStmt ){ 14216622cce3Sdanielk1977 if( makePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR; 14224ad1713cSdanielk1977 } 14236622cce3Sdanielk1977 Tcl_AppendResult(interp, zBuf, 0); 14246622cce3Sdanielk1977 return TCL_OK; 14256622cce3Sdanielk1977 } 14266622cce3Sdanielk1977 14274ad1713cSdanielk1977 /* 14284ad1713cSdanielk1977 ** Usage: sqlite3_open filename ?options-list? 14294ad1713cSdanielk1977 */ 14304ad1713cSdanielk1977 static int test_open( 14314ad1713cSdanielk1977 void * clientData, 14324ad1713cSdanielk1977 Tcl_Interp *interp, 14334ad1713cSdanielk1977 int objc, 14344ad1713cSdanielk1977 Tcl_Obj *CONST objv[] 14354ad1713cSdanielk1977 ){ 14364ad1713cSdanielk1977 const char *zFilename; 14374ad1713cSdanielk1977 sqlite3 *db; 14384ad1713cSdanielk1977 int rc; 14394ad1713cSdanielk1977 char zBuf[100]; 14404ad1713cSdanielk1977 14414ad1713cSdanielk1977 if( objc!=3 && objc!=2 ){ 14424ad1713cSdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 14434ad1713cSdanielk1977 Tcl_GetString(objv[0]), " filename options-list", 0); 14444ad1713cSdanielk1977 return TCL_ERROR; 14454ad1713cSdanielk1977 } 14464ad1713cSdanielk1977 14474ad1713cSdanielk1977 zFilename = Tcl_GetString(objv[1]); 14484f057f90Sdanielk1977 rc = sqlite3_open(zFilename, &db); 14494ad1713cSdanielk1977 14504ad1713cSdanielk1977 if( makePointerStr(interp, zBuf, db) ) return TCL_ERROR; 14514ad1713cSdanielk1977 Tcl_AppendResult(interp, zBuf, 0); 14524ad1713cSdanielk1977 return TCL_OK; 14534ad1713cSdanielk1977 } 14544ad1713cSdanielk1977 14554ad1713cSdanielk1977 /* 14564ad1713cSdanielk1977 ** Usage: sqlite3_open16 filename options 14574ad1713cSdanielk1977 */ 14584ad1713cSdanielk1977 static int test_open16( 14594ad1713cSdanielk1977 void * clientData, 14604ad1713cSdanielk1977 Tcl_Interp *interp, 14614ad1713cSdanielk1977 int objc, 14624ad1713cSdanielk1977 Tcl_Obj *CONST objv[] 14634ad1713cSdanielk1977 ){ 14644ad1713cSdanielk1977 const void *zFilename; 14654ad1713cSdanielk1977 sqlite3 *db; 14664ad1713cSdanielk1977 int rc; 14674ad1713cSdanielk1977 char zBuf[100]; 14684ad1713cSdanielk1977 14694ad1713cSdanielk1977 if( objc!=3 ){ 14704ad1713cSdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 14714ad1713cSdanielk1977 Tcl_GetString(objv[0]), " filename options-list", 0); 14724ad1713cSdanielk1977 return TCL_ERROR; 14734ad1713cSdanielk1977 } 14744ad1713cSdanielk1977 14754ad1713cSdanielk1977 zFilename = Tcl_GetByteArrayFromObj(objv[1], 0); 14764f057f90Sdanielk1977 rc = sqlite3_open16(zFilename, &db); 14774ad1713cSdanielk1977 14784ad1713cSdanielk1977 if( makePointerStr(interp, zBuf, db) ) return TCL_ERROR; 14794ad1713cSdanielk1977 Tcl_AppendResult(interp, zBuf, 0); 14804ad1713cSdanielk1977 return TCL_OK; 14814ad1713cSdanielk1977 } 1482d3d39e93Sdrh 1483d3d39e93Sdrh /* 1484106bb236Sdanielk1977 ** Usage: sqlite3_step STMT 1485106bb236Sdanielk1977 ** 1486106bb236Sdanielk1977 ** Advance the statement to the next row. 1487106bb236Sdanielk1977 */ 148817240fd9Sdanielk1977 static int test_step( 1489106bb236Sdanielk1977 void * clientData, 1490106bb236Sdanielk1977 Tcl_Interp *interp, 1491106bb236Sdanielk1977 int objc, 1492106bb236Sdanielk1977 Tcl_Obj *CONST objv[] 1493106bb236Sdanielk1977 ){ 1494106bb236Sdanielk1977 sqlite3_stmt *pStmt; 1495106bb236Sdanielk1977 int rc; 1496106bb236Sdanielk1977 1497e1cd9874Sdanielk1977 if( objc!=2 ){ 1498106bb236Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 1499106bb236Sdanielk1977 Tcl_GetString(objv[0]), " STMT", 0); 1500106bb236Sdanielk1977 return TCL_ERROR; 1501106bb236Sdanielk1977 } 1502106bb236Sdanielk1977 1503106bb236Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 150417240fd9Sdanielk1977 rc = sqlite3_step(pStmt); 1505106bb236Sdanielk1977 1506fbcd585fSdanielk1977 /* if( rc!=SQLITE_DONE && rc!=SQLITE_ROW ) return TCL_ERROR; */ 15076590493dSdanielk1977 Tcl_SetResult(interp, (char *)errorName(rc), 0); 1508e1cd9874Sdanielk1977 return TCL_OK; 1509e1cd9874Sdanielk1977 } 1510e1cd9874Sdanielk1977 1511e1cd9874Sdanielk1977 /* 151217240fd9Sdanielk1977 ** Usage: sqlite3_column_count STMT 151317240fd9Sdanielk1977 ** 151417240fd9Sdanielk1977 ** Return the number of columns returned by the sql statement STMT. 151517240fd9Sdanielk1977 */ 151617240fd9Sdanielk1977 static int test_column_count( 151717240fd9Sdanielk1977 void * clientData, 151817240fd9Sdanielk1977 Tcl_Interp *interp, 151917240fd9Sdanielk1977 int objc, 152017240fd9Sdanielk1977 Tcl_Obj *CONST objv[] 152117240fd9Sdanielk1977 ){ 152217240fd9Sdanielk1977 sqlite3_stmt *pStmt; 152317240fd9Sdanielk1977 152417240fd9Sdanielk1977 if( objc!=2 ){ 152517240fd9Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 152617240fd9Sdanielk1977 Tcl_GetString(objv[0]), " STMT column", 0); 152717240fd9Sdanielk1977 return TCL_ERROR; 152817240fd9Sdanielk1977 } 152917240fd9Sdanielk1977 153017240fd9Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 153117240fd9Sdanielk1977 153217240fd9Sdanielk1977 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_column_count(pStmt))); 153317240fd9Sdanielk1977 return TCL_OK; 153417240fd9Sdanielk1977 } 153517240fd9Sdanielk1977 153617240fd9Sdanielk1977 /* 15373cf86063Sdanielk1977 ** Usage: sqlite3_column_type STMT column 15383cf86063Sdanielk1977 ** 15393cf86063Sdanielk1977 ** Return the type of the data in column 'column' of the current row. 15403cf86063Sdanielk1977 */ 15413cf86063Sdanielk1977 static int test_column_type( 15423cf86063Sdanielk1977 void * clientData, 15433cf86063Sdanielk1977 Tcl_Interp *interp, 15443cf86063Sdanielk1977 int objc, 15453cf86063Sdanielk1977 Tcl_Obj *CONST objv[] 15463cf86063Sdanielk1977 ){ 15473cf86063Sdanielk1977 sqlite3_stmt *pStmt; 15483cf86063Sdanielk1977 int col; 15493cf86063Sdanielk1977 int tp; 15503cf86063Sdanielk1977 15513cf86063Sdanielk1977 if( objc!=3 ){ 15523cf86063Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 15533cf86063Sdanielk1977 Tcl_GetString(objv[0]), " STMT column", 0); 15543cf86063Sdanielk1977 return TCL_ERROR; 15553cf86063Sdanielk1977 } 15563cf86063Sdanielk1977 15573cf86063Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 15583cf86063Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; 15593cf86063Sdanielk1977 15603cf86063Sdanielk1977 tp = sqlite3_column_type(pStmt, col); 15613cf86063Sdanielk1977 switch( tp ){ 15629c054830Sdrh case SQLITE_INTEGER: 15633cf86063Sdanielk1977 Tcl_SetResult(interp, "INTEGER", TCL_STATIC); 15643cf86063Sdanielk1977 break; 15659c054830Sdrh case SQLITE_NULL: 15663cf86063Sdanielk1977 Tcl_SetResult(interp, "NULL", TCL_STATIC); 15673cf86063Sdanielk1977 break; 15689c054830Sdrh case SQLITE_FLOAT: 15693cf86063Sdanielk1977 Tcl_SetResult(interp, "FLOAT", TCL_STATIC); 15703cf86063Sdanielk1977 break; 15719c054830Sdrh case SQLITE_TEXT: 15723cf86063Sdanielk1977 Tcl_SetResult(interp, "TEXT", TCL_STATIC); 15733cf86063Sdanielk1977 break; 15749c054830Sdrh case SQLITE_BLOB: 15753cf86063Sdanielk1977 Tcl_SetResult(interp, "BLOB", TCL_STATIC); 15763cf86063Sdanielk1977 break; 15773cf86063Sdanielk1977 default: 15783cf86063Sdanielk1977 assert(0); 15793cf86063Sdanielk1977 } 15803cf86063Sdanielk1977 15813cf86063Sdanielk1977 return TCL_OK; 15823cf86063Sdanielk1977 } 15833cf86063Sdanielk1977 15843cf86063Sdanielk1977 /* 158504f2e68dSdanielk1977 ** Usage: sqlite3_column_int64 STMT column 15863cf86063Sdanielk1977 ** 15873cf86063Sdanielk1977 ** Return the data in column 'column' of the current row cast as an 158804f2e68dSdanielk1977 ** wide (64-bit) integer. 15893cf86063Sdanielk1977 */ 159004f2e68dSdanielk1977 static int test_column_int64( 15913cf86063Sdanielk1977 void * clientData, 15923cf86063Sdanielk1977 Tcl_Interp *interp, 15933cf86063Sdanielk1977 int objc, 15943cf86063Sdanielk1977 Tcl_Obj *CONST objv[] 15953cf86063Sdanielk1977 ){ 15963cf86063Sdanielk1977 sqlite3_stmt *pStmt; 15973cf86063Sdanielk1977 int col; 159804f2e68dSdanielk1977 i64 iVal; 15993cf86063Sdanielk1977 16003cf86063Sdanielk1977 if( objc!=3 ){ 16013cf86063Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 16023cf86063Sdanielk1977 Tcl_GetString(objv[0]), " STMT column", 0); 16033cf86063Sdanielk1977 return TCL_ERROR; 16043cf86063Sdanielk1977 } 16053cf86063Sdanielk1977 16063cf86063Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 16073cf86063Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; 16083cf86063Sdanielk1977 160904f2e68dSdanielk1977 iVal = sqlite3_column_int64(pStmt, col); 161004f2e68dSdanielk1977 Tcl_SetObjResult(interp, Tcl_NewWideIntObj(iVal)); 161104f2e68dSdanielk1977 return TCL_OK; 161204f2e68dSdanielk1977 } 161304f2e68dSdanielk1977 161404f2e68dSdanielk1977 /* 1615ea61b2c4Sdanielk1977 ** Usage: sqlite3_column_blob STMT column 1616ea61b2c4Sdanielk1977 */ 1617ea61b2c4Sdanielk1977 static int test_column_blob( 1618ea61b2c4Sdanielk1977 void * clientData, 1619ea61b2c4Sdanielk1977 Tcl_Interp *interp, 1620ea61b2c4Sdanielk1977 int objc, 1621ea61b2c4Sdanielk1977 Tcl_Obj *CONST objv[] 1622ea61b2c4Sdanielk1977 ){ 1623ea61b2c4Sdanielk1977 sqlite3_stmt *pStmt; 1624ea61b2c4Sdanielk1977 int col; 1625ea61b2c4Sdanielk1977 1626ea61b2c4Sdanielk1977 int len; 1627c572ef7fSdanielk1977 const void *pBlob; 1628ea61b2c4Sdanielk1977 1629ea61b2c4Sdanielk1977 if( objc!=3 ){ 1630ea61b2c4Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 1631ea61b2c4Sdanielk1977 Tcl_GetString(objv[0]), " STMT column", 0); 1632ea61b2c4Sdanielk1977 return TCL_ERROR; 1633ea61b2c4Sdanielk1977 } 1634ea61b2c4Sdanielk1977 1635ea61b2c4Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 1636ea61b2c4Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; 1637ea61b2c4Sdanielk1977 1638ea61b2c4Sdanielk1977 pBlob = sqlite3_column_blob(pStmt, col); 1639ea61b2c4Sdanielk1977 len = sqlite3_column_bytes(pStmt, col); 1640ea61b2c4Sdanielk1977 Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(pBlob, len)); 1641ea61b2c4Sdanielk1977 return TCL_OK; 1642ea61b2c4Sdanielk1977 } 1643ea61b2c4Sdanielk1977 1644ea61b2c4Sdanielk1977 /* 164504f2e68dSdanielk1977 ** Usage: sqlite3_column_double STMT column 164604f2e68dSdanielk1977 ** 164704f2e68dSdanielk1977 ** Return the data in column 'column' of the current row cast as a double. 164804f2e68dSdanielk1977 */ 164904f2e68dSdanielk1977 static int test_column_double( 165004f2e68dSdanielk1977 void * clientData, 165104f2e68dSdanielk1977 Tcl_Interp *interp, 165204f2e68dSdanielk1977 int objc, 165304f2e68dSdanielk1977 Tcl_Obj *CONST objv[] 165404f2e68dSdanielk1977 ){ 165504f2e68dSdanielk1977 sqlite3_stmt *pStmt; 165604f2e68dSdanielk1977 int col; 165704f2e68dSdanielk1977 double rVal; 165804f2e68dSdanielk1977 165904f2e68dSdanielk1977 if( objc!=3 ){ 166004f2e68dSdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 166104f2e68dSdanielk1977 Tcl_GetString(objv[0]), " STMT column", 0); 166204f2e68dSdanielk1977 return TCL_ERROR; 166304f2e68dSdanielk1977 } 166404f2e68dSdanielk1977 166504f2e68dSdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 166604f2e68dSdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; 166704f2e68dSdanielk1977 166804f2e68dSdanielk1977 rVal = sqlite3_column_double(pStmt, col); 1669c572ef7fSdanielk1977 Tcl_SetObjResult(interp, Tcl_NewDoubleObj(rVal)); 16703cf86063Sdanielk1977 return TCL_OK; 16713cf86063Sdanielk1977 } 16723cf86063Sdanielk1977 16733cf86063Sdanielk1977 /* 167417240fd9Sdanielk1977 ** Usage: sqlite3_data_count STMT 167517240fd9Sdanielk1977 ** 167617240fd9Sdanielk1977 ** Return the number of columns returned by the sql statement STMT. 167717240fd9Sdanielk1977 */ 167817240fd9Sdanielk1977 static int test_data_count( 167917240fd9Sdanielk1977 void * clientData, 168017240fd9Sdanielk1977 Tcl_Interp *interp, 168117240fd9Sdanielk1977 int objc, 168217240fd9Sdanielk1977 Tcl_Obj *CONST objv[] 168317240fd9Sdanielk1977 ){ 168417240fd9Sdanielk1977 sqlite3_stmt *pStmt; 168517240fd9Sdanielk1977 168617240fd9Sdanielk1977 if( objc!=2 ){ 168717240fd9Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 168817240fd9Sdanielk1977 Tcl_GetString(objv[0]), " STMT column", 0); 168917240fd9Sdanielk1977 return TCL_ERROR; 169017240fd9Sdanielk1977 } 169117240fd9Sdanielk1977 169217240fd9Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 169317240fd9Sdanielk1977 169417240fd9Sdanielk1977 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_data_count(pStmt))); 169517240fd9Sdanielk1977 return TCL_OK; 169617240fd9Sdanielk1977 } 169717240fd9Sdanielk1977 169817240fd9Sdanielk1977 /* 169904f2e68dSdanielk1977 ** Usage: sqlite3_column_text STMT column 170004f2e68dSdanielk1977 ** 170104f2e68dSdanielk1977 ** Usage: sqlite3_column_decltype STMT column 170204f2e68dSdanielk1977 ** 170304f2e68dSdanielk1977 ** Usage: sqlite3_column_name STMT column 170404f2e68dSdanielk1977 */ 170504f2e68dSdanielk1977 static int test_stmt_utf8( 170604f2e68dSdanielk1977 void * clientData, 170704f2e68dSdanielk1977 Tcl_Interp *interp, 170804f2e68dSdanielk1977 int objc, 170904f2e68dSdanielk1977 Tcl_Obj *CONST objv[] 171004f2e68dSdanielk1977 ){ 171104f2e68dSdanielk1977 sqlite3_stmt *pStmt; 171204f2e68dSdanielk1977 int col; 1713c572ef7fSdanielk1977 const char *(*xFunc)(sqlite3_stmt*, int) = clientData; 1714f93bbbeaSdanielk1977 const char *zRet; 171504f2e68dSdanielk1977 171604f2e68dSdanielk1977 if( objc!=3 ){ 171704f2e68dSdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 171804f2e68dSdanielk1977 Tcl_GetString(objv[0]), " STMT column", 0); 171904f2e68dSdanielk1977 return TCL_ERROR; 172004f2e68dSdanielk1977 } 172104f2e68dSdanielk1977 172204f2e68dSdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 172304f2e68dSdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; 1724f93bbbeaSdanielk1977 zRet = xFunc(pStmt, col); 1725f93bbbeaSdanielk1977 if( zRet ){ 1726f93bbbeaSdanielk1977 Tcl_SetResult(interp, (char *)zRet, 0); 1727f93bbbeaSdanielk1977 } 172804f2e68dSdanielk1977 return TCL_OK; 172904f2e68dSdanielk1977 } 173004f2e68dSdanielk1977 173104f2e68dSdanielk1977 /* 173204f2e68dSdanielk1977 ** Usage: sqlite3_column_text STMT column 173304f2e68dSdanielk1977 ** 173404f2e68dSdanielk1977 ** Usage: sqlite3_column_decltype STMT column 173504f2e68dSdanielk1977 ** 173604f2e68dSdanielk1977 ** Usage: sqlite3_column_name STMT column 173704f2e68dSdanielk1977 */ 173804f2e68dSdanielk1977 static int test_stmt_utf16( 173904f2e68dSdanielk1977 void * clientData, 174004f2e68dSdanielk1977 Tcl_Interp *interp, 174104f2e68dSdanielk1977 int objc, 174204f2e68dSdanielk1977 Tcl_Obj *CONST objv[] 174304f2e68dSdanielk1977 ){ 174404f2e68dSdanielk1977 sqlite3_stmt *pStmt; 174504f2e68dSdanielk1977 int col; 174604f2e68dSdanielk1977 Tcl_Obj *pRet; 174704f2e68dSdanielk1977 const void *zName16; 1748c572ef7fSdanielk1977 const void *(*xFunc)(sqlite3_stmt*, int) = clientData; 174904f2e68dSdanielk1977 175004f2e68dSdanielk1977 if( objc!=3 ){ 175104f2e68dSdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 175204f2e68dSdanielk1977 Tcl_GetString(objv[0]), " STMT column", 0); 175304f2e68dSdanielk1977 return TCL_ERROR; 175404f2e68dSdanielk1977 } 175504f2e68dSdanielk1977 175604f2e68dSdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 175704f2e68dSdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; 175804f2e68dSdanielk1977 175904f2e68dSdanielk1977 zName16 = xFunc(pStmt, col); 1760f93bbbeaSdanielk1977 if( zName16 ){ 176104f2e68dSdanielk1977 pRet = Tcl_NewByteArrayObj(zName16, sqlite3utf16ByteLen(zName16, -1)+2); 176204f2e68dSdanielk1977 Tcl_SetObjResult(interp, pRet); 1763f93bbbeaSdanielk1977 } 176404f2e68dSdanielk1977 176504f2e68dSdanielk1977 return TCL_OK; 176604f2e68dSdanielk1977 } 176704f2e68dSdanielk1977 176804f2e68dSdanielk1977 /* 176904f2e68dSdanielk1977 ** Usage: sqlite3_column_int STMT column 177004f2e68dSdanielk1977 ** 177104f2e68dSdanielk1977 ** Usage: sqlite3_column_bytes STMT column 177204f2e68dSdanielk1977 ** 177304f2e68dSdanielk1977 ** Usage: sqlite3_column_bytes16 STMT column 177404f2e68dSdanielk1977 ** 177504f2e68dSdanielk1977 */ 177604f2e68dSdanielk1977 static int test_stmt_int( 177704f2e68dSdanielk1977 void * clientData, 177804f2e68dSdanielk1977 Tcl_Interp *interp, 177904f2e68dSdanielk1977 int objc, 178004f2e68dSdanielk1977 Tcl_Obj *CONST objv[] 178104f2e68dSdanielk1977 ){ 178204f2e68dSdanielk1977 sqlite3_stmt *pStmt; 178304f2e68dSdanielk1977 int col; 1784c572ef7fSdanielk1977 int (*xFunc)(sqlite3_stmt*, int) = clientData; 178504f2e68dSdanielk1977 178604f2e68dSdanielk1977 if( objc!=3 ){ 178704f2e68dSdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 178804f2e68dSdanielk1977 Tcl_GetString(objv[0]), " STMT column", 0); 178904f2e68dSdanielk1977 return TCL_ERROR; 179004f2e68dSdanielk1977 } 179104f2e68dSdanielk1977 179204f2e68dSdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 179304f2e68dSdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; 179404f2e68dSdanielk1977 179504f2e68dSdanielk1977 Tcl_SetObjResult(interp, Tcl_NewIntObj(xFunc(pStmt, col))); 179604f2e68dSdanielk1977 return TCL_OK; 179704f2e68dSdanielk1977 } 179804f2e68dSdanielk1977 17999a1d0abeSdanielk1977 /* 18009a1d0abeSdanielk1977 ** Usage: sqlite3OsOpenReadWrite <filename> 18019a1d0abeSdanielk1977 */ 18029a1d0abeSdanielk1977 static int test_sqlite3OsOpenReadWrite( 18039a1d0abeSdanielk1977 void * clientData, 18049a1d0abeSdanielk1977 Tcl_Interp *interp, 18059a1d0abeSdanielk1977 int objc, 18069a1d0abeSdanielk1977 Tcl_Obj *CONST objv[] 18079a1d0abeSdanielk1977 ){ 18089a1d0abeSdanielk1977 OsFile * pFile; 18099a1d0abeSdanielk1977 int rc; 18109a1d0abeSdanielk1977 int dummy; 18119a1d0abeSdanielk1977 char zBuf[100]; 181204f2e68dSdanielk1977 18139a1d0abeSdanielk1977 if( objc!=2 ){ 18149a1d0abeSdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 18159a1d0abeSdanielk1977 Tcl_GetString(objv[0]), " filename", 0); 18169a1d0abeSdanielk1977 return TCL_ERROR; 18179a1d0abeSdanielk1977 } 18189a1d0abeSdanielk1977 18199a1d0abeSdanielk1977 pFile = sqliteMalloc(sizeof(OsFile)); 18209a1d0abeSdanielk1977 rc = sqlite3OsOpenReadWrite(Tcl_GetString(objv[1]), pFile, &dummy); 18219a1d0abeSdanielk1977 if( rc!=SQLITE_OK ){ 18229a1d0abeSdanielk1977 sqliteFree(pFile); 18239a1d0abeSdanielk1977 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC); 18249a1d0abeSdanielk1977 return TCL_ERROR; 18259a1d0abeSdanielk1977 } 18269a1d0abeSdanielk1977 makePointerStr(interp, zBuf, pFile); 18279a1d0abeSdanielk1977 Tcl_SetResult(interp, zBuf, 0); 18289a1d0abeSdanielk1977 return TCL_ERROR; 18299a1d0abeSdanielk1977 } 18309a1d0abeSdanielk1977 18319a1d0abeSdanielk1977 /* 18329a1d0abeSdanielk1977 ** Usage: sqlite3OsClose <file handle> 18339a1d0abeSdanielk1977 */ 18349a1d0abeSdanielk1977 static int test_sqlite3OsClose( 18359a1d0abeSdanielk1977 void * clientData, 18369a1d0abeSdanielk1977 Tcl_Interp *interp, 18379a1d0abeSdanielk1977 int objc, 18389a1d0abeSdanielk1977 Tcl_Obj *CONST objv[] 18399a1d0abeSdanielk1977 ){ 18409a1d0abeSdanielk1977 OsFile * pFile; 18419a1d0abeSdanielk1977 int rc; 18429a1d0abeSdanielk1977 18439a1d0abeSdanielk1977 if( objc!=2 ){ 18449a1d0abeSdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 18459a1d0abeSdanielk1977 Tcl_GetString(objv[0]), " filehandle", 0); 18469a1d0abeSdanielk1977 return TCL_ERROR; 18479a1d0abeSdanielk1977 } 18489a1d0abeSdanielk1977 18499a1d0abeSdanielk1977 if( getFilePointer(interp, Tcl_GetString(objv[1]), &pFile) ){ 18509a1d0abeSdanielk1977 return TCL_ERROR; 18519a1d0abeSdanielk1977 } 18529a1d0abeSdanielk1977 rc = sqlite3OsClose(pFile); 18539a1d0abeSdanielk1977 if( rc!=SQLITE_OK ){ 18549a1d0abeSdanielk1977 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC); 18559a1d0abeSdanielk1977 return TCL_ERROR; 18569a1d0abeSdanielk1977 } 18579a1d0abeSdanielk1977 sqliteFree(pFile); 18589a1d0abeSdanielk1977 return TCL_OK; 18599a1d0abeSdanielk1977 } 18609a1d0abeSdanielk1977 18619a1d0abeSdanielk1977 /* 18629a1d0abeSdanielk1977 ** Usage: sqlite3OsLock <file handle> <locktype> 18639a1d0abeSdanielk1977 */ 18649a1d0abeSdanielk1977 static int test_sqlite3OsLock( 18659a1d0abeSdanielk1977 void * clientData, 18669a1d0abeSdanielk1977 Tcl_Interp *interp, 18679a1d0abeSdanielk1977 int objc, 18689a1d0abeSdanielk1977 Tcl_Obj *CONST objv[] 18699a1d0abeSdanielk1977 ){ 18709a1d0abeSdanielk1977 OsFile * pFile; 18719a1d0abeSdanielk1977 int rc; 18729a1d0abeSdanielk1977 18739a1d0abeSdanielk1977 if( objc!=3 ){ 18749a1d0abeSdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 18759a1d0abeSdanielk1977 Tcl_GetString(objv[0]), 18769a1d0abeSdanielk1977 " filehandle (SHARED|RESERVED|PENDING|EXCLUSIVE)", 0); 18779a1d0abeSdanielk1977 return TCL_ERROR; 18789a1d0abeSdanielk1977 } 18799a1d0abeSdanielk1977 18809a1d0abeSdanielk1977 if( getFilePointer(interp, Tcl_GetString(objv[1]), &pFile) ){ 18819a1d0abeSdanielk1977 return TCL_ERROR; 18829a1d0abeSdanielk1977 } 18839a1d0abeSdanielk1977 18849a1d0abeSdanielk1977 if( 0==strcmp("SHARED", Tcl_GetString(objv[2])) ){ 18859a1d0abeSdanielk1977 rc = sqlite3OsLock(pFile, SHARED_LOCK); 18869a1d0abeSdanielk1977 } 18879a1d0abeSdanielk1977 else if( 0==strcmp("RESERVED", Tcl_GetString(objv[2])) ){ 18889a1d0abeSdanielk1977 rc = sqlite3OsLock(pFile, RESERVED_LOCK); 18899a1d0abeSdanielk1977 } 18909a1d0abeSdanielk1977 else if( 0==strcmp("PENDING", Tcl_GetString(objv[2])) ){ 18919a1d0abeSdanielk1977 rc = sqlite3OsLock(pFile, PENDING_LOCK); 18929a1d0abeSdanielk1977 } 18939a1d0abeSdanielk1977 else if( 0==strcmp("EXCLUSIVE", Tcl_GetString(objv[2])) ){ 18949a1d0abeSdanielk1977 rc = sqlite3OsLock(pFile, EXCLUSIVE_LOCK); 18959a1d0abeSdanielk1977 }else{ 18969a1d0abeSdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 18979a1d0abeSdanielk1977 Tcl_GetString(objv[0]), 18989a1d0abeSdanielk1977 " filehandle (SHARED|RESERVED|PENDING|EXCLUSIVE)", 0); 18999a1d0abeSdanielk1977 return TCL_ERROR; 19009a1d0abeSdanielk1977 } 19019a1d0abeSdanielk1977 19029a1d0abeSdanielk1977 if( rc!=SQLITE_OK ){ 19039a1d0abeSdanielk1977 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC); 19049a1d0abeSdanielk1977 return TCL_ERROR; 19059a1d0abeSdanielk1977 } 19069a1d0abeSdanielk1977 return TCL_OK; 19079a1d0abeSdanielk1977 } 19089a1d0abeSdanielk1977 19099a1d0abeSdanielk1977 /* 19109a1d0abeSdanielk1977 ** Usage: sqlite3OsUnlock <file handle> 19119a1d0abeSdanielk1977 */ 19129a1d0abeSdanielk1977 static int test_sqlite3OsUnlock( 19139a1d0abeSdanielk1977 void * clientData, 19149a1d0abeSdanielk1977 Tcl_Interp *interp, 19159a1d0abeSdanielk1977 int objc, 19169a1d0abeSdanielk1977 Tcl_Obj *CONST objv[] 19179a1d0abeSdanielk1977 ){ 19189a1d0abeSdanielk1977 OsFile * pFile; 19199a1d0abeSdanielk1977 int rc; 19209a1d0abeSdanielk1977 19219a1d0abeSdanielk1977 if( objc!=2 ){ 19229a1d0abeSdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 19239a1d0abeSdanielk1977 Tcl_GetString(objv[0]), " filehandle", 0); 19249a1d0abeSdanielk1977 return TCL_ERROR; 19259a1d0abeSdanielk1977 } 19269a1d0abeSdanielk1977 19279a1d0abeSdanielk1977 if( getFilePointer(interp, Tcl_GetString(objv[1]), &pFile) ){ 19289a1d0abeSdanielk1977 return TCL_ERROR; 19299a1d0abeSdanielk1977 } 1930a6abd041Sdrh rc = sqlite3OsUnlock(pFile, NO_LOCK); 19319a1d0abeSdanielk1977 if( rc!=SQLITE_OK ){ 19329a1d0abeSdanielk1977 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC); 19339a1d0abeSdanielk1977 return TCL_ERROR; 19349a1d0abeSdanielk1977 } 19359a1d0abeSdanielk1977 return TCL_OK; 19369a1d0abeSdanielk1977 } 1937d3d39e93Sdrh 1938d8123366Sdanielk1977 19396622cce3Sdanielk1977 /* 1940d1bf3512Sdrh ** Register commands with the TCL interpreter. 1941d1bf3512Sdrh */ 1942d1bf3512Sdrh int Sqlitetest1_Init(Tcl_Interp *interp){ 19436f8a503dSdanielk1977 extern int sqlite3_search_count; 19446f8a503dSdanielk1977 extern int sqlite3_interrupt_count; 19456f8a503dSdanielk1977 extern int sqlite3_open_file_count; 19466f8a503dSdanielk1977 extern int sqlite3_current_time; 1947c2eef3b3Sdrh static struct { 1948c2eef3b3Sdrh char *zName; 1949c2eef3b3Sdrh Tcl_CmdProc *xProc; 1950c2eef3b3Sdrh } aCmd[] = { 19516f8a503dSdanielk1977 { "sqlite3_mprintf_int", (Tcl_CmdProc*)sqlite3_mprintf_int }, 19526f8a503dSdanielk1977 { "sqlite3_mprintf_str", (Tcl_CmdProc*)sqlite3_mprintf_str }, 19536f8a503dSdanielk1977 { "sqlite3_mprintf_double", (Tcl_CmdProc*)sqlite3_mprintf_double }, 19546f8a503dSdanielk1977 { "sqlite3_mprintf_scaled", (Tcl_CmdProc*)sqlite3_mprintf_scaled }, 19556f8a503dSdanielk1977 { "sqlite3_mprintf_z_test", (Tcl_CmdProc*)test_mprintf_z }, 19566f8a503dSdanielk1977 { "sqlite3_last_insert_rowid", (Tcl_CmdProc*)test_last_rowid }, 19576f8a503dSdanielk1977 { "sqlite3_exec_printf", (Tcl_CmdProc*)test_exec_printf }, 19586f8a503dSdanielk1977 { "sqlite3_get_table_printf", (Tcl_CmdProc*)test_get_table_printf }, 19596f8a503dSdanielk1977 { "sqlite3_close", (Tcl_CmdProc*)sqlite_test_close }, 19606f8a503dSdanielk1977 { "sqlite3_create_function", (Tcl_CmdProc*)test_create_function }, 19616f8a503dSdanielk1977 { "sqlite3_create_aggregate", (Tcl_CmdProc*)test_create_aggregate }, 1962c2eef3b3Sdrh { "sqlite_register_test_function", (Tcl_CmdProc*)test_register_func }, 1963c2eef3b3Sdrh { "sqlite_abort", (Tcl_CmdProc*)sqlite_abort }, 1964faa57accSdrh #ifdef SQLITE_DEBUG 1965c2eef3b3Sdrh { "sqlite_malloc_fail", (Tcl_CmdProc*)sqlite_malloc_fail }, 1966c2eef3b3Sdrh { "sqlite_malloc_stat", (Tcl_CmdProc*)sqlite_malloc_stat }, 1967c2eef3b3Sdrh #endif 196896fc5fe6Sdanielk1977 { "sqlite_bind", (Tcl_CmdProc*)test_bind }, 196999ee3600Sdrh { "breakpoint", (Tcl_CmdProc*)test_breakpoint }, 1970c2eef3b3Sdrh }; 197151e3d8e2Sdanielk1977 static struct { 197251e3d8e2Sdanielk1977 char *zName; 197351e3d8e2Sdanielk1977 Tcl_ObjCmdProc *xProc; 197404f2e68dSdanielk1977 void *clientData; 197551e3d8e2Sdanielk1977 } aObjCmd[] = { 197604f2e68dSdanielk1977 { "sqlite3_bind_int32", test_bind_int32, 0 }, 197704f2e68dSdanielk1977 { "sqlite3_bind_int64", test_bind_int64 , 0 }, 197804f2e68dSdanielk1977 { "sqlite3_bind_double", test_bind_double, 0 }, 197904f2e68dSdanielk1977 { "sqlite3_bind_null", test_bind_null ,0 }, 198004f2e68dSdanielk1977 { "sqlite3_bind_text", test_bind_text ,0 }, 198104f2e68dSdanielk1977 { "sqlite3_bind_text16", test_bind_text16 ,0 }, 198204f2e68dSdanielk1977 { "sqlite3_bind_blob", test_bind_blob ,0 }, 198304f2e68dSdanielk1977 { "sqlite3_errcode", test_errcode ,0 }, 198404f2e68dSdanielk1977 { "sqlite3_errmsg", test_errmsg ,0 }, 198504f2e68dSdanielk1977 { "sqlite3_errmsg16", test_errmsg16 ,0 }, 198604f2e68dSdanielk1977 { "sqlite3_open", test_open ,0 }, 198704f2e68dSdanielk1977 { "sqlite3_open16", test_open16 ,0 }, 198804f2e68dSdanielk1977 198904f2e68dSdanielk1977 { "sqlite3_prepare", test_prepare ,0 }, 199004f2e68dSdanielk1977 { "sqlite3_prepare16", test_prepare16 ,0 }, 199104f2e68dSdanielk1977 { "sqlite3_finalize", test_finalize ,0 }, 199204f2e68dSdanielk1977 { "sqlite3_reset", test_reset ,0 }, 1993fbcd585fSdanielk1977 { "sqlite3_changes", test_changes ,0 }, 199404f2e68dSdanielk1977 { "sqlite3_step", test_step ,0 }, 199504f2e68dSdanielk1977 199604f2e68dSdanielk1977 /* sqlite3_column_*() API */ 199704f2e68dSdanielk1977 { "sqlite3_column_count", test_column_count ,0 }, 199804f2e68dSdanielk1977 { "sqlite3_data_count", test_data_count ,0 }, 199904f2e68dSdanielk1977 { "sqlite3_column_type", test_column_type ,0 }, 2000ea61b2c4Sdanielk1977 { "sqlite3_column_blob", test_column_blob ,0 }, 200104f2e68dSdanielk1977 { "sqlite3_column_double", test_column_double ,0 }, 200204f2e68dSdanielk1977 { "sqlite3_column_int64", test_column_int64 ,0 }, 200304f2e68dSdanielk1977 { "sqlite3_column_int", test_stmt_int ,sqlite3_column_int }, 200404f2e68dSdanielk1977 { "sqlite3_column_bytes", test_stmt_int ,sqlite3_column_bytes }, 200504f2e68dSdanielk1977 { "sqlite3_column_bytes16", test_stmt_int ,sqlite3_column_bytes16 }, 200604f2e68dSdanielk1977 { "sqlite3_column_text", test_stmt_utf8, sqlite3_column_text}, 200704f2e68dSdanielk1977 { "sqlite3_column_decltype", test_stmt_utf8, sqlite3_column_decltype}, 200804f2e68dSdanielk1977 { "sqlite3_column_name", test_stmt_utf8, sqlite3_column_name}, 200904f2e68dSdanielk1977 { "sqlite3_column_text16", test_stmt_utf16, sqlite3_column_text16}, 201004f2e68dSdanielk1977 { "sqlite3_column_decltype16", test_stmt_utf16,sqlite3_column_decltype16}, 201104f2e68dSdanielk1977 { "sqlite3_column_name16", test_stmt_utf16, sqlite3_column_name16}, 201204f2e68dSdanielk1977 20139a1d0abeSdanielk1977 /* Functions from os.h */ 20149a1d0abeSdanielk1977 { "sqlite3OsOpenReadWrite",test_sqlite3OsOpenReadWrite, 0 }, 20159a1d0abeSdanielk1977 { "sqlite3OsClose", test_sqlite3OsClose, 0 }, 20169a1d0abeSdanielk1977 { "sqlite3OsLock", test_sqlite3OsLock, 0 }, 20179a1d0abeSdanielk1977 { "sqlite3OsUnlock", test_sqlite3OsUnlock, 0 }, 20184e6af134Sdanielk1977 { "add_test_collate", test_collate, 0 }, 2019*8a6c550dSdanielk1977 { "sqlite3_crashseed", sqlite3_crashseed, 0 }, 20209a1d0abeSdanielk1977 202151e3d8e2Sdanielk1977 }; 2022c2eef3b3Sdrh int i; 20232ac3ee97Sdrh extern int sqlite3_os_trace; 2024c2eef3b3Sdrh 2025c2eef3b3Sdrh for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){ 2026c2eef3b3Sdrh Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0); 2027c2eef3b3Sdrh } 202851e3d8e2Sdanielk1977 for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){ 2029c572ef7fSdanielk1977 Tcl_CreateObjCommand(interp, aObjCmd[i].zName, 2030c572ef7fSdanielk1977 aObjCmd[i].xProc, aObjCmd[i].clientData, 0); 203151e3d8e2Sdanielk1977 } 20326490bebdSdanielk1977 Tcl_LinkVar(interp, "sqlite_search_count", 20336f8a503dSdanielk1977 (char*)&sqlite3_search_count, TCL_LINK_INT); 20346490bebdSdanielk1977 Tcl_LinkVar(interp, "sqlite_interrupt_count", 20356f8a503dSdanielk1977 (char*)&sqlite3_interrupt_count, TCL_LINK_INT); 20366490bebdSdanielk1977 Tcl_LinkVar(interp, "sqlite_open_file_count", 20376f8a503dSdanielk1977 (char*)&sqlite3_open_file_count, TCL_LINK_INT); 20386490bebdSdanielk1977 Tcl_LinkVar(interp, "sqlite_current_time", 20396f8a503dSdanielk1977 (char*)&sqlite3_current_time, TCL_LINK_INT); 20402ac3ee97Sdrh Tcl_LinkVar(interp, "sqlite_os_trace", 20412ac3ee97Sdrh (char*)&sqlite3_os_trace, TCL_LINK_INT); 20427c972decSdrh Tcl_LinkVar(interp, "sqlite_static_bind_value", 20437c972decSdrh (char*)&sqlite_static_bind_value, TCL_LINK_STRING); 2044d1bf3512Sdrh return TCL_OK; 2045d1bf3512Sdrh } 2046