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*9d213ef0Sdrh ** $Id: test1.c,v 1.91 2004/06/30 04:02:12 drh Exp $ 17d1bf3512Sdrh */ 18d1bf3512Sdrh #include "sqliteInt.h" 19d1bf3512Sdrh #include "tcl.h" 2094e92032Sdrh #include "os.h" 21d1bf3512Sdrh #include <stdlib.h> 22d1bf3512Sdrh #include <string.h> 23d1bf3512Sdrh 2494e92032Sdrh #if OS_WIN 2594e92032Sdrh # define PTR_FMT "%x" 2694e92032Sdrh #else 2794e92032Sdrh # define PTR_FMT "%p" 2894e92032Sdrh #endif 2994e92032Sdrh 30c572ef7fSdanielk1977 int sqlite3_exec_printf( 31c572ef7fSdanielk1977 sqlite *db, /* An open database */ 32c572ef7fSdanielk1977 const char *sqlFormat, /* printf-style format string for the SQL */ 33c572ef7fSdanielk1977 sqlite_callback xCallback, /* Callback function */ 34c572ef7fSdanielk1977 void *pArg, /* 1st argument to callback function */ 35c572ef7fSdanielk1977 char **errmsg, /* Error msg written here */ 36c572ef7fSdanielk1977 ... /* Arguments to the format string. */ 37c572ef7fSdanielk1977 ); 38c572ef7fSdanielk1977 int sqlite3_get_table_printf( 39c572ef7fSdanielk1977 sqlite *db, /* An open database */ 40c572ef7fSdanielk1977 const char *sqlFormat, /* printf-style format string for the SQL */ 41c572ef7fSdanielk1977 char ***resultp, /* Result written to a char *[] that this points to */ 42c572ef7fSdanielk1977 int *nrow, /* Number of result rows written here */ 43c572ef7fSdanielk1977 int *ncol, /* Number of result columns written here */ 44c572ef7fSdanielk1977 char **errmsg, /* Error msg written here */ 45c572ef7fSdanielk1977 ... /* Arguments to the format string */ 46c572ef7fSdanielk1977 ); 47c572ef7fSdanielk1977 486622cce3Sdanielk1977 static const char * errorName(int rc){ 496622cce3Sdanielk1977 const char *zName = 0; 506622cce3Sdanielk1977 switch( rc ){ 516622cce3Sdanielk1977 case SQLITE_OK: zName = "SQLITE_OK"; break; 526622cce3Sdanielk1977 case SQLITE_ERROR: zName = "SQLITE_ERROR"; break; 536622cce3Sdanielk1977 case SQLITE_INTERNAL: zName = "SQLITE_INTERNAL"; break; 546622cce3Sdanielk1977 case SQLITE_PERM: zName = "SQLITE_PERM"; break; 556622cce3Sdanielk1977 case SQLITE_ABORT: zName = "SQLITE_ABORT"; break; 566622cce3Sdanielk1977 case SQLITE_BUSY: zName = "SQLITE_BUSY"; break; 576622cce3Sdanielk1977 case SQLITE_LOCKED: zName = "SQLITE_LOCKED"; break; 586622cce3Sdanielk1977 case SQLITE_NOMEM: zName = "SQLITE_NOMEM"; break; 596622cce3Sdanielk1977 case SQLITE_READONLY: zName = "SQLITE_READONLY"; break; 606622cce3Sdanielk1977 case SQLITE_INTERRUPT: zName = "SQLITE_INTERRUPT"; break; 616622cce3Sdanielk1977 case SQLITE_IOERR: zName = "SQLITE_IOERR"; break; 626622cce3Sdanielk1977 case SQLITE_CORRUPT: zName = "SQLITE_CORRUPT"; break; 636622cce3Sdanielk1977 case SQLITE_NOTFOUND: zName = "SQLITE_NOTFOUND"; break; 646622cce3Sdanielk1977 case SQLITE_FULL: zName = "SQLITE_FULL"; break; 656622cce3Sdanielk1977 case SQLITE_CANTOPEN: zName = "SQLITE_CANTOPEN"; break; 666622cce3Sdanielk1977 case SQLITE_PROTOCOL: zName = "SQLITE_PROTOCOL"; break; 676622cce3Sdanielk1977 case SQLITE_EMPTY: zName = "SQLITE_EMPTY"; break; 686622cce3Sdanielk1977 case SQLITE_SCHEMA: zName = "SQLITE_SCHEMA"; break; 696622cce3Sdanielk1977 case SQLITE_TOOBIG: zName = "SQLITE_TOOBIG"; break; 706622cce3Sdanielk1977 case SQLITE_CONSTRAINT: zName = "SQLITE_CONSTRAINT"; break; 716622cce3Sdanielk1977 case SQLITE_MISMATCH: zName = "SQLITE_MISMATCH"; break; 726622cce3Sdanielk1977 case SQLITE_MISUSE: zName = "SQLITE_MISUSE"; break; 736622cce3Sdanielk1977 case SQLITE_NOLFS: zName = "SQLITE_NOLFS"; break; 746622cce3Sdanielk1977 case SQLITE_AUTH: zName = "SQLITE_AUTH"; break; 756622cce3Sdanielk1977 case SQLITE_FORMAT: zName = "SQLITE_FORMAT"; break; 766622cce3Sdanielk1977 case SQLITE_RANGE: zName = "SQLITE_RANGE"; break; 776622cce3Sdanielk1977 case SQLITE_ROW: zName = "SQLITE_ROW"; break; 786622cce3Sdanielk1977 case SQLITE_DONE: zName = "SQLITE_DONE"; break; 79312d6b36Sdanielk1977 case SQLITE_NOTADB: zName = "SQLITE_NOTADB"; break; 806622cce3Sdanielk1977 default: zName = "SQLITE_Unknown"; break; 816622cce3Sdanielk1977 } 826622cce3Sdanielk1977 return zName; 836622cce3Sdanielk1977 } 846622cce3Sdanielk1977 85d1bf3512Sdrh /* 86b86ccfb2Sdrh ** Decode a pointer to an sqlite object. 87b86ccfb2Sdrh */ 8890f405e3Sdrh static int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite **ppDb){ 8990f405e3Sdrh if( sscanf(zA, PTR_FMT, (void**)ppDb)!=1 && 9090f405e3Sdrh (zA[0]!='0' || zA[1]!='x' || sscanf(&zA[2], PTR_FMT, (void**)ppDb)!=1) 9190f405e3Sdrh ){ 9290f405e3Sdrh Tcl_AppendResult(interp, "\"", zA, "\" is not a valid pointer value", 0); 93b86ccfb2Sdrh return TCL_ERROR; 94b86ccfb2Sdrh } 95b86ccfb2Sdrh return TCL_OK; 96b86ccfb2Sdrh } 97b86ccfb2Sdrh 98b86ccfb2Sdrh /* 9951e3d8e2Sdanielk1977 ** Decode a pointer to an sqlite3_stmt object. 10051e3d8e2Sdanielk1977 */ 10151e3d8e2Sdanielk1977 static int getStmtPointer( 10251e3d8e2Sdanielk1977 Tcl_Interp *interp, 10351e3d8e2Sdanielk1977 const char *zArg, 10451e3d8e2Sdanielk1977 sqlite3_stmt **ppStmt 10551e3d8e2Sdanielk1977 ){ 10651e3d8e2Sdanielk1977 if( sscanf(zArg, PTR_FMT, (void**)ppStmt)!=1 ){ 10751e3d8e2Sdanielk1977 Tcl_AppendResult(interp, "\"", zArg, "\" is not a valid pointer value", 0); 10851e3d8e2Sdanielk1977 return TCL_ERROR; 10951e3d8e2Sdanielk1977 } 11051e3d8e2Sdanielk1977 return TCL_OK; 11151e3d8e2Sdanielk1977 } 11251e3d8e2Sdanielk1977 11351e3d8e2Sdanielk1977 /* 1149a1d0abeSdanielk1977 ** Decode a pointer to an sqlite3_stmt object. 1159a1d0abeSdanielk1977 */ 1169a1d0abeSdanielk1977 static int getFilePointer( 1179a1d0abeSdanielk1977 Tcl_Interp *interp, 1189a1d0abeSdanielk1977 const char *zArg, 1199a1d0abeSdanielk1977 OsFile **ppFile 1209a1d0abeSdanielk1977 ){ 1219a1d0abeSdanielk1977 if( sscanf(zArg, PTR_FMT, (void**)ppFile)!=1 ){ 1229a1d0abeSdanielk1977 Tcl_AppendResult(interp, "\"", zArg, "\" is not a valid pointer value", 0); 1239a1d0abeSdanielk1977 return TCL_ERROR; 1249a1d0abeSdanielk1977 } 1259a1d0abeSdanielk1977 return TCL_OK; 1269a1d0abeSdanielk1977 } 1279a1d0abeSdanielk1977 1289a1d0abeSdanielk1977 /* 1297d8085a8Sdrh ** Generate a text representation of a pointer that can be understood 1307d8085a8Sdrh ** by the getDbPointer and getVmPointer routines above. 1317d8085a8Sdrh ** 1327d8085a8Sdrh ** The problem is, on some machines (Solaris) if you do a printf with 1337d8085a8Sdrh ** "%p" you cannot turn around and do a scanf with the same "%p" and 1347d8085a8Sdrh ** get your pointer back. You have to prepend a "0x" before it will 1357d8085a8Sdrh ** work. Or at least that is what is reported to me (drh). But this 1367d8085a8Sdrh ** behavior varies from machine to machine. The solution used her is 1377d8085a8Sdrh ** to test the string right after it is generated to see if it can be 1387d8085a8Sdrh ** understood by scanf, and if not, try prepending an "0x" to see if 1397d8085a8Sdrh ** that helps. If nothing works, a fatal error is generated. 1407d8085a8Sdrh */ 1417d8085a8Sdrh static int makePointerStr(Tcl_Interp *interp, char *zPtr, void *p){ 1427d8085a8Sdrh void *p2; 1437d8085a8Sdrh sprintf(zPtr, PTR_FMT, p); 1447d8085a8Sdrh if( sscanf(zPtr, PTR_FMT, &p2)!=1 || p2!=p ){ 1457d8085a8Sdrh sprintf(zPtr, "0x" PTR_FMT, p); 1467d8085a8Sdrh if( sscanf(zPtr, PTR_FMT, &p2)!=1 || p2!=p ){ 1477d8085a8Sdrh Tcl_AppendResult(interp, "unable to convert a pointer to a string " 1487d8085a8Sdrh "in the file " __FILE__ " in function makePointerStr(). Please " 1497d8085a8Sdrh "report this problem to the SQLite mailing list or as a new but " 1507d8085a8Sdrh "report. Please provide detailed information about how you compiled " 1517d8085a8Sdrh "SQLite and what computer you are running on.", 0); 1527d8085a8Sdrh return TCL_ERROR; 1537d8085a8Sdrh } 1547d8085a8Sdrh } 1557d8085a8Sdrh return TCL_OK; 1567d8085a8Sdrh } 1577d8085a8Sdrh 1587d8085a8Sdrh /* 1596f8a503dSdanielk1977 ** The callback routine for sqlite3_exec_printf(). 160d1bf3512Sdrh */ 161d1bf3512Sdrh static int exec_printf_cb(void *pArg, int argc, char **argv, char **name){ 162d1bf3512Sdrh Tcl_DString *str = (Tcl_DString*)pArg; 163d1bf3512Sdrh int i; 164d1bf3512Sdrh 165d1bf3512Sdrh if( Tcl_DStringLength(str)==0 ){ 166d1bf3512Sdrh for(i=0; i<argc; i++){ 167d1bf3512Sdrh Tcl_DStringAppendElement(str, name[i] ? name[i] : "NULL"); 168d1bf3512Sdrh } 169d1bf3512Sdrh } 170d1bf3512Sdrh for(i=0; i<argc; i++){ 171d1bf3512Sdrh Tcl_DStringAppendElement(str, argv[i] ? argv[i] : "NULL"); 172d1bf3512Sdrh } 173d1bf3512Sdrh return 0; 174d1bf3512Sdrh } 175d1bf3512Sdrh 176d1bf3512Sdrh /* 1776f8a503dSdanielk1977 ** Usage: sqlite3_exec_printf DB FORMAT STRING 178d1bf3512Sdrh ** 1796f8a503dSdanielk1977 ** Invoke the sqlite3_exec_printf() interface using the open database 180d1bf3512Sdrh ** DB. The SQL is the string FORMAT. The format string should contain 181d1bf3512Sdrh ** one %s or %q. STRING is the value inserted into %s or %q. 182d1bf3512Sdrh */ 183d1bf3512Sdrh static int test_exec_printf( 184d1bf3512Sdrh void *NotUsed, 185d1bf3512Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 186d1bf3512Sdrh int argc, /* Number of arguments */ 187d1bf3512Sdrh char **argv /* Text of each argument */ 188d1bf3512Sdrh ){ 189d1bf3512Sdrh sqlite *db; 190d1bf3512Sdrh Tcl_DString str; 191d1bf3512Sdrh int rc; 192d1bf3512Sdrh char *zErr = 0; 193d1bf3512Sdrh char zBuf[30]; 194d1bf3512Sdrh if( argc!=4 ){ 195d1bf3512Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 196d1bf3512Sdrh " DB FORMAT STRING", 0); 197d1bf3512Sdrh return TCL_ERROR; 198d1bf3512Sdrh } 199b86ccfb2Sdrh if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; 200d1bf3512Sdrh Tcl_DStringInit(&str); 2016f8a503dSdanielk1977 rc = sqlite3_exec_printf(db, argv[2], exec_printf_cb, &str, &zErr, argv[3]); 202d1bf3512Sdrh sprintf(zBuf, "%d", rc); 203d1bf3512Sdrh Tcl_AppendElement(interp, zBuf); 204d1bf3512Sdrh Tcl_AppendElement(interp, rc==SQLITE_OK ? Tcl_DStringValue(&str) : zErr); 205d1bf3512Sdrh Tcl_DStringFree(&str); 206d1bf3512Sdrh if( zErr ) free(zErr); 207d1bf3512Sdrh return TCL_OK; 208d1bf3512Sdrh } 209d1bf3512Sdrh 210d1bf3512Sdrh /* 2116f8a503dSdanielk1977 ** Usage: sqlite3_mprintf_z_test SEPARATOR ARG0 ARG1 ... 212d93d8a81Sdrh ** 213d93d8a81Sdrh ** Test the %z format of mprintf(). Use multiple mprintf() calls to 214d93d8a81Sdrh ** concatenate arg0 through argn using separator as the separator. 215d93d8a81Sdrh ** Return the result. 216d93d8a81Sdrh */ 217d93d8a81Sdrh static int test_mprintf_z( 218d93d8a81Sdrh void *NotUsed, 219d93d8a81Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 220d93d8a81Sdrh int argc, /* Number of arguments */ 221d93d8a81Sdrh char **argv /* Text of each argument */ 222d93d8a81Sdrh ){ 223d93d8a81Sdrh char *zResult = 0; 224d93d8a81Sdrh int i; 225d93d8a81Sdrh 226d93d8a81Sdrh for(i=2; i<argc; i++){ 2274adee20fSdanielk1977 zResult = sqlite3MPrintf("%z%s%s", zResult, argv[1], argv[i]); 228d93d8a81Sdrh } 229d93d8a81Sdrh Tcl_AppendResult(interp, zResult, 0); 2305f968436Sdrh sqliteFree(zResult); 231d93d8a81Sdrh return TCL_OK; 232d93d8a81Sdrh } 233d93d8a81Sdrh 234d93d8a81Sdrh /* 2356f8a503dSdanielk1977 ** Usage: sqlite3_get_table_printf DB FORMAT STRING 236d1bf3512Sdrh ** 2376f8a503dSdanielk1977 ** Invoke the sqlite3_get_table_printf() interface using the open database 238d1bf3512Sdrh ** DB. The SQL is the string FORMAT. The format string should contain 239d1bf3512Sdrh ** one %s or %q. STRING is the value inserted into %s or %q. 240d1bf3512Sdrh */ 241d1bf3512Sdrh static int test_get_table_printf( 242d1bf3512Sdrh void *NotUsed, 243d1bf3512Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 244d1bf3512Sdrh int argc, /* Number of arguments */ 245d1bf3512Sdrh char **argv /* Text of each argument */ 246d1bf3512Sdrh ){ 247d1bf3512Sdrh sqlite *db; 248d1bf3512Sdrh Tcl_DString str; 249d1bf3512Sdrh int rc; 250d1bf3512Sdrh char *zErr = 0; 251d1bf3512Sdrh int nRow, nCol; 252d1bf3512Sdrh char **aResult; 253d1bf3512Sdrh int i; 254d1bf3512Sdrh char zBuf[30]; 255d1bf3512Sdrh if( argc!=4 ){ 256d1bf3512Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 257d1bf3512Sdrh " DB FORMAT STRING", 0); 258d1bf3512Sdrh return TCL_ERROR; 259d1bf3512Sdrh } 260b86ccfb2Sdrh if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; 261d1bf3512Sdrh Tcl_DStringInit(&str); 2626f8a503dSdanielk1977 rc = sqlite3_get_table_printf(db, argv[2], &aResult, &nRow, &nCol, 263d1bf3512Sdrh &zErr, argv[3]); 264d1bf3512Sdrh sprintf(zBuf, "%d", rc); 265d1bf3512Sdrh Tcl_AppendElement(interp, zBuf); 266d1bf3512Sdrh if( rc==SQLITE_OK ){ 267d1bf3512Sdrh sprintf(zBuf, "%d", nRow); 268d1bf3512Sdrh Tcl_AppendElement(interp, zBuf); 269d1bf3512Sdrh sprintf(zBuf, "%d", nCol); 270d1bf3512Sdrh Tcl_AppendElement(interp, zBuf); 271d1bf3512Sdrh for(i=0; i<(nRow+1)*nCol; i++){ 272d1bf3512Sdrh Tcl_AppendElement(interp, aResult[i] ? aResult[i] : "NULL"); 273d1bf3512Sdrh } 274d1bf3512Sdrh }else{ 275d1bf3512Sdrh Tcl_AppendElement(interp, zErr); 276d1bf3512Sdrh } 2776f8a503dSdanielk1977 sqlite3_free_table(aResult); 278d1bf3512Sdrh if( zErr ) free(zErr); 279d1bf3512Sdrh return TCL_OK; 280d1bf3512Sdrh } 281d1bf3512Sdrh 282af9ff33aSdrh 283af9ff33aSdrh /* 2846f8a503dSdanielk1977 ** Usage: sqlite3_last_insert_rowid DB 285af9ff33aSdrh ** 286af9ff33aSdrh ** Returns the integer ROWID of the most recent insert. 287af9ff33aSdrh */ 288af9ff33aSdrh static int test_last_rowid( 289af9ff33aSdrh void *NotUsed, 290af9ff33aSdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 291af9ff33aSdrh int argc, /* Number of arguments */ 292af9ff33aSdrh char **argv /* Text of each argument */ 293af9ff33aSdrh ){ 294af9ff33aSdrh sqlite *db; 295af9ff33aSdrh char zBuf[30]; 296af9ff33aSdrh 297af9ff33aSdrh if( argc!=2 ){ 298af9ff33aSdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " DB\"", 0); 299af9ff33aSdrh return TCL_ERROR; 300af9ff33aSdrh } 301b86ccfb2Sdrh if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; 302c572ef7fSdanielk1977 sprintf(zBuf, "%lld", sqlite3_last_insert_rowid(db)); 303af9ff33aSdrh Tcl_AppendResult(interp, zBuf, 0); 304af9ff33aSdrh return SQLITE_OK; 305af9ff33aSdrh } 306af9ff33aSdrh 307d1bf3512Sdrh /* 3086f8a503dSdanielk1977 ** Usage: sqlite3_close DB 309d1bf3512Sdrh ** 3106f8a503dSdanielk1977 ** Closes the database opened by sqlite3_open. 311d1bf3512Sdrh */ 312d1bf3512Sdrh static int sqlite_test_close( 313d1bf3512Sdrh void *NotUsed, 314d1bf3512Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 315d1bf3512Sdrh int argc, /* Number of arguments */ 316d1bf3512Sdrh char **argv /* Text of each argument */ 317d1bf3512Sdrh ){ 318d1bf3512Sdrh sqlite *db; 31996d81f99Sdanielk1977 int rc; 320d1bf3512Sdrh if( argc!=2 ){ 321d1bf3512Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 322d1bf3512Sdrh " FILENAME\"", 0); 323d1bf3512Sdrh return TCL_ERROR; 324d1bf3512Sdrh } 325b86ccfb2Sdrh if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; 32696d81f99Sdanielk1977 rc = sqlite3_close(db); 327f9d64d2cSdanielk1977 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC); 328d1bf3512Sdrh return TCL_OK; 329d1bf3512Sdrh } 330d1bf3512Sdrh 331d1bf3512Sdrh /* 332c22bd47dSdrh ** Implementation of the x_coalesce() function. 333c22bd47dSdrh ** Return the first argument non-NULL argument. 334c22bd47dSdrh */ 3350ae8b831Sdanielk1977 static void ifnullFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ 336c22bd47dSdrh int i; 337c22bd47dSdrh for(i=0; i<argc; i++){ 3389c054830Sdrh if( SQLITE_NULL!=sqlite3_value_type(argv[i]) ){ 339d8123366Sdanielk1977 sqlite3_result_text(context, sqlite3_value_text(argv[i]), -1, 340d8123366Sdanielk1977 SQLITE_TRANSIENT); 341c22bd47dSdrh break; 342c22bd47dSdrh } 343c22bd47dSdrh } 344c22bd47dSdrh } 345c22bd47dSdrh 346c22bd47dSdrh /* 347d1d9fc33Sdrh ** A structure into which to accumulate text. 348d1d9fc33Sdrh */ 349d1d9fc33Sdrh struct dstr { 350d1d9fc33Sdrh int nAlloc; /* Space allocated */ 351d1d9fc33Sdrh int nUsed; /* Space used */ 352d1d9fc33Sdrh char *z; /* The space */ 353d1d9fc33Sdrh }; 354d1d9fc33Sdrh 355d1d9fc33Sdrh /* 356d1d9fc33Sdrh ** Append text to a dstr 357d1d9fc33Sdrh */ 358d1d9fc33Sdrh static void dstrAppend(struct dstr *p, const char *z, int divider){ 359d1d9fc33Sdrh int n = strlen(z); 360d1d9fc33Sdrh if( p->nUsed + n + 2 > p->nAlloc ){ 361d1d9fc33Sdrh char *zNew; 362d1d9fc33Sdrh p->nAlloc = p->nAlloc*2 + n + 200; 363d1d9fc33Sdrh zNew = sqliteRealloc(p->z, p->nAlloc); 364d1d9fc33Sdrh if( zNew==0 ){ 365d1d9fc33Sdrh sqliteFree(p->z); 366d1d9fc33Sdrh memset(p, 0, sizeof(*p)); 367d1d9fc33Sdrh return; 368d1d9fc33Sdrh } 369d1d9fc33Sdrh p->z = zNew; 370d1d9fc33Sdrh } 371d1d9fc33Sdrh if( divider && p->nUsed>0 ){ 372d1d9fc33Sdrh p->z[p->nUsed++] = divider; 373d1d9fc33Sdrh } 374d1d9fc33Sdrh memcpy(&p->z[p->nUsed], z, n+1); 375d1d9fc33Sdrh p->nUsed += n; 376d1d9fc33Sdrh } 377d1d9fc33Sdrh 378d1d9fc33Sdrh /* 3794adee20fSdanielk1977 ** Invoked for each callback from sqlite3ExecFunc 380d1d9fc33Sdrh */ 381d1d9fc33Sdrh static int execFuncCallback(void *pData, int argc, char **argv, char **NotUsed){ 382d1d9fc33Sdrh struct dstr *p = (struct dstr*)pData; 383d1d9fc33Sdrh int i; 384d1d9fc33Sdrh for(i=0; i<argc; i++){ 385d1d9fc33Sdrh if( argv[i]==0 ){ 386d1d9fc33Sdrh dstrAppend(p, "NULL", ' '); 387d1d9fc33Sdrh }else{ 388d1d9fc33Sdrh dstrAppend(p, argv[i], ' '); 389d1d9fc33Sdrh } 390d1d9fc33Sdrh } 391d1d9fc33Sdrh return 0; 392d1d9fc33Sdrh } 393d1d9fc33Sdrh 394d1d9fc33Sdrh /* 395e35ee196Sdanielk1977 ** Implementation of the x_sqlite_exec() function. This function takes 396c22bd47dSdrh ** a single argument and attempts to execute that argument as SQL code. 3976cbe1f1bSdrh ** This is illegal and should set the SQLITE_MISUSE flag on the database. 398c22bd47dSdrh ** 3996f8a503dSdanielk1977 ** 2004-Jan-07: We have changed this to make it legal to call sqlite3_exec() 400d1d9fc33Sdrh ** from within a function call. 401d1d9fc33Sdrh ** 402c22bd47dSdrh ** This routine simulates the effect of having two threads attempt to 403c22bd47dSdrh ** use the same database at the same time. 404c22bd47dSdrh */ 40551ad0ecdSdanielk1977 static void sqlite3ExecFunc( 4060ae8b831Sdanielk1977 sqlite3_context *context, 40751ad0ecdSdanielk1977 int argc, 40851ad0ecdSdanielk1977 sqlite3_value **argv 40951ad0ecdSdanielk1977 ){ 410d1d9fc33Sdrh struct dstr x; 411d1d9fc33Sdrh memset(&x, 0, sizeof(x)); 41251ad0ecdSdanielk1977 sqlite3_exec((sqlite*)sqlite3_user_data(context), 4134f26d6c4Sdrh sqlite3_value_text(argv[0]), 414d1d9fc33Sdrh execFuncCallback, &x, 0); 415d8123366Sdanielk1977 sqlite3_result_text(context, x.z, x.nUsed, SQLITE_TRANSIENT); 416d1d9fc33Sdrh sqliteFree(x.z); 417c22bd47dSdrh } 418c22bd47dSdrh 419c22bd47dSdrh /* 420c22bd47dSdrh ** Usage: sqlite_test_create_function DB 421c22bd47dSdrh ** 4226f8a503dSdanielk1977 ** Call the sqlite3_create_function API on the given database in order 423c22bd47dSdrh ** to create a function named "x_coalesce". This function does the same thing 424c22bd47dSdrh ** as the "coalesce" function. This function also registers an SQL function 425e35ee196Sdanielk1977 ** named "x_sqlite_exec" that invokes sqlite3_exec(). Invoking sqlite3_exec() 426c22bd47dSdrh ** in this way is illegal recursion and should raise an SQLITE_MISUSE error. 427c22bd47dSdrh ** The effect is similar to trying to use the same database connection from 428c22bd47dSdrh ** two threads at the same time. 429c22bd47dSdrh ** 430c22bd47dSdrh ** The original motivation for this routine was to be able to call the 4316f8a503dSdanielk1977 ** sqlite3_create_function function while a query is in progress in order 432c22bd47dSdrh ** to test the SQLITE_MISUSE detection logic. 433c22bd47dSdrh */ 434c2eef3b3Sdrh static int test_create_function( 435c22bd47dSdrh void *NotUsed, 436c22bd47dSdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 437c22bd47dSdrh int argc, /* Number of arguments */ 438c22bd47dSdrh char **argv /* Text of each argument */ 439c22bd47dSdrh ){ 440c22bd47dSdrh sqlite *db; 441312d6b36Sdanielk1977 sqlite3_value *pVal; 442c22bd47dSdrh extern void Md5_Register(sqlite*); 443312d6b36Sdanielk1977 444c22bd47dSdrh if( argc!=2 ){ 445c22bd47dSdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 446c22bd47dSdrh " FILENAME\"", 0); 447c22bd47dSdrh return TCL_ERROR; 448c22bd47dSdrh } 449b86ccfb2Sdrh if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; 450312d6b36Sdanielk1977 sqlite3_create_function(db, "x_coalesce", -1, SQLITE_ANY, 0, 451d8123366Sdanielk1977 ifnullFunc, 0, 0); 452312d6b36Sdanielk1977 453312d6b36Sdanielk1977 /* Use the sqlite3_create_function16() API here. Mainly for fun, but also 454312d6b36Sdanielk1977 ** because it is not tested anywhere else. */ 455312d6b36Sdanielk1977 pVal = sqlite3ValueNew(); 456312d6b36Sdanielk1977 sqlite3ValueSetStr(pVal, -1, "x_sqlite_exec", SQLITE_UTF8, SQLITE_STATIC); 457312d6b36Sdanielk1977 sqlite3_create_function16(db, sqlite3ValueText(pVal, SQLITE_UTF16NATIVE), 458312d6b36Sdanielk1977 1, SQLITE_UTF16, db, sqlite3ExecFunc, 0, 0); 459312d6b36Sdanielk1977 sqlite3ValueFree(pVal); 460c22bd47dSdrh return TCL_OK; 461c22bd47dSdrh } 462c22bd47dSdrh 463c22bd47dSdrh /* 464c22bd47dSdrh ** Routines to implement the x_count() aggregate function. 465c22bd47dSdrh */ 466c22bd47dSdrh typedef struct CountCtx CountCtx; 467c22bd47dSdrh struct CountCtx { 468c22bd47dSdrh int n; 469c22bd47dSdrh }; 4700ae8b831Sdanielk1977 static void countStep(sqlite3_context *context, int argc, sqlite3_value **argv){ 471c22bd47dSdrh CountCtx *p; 4724f26d6c4Sdrh p = sqlite3_aggregate_context(context, sizeof(*p)); 4739c054830Sdrh if( (argc==0 || SQLITE_NULL!=sqlite3_value_type(argv[0]) ) && p ){ 474c22bd47dSdrh p->n++; 475c22bd47dSdrh } 476c22bd47dSdrh } 4770ae8b831Sdanielk1977 static void countFinalize(sqlite3_context *context){ 478c22bd47dSdrh CountCtx *p; 4794f26d6c4Sdrh p = sqlite3_aggregate_context(context, sizeof(*p)); 480c572ef7fSdanielk1977 sqlite3_result_int(context, p ? p->n : 0); 481c22bd47dSdrh } 482c22bd47dSdrh 483c22bd47dSdrh /* 484c22bd47dSdrh ** Usage: sqlite_test_create_aggregate DB 485c22bd47dSdrh ** 4866f8a503dSdanielk1977 ** Call the sqlite3_create_function API on the given database in order 487c22bd47dSdrh ** to create a function named "x_count". This function does the same thing 488c22bd47dSdrh ** as the "md5sum" function. 489c22bd47dSdrh ** 490c22bd47dSdrh ** The original motivation for this routine was to be able to call the 4916f8a503dSdanielk1977 ** sqlite3_create_aggregate function while a query is in progress in order 492c22bd47dSdrh ** to test the SQLITE_MISUSE detection logic. 493c22bd47dSdrh */ 494c2eef3b3Sdrh static int test_create_aggregate( 495c22bd47dSdrh void *NotUsed, 496c22bd47dSdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 497c22bd47dSdrh int argc, /* Number of arguments */ 498c22bd47dSdrh char **argv /* Text of each argument */ 499c22bd47dSdrh ){ 500c22bd47dSdrh sqlite *db; 501c22bd47dSdrh if( argc!=2 ){ 502c22bd47dSdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 503c22bd47dSdrh " FILENAME\"", 0); 504c22bd47dSdrh return TCL_ERROR; 505c22bd47dSdrh } 506b86ccfb2Sdrh if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; 507f9d64d2cSdanielk1977 sqlite3_create_function(db, "x_count", 0, SQLITE_UTF8, 0, 0, 508d8123366Sdanielk1977 countStep,countFinalize); 509f9d64d2cSdanielk1977 sqlite3_create_function(db, "x_count", 1, SQLITE_UTF8, 0, 0, 510d8123366Sdanielk1977 countStep,countFinalize); 511c22bd47dSdrh return TCL_OK; 512c22bd47dSdrh } 513c22bd47dSdrh 514c22bd47dSdrh 515c22bd47dSdrh 516c22bd47dSdrh /* 5176f8a503dSdanielk1977 ** Usage: sqlite3_mprintf_int FORMAT INTEGER INTEGER INTEGER 518d1bf3512Sdrh ** 519d1bf3512Sdrh ** Call mprintf with three integer arguments 520d1bf3512Sdrh */ 5216f8a503dSdanielk1977 static int sqlite3_mprintf_int( 522d1bf3512Sdrh void *NotUsed, 523d1bf3512Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 524d1bf3512Sdrh int argc, /* Number of arguments */ 525d1bf3512Sdrh char **argv /* Text of each argument */ 526d1bf3512Sdrh ){ 527d1bf3512Sdrh int a[3], i; 528d1bf3512Sdrh char *z; 529d1bf3512Sdrh if( argc!=5 ){ 530d1bf3512Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 531d1bf3512Sdrh " FORMAT INT INT INT\"", 0); 532d1bf3512Sdrh return TCL_ERROR; 533d1bf3512Sdrh } 534d1bf3512Sdrh for(i=2; i<5; i++){ 535d1bf3512Sdrh if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR; 536d1bf3512Sdrh } 5376f8a503dSdanielk1977 z = sqlite3_mprintf(argv[1], a[0], a[1], a[2]); 538d1bf3512Sdrh Tcl_AppendResult(interp, z, 0); 5393f4fedb2Sdrh sqlite3_free(z); 540d1bf3512Sdrh return TCL_OK; 541d1bf3512Sdrh } 542d1bf3512Sdrh 543d1bf3512Sdrh /* 544*9d213ef0Sdrh ** If zNum represents an integer that will fit in 64-bits, then set 545*9d213ef0Sdrh ** *pValue to that integer and return true. Otherwise return false. 546*9d213ef0Sdrh */ 547*9d213ef0Sdrh static int sqlite3GetInt64(const char *zNum, i64 *pValue){ 548*9d213ef0Sdrh if( sqlite3FitsIn64Bits(zNum) ){ 549*9d213ef0Sdrh sqlite3atoi64(zNum, pValue); 550*9d213ef0Sdrh return 1; 551*9d213ef0Sdrh } 552*9d213ef0Sdrh return 0; 553*9d213ef0Sdrh } 554*9d213ef0Sdrh 555*9d213ef0Sdrh /* 556e9707671Sdrh ** Usage: sqlite3_mprintf_int64 FORMAT INTEGER INTEGER INTEGER 557e9707671Sdrh ** 558e9707671Sdrh ** Call mprintf with three 64-bit integer arguments 559e9707671Sdrh */ 560e9707671Sdrh static int sqlite3_mprintf_int64( 561e9707671Sdrh void *NotUsed, 562e9707671Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 563e9707671Sdrh int argc, /* Number of arguments */ 564e9707671Sdrh char **argv /* Text of each argument */ 565e9707671Sdrh ){ 566e9707671Sdrh int i; 567e9707671Sdrh sqlite_int64 a[3]; 568e9707671Sdrh char *z; 569e9707671Sdrh if( argc!=5 ){ 570e9707671Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 571e9707671Sdrh " FORMAT INT INT INT\"", 0); 572e9707671Sdrh return TCL_ERROR; 573e9707671Sdrh } 574e9707671Sdrh for(i=2; i<5; i++){ 575e9707671Sdrh if( !sqlite3GetInt64(argv[i], &a[i-2]) ){ 576e9707671Sdrh Tcl_AppendResult(interp, "argument is not a valid 64-bit integer", 0); 577e9707671Sdrh return TCL_ERROR; 578e9707671Sdrh } 579e9707671Sdrh } 580e9707671Sdrh z = sqlite3_mprintf(argv[1], a[0], a[1], a[2]); 581e9707671Sdrh Tcl_AppendResult(interp, z, 0); 582e9707671Sdrh sqlite3_free(z); 583e9707671Sdrh return TCL_OK; 584e9707671Sdrh } 585e9707671Sdrh 586e9707671Sdrh /* 5876f8a503dSdanielk1977 ** Usage: sqlite3_mprintf_str FORMAT INTEGER INTEGER STRING 588d1bf3512Sdrh ** 589d1bf3512Sdrh ** Call mprintf with two integer arguments and one string argument 590d1bf3512Sdrh */ 5916f8a503dSdanielk1977 static int sqlite3_mprintf_str( 592d1bf3512Sdrh void *NotUsed, 593d1bf3512Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 594d1bf3512Sdrh int argc, /* Number of arguments */ 595d1bf3512Sdrh char **argv /* Text of each argument */ 596d1bf3512Sdrh ){ 597d1bf3512Sdrh int a[3], i; 598d1bf3512Sdrh char *z; 599f220b24fSchw if( argc<4 || argc>5 ){ 600d1bf3512Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 601f220b24fSchw " FORMAT INT INT ?STRING?\"", 0); 602d1bf3512Sdrh return TCL_ERROR; 603d1bf3512Sdrh } 604d1bf3512Sdrh for(i=2; i<4; i++){ 605d1bf3512Sdrh if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR; 606d1bf3512Sdrh } 6076f8a503dSdanielk1977 z = sqlite3_mprintf(argv[1], a[0], a[1], argc>4 ? argv[4] : NULL); 608d1bf3512Sdrh Tcl_AppendResult(interp, z, 0); 6093f4fedb2Sdrh sqlite3_free(z); 610d1bf3512Sdrh return TCL_OK; 611d1bf3512Sdrh } 612d1bf3512Sdrh 613d1bf3512Sdrh /* 6146f8a503dSdanielk1977 ** Usage: sqlite3_mprintf_str FORMAT INTEGER INTEGER DOUBLE 615d1bf3512Sdrh ** 616d1bf3512Sdrh ** Call mprintf with two integer arguments and one double argument 617d1bf3512Sdrh */ 6186f8a503dSdanielk1977 static int sqlite3_mprintf_double( 619d1bf3512Sdrh void *NotUsed, 620d1bf3512Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 621d1bf3512Sdrh int argc, /* Number of arguments */ 622d1bf3512Sdrh char **argv /* Text of each argument */ 623d1bf3512Sdrh ){ 624d1bf3512Sdrh int a[3], i; 625d1bf3512Sdrh double r; 626d1bf3512Sdrh char *z; 627d1bf3512Sdrh if( argc!=5 ){ 628d1bf3512Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 629d1bf3512Sdrh " FORMAT INT INT STRING\"", 0); 630d1bf3512Sdrh return TCL_ERROR; 631d1bf3512Sdrh } 632d1bf3512Sdrh for(i=2; i<4; i++){ 633d1bf3512Sdrh if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR; 634d1bf3512Sdrh } 635d1bf3512Sdrh if( Tcl_GetDouble(interp, argv[4], &r) ) return TCL_ERROR; 6366f8a503dSdanielk1977 z = sqlite3_mprintf(argv[1], a[0], a[1], r); 637d1bf3512Sdrh Tcl_AppendResult(interp, z, 0); 6383f4fedb2Sdrh sqlite3_free(z); 639d1bf3512Sdrh return TCL_OK; 640d1bf3512Sdrh } 641d1bf3512Sdrh 642d1bf3512Sdrh /* 6436f8a503dSdanielk1977 ** Usage: sqlite3_mprintf_str FORMAT DOUBLE DOUBLE 644b621c237Sdrh ** 645b621c237Sdrh ** Call mprintf with a single double argument which is the product of the 646b621c237Sdrh ** two arguments given above. This is used to generate overflow and underflow 647b621c237Sdrh ** doubles to test that they are converted properly. 648b621c237Sdrh */ 6496f8a503dSdanielk1977 static int sqlite3_mprintf_scaled( 650b621c237Sdrh void *NotUsed, 651b621c237Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 652b621c237Sdrh int argc, /* Number of arguments */ 653b621c237Sdrh char **argv /* Text of each argument */ 654b621c237Sdrh ){ 655b621c237Sdrh int i; 656b621c237Sdrh double r[2]; 657b621c237Sdrh char *z; 658b621c237Sdrh if( argc!=4 ){ 659b621c237Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 660b621c237Sdrh " FORMAT DOUBLE DOUBLE\"", 0); 661b621c237Sdrh return TCL_ERROR; 662b621c237Sdrh } 663b621c237Sdrh for(i=2; i<4; i++){ 664b621c237Sdrh if( Tcl_GetDouble(interp, argv[i], &r[i-2]) ) return TCL_ERROR; 665b621c237Sdrh } 6666f8a503dSdanielk1977 z = sqlite3_mprintf(argv[1], r[0]*r[1]); 667b621c237Sdrh Tcl_AppendResult(interp, z, 0); 6683f4fedb2Sdrh sqlite3_free(z); 669b621c237Sdrh return TCL_OK; 670b621c237Sdrh } 671b621c237Sdrh 672b621c237Sdrh /* 673daffd0e5Sdrh ** Usage: sqlite_malloc_fail N 674daffd0e5Sdrh ** 675afa4a020Sdrh ** Rig sqliteMalloc() to fail on the N-th call. Turn off this mechanism 6766f8a503dSdanielk1977 ** and reset the sqlite3_malloc_failed variable is N==0. 677daffd0e5Sdrh */ 678faa57accSdrh #ifdef SQLITE_DEBUG 679daffd0e5Sdrh static int sqlite_malloc_fail( 680daffd0e5Sdrh void *NotUsed, 681daffd0e5Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 682daffd0e5Sdrh int argc, /* Number of arguments */ 683daffd0e5Sdrh char **argv /* Text of each argument */ 684daffd0e5Sdrh ){ 685daffd0e5Sdrh int n; 686daffd0e5Sdrh if( argc!=2 ){ 687daffd0e5Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " N\"", 0); 688daffd0e5Sdrh return TCL_ERROR; 689daffd0e5Sdrh } 690daffd0e5Sdrh if( Tcl_GetInt(interp, argv[1], &n) ) return TCL_ERROR; 6916f8a503dSdanielk1977 sqlite3_iMallocFail = n; 6926f8a503dSdanielk1977 sqlite3_malloc_failed = 0; 693daffd0e5Sdrh return TCL_OK; 694daffd0e5Sdrh } 695daffd0e5Sdrh #endif 696daffd0e5Sdrh 697daffd0e5Sdrh /* 698daffd0e5Sdrh ** Usage: sqlite_malloc_stat 699daffd0e5Sdrh ** 700daffd0e5Sdrh ** Return the number of prior calls to sqliteMalloc() and sqliteFree(). 701daffd0e5Sdrh */ 702faa57accSdrh #ifdef SQLITE_DEBUG 703daffd0e5Sdrh static int sqlite_malloc_stat( 704daffd0e5Sdrh void *NotUsed, 705daffd0e5Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 706daffd0e5Sdrh int argc, /* Number of arguments */ 707daffd0e5Sdrh char **argv /* Text of each argument */ 708daffd0e5Sdrh ){ 709daffd0e5Sdrh char zBuf[200]; 7106f8a503dSdanielk1977 sprintf(zBuf, "%d %d %d", sqlite3_nMalloc, sqlite3_nFree, sqlite3_iMallocFail); 711daffd0e5Sdrh Tcl_AppendResult(interp, zBuf, 0); 712daffd0e5Sdrh return TCL_OK; 713daffd0e5Sdrh } 714daffd0e5Sdrh #endif 715daffd0e5Sdrh 716daffd0e5Sdrh /* 71728b4e489Sdrh ** Usage: sqlite_abort 71828b4e489Sdrh ** 71928b4e489Sdrh ** Shutdown the process immediately. This is not a clean shutdown. 72028b4e489Sdrh ** This command is used to test the recoverability of a database in 72128b4e489Sdrh ** the event of a program crash. 72228b4e489Sdrh */ 72328b4e489Sdrh static int sqlite_abort( 72428b4e489Sdrh void *NotUsed, 72528b4e489Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 72628b4e489Sdrh int argc, /* Number of arguments */ 72728b4e489Sdrh char **argv /* Text of each argument */ 72828b4e489Sdrh ){ 72928b4e489Sdrh assert( interp==0 ); /* This will always fail */ 73028b4e489Sdrh return TCL_OK; 73128b4e489Sdrh } 73228b4e489Sdrh 73328b4e489Sdrh /* 7346cbe1f1bSdrh ** The following routine is a user-defined SQL function whose purpose 7356cbe1f1bSdrh ** is to test the sqlite_set_result() API. 7366cbe1f1bSdrh */ 7370ae8b831Sdanielk1977 static void testFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ 7386cbe1f1bSdrh while( argc>=2 ){ 7394f26d6c4Sdrh const char *zArg0 = sqlite3_value_text(argv[0]); 7406d88bad4Sdanielk1977 if( zArg0 ){ 7416d88bad4Sdanielk1977 if( 0==sqlite3StrICmp(zArg0, "int") ){ 7426d88bad4Sdanielk1977 sqlite3_result_int(context, sqlite3_value_int(argv[1])); 7436d88bad4Sdanielk1977 }else if( sqlite3StrICmp(zArg0,"int64")==0 ){ 7446d88bad4Sdanielk1977 sqlite3_result_int64(context, sqlite3_value_int64(argv[1])); 74551ad0ecdSdanielk1977 }else if( sqlite3StrICmp(zArg0,"string")==0 ){ 746d8123366Sdanielk1977 sqlite3_result_text(context, sqlite3_value_text(argv[1]), -1, 747d8123366Sdanielk1977 SQLITE_TRANSIENT); 74851ad0ecdSdanielk1977 }else if( sqlite3StrICmp(zArg0,"double")==0 ){ 7496d88bad4Sdanielk1977 sqlite3_result_double(context, sqlite3_value_double(argv[1])); 7506d88bad4Sdanielk1977 }else if( sqlite3StrICmp(zArg0,"null")==0 ){ 7516d88bad4Sdanielk1977 sqlite3_result_null(context); 7526d88bad4Sdanielk1977 }else if( sqlite3StrICmp(zArg0,"value")==0 ){ 7536d88bad4Sdanielk1977 sqlite3_result_value(context, argv[sqlite3_value_int(argv[1])]); 7546cbe1f1bSdrh }else{ 7556d88bad4Sdanielk1977 goto error_out; 7566d88bad4Sdanielk1977 } 7576d88bad4Sdanielk1977 }else{ 7586d88bad4Sdanielk1977 goto error_out; 7596cbe1f1bSdrh } 7606cbe1f1bSdrh argc -= 2; 7616cbe1f1bSdrh argv += 2; 7626cbe1f1bSdrh } 7636d88bad4Sdanielk1977 return; 7646d88bad4Sdanielk1977 7656d88bad4Sdanielk1977 error_out: 7666d88bad4Sdanielk1977 sqlite3_result_error(context,"first argument should be one of: " 7676d88bad4Sdanielk1977 "int int64 string double null value", -1); 7686cbe1f1bSdrh } 7696cbe1f1bSdrh 7706cbe1f1bSdrh /* 7716cbe1f1bSdrh ** Usage: sqlite_register_test_function DB NAME 7726cbe1f1bSdrh ** 7736cbe1f1bSdrh ** Register the test SQL function on the database DB under the name NAME. 7746cbe1f1bSdrh */ 775c2eef3b3Sdrh static int test_register_func( 7766cbe1f1bSdrh void *NotUsed, 7776cbe1f1bSdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 7786cbe1f1bSdrh int argc, /* Number of arguments */ 7796cbe1f1bSdrh char **argv /* Text of each argument */ 7806cbe1f1bSdrh ){ 7816cbe1f1bSdrh sqlite *db; 7826cbe1f1bSdrh int rc; 7836cbe1f1bSdrh if( argc!=3 ){ 7846cbe1f1bSdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 7856cbe1f1bSdrh " DB FUNCTION-NAME", 0); 7866cbe1f1bSdrh return TCL_ERROR; 7876cbe1f1bSdrh } 788b86ccfb2Sdrh if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; 789f9d64d2cSdanielk1977 rc = sqlite3_create_function(db, argv[2], -1, SQLITE_UTF8, 0, 790d8123366Sdanielk1977 testFunc, 0, 0); 7916cbe1f1bSdrh if( rc!=0 ){ 792f20b21c8Sdanielk1977 Tcl_AppendResult(interp, sqlite3ErrStr(rc), 0); 7936cbe1f1bSdrh return TCL_ERROR; 7946cbe1f1bSdrh } 7956cbe1f1bSdrh return TCL_OK; 7966cbe1f1bSdrh } 7976cbe1f1bSdrh 7986cbe1f1bSdrh /* 799106bb236Sdanielk1977 ** Usage: sqlite3_finalize STMT 800b86ccfb2Sdrh ** 801106bb236Sdanielk1977 ** Finalize a statement handle. 802b86ccfb2Sdrh */ 803b86ccfb2Sdrh static int test_finalize( 804106bb236Sdanielk1977 void * clientData, 805106bb236Sdanielk1977 Tcl_Interp *interp, 806106bb236Sdanielk1977 int objc, 807106bb236Sdanielk1977 Tcl_Obj *CONST objv[] 808b86ccfb2Sdrh ){ 809106bb236Sdanielk1977 sqlite3_stmt *pStmt; 810b86ccfb2Sdrh int rc; 811106bb236Sdanielk1977 812106bb236Sdanielk1977 if( objc!=2 ){ 813106bb236Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 814106bb236Sdanielk1977 Tcl_GetStringFromObj(objv[0], 0), " <STMT>", 0); 815b86ccfb2Sdrh return TCL_ERROR; 816b86ccfb2Sdrh } 817106bb236Sdanielk1977 818106bb236Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 819106bb236Sdanielk1977 820fc57d7bfSdanielk1977 rc = sqlite3_finalize(pStmt); 821b77f5dadSdanielk1977 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC); 822106bb236Sdanielk1977 return TCL_OK; 823106bb236Sdanielk1977 } 824106bb236Sdanielk1977 825106bb236Sdanielk1977 /* 826106bb236Sdanielk1977 ** Usage: sqlite3_reset STMT 827106bb236Sdanielk1977 ** 828106bb236Sdanielk1977 ** Finalize a statement handle. 829106bb236Sdanielk1977 */ 830106bb236Sdanielk1977 static int test_reset( 831106bb236Sdanielk1977 void * clientData, 832106bb236Sdanielk1977 Tcl_Interp *interp, 833106bb236Sdanielk1977 int objc, 834106bb236Sdanielk1977 Tcl_Obj *CONST objv[] 835106bb236Sdanielk1977 ){ 836106bb236Sdanielk1977 sqlite3_stmt *pStmt; 837106bb236Sdanielk1977 int rc; 838106bb236Sdanielk1977 839106bb236Sdanielk1977 if( objc!=2 ){ 840106bb236Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 841106bb236Sdanielk1977 Tcl_GetStringFromObj(objv[0], 0), " <STMT>", 0); 842106bb236Sdanielk1977 return TCL_ERROR; 843106bb236Sdanielk1977 } 844106bb236Sdanielk1977 845106bb236Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 846106bb236Sdanielk1977 847fc57d7bfSdanielk1977 rc = sqlite3_reset(pStmt); 848106bb236Sdanielk1977 if( rc ){ 849b86ccfb2Sdrh return TCL_ERROR; 850b86ccfb2Sdrh } 851b86ccfb2Sdrh return TCL_OK; 852b86ccfb2Sdrh } 853b86ccfb2Sdrh 8545a38705eSdrh /* 855fbcd585fSdanielk1977 ** Usage: sqlite3_changes DB 85650457896Sdrh ** 857fbcd585fSdanielk1977 ** Return the number of changes made to the database by the last SQL 858fbcd585fSdanielk1977 ** execution. 85950457896Sdrh */ 860fbcd585fSdanielk1977 static int test_changes( 861fbcd585fSdanielk1977 void * clientData, 862fbcd585fSdanielk1977 Tcl_Interp *interp, 863fbcd585fSdanielk1977 int objc, 864fbcd585fSdanielk1977 Tcl_Obj *CONST objv[] 865fbcd585fSdanielk1977 ){ 866fbcd585fSdanielk1977 sqlite3 *db; 867fbcd585fSdanielk1977 if( objc!=2 ){ 868fbcd585fSdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 869fbcd585fSdanielk1977 Tcl_GetString(objv[0]), " DB", 0); 870fbcd585fSdanielk1977 return TCL_ERROR; 871fbcd585fSdanielk1977 } 872fbcd585fSdanielk1977 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 873fbcd585fSdanielk1977 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_changes(db))); 874fbcd585fSdanielk1977 return TCL_OK; 875fbcd585fSdanielk1977 } 87650457896Sdrh 87750457896Sdrh /* 8787c972decSdrh ** This is the "static_bind_value" that variables are bound to when 8796f8a503dSdanielk1977 ** the FLAG option of sqlite3_bind is "static" 88050457896Sdrh */ 8817c972decSdrh static char *sqlite_static_bind_value = 0; 8827c972decSdrh 8837c972decSdrh /* 8846f8a503dSdanielk1977 ** Usage: sqlite3_bind VM IDX VALUE FLAGS 8857c972decSdrh ** 8867c972decSdrh ** Sets the value of the IDX-th occurance of "?" in the original SQL 8877c972decSdrh ** string. VALUE is the new value. If FLAGS=="null" then VALUE is 8887c972decSdrh ** ignored and the value is set to NULL. If FLAGS=="static" then 8897c972decSdrh ** the value is set to the value of a static variable named 8907c972decSdrh ** "sqlite_static_bind_value". If FLAGS=="normal" then a copy 8917c972decSdrh ** of the VALUE is made. 8927c972decSdrh */ 8937c972decSdrh static int test_bind( 89450457896Sdrh void *NotUsed, 89550457896Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 89650457896Sdrh int argc, /* Number of arguments */ 89750457896Sdrh char **argv /* Text of each argument */ 89850457896Sdrh ){ 899fc57d7bfSdanielk1977 sqlite3_stmt *pStmt; 90050457896Sdrh int rc; 9017c972decSdrh int idx; 9027c972decSdrh if( argc!=5 ){ 90350457896Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 9047c972decSdrh " VM IDX VALUE (null|static|normal)\"", 0); 90550457896Sdrh return TCL_ERROR; 90650457896Sdrh } 907fc57d7bfSdanielk1977 if( getStmtPointer(interp, argv[1], &pStmt) ) return TCL_ERROR; 9087c972decSdrh if( Tcl_GetInt(interp, argv[2], &idx) ) return TCL_ERROR; 9097c972decSdrh if( strcmp(argv[4],"null")==0 ){ 910fc57d7bfSdanielk1977 rc = sqlite3_bind_null(pStmt, idx); 9117c972decSdrh }else if( strcmp(argv[4],"static")==0 ){ 912fc57d7bfSdanielk1977 rc = sqlite3_bind_text(pStmt, idx, sqlite_static_bind_value, -1, 0); 9137c972decSdrh }else if( strcmp(argv[4],"normal")==0 ){ 914d8123366Sdanielk1977 rc = sqlite3_bind_text(pStmt, idx, argv[3], -1, SQLITE_TRANSIENT); 9157c972decSdrh }else{ 9167c972decSdrh Tcl_AppendResult(interp, "4th argument should be " 9177c972decSdrh "\"null\" or \"static\" or \"normal\"", 0); 9187c972decSdrh return TCL_ERROR; 9197c972decSdrh } 92050457896Sdrh if( rc ){ 92150457896Sdrh char zBuf[50]; 92250457896Sdrh sprintf(zBuf, "(%d) ", rc); 923f20b21c8Sdanielk1977 Tcl_AppendResult(interp, zBuf, sqlite3ErrStr(rc), 0); 92450457896Sdrh return TCL_ERROR; 92550457896Sdrh } 92650457896Sdrh return TCL_OK; 92750457896Sdrh } 92850457896Sdrh 9294e6af134Sdanielk1977 9304e6af134Sdanielk1977 /* 9314e6af134Sdanielk1977 ** Usage: add_test_collate <db ptr> <utf8> <utf16le> <utf16be> 9324e6af134Sdanielk1977 ** 9334e6af134Sdanielk1977 ** This function is used to test that SQLite selects the correct collation 9344e6af134Sdanielk1977 ** sequence callback when multiple versions (for different text encodings) 9354e6af134Sdanielk1977 ** are available. 9364e6af134Sdanielk1977 ** 9374e6af134Sdanielk1977 ** Calling this routine registers the collation sequence "test_collate" 9384e6af134Sdanielk1977 ** with database handle <db>. The second argument must be a list of three 9394e6af134Sdanielk1977 ** boolean values. If the first is true, then a version of test_collate is 9404e6af134Sdanielk1977 ** registered for UTF-8, if the second is true, a version is registered for 9414e6af134Sdanielk1977 ** UTF-16le, if the third is true, a UTF-16be version is available. 9424e6af134Sdanielk1977 ** Previous versions of test_collate are deleted. 9434e6af134Sdanielk1977 ** 9444e6af134Sdanielk1977 ** The collation sequence test_collate is implemented by calling the 9454e6af134Sdanielk1977 ** following TCL script: 9464e6af134Sdanielk1977 ** 9474e6af134Sdanielk1977 ** "test_collate <enc> <lhs> <rhs>" 9484e6af134Sdanielk1977 ** 9494e6af134Sdanielk1977 ** The <lhs> and <rhs> are the two values being compared, encoded in UTF-8. 9504e6af134Sdanielk1977 ** The <enc> parameter is the encoding of the collation function that 9514e6af134Sdanielk1977 ** SQLite selected to call. The TCL test script implements the 9524e6af134Sdanielk1977 ** "test_collate" proc. 9534e6af134Sdanielk1977 ** 9544e6af134Sdanielk1977 ** Note that this will only work with one intepreter at a time, as the 9554e6af134Sdanielk1977 ** interp pointer to use when evaluating the TCL script is stored in 9564e6af134Sdanielk1977 ** pTestCollateInterp. 9574e6af134Sdanielk1977 */ 9584e6af134Sdanielk1977 static Tcl_Interp* pTestCollateInterp; 9594e6af134Sdanielk1977 static int test_collate_func( 9604e6af134Sdanielk1977 void *pCtx, 9614e6af134Sdanielk1977 int nA, const void *zA, 9624e6af134Sdanielk1977 int nB, const void *zB 9634e6af134Sdanielk1977 ){ 9644e6af134Sdanielk1977 Tcl_Interp *i = pTestCollateInterp; 9654e6af134Sdanielk1977 int encin = (int)pCtx; 9664e6af134Sdanielk1977 int res; 9674e6af134Sdanielk1977 9684e6af134Sdanielk1977 sqlite3_value *pVal; 9694e6af134Sdanielk1977 Tcl_Obj *pX; 9704e6af134Sdanielk1977 9714e6af134Sdanielk1977 pX = Tcl_NewStringObj("test_collate", -1); 9724e6af134Sdanielk1977 Tcl_IncrRefCount(pX); 9734e6af134Sdanielk1977 9744e6af134Sdanielk1977 switch( encin ){ 9754e6af134Sdanielk1977 case SQLITE_UTF8: 9764e6af134Sdanielk1977 Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-8",-1)); 9774e6af134Sdanielk1977 break; 9784e6af134Sdanielk1977 case SQLITE_UTF16LE: 9794e6af134Sdanielk1977 Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-16LE",-1)); 9804e6af134Sdanielk1977 break; 9814e6af134Sdanielk1977 case SQLITE_UTF16BE: 9824e6af134Sdanielk1977 Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-16BE",-1)); 9834e6af134Sdanielk1977 break; 9844e6af134Sdanielk1977 default: 9854e6af134Sdanielk1977 assert(0); 9864e6af134Sdanielk1977 } 9874e6af134Sdanielk1977 9884e6af134Sdanielk1977 pVal = sqlite3ValueNew(); 989bfd6cce5Sdanielk1977 sqlite3ValueSetStr(pVal, nA, zA, encin, SQLITE_STATIC); 9904e6af134Sdanielk1977 Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj(sqlite3_value_text(pVal),-1)); 991bfd6cce5Sdanielk1977 sqlite3ValueSetStr(pVal, nB, zB, encin, SQLITE_STATIC); 9924e6af134Sdanielk1977 Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj(sqlite3_value_text(pVal),-1)); 9934e6af134Sdanielk1977 sqlite3ValueFree(pVal); 9944e6af134Sdanielk1977 9954e6af134Sdanielk1977 Tcl_EvalObjEx(i, pX, 0); 9964e6af134Sdanielk1977 Tcl_DecrRefCount(pX); 9974e6af134Sdanielk1977 Tcl_GetIntFromObj(i, Tcl_GetObjResult(i), &res); 9984e6af134Sdanielk1977 return res; 9994e6af134Sdanielk1977 } 10004e6af134Sdanielk1977 static int test_collate( 10014e6af134Sdanielk1977 void * clientData, 10024e6af134Sdanielk1977 Tcl_Interp *interp, 10034e6af134Sdanielk1977 int objc, 10044e6af134Sdanielk1977 Tcl_Obj *CONST objv[] 10054e6af134Sdanielk1977 ){ 10064e6af134Sdanielk1977 sqlite3 *db; 10074e6af134Sdanielk1977 int val; 1008312d6b36Sdanielk1977 sqlite3_value *pVal; 10094e6af134Sdanielk1977 10104e6af134Sdanielk1977 if( objc!=5 ) goto bad_args; 10114e6af134Sdanielk1977 pTestCollateInterp = interp; 10124e6af134Sdanielk1977 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 10134e6af134Sdanielk1977 10144e6af134Sdanielk1977 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[2], &val) ) return TCL_ERROR; 10154e6af134Sdanielk1977 sqlite3_create_collation(db, "test_collate", SQLITE_UTF8, 10164e6af134Sdanielk1977 (void *)SQLITE_UTF8, val?test_collate_func:0); 10174e6af134Sdanielk1977 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[3], &val) ) return TCL_ERROR; 10184e6af134Sdanielk1977 sqlite3_create_collation(db, "test_collate", SQLITE_UTF16LE, 10194e6af134Sdanielk1977 (void *)SQLITE_UTF16LE, val?test_collate_func:0); 10204e6af134Sdanielk1977 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[4], &val) ) return TCL_ERROR; 1021312d6b36Sdanielk1977 1022312d6b36Sdanielk1977 pVal = sqlite3ValueNew(); 1023312d6b36Sdanielk1977 sqlite3ValueSetStr(pVal, -1, "test_collate", SQLITE_UTF8, SQLITE_STATIC); 1024312d6b36Sdanielk1977 sqlite3_create_collation16(db, sqlite3ValueText(pVal, SQLITE_UTF16NATIVE), 1025312d6b36Sdanielk1977 SQLITE_UTF16BE, (void *)SQLITE_UTF16BE, val?test_collate_func:0); 1026312d6b36Sdanielk1977 sqlite3ValueFree(pVal); 10274e6af134Sdanielk1977 10284e6af134Sdanielk1977 return TCL_OK; 10294e6af134Sdanielk1977 10304e6af134Sdanielk1977 bad_args: 10314e6af134Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 10324e6af134Sdanielk1977 Tcl_GetStringFromObj(objv[0], 0), " <DB> <utf8> <utf16le> <utf16be>", 0); 10334e6af134Sdanielk1977 return TCL_ERROR; 10344e6af134Sdanielk1977 } 10354e6af134Sdanielk1977 1036312d6b36Sdanielk1977 static void test_collate_needed_cb( 1037312d6b36Sdanielk1977 void *pCtx, 1038312d6b36Sdanielk1977 sqlite3 *db, 1039312d6b36Sdanielk1977 int eTextRep, 1040312d6b36Sdanielk1977 const void *notUsed 1041312d6b36Sdanielk1977 ){ 1042312d6b36Sdanielk1977 int enc = db->enc; 1043312d6b36Sdanielk1977 sqlite3_create_collation( 1044312d6b36Sdanielk1977 db, "test_collate", db->enc, (void *)enc, test_collate_func); 1045312d6b36Sdanielk1977 } 1046312d6b36Sdanielk1977 1047312d6b36Sdanielk1977 /* 1048312d6b36Sdanielk1977 ** Usage: add_test_collate_needed DB 1049312d6b36Sdanielk1977 */ 1050312d6b36Sdanielk1977 static int test_collate_needed( 1051312d6b36Sdanielk1977 void * clientData, 1052312d6b36Sdanielk1977 Tcl_Interp *interp, 1053312d6b36Sdanielk1977 int objc, 1054312d6b36Sdanielk1977 Tcl_Obj *CONST objv[] 1055312d6b36Sdanielk1977 ){ 1056312d6b36Sdanielk1977 sqlite3 *db; 1057312d6b36Sdanielk1977 1058312d6b36Sdanielk1977 if( objc!=2 ) goto bad_args; 1059312d6b36Sdanielk1977 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 1060312d6b36Sdanielk1977 sqlite3_collation_needed16(db, 0, test_collate_needed_cb); 1061312d6b36Sdanielk1977 return TCL_OK; 1062312d6b36Sdanielk1977 1063312d6b36Sdanielk1977 bad_args: 1064312d6b36Sdanielk1977 Tcl_WrongNumArgs(interp, 1, objv, "DB"); 1065312d6b36Sdanielk1977 return TCL_ERROR; 1066312d6b36Sdanielk1977 } 1067312d6b36Sdanielk1977 1068c8e9a2dfSdanielk1977 /* 1069c8e9a2dfSdanielk1977 ** Usage: add_test_function <db ptr> <utf8> <utf16le> <utf16be> 1070c8e9a2dfSdanielk1977 ** 1071c8e9a2dfSdanielk1977 ** This function is used to test that SQLite selects the correct user 1072c8e9a2dfSdanielk1977 ** function callback when multiple versions (for different text encodings) 1073c8e9a2dfSdanielk1977 ** are available. 1074c8e9a2dfSdanielk1977 ** 1075c8e9a2dfSdanielk1977 ** Calling this routine registers up to three versions of the user function 1076c8e9a2dfSdanielk1977 ** "test_function" with database handle <db>. If the second argument is 1077c8e9a2dfSdanielk1977 ** true, then a version of test_function is registered for UTF-8, if the 1078c8e9a2dfSdanielk1977 ** third is true, a version is registered for UTF-16le, if the fourth is 1079c8e9a2dfSdanielk1977 ** true, a UTF-16be version is available. Previous versions of 1080c8e9a2dfSdanielk1977 ** test_function are deleted. 1081c8e9a2dfSdanielk1977 ** 1082c8e9a2dfSdanielk1977 ** The user function is implemented by calling the following TCL script: 1083c8e9a2dfSdanielk1977 ** 1084c8e9a2dfSdanielk1977 ** "test_function <enc> <arg>" 1085c8e9a2dfSdanielk1977 ** 1086c8e9a2dfSdanielk1977 ** Where <enc> is one of UTF-8, UTF-16LE or UTF16BE, and <arg> is the 1087c8e9a2dfSdanielk1977 ** single argument passed to the SQL function. The value returned by 1088c8e9a2dfSdanielk1977 ** the TCL script is used as the return value of the SQL function. It 1089c8e9a2dfSdanielk1977 ** is passed to SQLite using UTF-16BE for a UTF-8 test_function(), UTF-8 1090c8e9a2dfSdanielk1977 ** for a UTF-16LE test_function(), and UTF-16LE for an implementation that 1091c8e9a2dfSdanielk1977 ** prefers UTF-16BE. 1092c8e9a2dfSdanielk1977 */ 1093c8e9a2dfSdanielk1977 static void test_function_utf8( 1094c8e9a2dfSdanielk1977 sqlite3_context *pCtx, 1095c8e9a2dfSdanielk1977 int nArg, 1096c8e9a2dfSdanielk1977 sqlite3_value **argv 1097c8e9a2dfSdanielk1977 ){ 1098c8e9a2dfSdanielk1977 Tcl_Interp *interp; 1099c8e9a2dfSdanielk1977 Tcl_Obj *pX; 1100c8e9a2dfSdanielk1977 sqlite3_value *pVal; 1101c8e9a2dfSdanielk1977 interp = (Tcl_Interp *)sqlite3_user_data(pCtx); 1102c8e9a2dfSdanielk1977 pX = Tcl_NewStringObj("test_function", -1); 1103c8e9a2dfSdanielk1977 Tcl_IncrRefCount(pX); 1104c8e9a2dfSdanielk1977 Tcl_ListObjAppendElement(interp, pX, Tcl_NewStringObj("UTF-8", -1)); 1105c8e9a2dfSdanielk1977 Tcl_ListObjAppendElement(interp, pX, 1106c8e9a2dfSdanielk1977 Tcl_NewStringObj(sqlite3_value_text(argv[0]), -1)); 1107c8e9a2dfSdanielk1977 Tcl_EvalObjEx(interp, pX, 0); 1108c8e9a2dfSdanielk1977 Tcl_DecrRefCount(pX); 1109c8e9a2dfSdanielk1977 sqlite3_result_text(pCtx, Tcl_GetStringResult(interp), -1, SQLITE_TRANSIENT); 1110c8e9a2dfSdanielk1977 pVal = sqlite3ValueNew(); 1111c8e9a2dfSdanielk1977 sqlite3ValueSetStr(pVal, -1, Tcl_GetStringResult(interp), 1112c8e9a2dfSdanielk1977 SQLITE_UTF8, SQLITE_STATIC); 1113c8e9a2dfSdanielk1977 sqlite3_result_text16be(pCtx, sqlite3_value_text16be(pVal), 1114c8e9a2dfSdanielk1977 -1, SQLITE_TRANSIENT); 1115c8e9a2dfSdanielk1977 sqlite3ValueFree(pVal); 1116c8e9a2dfSdanielk1977 } 1117c8e9a2dfSdanielk1977 static void test_function_utf16le( 1118c8e9a2dfSdanielk1977 sqlite3_context *pCtx, 1119c8e9a2dfSdanielk1977 int nArg, 1120c8e9a2dfSdanielk1977 sqlite3_value **argv 1121c8e9a2dfSdanielk1977 ){ 1122c8e9a2dfSdanielk1977 Tcl_Interp *interp; 1123c8e9a2dfSdanielk1977 Tcl_Obj *pX; 1124c8e9a2dfSdanielk1977 sqlite3_value *pVal; 1125c8e9a2dfSdanielk1977 interp = (Tcl_Interp *)sqlite3_user_data(pCtx); 1126c8e9a2dfSdanielk1977 pX = Tcl_NewStringObj("test_function", -1); 1127c8e9a2dfSdanielk1977 Tcl_IncrRefCount(pX); 1128c8e9a2dfSdanielk1977 Tcl_ListObjAppendElement(interp, pX, Tcl_NewStringObj("UTF-16LE", -1)); 1129c8e9a2dfSdanielk1977 Tcl_ListObjAppendElement(interp, pX, 1130c8e9a2dfSdanielk1977 Tcl_NewStringObj(sqlite3_value_text(argv[0]), -1)); 1131c8e9a2dfSdanielk1977 Tcl_EvalObjEx(interp, pX, 0); 1132c8e9a2dfSdanielk1977 Tcl_DecrRefCount(pX); 1133c8e9a2dfSdanielk1977 pVal = sqlite3ValueNew(); 1134c8e9a2dfSdanielk1977 sqlite3ValueSetStr(pVal, -1, Tcl_GetStringResult(interp), 1135c8e9a2dfSdanielk1977 SQLITE_UTF8, SQLITE_STATIC); 1136c8e9a2dfSdanielk1977 sqlite3_result_text(pCtx,sqlite3_value_text(pVal),-1,SQLITE_TRANSIENT); 1137c8e9a2dfSdanielk1977 sqlite3ValueFree(pVal); 1138c8e9a2dfSdanielk1977 } 1139c8e9a2dfSdanielk1977 static void test_function_utf16be( 1140c8e9a2dfSdanielk1977 sqlite3_context *pCtx, 1141c8e9a2dfSdanielk1977 int nArg, 1142c8e9a2dfSdanielk1977 sqlite3_value **argv 1143c8e9a2dfSdanielk1977 ){ 1144c8e9a2dfSdanielk1977 Tcl_Interp *interp; 1145c8e9a2dfSdanielk1977 Tcl_Obj *pX; 1146c8e9a2dfSdanielk1977 sqlite3_value *pVal; 1147c8e9a2dfSdanielk1977 interp = (Tcl_Interp *)sqlite3_user_data(pCtx); 1148c8e9a2dfSdanielk1977 pX = Tcl_NewStringObj("test_function", -1); 1149c8e9a2dfSdanielk1977 Tcl_IncrRefCount(pX); 1150c8e9a2dfSdanielk1977 Tcl_ListObjAppendElement(interp, pX, Tcl_NewStringObj("UTF-16BE", -1)); 1151c8e9a2dfSdanielk1977 Tcl_ListObjAppendElement(interp, pX, 1152c8e9a2dfSdanielk1977 Tcl_NewStringObj(sqlite3_value_text(argv[0]), -1)); 1153c8e9a2dfSdanielk1977 Tcl_EvalObjEx(interp, pX, 0); 1154c8e9a2dfSdanielk1977 Tcl_DecrRefCount(pX); 1155c8e9a2dfSdanielk1977 pVal = sqlite3ValueNew(); 1156c8e9a2dfSdanielk1977 sqlite3ValueSetStr(pVal, -1, Tcl_GetStringResult(interp), 1157c8e9a2dfSdanielk1977 SQLITE_UTF8, SQLITE_STATIC); 1158c8e9a2dfSdanielk1977 sqlite3_result_text16le(pCtx, sqlite3_value_text16le(pVal), 1159c8e9a2dfSdanielk1977 -1, SQLITE_TRANSIENT); 1160c8e9a2dfSdanielk1977 sqlite3ValueFree(pVal); 1161c8e9a2dfSdanielk1977 } 1162c8e9a2dfSdanielk1977 static int test_function( 1163c8e9a2dfSdanielk1977 void * clientData, 1164c8e9a2dfSdanielk1977 Tcl_Interp *interp, 1165c8e9a2dfSdanielk1977 int objc, 1166c8e9a2dfSdanielk1977 Tcl_Obj *CONST objv[] 1167c8e9a2dfSdanielk1977 ){ 1168c8e9a2dfSdanielk1977 sqlite3 *db; 1169c8e9a2dfSdanielk1977 int val; 1170c8e9a2dfSdanielk1977 1171c8e9a2dfSdanielk1977 if( objc!=5 ) goto bad_args; 1172c8e9a2dfSdanielk1977 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 1173c8e9a2dfSdanielk1977 1174c8e9a2dfSdanielk1977 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[2], &val) ) return TCL_ERROR; 1175c8e9a2dfSdanielk1977 if( val ){ 1176c8e9a2dfSdanielk1977 sqlite3_create_function(db, "test_function", 1, SQLITE_UTF8, 1177c8e9a2dfSdanielk1977 interp, test_function_utf8, 0, 0); 1178c8e9a2dfSdanielk1977 } 1179c8e9a2dfSdanielk1977 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[3], &val) ) return TCL_ERROR; 1180c8e9a2dfSdanielk1977 if( val ){ 1181c8e9a2dfSdanielk1977 sqlite3_create_function(db, "test_function", 1, SQLITE_UTF16LE, 1182c8e9a2dfSdanielk1977 interp, test_function_utf16le, 0, 0); 1183c8e9a2dfSdanielk1977 } 1184c8e9a2dfSdanielk1977 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[4], &val) ) return TCL_ERROR; 1185c8e9a2dfSdanielk1977 if( val ){ 1186c8e9a2dfSdanielk1977 sqlite3_create_function(db, "test_function", 1, SQLITE_UTF16BE, 1187c8e9a2dfSdanielk1977 interp, test_function_utf16be, 0, 0); 1188c8e9a2dfSdanielk1977 } 1189c8e9a2dfSdanielk1977 1190c8e9a2dfSdanielk1977 return TCL_OK; 1191c8e9a2dfSdanielk1977 bad_args: 1192c8e9a2dfSdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 1193c8e9a2dfSdanielk1977 Tcl_GetStringFromObj(objv[0], 0), " <DB> <utf8> <utf16le> <utf16be>", 0); 1194c8e9a2dfSdanielk1977 return TCL_ERROR; 1195c8e9a2dfSdanielk1977 } 1196c8e9a2dfSdanielk1977 1197312d6b36Sdanielk1977 /* 1198312d6b36Sdanielk1977 ** Usage: test_errstr <err code> 1199312d6b36Sdanielk1977 ** 1200312d6b36Sdanielk1977 ** Test that the english language string equivalents for sqlite error codes 1201312d6b36Sdanielk1977 ** are sane. The parameter is an integer representing an sqlite error code. 1202312d6b36Sdanielk1977 ** The result is a list of two elements, the string representation of the 1203312d6b36Sdanielk1977 ** error code and the english language explanation. 1204312d6b36Sdanielk1977 */ 1205312d6b36Sdanielk1977 static int test_errstr( 1206312d6b36Sdanielk1977 void * clientData, 1207312d6b36Sdanielk1977 Tcl_Interp *interp, 1208312d6b36Sdanielk1977 int objc, 1209312d6b36Sdanielk1977 Tcl_Obj *CONST objv[] 1210312d6b36Sdanielk1977 ){ 1211312d6b36Sdanielk1977 char *zCode; 1212312d6b36Sdanielk1977 int i; 1213312d6b36Sdanielk1977 if( objc!=1 ){ 1214312d6b36Sdanielk1977 Tcl_WrongNumArgs(interp, 1, objv, "<error code>"); 1215312d6b36Sdanielk1977 } 1216312d6b36Sdanielk1977 1217312d6b36Sdanielk1977 zCode = Tcl_GetString(objv[1]); 1218312d6b36Sdanielk1977 for(i=0; i<200; i++){ 1219312d6b36Sdanielk1977 if( 0==strcmp(errorName(i), zCode) ) break; 1220312d6b36Sdanielk1977 } 1221312d6b36Sdanielk1977 Tcl_SetResult(interp, (char *)sqlite3ErrStr(i), 0); 1222312d6b36Sdanielk1977 return TCL_OK; 1223312d6b36Sdanielk1977 } 1224312d6b36Sdanielk1977 1225c8e9a2dfSdanielk1977 static int sqlite3_crashparams( 12268a6c550dSdanielk1977 void * clientData, 12278a6c550dSdanielk1977 Tcl_Interp *interp, 12288a6c550dSdanielk1977 int objc, 12298a6c550dSdanielk1977 Tcl_Obj *CONST objv[] 12308a6c550dSdanielk1977 ){ 12318a6c550dSdanielk1977 #ifdef OS_TEST 1232c8e9a2dfSdanielk1977 int delay; 1233c8e9a2dfSdanielk1977 if( objc!=3 ) goto bad_args; 1234c8e9a2dfSdanielk1977 if( Tcl_GetIntFromObj(interp, objv[1], &delay) ) return TCL_ERROR; 1235c8e9a2dfSdanielk1977 sqlite3SetCrashParams(delay, Tcl_GetString(objv[2])); 12368a6c550dSdanielk1977 #endif 12378a6c550dSdanielk1977 return TCL_OK; 12388a6c550dSdanielk1977 1239241db313Sdrh #ifdef OS_TEST 12408a6c550dSdanielk1977 bad_args: 12418a6c550dSdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 1242c8e9a2dfSdanielk1977 Tcl_GetStringFromObj(objv[0], 0), "<delay> <filename>", 0); 12438a6c550dSdanielk1977 return TCL_ERROR; 1244241db313Sdrh #endif 12458a6c550dSdanielk1977 } 12468a6c550dSdanielk1977 12478a6c550dSdanielk1977 124850457896Sdrh /* 124999ee3600Sdrh ** Usage: breakpoint 125099ee3600Sdrh ** 125199ee3600Sdrh ** This routine exists for one purpose - to provide a place to put a 125299ee3600Sdrh ** breakpoint with GDB that can be triggered using TCL code. The use 125399ee3600Sdrh ** for this is when a particular test fails on (say) the 1485th iteration. 125499ee3600Sdrh ** In the TCL test script, we can add code like this: 125599ee3600Sdrh ** 125699ee3600Sdrh ** if {$i==1485} breakpoint 125799ee3600Sdrh ** 125899ee3600Sdrh ** Then run testfixture in the debugger and wait for the breakpoint to 125999ee3600Sdrh ** fire. Then additional breakpoints can be set to trace down the bug. 126099ee3600Sdrh */ 126199ee3600Sdrh static int test_breakpoint( 126299ee3600Sdrh void *NotUsed, 126399ee3600Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 126499ee3600Sdrh int argc, /* Number of arguments */ 126599ee3600Sdrh char **argv /* Text of each argument */ 126699ee3600Sdrh ){ 126799ee3600Sdrh return TCL_OK; /* Do nothing */ 126899ee3600Sdrh } 126999ee3600Sdrh 1270241db313Sdrh /* 1271241db313Sdrh ** Usage: sqlite3_bind_int STMT N VALUE 1272241db313Sdrh ** 1273241db313Sdrh ** Test the sqlite3_bind_int interface. STMT is a prepared statement. 1274241db313Sdrh ** N is the index of a wildcard in the prepared statement. This command 1275241db313Sdrh ** binds a 32-bit integer VALUE to that wildcard. 1276241db313Sdrh */ 1277241db313Sdrh static int test_bind_int( 127851e3d8e2Sdanielk1977 void * clientData, 127951e3d8e2Sdanielk1977 Tcl_Interp *interp, 128051e3d8e2Sdanielk1977 int objc, 128151e3d8e2Sdanielk1977 Tcl_Obj *CONST objv[] 128251e3d8e2Sdanielk1977 ){ 128351e3d8e2Sdanielk1977 sqlite3_stmt *pStmt; 128451e3d8e2Sdanielk1977 int idx; 128551e3d8e2Sdanielk1977 int value; 128651e3d8e2Sdanielk1977 int rc; 128751e3d8e2Sdanielk1977 128851e3d8e2Sdanielk1977 if( objc!=4 ){ 128951e3d8e2Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 1290241db313Sdrh Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE", 0); 129151e3d8e2Sdanielk1977 return TCL_ERROR; 129251e3d8e2Sdanielk1977 } 129351e3d8e2Sdanielk1977 129451e3d8e2Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 129551e3d8e2Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; 129651e3d8e2Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[3], &value) ) return TCL_ERROR; 129751e3d8e2Sdanielk1977 1298c572ef7fSdanielk1977 rc = sqlite3_bind_int(pStmt, idx, value); 129951e3d8e2Sdanielk1977 if( rc!=SQLITE_OK ){ 130051e3d8e2Sdanielk1977 return TCL_ERROR; 130151e3d8e2Sdanielk1977 } 130251e3d8e2Sdanielk1977 130351e3d8e2Sdanielk1977 return TCL_OK; 130451e3d8e2Sdanielk1977 } 130551e3d8e2Sdanielk1977 1306241db313Sdrh 1307241db313Sdrh /* 1308241db313Sdrh ** Usage: sqlite3_bind_int64 STMT N VALUE 1309241db313Sdrh ** 1310241db313Sdrh ** Test the sqlite3_bind_int64 interface. STMT is a prepared statement. 1311241db313Sdrh ** N is the index of a wildcard in the prepared statement. This command 1312241db313Sdrh ** binds a 64-bit integer VALUE to that wildcard. 1313241db313Sdrh */ 131451e3d8e2Sdanielk1977 static int test_bind_int64( 131551e3d8e2Sdanielk1977 void * clientData, 131651e3d8e2Sdanielk1977 Tcl_Interp *interp, 131751e3d8e2Sdanielk1977 int objc, 131851e3d8e2Sdanielk1977 Tcl_Obj *CONST objv[] 131951e3d8e2Sdanielk1977 ){ 132051e3d8e2Sdanielk1977 sqlite3_stmt *pStmt; 132151e3d8e2Sdanielk1977 int idx; 132251e3d8e2Sdanielk1977 i64 value; 132351e3d8e2Sdanielk1977 int rc; 132451e3d8e2Sdanielk1977 132551e3d8e2Sdanielk1977 if( objc!=4 ){ 132651e3d8e2Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 1327241db313Sdrh Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE", 0); 132851e3d8e2Sdanielk1977 return TCL_ERROR; 132951e3d8e2Sdanielk1977 } 133051e3d8e2Sdanielk1977 133151e3d8e2Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 133251e3d8e2Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; 133351e3d8e2Sdanielk1977 if( Tcl_GetWideIntFromObj(interp, objv[3], &value) ) return TCL_ERROR; 133451e3d8e2Sdanielk1977 133551e3d8e2Sdanielk1977 rc = sqlite3_bind_int64(pStmt, idx, value); 133651e3d8e2Sdanielk1977 if( rc!=SQLITE_OK ){ 133751e3d8e2Sdanielk1977 return TCL_ERROR; 133851e3d8e2Sdanielk1977 } 133951e3d8e2Sdanielk1977 134051e3d8e2Sdanielk1977 return TCL_OK; 134151e3d8e2Sdanielk1977 } 134251e3d8e2Sdanielk1977 1343241db313Sdrh 1344241db313Sdrh /* 1345241db313Sdrh ** Usage: sqlite3_bind_double STMT N VALUE 1346241db313Sdrh ** 1347241db313Sdrh ** Test the sqlite3_bind_double interface. STMT is a prepared statement. 1348241db313Sdrh ** N is the index of a wildcard in the prepared statement. This command 1349241db313Sdrh ** binds a 64-bit integer VALUE to that wildcard. 1350241db313Sdrh */ 135151e3d8e2Sdanielk1977 static int test_bind_double( 135251e3d8e2Sdanielk1977 void * clientData, 135351e3d8e2Sdanielk1977 Tcl_Interp *interp, 135451e3d8e2Sdanielk1977 int objc, 135551e3d8e2Sdanielk1977 Tcl_Obj *CONST objv[] 135651e3d8e2Sdanielk1977 ){ 135751e3d8e2Sdanielk1977 sqlite3_stmt *pStmt; 135851e3d8e2Sdanielk1977 int idx; 135951e3d8e2Sdanielk1977 double value; 136051e3d8e2Sdanielk1977 int rc; 136151e3d8e2Sdanielk1977 136251e3d8e2Sdanielk1977 if( objc!=4 ){ 136351e3d8e2Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 1364241db313Sdrh Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE", 0); 136551e3d8e2Sdanielk1977 return TCL_ERROR; 136651e3d8e2Sdanielk1977 } 136751e3d8e2Sdanielk1977 136851e3d8e2Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 136951e3d8e2Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; 137051e3d8e2Sdanielk1977 if( Tcl_GetDoubleFromObj(interp, objv[3], &value) ) return TCL_ERROR; 137151e3d8e2Sdanielk1977 137251e3d8e2Sdanielk1977 rc = sqlite3_bind_double(pStmt, idx, value); 137351e3d8e2Sdanielk1977 if( rc!=SQLITE_OK ){ 137451e3d8e2Sdanielk1977 return TCL_ERROR; 137551e3d8e2Sdanielk1977 } 137651e3d8e2Sdanielk1977 137751e3d8e2Sdanielk1977 return TCL_OK; 137851e3d8e2Sdanielk1977 } 137951e3d8e2Sdanielk1977 1380241db313Sdrh /* 1381241db313Sdrh ** Usage: sqlite3_bind_null STMT N 1382241db313Sdrh ** 1383241db313Sdrh ** Test the sqlite3_bind_null interface. STMT is a prepared statement. 1384241db313Sdrh ** N is the index of a wildcard in the prepared statement. This command 1385241db313Sdrh ** binds a NULL to the wildcard. 1386241db313Sdrh */ 138751e3d8e2Sdanielk1977 static int test_bind_null( 138851e3d8e2Sdanielk1977 void * clientData, 138951e3d8e2Sdanielk1977 Tcl_Interp *interp, 139051e3d8e2Sdanielk1977 int objc, 139151e3d8e2Sdanielk1977 Tcl_Obj *CONST objv[] 139251e3d8e2Sdanielk1977 ){ 139351e3d8e2Sdanielk1977 sqlite3_stmt *pStmt; 139451e3d8e2Sdanielk1977 int idx; 139551e3d8e2Sdanielk1977 int rc; 139651e3d8e2Sdanielk1977 139751e3d8e2Sdanielk1977 if( objc!=3 ){ 139851e3d8e2Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 1399241db313Sdrh Tcl_GetStringFromObj(objv[0], 0), " STMT N", 0); 140051e3d8e2Sdanielk1977 return TCL_ERROR; 140151e3d8e2Sdanielk1977 } 140251e3d8e2Sdanielk1977 140351e3d8e2Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 140451e3d8e2Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; 140551e3d8e2Sdanielk1977 140651e3d8e2Sdanielk1977 rc = sqlite3_bind_null(pStmt, idx); 140751e3d8e2Sdanielk1977 if( rc!=SQLITE_OK ){ 140851e3d8e2Sdanielk1977 return TCL_ERROR; 140951e3d8e2Sdanielk1977 } 141051e3d8e2Sdanielk1977 141151e3d8e2Sdanielk1977 return TCL_OK; 141251e3d8e2Sdanielk1977 } 141351e3d8e2Sdanielk1977 1414241db313Sdrh /* 1415241db313Sdrh ** Usage: sqlite3_bind_text STMT N STRING BYTES 1416241db313Sdrh ** 1417241db313Sdrh ** Test the sqlite3_bind_text interface. STMT is a prepared statement. 1418241db313Sdrh ** N is the index of a wildcard in the prepared statement. This command 1419241db313Sdrh ** binds a UTF-8 string STRING to the wildcard. The string is BYTES bytes 1420241db313Sdrh ** long. 1421241db313Sdrh */ 142251e3d8e2Sdanielk1977 static int test_bind_text( 142351e3d8e2Sdanielk1977 void * clientData, 142451e3d8e2Sdanielk1977 Tcl_Interp *interp, 142551e3d8e2Sdanielk1977 int objc, 142651e3d8e2Sdanielk1977 Tcl_Obj *CONST objv[] 142751e3d8e2Sdanielk1977 ){ 142851e3d8e2Sdanielk1977 sqlite3_stmt *pStmt; 142951e3d8e2Sdanielk1977 int idx; 143051e3d8e2Sdanielk1977 int bytes; 143151e3d8e2Sdanielk1977 char *value; 143251e3d8e2Sdanielk1977 int rc; 143351e3d8e2Sdanielk1977 143451e3d8e2Sdanielk1977 if( objc!=5 ){ 143551e3d8e2Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 1436241db313Sdrh Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE BYTES", 0); 143751e3d8e2Sdanielk1977 return TCL_ERROR; 143851e3d8e2Sdanielk1977 } 143951e3d8e2Sdanielk1977 144051e3d8e2Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 144151e3d8e2Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; 144251e3d8e2Sdanielk1977 value = Tcl_GetString(objv[3]); 144351e3d8e2Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[4], &bytes) ) return TCL_ERROR; 144451e3d8e2Sdanielk1977 1445d8123366Sdanielk1977 rc = sqlite3_bind_text(pStmt, idx, value, bytes, SQLITE_TRANSIENT); 144651e3d8e2Sdanielk1977 if( rc!=SQLITE_OK ){ 144751e3d8e2Sdanielk1977 return TCL_ERROR; 144851e3d8e2Sdanielk1977 } 144951e3d8e2Sdanielk1977 145051e3d8e2Sdanielk1977 return TCL_OK; 145151e3d8e2Sdanielk1977 } 145251e3d8e2Sdanielk1977 1453241db313Sdrh /* 1454241db313Sdrh ** Usage: sqlite3_bind_text16 STMT N STRING BYTES 1455241db313Sdrh ** 1456241db313Sdrh ** Test the sqlite3_bind_text16 interface. STMT is a prepared statement. 1457241db313Sdrh ** N is the index of a wildcard in the prepared statement. This command 1458241db313Sdrh ** binds a UTF-16 string STRING to the wildcard. The string is BYTES bytes 1459241db313Sdrh ** long. 1460241db313Sdrh */ 146151e3d8e2Sdanielk1977 static int test_bind_text16( 146251e3d8e2Sdanielk1977 void * clientData, 146351e3d8e2Sdanielk1977 Tcl_Interp *interp, 146451e3d8e2Sdanielk1977 int objc, 146551e3d8e2Sdanielk1977 Tcl_Obj *CONST objv[] 146651e3d8e2Sdanielk1977 ){ 146751e3d8e2Sdanielk1977 sqlite3_stmt *pStmt; 146851e3d8e2Sdanielk1977 int idx; 146951e3d8e2Sdanielk1977 int bytes; 147051e3d8e2Sdanielk1977 char *value; 147151e3d8e2Sdanielk1977 int rc; 147251e3d8e2Sdanielk1977 147351e3d8e2Sdanielk1977 if( objc!=5 ){ 147451e3d8e2Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 1475241db313Sdrh Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE BYTES", 0); 147651e3d8e2Sdanielk1977 return TCL_ERROR; 147751e3d8e2Sdanielk1977 } 147851e3d8e2Sdanielk1977 147951e3d8e2Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 148051e3d8e2Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; 148151e3d8e2Sdanielk1977 value = Tcl_GetByteArrayFromObj(objv[3], 0); 148251e3d8e2Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[4], &bytes) ) return TCL_ERROR; 148351e3d8e2Sdanielk1977 1484d8123366Sdanielk1977 rc = sqlite3_bind_text16(pStmt, idx, (void *)value, bytes, SQLITE_TRANSIENT); 148551e3d8e2Sdanielk1977 if( rc!=SQLITE_OK ){ 148651e3d8e2Sdanielk1977 return TCL_ERROR; 148751e3d8e2Sdanielk1977 } 148851e3d8e2Sdanielk1977 148951e3d8e2Sdanielk1977 return TCL_OK; 149051e3d8e2Sdanielk1977 } 149151e3d8e2Sdanielk1977 1492241db313Sdrh /* 1493241db313Sdrh ** Usage: sqlite3_bind_blob STMT N DATA BYTES 1494241db313Sdrh ** 1495241db313Sdrh ** Test the sqlite3_bind_blob interface. STMT is a prepared statement. 1496241db313Sdrh ** N is the index of a wildcard in the prepared statement. This command 1497241db313Sdrh ** binds a BLOB to the wildcard. The BLOB is BYTES bytes in size. 1498241db313Sdrh */ 149951e3d8e2Sdanielk1977 static int test_bind_blob( 150051e3d8e2Sdanielk1977 void * clientData, 150151e3d8e2Sdanielk1977 Tcl_Interp *interp, 150251e3d8e2Sdanielk1977 int objc, 150351e3d8e2Sdanielk1977 Tcl_Obj *CONST objv[] 150451e3d8e2Sdanielk1977 ){ 150551e3d8e2Sdanielk1977 sqlite3_stmt *pStmt; 150651e3d8e2Sdanielk1977 int idx; 150751e3d8e2Sdanielk1977 int bytes; 150851e3d8e2Sdanielk1977 char *value; 150951e3d8e2Sdanielk1977 int rc; 151051e3d8e2Sdanielk1977 151151e3d8e2Sdanielk1977 if( objc!=5 ){ 151251e3d8e2Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 1513241db313Sdrh Tcl_GetStringFromObj(objv[0], 0), " STMT N DATA BYTES", 0); 151451e3d8e2Sdanielk1977 return TCL_ERROR; 151551e3d8e2Sdanielk1977 } 151651e3d8e2Sdanielk1977 151751e3d8e2Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 151851e3d8e2Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; 151951e3d8e2Sdanielk1977 value = Tcl_GetString(objv[3]); 152049e4643eSdanielk1977 if( Tcl_GetIntFromObj(interp, objv[4], &bytes) ) return TCL_ERROR; 152151e3d8e2Sdanielk1977 1522d8123366Sdanielk1977 rc = sqlite3_bind_blob(pStmt, idx, value, bytes, SQLITE_TRANSIENT); 152351e3d8e2Sdanielk1977 if( rc!=SQLITE_OK ){ 152451e3d8e2Sdanielk1977 return TCL_ERROR; 152551e3d8e2Sdanielk1977 } 152651e3d8e2Sdanielk1977 152751e3d8e2Sdanielk1977 return TCL_OK; 152851e3d8e2Sdanielk1977 } 152951e3d8e2Sdanielk1977 153099ee3600Sdrh /* 15316622cce3Sdanielk1977 ** Usage: sqlite3_errcode DB 15326622cce3Sdanielk1977 ** 15336622cce3Sdanielk1977 ** Return the string representation of the most recent sqlite3_* API 15346622cce3Sdanielk1977 ** error code. e.g. "SQLITE_ERROR". 15356622cce3Sdanielk1977 */ 15366622cce3Sdanielk1977 static int test_errcode( 15376622cce3Sdanielk1977 void * clientData, 15386622cce3Sdanielk1977 Tcl_Interp *interp, 15396622cce3Sdanielk1977 int objc, 15406622cce3Sdanielk1977 Tcl_Obj *CONST objv[] 15416622cce3Sdanielk1977 ){ 15426622cce3Sdanielk1977 sqlite3 *db; 15436622cce3Sdanielk1977 15446622cce3Sdanielk1977 if( objc!=2 ){ 15456622cce3Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 15466622cce3Sdanielk1977 Tcl_GetString(objv[0]), " DB", 0); 15476622cce3Sdanielk1977 return TCL_ERROR; 15486622cce3Sdanielk1977 } 15496622cce3Sdanielk1977 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 15506622cce3Sdanielk1977 Tcl_SetResult(interp, (char *)errorName(sqlite3_errcode(db)), 0); 15516622cce3Sdanielk1977 return TCL_OK; 15526622cce3Sdanielk1977 } 15536622cce3Sdanielk1977 15546622cce3Sdanielk1977 /* 15556622cce3Sdanielk1977 ** Usage: test_errmsg DB 15566622cce3Sdanielk1977 ** 15576622cce3Sdanielk1977 ** Returns the UTF-8 representation of the error message string for the 15586622cce3Sdanielk1977 ** most recent sqlite3_* API call. 15596622cce3Sdanielk1977 */ 15606622cce3Sdanielk1977 static int test_errmsg( 15616622cce3Sdanielk1977 void * clientData, 15626622cce3Sdanielk1977 Tcl_Interp *interp, 15636622cce3Sdanielk1977 int objc, 15646622cce3Sdanielk1977 Tcl_Obj *CONST objv[] 15656622cce3Sdanielk1977 ){ 15666622cce3Sdanielk1977 sqlite *db; 15676622cce3Sdanielk1977 const char *zErr; 15686622cce3Sdanielk1977 15696622cce3Sdanielk1977 if( objc!=2 ){ 15706622cce3Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 15716622cce3Sdanielk1977 Tcl_GetString(objv[0]), " DB", 0); 15726622cce3Sdanielk1977 return TCL_ERROR; 15736622cce3Sdanielk1977 } 15746622cce3Sdanielk1977 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 15756622cce3Sdanielk1977 15766622cce3Sdanielk1977 zErr = sqlite3_errmsg(db); 15776622cce3Sdanielk1977 Tcl_SetObjResult(interp, Tcl_NewStringObj(zErr, -1)); 15786622cce3Sdanielk1977 return TCL_OK; 15796622cce3Sdanielk1977 } 15806622cce3Sdanielk1977 15816622cce3Sdanielk1977 /* 15826622cce3Sdanielk1977 ** Usage: test_errmsg16 DB 15836622cce3Sdanielk1977 ** 15846622cce3Sdanielk1977 ** Returns the UTF-16 representation of the error message string for the 15856622cce3Sdanielk1977 ** most recent sqlite3_* API call. This is a byte array object at the TCL 15866622cce3Sdanielk1977 ** level, and it includes the 0x00 0x00 terminator bytes at the end of the 15876622cce3Sdanielk1977 ** UTF-16 string. 15886622cce3Sdanielk1977 */ 15896622cce3Sdanielk1977 static int test_errmsg16( 15906622cce3Sdanielk1977 void * clientData, 15916622cce3Sdanielk1977 Tcl_Interp *interp, 15926622cce3Sdanielk1977 int objc, 15936622cce3Sdanielk1977 Tcl_Obj *CONST objv[] 15946622cce3Sdanielk1977 ){ 15956622cce3Sdanielk1977 sqlite *db; 15966622cce3Sdanielk1977 const void *zErr; 15976622cce3Sdanielk1977 int bytes; 15986622cce3Sdanielk1977 15996622cce3Sdanielk1977 if( objc!=2 ){ 16006622cce3Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 16016622cce3Sdanielk1977 Tcl_GetString(objv[0]), " DB", 0); 16026622cce3Sdanielk1977 return TCL_ERROR; 16036622cce3Sdanielk1977 } 16046622cce3Sdanielk1977 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 16056622cce3Sdanielk1977 16066622cce3Sdanielk1977 zErr = sqlite3_errmsg16(db); 16076622cce3Sdanielk1977 bytes = sqlite3utf16ByteLen(zErr, -1); 16086622cce3Sdanielk1977 Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(zErr, bytes)); 16096622cce3Sdanielk1977 return TCL_OK; 16106622cce3Sdanielk1977 } 16116622cce3Sdanielk1977 16126622cce3Sdanielk1977 /* 16136622cce3Sdanielk1977 ** Usage: sqlite3_prepare DB sql bytes tailvar 16146622cce3Sdanielk1977 ** 16156622cce3Sdanielk1977 ** Compile up to <bytes> bytes of the supplied SQL string <sql> using 16166622cce3Sdanielk1977 ** database handle <DB>. The parameter <tailval> is the name of a global 16176622cce3Sdanielk1977 ** variable that is set to the unused portion of <sql> (if any). A 16186622cce3Sdanielk1977 ** STMT handle is returned. 16196622cce3Sdanielk1977 */ 16206622cce3Sdanielk1977 static int test_prepare( 16216622cce3Sdanielk1977 void * clientData, 16226622cce3Sdanielk1977 Tcl_Interp *interp, 16236622cce3Sdanielk1977 int objc, 16246622cce3Sdanielk1977 Tcl_Obj *CONST objv[] 16256622cce3Sdanielk1977 ){ 16266622cce3Sdanielk1977 sqlite3 *db; 16276622cce3Sdanielk1977 const char *zSql; 16286622cce3Sdanielk1977 int bytes; 16296622cce3Sdanielk1977 const char *zTail = 0; 16306622cce3Sdanielk1977 sqlite3_stmt *pStmt = 0; 16316622cce3Sdanielk1977 char zBuf[50]; 16324ad1713cSdanielk1977 int rc; 16336622cce3Sdanielk1977 16346622cce3Sdanielk1977 if( objc!=5 ){ 16356622cce3Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 16366622cce3Sdanielk1977 Tcl_GetString(objv[0]), " DB sql bytes tailvar", 0); 16376622cce3Sdanielk1977 return TCL_ERROR; 16386622cce3Sdanielk1977 } 16396622cce3Sdanielk1977 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 16406622cce3Sdanielk1977 zSql = Tcl_GetString(objv[2]); 16416622cce3Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR; 16426622cce3Sdanielk1977 16434ad1713cSdanielk1977 rc = sqlite3_prepare(db, zSql, bytes, &pStmt, &zTail); 16446622cce3Sdanielk1977 if( zTail ){ 16456622cce3Sdanielk1977 if( bytes>=0 ){ 16466622cce3Sdanielk1977 bytes = bytes - (zTail-zSql); 16476622cce3Sdanielk1977 } 16486622cce3Sdanielk1977 Tcl_ObjSetVar2(interp, objv[4], 0, Tcl_NewStringObj(zTail, bytes), 0); 16496622cce3Sdanielk1977 } 16504ad1713cSdanielk1977 if( rc!=SQLITE_OK ){ 16514ad1713cSdanielk1977 assert( pStmt==0 ); 16524ad1713cSdanielk1977 sprintf(zBuf, "(%d) ", rc); 16534ad1713cSdanielk1977 Tcl_AppendResult(interp, zBuf, sqlite3_errmsg(db), 0); 16544ad1713cSdanielk1977 return TCL_ERROR; 16554ad1713cSdanielk1977 } 16566622cce3Sdanielk1977 16574ad1713cSdanielk1977 if( pStmt ){ 16586622cce3Sdanielk1977 if( makePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR; 16596622cce3Sdanielk1977 Tcl_AppendResult(interp, zBuf, 0); 16604ad1713cSdanielk1977 } 16616622cce3Sdanielk1977 return TCL_OK; 16626622cce3Sdanielk1977 } 16636622cce3Sdanielk1977 16646622cce3Sdanielk1977 /* 16656622cce3Sdanielk1977 ** Usage: sqlite3_prepare DB sql bytes tailvar 16666622cce3Sdanielk1977 ** 16676622cce3Sdanielk1977 ** Compile up to <bytes> bytes of the supplied SQL string <sql> using 16686622cce3Sdanielk1977 ** database handle <DB>. The parameter <tailval> is the name of a global 16696622cce3Sdanielk1977 ** variable that is set to the unused portion of <sql> (if any). A 16706622cce3Sdanielk1977 ** STMT handle is returned. 16716622cce3Sdanielk1977 */ 16726622cce3Sdanielk1977 static int test_prepare16( 16736622cce3Sdanielk1977 void * clientData, 16746622cce3Sdanielk1977 Tcl_Interp *interp, 16756622cce3Sdanielk1977 int objc, 16766622cce3Sdanielk1977 Tcl_Obj *CONST objv[] 16776622cce3Sdanielk1977 ){ 16786622cce3Sdanielk1977 sqlite3 *db; 16796622cce3Sdanielk1977 const void *zSql; 16806622cce3Sdanielk1977 const void *zTail = 0; 16816622cce3Sdanielk1977 Tcl_Obj *pTail = 0; 16826622cce3Sdanielk1977 sqlite3_stmt *pStmt = 0; 16836622cce3Sdanielk1977 char zBuf[50]; 16846622cce3Sdanielk1977 int bytes; /* The integer specified as arg 3 */ 16856622cce3Sdanielk1977 int objlen; /* The byte-array length of arg 2 */ 16866622cce3Sdanielk1977 16876622cce3Sdanielk1977 if( objc!=5 ){ 16886622cce3Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 16896622cce3Sdanielk1977 Tcl_GetString(objv[0]), " DB sql bytes tailvar", 0); 16906622cce3Sdanielk1977 return TCL_ERROR; 16916622cce3Sdanielk1977 } 16926622cce3Sdanielk1977 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 16936622cce3Sdanielk1977 zSql = Tcl_GetByteArrayFromObj(objv[2], &objlen); 16946622cce3Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR; 16956622cce3Sdanielk1977 16966622cce3Sdanielk1977 if( SQLITE_OK!=sqlite3_prepare16(db, zSql, bytes, &pStmt, &zTail) ){ 16976622cce3Sdanielk1977 return TCL_ERROR; 16986622cce3Sdanielk1977 } 16996622cce3Sdanielk1977 17006622cce3Sdanielk1977 if( zTail ){ 17016622cce3Sdanielk1977 objlen = objlen - ((u8 *)zTail-(u8 *)zSql); 17026622cce3Sdanielk1977 }else{ 17036622cce3Sdanielk1977 objlen = 0; 17046622cce3Sdanielk1977 } 17056622cce3Sdanielk1977 pTail = Tcl_NewByteArrayObj((u8 *)zTail, objlen); 17066622cce3Sdanielk1977 Tcl_IncrRefCount(pTail); 17076622cce3Sdanielk1977 Tcl_ObjSetVar2(interp, objv[4], 0, pTail, 0); 17084ad1713cSdanielk1977 Tcl_DecrRefCount(pTail); 17096622cce3Sdanielk1977 17104ad1713cSdanielk1977 if( pStmt ){ 17116622cce3Sdanielk1977 if( makePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR; 17124ad1713cSdanielk1977 } 17136622cce3Sdanielk1977 Tcl_AppendResult(interp, zBuf, 0); 17146622cce3Sdanielk1977 return TCL_OK; 17156622cce3Sdanielk1977 } 17166622cce3Sdanielk1977 17174ad1713cSdanielk1977 /* 17184ad1713cSdanielk1977 ** Usage: sqlite3_open filename ?options-list? 17194ad1713cSdanielk1977 */ 17204ad1713cSdanielk1977 static int test_open( 17214ad1713cSdanielk1977 void * clientData, 17224ad1713cSdanielk1977 Tcl_Interp *interp, 17234ad1713cSdanielk1977 int objc, 17244ad1713cSdanielk1977 Tcl_Obj *CONST objv[] 17254ad1713cSdanielk1977 ){ 17264ad1713cSdanielk1977 const char *zFilename; 17274ad1713cSdanielk1977 sqlite3 *db; 17284ad1713cSdanielk1977 int rc; 17294ad1713cSdanielk1977 char zBuf[100]; 17304ad1713cSdanielk1977 17314ad1713cSdanielk1977 if( objc!=3 && objc!=2 ){ 17324ad1713cSdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 17334ad1713cSdanielk1977 Tcl_GetString(objv[0]), " filename options-list", 0); 17344ad1713cSdanielk1977 return TCL_ERROR; 17354ad1713cSdanielk1977 } 17364ad1713cSdanielk1977 17374ad1713cSdanielk1977 zFilename = Tcl_GetString(objv[1]); 17384f057f90Sdanielk1977 rc = sqlite3_open(zFilename, &db); 17394ad1713cSdanielk1977 17404ad1713cSdanielk1977 if( makePointerStr(interp, zBuf, db) ) return TCL_ERROR; 17414ad1713cSdanielk1977 Tcl_AppendResult(interp, zBuf, 0); 17424ad1713cSdanielk1977 return TCL_OK; 17434ad1713cSdanielk1977 } 17444ad1713cSdanielk1977 17454ad1713cSdanielk1977 /* 17464ad1713cSdanielk1977 ** Usage: sqlite3_open16 filename options 17474ad1713cSdanielk1977 */ 17484ad1713cSdanielk1977 static int test_open16( 17494ad1713cSdanielk1977 void * clientData, 17504ad1713cSdanielk1977 Tcl_Interp *interp, 17514ad1713cSdanielk1977 int objc, 17524ad1713cSdanielk1977 Tcl_Obj *CONST objv[] 17534ad1713cSdanielk1977 ){ 17544ad1713cSdanielk1977 const void *zFilename; 17554ad1713cSdanielk1977 sqlite3 *db; 17564ad1713cSdanielk1977 int rc; 17574ad1713cSdanielk1977 char zBuf[100]; 17584ad1713cSdanielk1977 17594ad1713cSdanielk1977 if( objc!=3 ){ 17604ad1713cSdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 17614ad1713cSdanielk1977 Tcl_GetString(objv[0]), " filename options-list", 0); 17624ad1713cSdanielk1977 return TCL_ERROR; 17634ad1713cSdanielk1977 } 17644ad1713cSdanielk1977 17654ad1713cSdanielk1977 zFilename = Tcl_GetByteArrayFromObj(objv[1], 0); 17664f057f90Sdanielk1977 rc = sqlite3_open16(zFilename, &db); 17674ad1713cSdanielk1977 17684ad1713cSdanielk1977 if( makePointerStr(interp, zBuf, db) ) return TCL_ERROR; 17694ad1713cSdanielk1977 Tcl_AppendResult(interp, zBuf, 0); 17704ad1713cSdanielk1977 return TCL_OK; 17714ad1713cSdanielk1977 } 1772d3d39e93Sdrh 1773d3d39e93Sdrh /* 1774106bb236Sdanielk1977 ** Usage: sqlite3_step STMT 1775106bb236Sdanielk1977 ** 1776106bb236Sdanielk1977 ** Advance the statement to the next row. 1777106bb236Sdanielk1977 */ 177817240fd9Sdanielk1977 static int test_step( 1779106bb236Sdanielk1977 void * clientData, 1780106bb236Sdanielk1977 Tcl_Interp *interp, 1781106bb236Sdanielk1977 int objc, 1782106bb236Sdanielk1977 Tcl_Obj *CONST objv[] 1783106bb236Sdanielk1977 ){ 1784106bb236Sdanielk1977 sqlite3_stmt *pStmt; 1785106bb236Sdanielk1977 int rc; 1786106bb236Sdanielk1977 1787e1cd9874Sdanielk1977 if( objc!=2 ){ 1788106bb236Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 1789106bb236Sdanielk1977 Tcl_GetString(objv[0]), " STMT", 0); 1790106bb236Sdanielk1977 return TCL_ERROR; 1791106bb236Sdanielk1977 } 1792106bb236Sdanielk1977 1793106bb236Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 179417240fd9Sdanielk1977 rc = sqlite3_step(pStmt); 1795106bb236Sdanielk1977 1796fbcd585fSdanielk1977 /* if( rc!=SQLITE_DONE && rc!=SQLITE_ROW ) return TCL_ERROR; */ 17976590493dSdanielk1977 Tcl_SetResult(interp, (char *)errorName(rc), 0); 1798e1cd9874Sdanielk1977 return TCL_OK; 1799e1cd9874Sdanielk1977 } 1800e1cd9874Sdanielk1977 1801e1cd9874Sdanielk1977 /* 180217240fd9Sdanielk1977 ** Usage: sqlite3_column_count STMT 180317240fd9Sdanielk1977 ** 180417240fd9Sdanielk1977 ** Return the number of columns returned by the sql statement STMT. 180517240fd9Sdanielk1977 */ 180617240fd9Sdanielk1977 static int test_column_count( 180717240fd9Sdanielk1977 void * clientData, 180817240fd9Sdanielk1977 Tcl_Interp *interp, 180917240fd9Sdanielk1977 int objc, 181017240fd9Sdanielk1977 Tcl_Obj *CONST objv[] 181117240fd9Sdanielk1977 ){ 181217240fd9Sdanielk1977 sqlite3_stmt *pStmt; 181317240fd9Sdanielk1977 181417240fd9Sdanielk1977 if( objc!=2 ){ 181517240fd9Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 181617240fd9Sdanielk1977 Tcl_GetString(objv[0]), " STMT column", 0); 181717240fd9Sdanielk1977 return TCL_ERROR; 181817240fd9Sdanielk1977 } 181917240fd9Sdanielk1977 182017240fd9Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 182117240fd9Sdanielk1977 182217240fd9Sdanielk1977 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_column_count(pStmt))); 182317240fd9Sdanielk1977 return TCL_OK; 182417240fd9Sdanielk1977 } 182517240fd9Sdanielk1977 182617240fd9Sdanielk1977 /* 18273cf86063Sdanielk1977 ** Usage: sqlite3_column_type STMT column 18283cf86063Sdanielk1977 ** 18293cf86063Sdanielk1977 ** Return the type of the data in column 'column' of the current row. 18303cf86063Sdanielk1977 */ 18313cf86063Sdanielk1977 static int test_column_type( 18323cf86063Sdanielk1977 void * clientData, 18333cf86063Sdanielk1977 Tcl_Interp *interp, 18343cf86063Sdanielk1977 int objc, 18353cf86063Sdanielk1977 Tcl_Obj *CONST objv[] 18363cf86063Sdanielk1977 ){ 18373cf86063Sdanielk1977 sqlite3_stmt *pStmt; 18383cf86063Sdanielk1977 int col; 18393cf86063Sdanielk1977 int tp; 18403cf86063Sdanielk1977 18413cf86063Sdanielk1977 if( objc!=3 ){ 18423cf86063Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 18433cf86063Sdanielk1977 Tcl_GetString(objv[0]), " STMT column", 0); 18443cf86063Sdanielk1977 return TCL_ERROR; 18453cf86063Sdanielk1977 } 18463cf86063Sdanielk1977 18473cf86063Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 18483cf86063Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; 18493cf86063Sdanielk1977 18503cf86063Sdanielk1977 tp = sqlite3_column_type(pStmt, col); 18513cf86063Sdanielk1977 switch( tp ){ 18529c054830Sdrh case SQLITE_INTEGER: 18533cf86063Sdanielk1977 Tcl_SetResult(interp, "INTEGER", TCL_STATIC); 18543cf86063Sdanielk1977 break; 18559c054830Sdrh case SQLITE_NULL: 18563cf86063Sdanielk1977 Tcl_SetResult(interp, "NULL", TCL_STATIC); 18573cf86063Sdanielk1977 break; 18589c054830Sdrh case SQLITE_FLOAT: 18593cf86063Sdanielk1977 Tcl_SetResult(interp, "FLOAT", TCL_STATIC); 18603cf86063Sdanielk1977 break; 18619c054830Sdrh case SQLITE_TEXT: 18623cf86063Sdanielk1977 Tcl_SetResult(interp, "TEXT", TCL_STATIC); 18633cf86063Sdanielk1977 break; 18649c054830Sdrh case SQLITE_BLOB: 18653cf86063Sdanielk1977 Tcl_SetResult(interp, "BLOB", TCL_STATIC); 18663cf86063Sdanielk1977 break; 18673cf86063Sdanielk1977 default: 18683cf86063Sdanielk1977 assert(0); 18693cf86063Sdanielk1977 } 18703cf86063Sdanielk1977 18713cf86063Sdanielk1977 return TCL_OK; 18723cf86063Sdanielk1977 } 18733cf86063Sdanielk1977 18743cf86063Sdanielk1977 /* 187504f2e68dSdanielk1977 ** Usage: sqlite3_column_int64 STMT column 18763cf86063Sdanielk1977 ** 18773cf86063Sdanielk1977 ** Return the data in column 'column' of the current row cast as an 187804f2e68dSdanielk1977 ** wide (64-bit) integer. 18793cf86063Sdanielk1977 */ 188004f2e68dSdanielk1977 static int test_column_int64( 18813cf86063Sdanielk1977 void * clientData, 18823cf86063Sdanielk1977 Tcl_Interp *interp, 18833cf86063Sdanielk1977 int objc, 18843cf86063Sdanielk1977 Tcl_Obj *CONST objv[] 18853cf86063Sdanielk1977 ){ 18863cf86063Sdanielk1977 sqlite3_stmt *pStmt; 18873cf86063Sdanielk1977 int col; 188804f2e68dSdanielk1977 i64 iVal; 18893cf86063Sdanielk1977 18903cf86063Sdanielk1977 if( objc!=3 ){ 18913cf86063Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 18923cf86063Sdanielk1977 Tcl_GetString(objv[0]), " STMT column", 0); 18933cf86063Sdanielk1977 return TCL_ERROR; 18943cf86063Sdanielk1977 } 18953cf86063Sdanielk1977 18963cf86063Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 18973cf86063Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; 18983cf86063Sdanielk1977 189904f2e68dSdanielk1977 iVal = sqlite3_column_int64(pStmt, col); 190004f2e68dSdanielk1977 Tcl_SetObjResult(interp, Tcl_NewWideIntObj(iVal)); 190104f2e68dSdanielk1977 return TCL_OK; 190204f2e68dSdanielk1977 } 190304f2e68dSdanielk1977 190404f2e68dSdanielk1977 /* 1905ea61b2c4Sdanielk1977 ** Usage: sqlite3_column_blob STMT column 1906ea61b2c4Sdanielk1977 */ 1907ea61b2c4Sdanielk1977 static int test_column_blob( 1908ea61b2c4Sdanielk1977 void * clientData, 1909ea61b2c4Sdanielk1977 Tcl_Interp *interp, 1910ea61b2c4Sdanielk1977 int objc, 1911ea61b2c4Sdanielk1977 Tcl_Obj *CONST objv[] 1912ea61b2c4Sdanielk1977 ){ 1913ea61b2c4Sdanielk1977 sqlite3_stmt *pStmt; 1914ea61b2c4Sdanielk1977 int col; 1915ea61b2c4Sdanielk1977 1916ea61b2c4Sdanielk1977 int len; 1917c572ef7fSdanielk1977 const void *pBlob; 1918ea61b2c4Sdanielk1977 1919ea61b2c4Sdanielk1977 if( objc!=3 ){ 1920ea61b2c4Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 1921ea61b2c4Sdanielk1977 Tcl_GetString(objv[0]), " STMT column", 0); 1922ea61b2c4Sdanielk1977 return TCL_ERROR; 1923ea61b2c4Sdanielk1977 } 1924ea61b2c4Sdanielk1977 1925ea61b2c4Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 1926ea61b2c4Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; 1927ea61b2c4Sdanielk1977 1928ea61b2c4Sdanielk1977 pBlob = sqlite3_column_blob(pStmt, col); 1929ea61b2c4Sdanielk1977 len = sqlite3_column_bytes(pStmt, col); 1930ea61b2c4Sdanielk1977 Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(pBlob, len)); 1931ea61b2c4Sdanielk1977 return TCL_OK; 1932ea61b2c4Sdanielk1977 } 1933ea61b2c4Sdanielk1977 1934ea61b2c4Sdanielk1977 /* 193504f2e68dSdanielk1977 ** Usage: sqlite3_column_double STMT column 193604f2e68dSdanielk1977 ** 193704f2e68dSdanielk1977 ** Return the data in column 'column' of the current row cast as a double. 193804f2e68dSdanielk1977 */ 193904f2e68dSdanielk1977 static int test_column_double( 194004f2e68dSdanielk1977 void * clientData, 194104f2e68dSdanielk1977 Tcl_Interp *interp, 194204f2e68dSdanielk1977 int objc, 194304f2e68dSdanielk1977 Tcl_Obj *CONST objv[] 194404f2e68dSdanielk1977 ){ 194504f2e68dSdanielk1977 sqlite3_stmt *pStmt; 194604f2e68dSdanielk1977 int col; 194704f2e68dSdanielk1977 double rVal; 194804f2e68dSdanielk1977 194904f2e68dSdanielk1977 if( objc!=3 ){ 195004f2e68dSdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 195104f2e68dSdanielk1977 Tcl_GetString(objv[0]), " STMT column", 0); 195204f2e68dSdanielk1977 return TCL_ERROR; 195304f2e68dSdanielk1977 } 195404f2e68dSdanielk1977 195504f2e68dSdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 195604f2e68dSdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; 195704f2e68dSdanielk1977 195804f2e68dSdanielk1977 rVal = sqlite3_column_double(pStmt, col); 1959c572ef7fSdanielk1977 Tcl_SetObjResult(interp, Tcl_NewDoubleObj(rVal)); 19603cf86063Sdanielk1977 return TCL_OK; 19613cf86063Sdanielk1977 } 19623cf86063Sdanielk1977 19633cf86063Sdanielk1977 /* 196417240fd9Sdanielk1977 ** Usage: sqlite3_data_count STMT 196517240fd9Sdanielk1977 ** 196617240fd9Sdanielk1977 ** Return the number of columns returned by the sql statement STMT. 196717240fd9Sdanielk1977 */ 196817240fd9Sdanielk1977 static int test_data_count( 196917240fd9Sdanielk1977 void * clientData, 197017240fd9Sdanielk1977 Tcl_Interp *interp, 197117240fd9Sdanielk1977 int objc, 197217240fd9Sdanielk1977 Tcl_Obj *CONST objv[] 197317240fd9Sdanielk1977 ){ 197417240fd9Sdanielk1977 sqlite3_stmt *pStmt; 197517240fd9Sdanielk1977 197617240fd9Sdanielk1977 if( objc!=2 ){ 197717240fd9Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 197817240fd9Sdanielk1977 Tcl_GetString(objv[0]), " STMT column", 0); 197917240fd9Sdanielk1977 return TCL_ERROR; 198017240fd9Sdanielk1977 } 198117240fd9Sdanielk1977 198217240fd9Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 198317240fd9Sdanielk1977 198417240fd9Sdanielk1977 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_data_count(pStmt))); 198517240fd9Sdanielk1977 return TCL_OK; 198617240fd9Sdanielk1977 } 198717240fd9Sdanielk1977 198817240fd9Sdanielk1977 /* 198904f2e68dSdanielk1977 ** Usage: sqlite3_column_text STMT column 199004f2e68dSdanielk1977 ** 199104f2e68dSdanielk1977 ** Usage: sqlite3_column_decltype STMT column 199204f2e68dSdanielk1977 ** 199304f2e68dSdanielk1977 ** Usage: sqlite3_column_name STMT column 199404f2e68dSdanielk1977 */ 199504f2e68dSdanielk1977 static int test_stmt_utf8( 1996241db313Sdrh void * clientData, /* Pointer to SQLite API function to be invoke */ 199704f2e68dSdanielk1977 Tcl_Interp *interp, 199804f2e68dSdanielk1977 int objc, 199904f2e68dSdanielk1977 Tcl_Obj *CONST objv[] 200004f2e68dSdanielk1977 ){ 200104f2e68dSdanielk1977 sqlite3_stmt *pStmt; 200204f2e68dSdanielk1977 int col; 2003c572ef7fSdanielk1977 const char *(*xFunc)(sqlite3_stmt*, int) = clientData; 2004f93bbbeaSdanielk1977 const char *zRet; 200504f2e68dSdanielk1977 200604f2e68dSdanielk1977 if( objc!=3 ){ 200704f2e68dSdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 200804f2e68dSdanielk1977 Tcl_GetString(objv[0]), " STMT column", 0); 200904f2e68dSdanielk1977 return TCL_ERROR; 201004f2e68dSdanielk1977 } 201104f2e68dSdanielk1977 201204f2e68dSdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 201304f2e68dSdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; 2014f93bbbeaSdanielk1977 zRet = xFunc(pStmt, col); 2015f93bbbeaSdanielk1977 if( zRet ){ 2016f93bbbeaSdanielk1977 Tcl_SetResult(interp, (char *)zRet, 0); 2017f93bbbeaSdanielk1977 } 201804f2e68dSdanielk1977 return TCL_OK; 201904f2e68dSdanielk1977 } 202004f2e68dSdanielk1977 202104f2e68dSdanielk1977 /* 202204f2e68dSdanielk1977 ** Usage: sqlite3_column_text STMT column 202304f2e68dSdanielk1977 ** 202404f2e68dSdanielk1977 ** Usage: sqlite3_column_decltype STMT column 202504f2e68dSdanielk1977 ** 202604f2e68dSdanielk1977 ** Usage: sqlite3_column_name STMT column 202704f2e68dSdanielk1977 */ 202804f2e68dSdanielk1977 static int test_stmt_utf16( 2029241db313Sdrh void * clientData, /* Pointer to SQLite API function to be invoked */ 203004f2e68dSdanielk1977 Tcl_Interp *interp, 203104f2e68dSdanielk1977 int objc, 203204f2e68dSdanielk1977 Tcl_Obj *CONST objv[] 203304f2e68dSdanielk1977 ){ 203404f2e68dSdanielk1977 sqlite3_stmt *pStmt; 203504f2e68dSdanielk1977 int col; 203604f2e68dSdanielk1977 Tcl_Obj *pRet; 203704f2e68dSdanielk1977 const void *zName16; 2038c572ef7fSdanielk1977 const void *(*xFunc)(sqlite3_stmt*, int) = clientData; 203904f2e68dSdanielk1977 204004f2e68dSdanielk1977 if( objc!=3 ){ 204104f2e68dSdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 204204f2e68dSdanielk1977 Tcl_GetString(objv[0]), " STMT column", 0); 204304f2e68dSdanielk1977 return TCL_ERROR; 204404f2e68dSdanielk1977 } 204504f2e68dSdanielk1977 204604f2e68dSdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 204704f2e68dSdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; 204804f2e68dSdanielk1977 204904f2e68dSdanielk1977 zName16 = xFunc(pStmt, col); 2050f93bbbeaSdanielk1977 if( zName16 ){ 205104f2e68dSdanielk1977 pRet = Tcl_NewByteArrayObj(zName16, sqlite3utf16ByteLen(zName16, -1)+2); 205204f2e68dSdanielk1977 Tcl_SetObjResult(interp, pRet); 2053f93bbbeaSdanielk1977 } 205404f2e68dSdanielk1977 205504f2e68dSdanielk1977 return TCL_OK; 205604f2e68dSdanielk1977 } 205704f2e68dSdanielk1977 205804f2e68dSdanielk1977 /* 205904f2e68dSdanielk1977 ** Usage: sqlite3_column_int STMT column 206004f2e68dSdanielk1977 ** 206104f2e68dSdanielk1977 ** Usage: sqlite3_column_bytes STMT column 206204f2e68dSdanielk1977 ** 206304f2e68dSdanielk1977 ** Usage: sqlite3_column_bytes16 STMT column 206404f2e68dSdanielk1977 ** 206504f2e68dSdanielk1977 */ 206604f2e68dSdanielk1977 static int test_stmt_int( 2067241db313Sdrh void * clientData, /* Pointer to SQLite API function to be invoked */ 206804f2e68dSdanielk1977 Tcl_Interp *interp, 206904f2e68dSdanielk1977 int objc, 207004f2e68dSdanielk1977 Tcl_Obj *CONST objv[] 207104f2e68dSdanielk1977 ){ 207204f2e68dSdanielk1977 sqlite3_stmt *pStmt; 207304f2e68dSdanielk1977 int col; 2074c572ef7fSdanielk1977 int (*xFunc)(sqlite3_stmt*, int) = clientData; 207504f2e68dSdanielk1977 207604f2e68dSdanielk1977 if( objc!=3 ){ 207704f2e68dSdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 207804f2e68dSdanielk1977 Tcl_GetString(objv[0]), " STMT column", 0); 207904f2e68dSdanielk1977 return TCL_ERROR; 208004f2e68dSdanielk1977 } 208104f2e68dSdanielk1977 208204f2e68dSdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 208304f2e68dSdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; 208404f2e68dSdanielk1977 208504f2e68dSdanielk1977 Tcl_SetObjResult(interp, Tcl_NewIntObj(xFunc(pStmt, col))); 208604f2e68dSdanielk1977 return TCL_OK; 208704f2e68dSdanielk1977 } 208804f2e68dSdanielk1977 20899a1d0abeSdanielk1977 /* 20909a1d0abeSdanielk1977 ** Usage: sqlite3OsOpenReadWrite <filename> 20919a1d0abeSdanielk1977 */ 20929a1d0abeSdanielk1977 static int test_sqlite3OsOpenReadWrite( 20939a1d0abeSdanielk1977 void * clientData, 20949a1d0abeSdanielk1977 Tcl_Interp *interp, 20959a1d0abeSdanielk1977 int objc, 20969a1d0abeSdanielk1977 Tcl_Obj *CONST objv[] 20979a1d0abeSdanielk1977 ){ 20989a1d0abeSdanielk1977 OsFile * pFile; 20999a1d0abeSdanielk1977 int rc; 21009a1d0abeSdanielk1977 int dummy; 21019a1d0abeSdanielk1977 char zBuf[100]; 210204f2e68dSdanielk1977 21039a1d0abeSdanielk1977 if( objc!=2 ){ 21049a1d0abeSdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 21059a1d0abeSdanielk1977 Tcl_GetString(objv[0]), " filename", 0); 21069a1d0abeSdanielk1977 return TCL_ERROR; 21079a1d0abeSdanielk1977 } 21089a1d0abeSdanielk1977 21099a1d0abeSdanielk1977 pFile = sqliteMalloc(sizeof(OsFile)); 21109a1d0abeSdanielk1977 rc = sqlite3OsOpenReadWrite(Tcl_GetString(objv[1]), pFile, &dummy); 21119a1d0abeSdanielk1977 if( rc!=SQLITE_OK ){ 21129a1d0abeSdanielk1977 sqliteFree(pFile); 21139a1d0abeSdanielk1977 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC); 21149a1d0abeSdanielk1977 return TCL_ERROR; 21159a1d0abeSdanielk1977 } 21169a1d0abeSdanielk1977 makePointerStr(interp, zBuf, pFile); 21179a1d0abeSdanielk1977 Tcl_SetResult(interp, zBuf, 0); 21189a1d0abeSdanielk1977 return TCL_ERROR; 21199a1d0abeSdanielk1977 } 21209a1d0abeSdanielk1977 21219a1d0abeSdanielk1977 /* 21229a1d0abeSdanielk1977 ** Usage: sqlite3OsClose <file handle> 21239a1d0abeSdanielk1977 */ 21249a1d0abeSdanielk1977 static int test_sqlite3OsClose( 21259a1d0abeSdanielk1977 void * clientData, 21269a1d0abeSdanielk1977 Tcl_Interp *interp, 21279a1d0abeSdanielk1977 int objc, 21289a1d0abeSdanielk1977 Tcl_Obj *CONST objv[] 21299a1d0abeSdanielk1977 ){ 21309a1d0abeSdanielk1977 OsFile * pFile; 21319a1d0abeSdanielk1977 int rc; 21329a1d0abeSdanielk1977 21339a1d0abeSdanielk1977 if( objc!=2 ){ 21349a1d0abeSdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 21359a1d0abeSdanielk1977 Tcl_GetString(objv[0]), " filehandle", 0); 21369a1d0abeSdanielk1977 return TCL_ERROR; 21379a1d0abeSdanielk1977 } 21389a1d0abeSdanielk1977 21399a1d0abeSdanielk1977 if( getFilePointer(interp, Tcl_GetString(objv[1]), &pFile) ){ 21409a1d0abeSdanielk1977 return TCL_ERROR; 21419a1d0abeSdanielk1977 } 21429a1d0abeSdanielk1977 rc = sqlite3OsClose(pFile); 21439a1d0abeSdanielk1977 if( rc!=SQLITE_OK ){ 21449a1d0abeSdanielk1977 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC); 21459a1d0abeSdanielk1977 return TCL_ERROR; 21469a1d0abeSdanielk1977 } 21479a1d0abeSdanielk1977 sqliteFree(pFile); 21489a1d0abeSdanielk1977 return TCL_OK; 21499a1d0abeSdanielk1977 } 21509a1d0abeSdanielk1977 21519a1d0abeSdanielk1977 /* 21529a1d0abeSdanielk1977 ** Usage: sqlite3OsLock <file handle> <locktype> 21539a1d0abeSdanielk1977 */ 21549a1d0abeSdanielk1977 static int test_sqlite3OsLock( 21559a1d0abeSdanielk1977 void * clientData, 21569a1d0abeSdanielk1977 Tcl_Interp *interp, 21579a1d0abeSdanielk1977 int objc, 21589a1d0abeSdanielk1977 Tcl_Obj *CONST objv[] 21599a1d0abeSdanielk1977 ){ 21609a1d0abeSdanielk1977 OsFile * pFile; 21619a1d0abeSdanielk1977 int rc; 21629a1d0abeSdanielk1977 21639a1d0abeSdanielk1977 if( objc!=3 ){ 21649a1d0abeSdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 21659a1d0abeSdanielk1977 Tcl_GetString(objv[0]), 21669a1d0abeSdanielk1977 " filehandle (SHARED|RESERVED|PENDING|EXCLUSIVE)", 0); 21679a1d0abeSdanielk1977 return TCL_ERROR; 21689a1d0abeSdanielk1977 } 21699a1d0abeSdanielk1977 21709a1d0abeSdanielk1977 if( getFilePointer(interp, Tcl_GetString(objv[1]), &pFile) ){ 21719a1d0abeSdanielk1977 return TCL_ERROR; 21729a1d0abeSdanielk1977 } 21739a1d0abeSdanielk1977 21749a1d0abeSdanielk1977 if( 0==strcmp("SHARED", Tcl_GetString(objv[2])) ){ 21759a1d0abeSdanielk1977 rc = sqlite3OsLock(pFile, SHARED_LOCK); 21769a1d0abeSdanielk1977 } 21779a1d0abeSdanielk1977 else if( 0==strcmp("RESERVED", Tcl_GetString(objv[2])) ){ 21789a1d0abeSdanielk1977 rc = sqlite3OsLock(pFile, RESERVED_LOCK); 21799a1d0abeSdanielk1977 } 21809a1d0abeSdanielk1977 else if( 0==strcmp("PENDING", Tcl_GetString(objv[2])) ){ 21819a1d0abeSdanielk1977 rc = sqlite3OsLock(pFile, PENDING_LOCK); 21829a1d0abeSdanielk1977 } 21839a1d0abeSdanielk1977 else if( 0==strcmp("EXCLUSIVE", Tcl_GetString(objv[2])) ){ 21849a1d0abeSdanielk1977 rc = sqlite3OsLock(pFile, EXCLUSIVE_LOCK); 21859a1d0abeSdanielk1977 }else{ 21869a1d0abeSdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 21879a1d0abeSdanielk1977 Tcl_GetString(objv[0]), 21889a1d0abeSdanielk1977 " filehandle (SHARED|RESERVED|PENDING|EXCLUSIVE)", 0); 21899a1d0abeSdanielk1977 return TCL_ERROR; 21909a1d0abeSdanielk1977 } 21919a1d0abeSdanielk1977 21929a1d0abeSdanielk1977 if( rc!=SQLITE_OK ){ 21939a1d0abeSdanielk1977 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC); 21949a1d0abeSdanielk1977 return TCL_ERROR; 21959a1d0abeSdanielk1977 } 21969a1d0abeSdanielk1977 return TCL_OK; 21979a1d0abeSdanielk1977 } 21989a1d0abeSdanielk1977 21999a1d0abeSdanielk1977 /* 22009a1d0abeSdanielk1977 ** Usage: sqlite3OsUnlock <file handle> 22019a1d0abeSdanielk1977 */ 22029a1d0abeSdanielk1977 static int test_sqlite3OsUnlock( 22039a1d0abeSdanielk1977 void * clientData, 22049a1d0abeSdanielk1977 Tcl_Interp *interp, 22059a1d0abeSdanielk1977 int objc, 22069a1d0abeSdanielk1977 Tcl_Obj *CONST objv[] 22079a1d0abeSdanielk1977 ){ 22089a1d0abeSdanielk1977 OsFile * pFile; 22099a1d0abeSdanielk1977 int rc; 22109a1d0abeSdanielk1977 22119a1d0abeSdanielk1977 if( objc!=2 ){ 22129a1d0abeSdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 22139a1d0abeSdanielk1977 Tcl_GetString(objv[0]), " filehandle", 0); 22149a1d0abeSdanielk1977 return TCL_ERROR; 22159a1d0abeSdanielk1977 } 22169a1d0abeSdanielk1977 22179a1d0abeSdanielk1977 if( getFilePointer(interp, Tcl_GetString(objv[1]), &pFile) ){ 22189a1d0abeSdanielk1977 return TCL_ERROR; 22199a1d0abeSdanielk1977 } 2220a6abd041Sdrh rc = sqlite3OsUnlock(pFile, NO_LOCK); 22219a1d0abeSdanielk1977 if( rc!=SQLITE_OK ){ 22229a1d0abeSdanielk1977 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC); 22239a1d0abeSdanielk1977 return TCL_ERROR; 22249a1d0abeSdanielk1977 } 22259a1d0abeSdanielk1977 return TCL_OK; 22269a1d0abeSdanielk1977 } 2227d3d39e93Sdrh 2228d8123366Sdanielk1977 22296622cce3Sdanielk1977 /* 2230d1bf3512Sdrh ** Register commands with the TCL interpreter. 2231d1bf3512Sdrh */ 2232d1bf3512Sdrh int Sqlitetest1_Init(Tcl_Interp *interp){ 22336f8a503dSdanielk1977 extern int sqlite3_search_count; 22346f8a503dSdanielk1977 extern int sqlite3_interrupt_count; 22356f8a503dSdanielk1977 extern int sqlite3_open_file_count; 22366f8a503dSdanielk1977 extern int sqlite3_current_time; 2237c2eef3b3Sdrh static struct { 2238c2eef3b3Sdrh char *zName; 2239c2eef3b3Sdrh Tcl_CmdProc *xProc; 2240c2eef3b3Sdrh } aCmd[] = { 22416f8a503dSdanielk1977 { "sqlite3_mprintf_int", (Tcl_CmdProc*)sqlite3_mprintf_int }, 2242e9707671Sdrh { "sqlite3_mprintf_int64", (Tcl_CmdProc*)sqlite3_mprintf_int64 }, 22436f8a503dSdanielk1977 { "sqlite3_mprintf_str", (Tcl_CmdProc*)sqlite3_mprintf_str }, 22446f8a503dSdanielk1977 { "sqlite3_mprintf_double", (Tcl_CmdProc*)sqlite3_mprintf_double }, 22456f8a503dSdanielk1977 { "sqlite3_mprintf_scaled", (Tcl_CmdProc*)sqlite3_mprintf_scaled }, 22466f8a503dSdanielk1977 { "sqlite3_mprintf_z_test", (Tcl_CmdProc*)test_mprintf_z }, 22476f8a503dSdanielk1977 { "sqlite3_last_insert_rowid", (Tcl_CmdProc*)test_last_rowid }, 22486f8a503dSdanielk1977 { "sqlite3_exec_printf", (Tcl_CmdProc*)test_exec_printf }, 22496f8a503dSdanielk1977 { "sqlite3_get_table_printf", (Tcl_CmdProc*)test_get_table_printf }, 22506f8a503dSdanielk1977 { "sqlite3_close", (Tcl_CmdProc*)sqlite_test_close }, 22516f8a503dSdanielk1977 { "sqlite3_create_function", (Tcl_CmdProc*)test_create_function }, 22526f8a503dSdanielk1977 { "sqlite3_create_aggregate", (Tcl_CmdProc*)test_create_aggregate }, 2253c2eef3b3Sdrh { "sqlite_register_test_function", (Tcl_CmdProc*)test_register_func }, 2254c2eef3b3Sdrh { "sqlite_abort", (Tcl_CmdProc*)sqlite_abort }, 2255faa57accSdrh #ifdef SQLITE_DEBUG 2256c2eef3b3Sdrh { "sqlite_malloc_fail", (Tcl_CmdProc*)sqlite_malloc_fail }, 2257c2eef3b3Sdrh { "sqlite_malloc_stat", (Tcl_CmdProc*)sqlite_malloc_stat }, 2258c2eef3b3Sdrh #endif 225996fc5fe6Sdanielk1977 { "sqlite_bind", (Tcl_CmdProc*)test_bind }, 226099ee3600Sdrh { "breakpoint", (Tcl_CmdProc*)test_breakpoint }, 2261c2eef3b3Sdrh }; 226251e3d8e2Sdanielk1977 static struct { 226351e3d8e2Sdanielk1977 char *zName; 226451e3d8e2Sdanielk1977 Tcl_ObjCmdProc *xProc; 226504f2e68dSdanielk1977 void *clientData; 226651e3d8e2Sdanielk1977 } aObjCmd[] = { 2267241db313Sdrh { "sqlite3_bind_int", test_bind_int, 0 }, 226804f2e68dSdanielk1977 { "sqlite3_bind_int64", test_bind_int64, 0 }, 226904f2e68dSdanielk1977 { "sqlite3_bind_double", test_bind_double, 0 }, 227004f2e68dSdanielk1977 { "sqlite3_bind_null", test_bind_null ,0 }, 227104f2e68dSdanielk1977 { "sqlite3_bind_text", test_bind_text ,0 }, 227204f2e68dSdanielk1977 { "sqlite3_bind_text16", test_bind_text16 ,0 }, 227304f2e68dSdanielk1977 { "sqlite3_bind_blob", test_bind_blob ,0 }, 227404f2e68dSdanielk1977 { "sqlite3_errcode", test_errcode ,0 }, 227504f2e68dSdanielk1977 { "sqlite3_errmsg", test_errmsg ,0 }, 227604f2e68dSdanielk1977 { "sqlite3_errmsg16", test_errmsg16 ,0 }, 227704f2e68dSdanielk1977 { "sqlite3_open", test_open ,0 }, 227804f2e68dSdanielk1977 { "sqlite3_open16", test_open16 ,0 }, 227904f2e68dSdanielk1977 228004f2e68dSdanielk1977 { "sqlite3_prepare", test_prepare ,0 }, 228104f2e68dSdanielk1977 { "sqlite3_prepare16", test_prepare16 ,0 }, 228204f2e68dSdanielk1977 { "sqlite3_finalize", test_finalize ,0 }, 228304f2e68dSdanielk1977 { "sqlite3_reset", test_reset ,0 }, 2284fbcd585fSdanielk1977 { "sqlite3_changes", test_changes ,0 }, 228504f2e68dSdanielk1977 { "sqlite3_step", test_step ,0 }, 228604f2e68dSdanielk1977 228704f2e68dSdanielk1977 /* sqlite3_column_*() API */ 228804f2e68dSdanielk1977 { "sqlite3_column_count", test_column_count ,0 }, 228904f2e68dSdanielk1977 { "sqlite3_data_count", test_data_count ,0 }, 229004f2e68dSdanielk1977 { "sqlite3_column_type", test_column_type ,0 }, 2291ea61b2c4Sdanielk1977 { "sqlite3_column_blob", test_column_blob ,0 }, 229204f2e68dSdanielk1977 { "sqlite3_column_double", test_column_double ,0 }, 229304f2e68dSdanielk1977 { "sqlite3_column_int64", test_column_int64 ,0 }, 229404f2e68dSdanielk1977 { "sqlite3_column_int", test_stmt_int, sqlite3_column_int }, 229504f2e68dSdanielk1977 { "sqlite3_column_bytes", test_stmt_int, sqlite3_column_bytes }, 229604f2e68dSdanielk1977 { "sqlite3_column_bytes16", test_stmt_int, sqlite3_column_bytes16 }, 229704f2e68dSdanielk1977 { "sqlite3_column_text", test_stmt_utf8, sqlite3_column_text }, 229804f2e68dSdanielk1977 { "sqlite3_column_decltype", test_stmt_utf8, sqlite3_column_decltype }, 229904f2e68dSdanielk1977 { "sqlite3_column_name", test_stmt_utf8, sqlite3_column_name }, 230004f2e68dSdanielk1977 { "sqlite3_column_text16", test_stmt_utf16, sqlite3_column_text16 }, 230104f2e68dSdanielk1977 { "sqlite3_column_decltype16", test_stmt_utf16, sqlite3_column_decltype16}, 230204f2e68dSdanielk1977 { "sqlite3_column_name16", test_stmt_utf16, sqlite3_column_name16 }, 230304f2e68dSdanielk1977 23049a1d0abeSdanielk1977 /* Functions from os.h */ 23059a1d0abeSdanielk1977 { "sqlite3OsOpenReadWrite",test_sqlite3OsOpenReadWrite, 0 }, 23069a1d0abeSdanielk1977 { "sqlite3OsClose", test_sqlite3OsClose, 0 }, 23079a1d0abeSdanielk1977 { "sqlite3OsLock", test_sqlite3OsLock, 0 }, 2308312d6b36Sdanielk1977 2309312d6b36Sdanielk1977 /* Custom test interfaces */ 23109a1d0abeSdanielk1977 { "sqlite3OsUnlock", test_sqlite3OsUnlock, 0 }, 23114e6af134Sdanielk1977 { "add_test_collate", test_collate, 0 }, 2312312d6b36Sdanielk1977 { "add_test_collate_needed", test_collate_needed, 0 }, 2313c8e9a2dfSdanielk1977 { "add_test_function", test_function, 0 }, 2314c8e9a2dfSdanielk1977 { "sqlite3_crashparams", sqlite3_crashparams, 0 }, 2315312d6b36Sdanielk1977 { "sqlite3_test_errstr", test_errstr, 0 }, 23169a1d0abeSdanielk1977 231751e3d8e2Sdanielk1977 }; 2318c2eef3b3Sdrh int i; 23192ac3ee97Sdrh extern int sqlite3_os_trace; 2320c2eef3b3Sdrh 2321c2eef3b3Sdrh for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){ 2322c2eef3b3Sdrh Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0); 2323c2eef3b3Sdrh } 232451e3d8e2Sdanielk1977 for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){ 2325c572ef7fSdanielk1977 Tcl_CreateObjCommand(interp, aObjCmd[i].zName, 2326c572ef7fSdanielk1977 aObjCmd[i].xProc, aObjCmd[i].clientData, 0); 232751e3d8e2Sdanielk1977 } 23286490bebdSdanielk1977 Tcl_LinkVar(interp, "sqlite_search_count", 23296f8a503dSdanielk1977 (char*)&sqlite3_search_count, TCL_LINK_INT); 23306490bebdSdanielk1977 Tcl_LinkVar(interp, "sqlite_interrupt_count", 23316f8a503dSdanielk1977 (char*)&sqlite3_interrupt_count, TCL_LINK_INT); 23326490bebdSdanielk1977 Tcl_LinkVar(interp, "sqlite_open_file_count", 23336f8a503dSdanielk1977 (char*)&sqlite3_open_file_count, TCL_LINK_INT); 23346490bebdSdanielk1977 Tcl_LinkVar(interp, "sqlite_current_time", 23356f8a503dSdanielk1977 (char*)&sqlite3_current_time, TCL_LINK_INT); 23362ac3ee97Sdrh Tcl_LinkVar(interp, "sqlite_os_trace", 23372ac3ee97Sdrh (char*)&sqlite3_os_trace, TCL_LINK_INT); 23387c972decSdrh Tcl_LinkVar(interp, "sqlite_static_bind_value", 23397c972decSdrh (char*)&sqlite_static_bind_value, TCL_LINK_STRING); 2340d1bf3512Sdrh return TCL_OK; 2341d1bf3512Sdrh } 2342