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 ************************************************************************* 1205a82983Sdrh ** Code for testing all sorts of SQLite interfaces. This code 13d1bf3512Sdrh ** is not included in the SQLite library. It is used for automated 14d1bf3512Sdrh ** testing of the SQLite library. 15d1bf3512Sdrh */ 16d1bf3512Sdrh #include "sqliteInt.h" 17f74b9e09Smistachkin #if SQLITE_OS_WIN 18f74b9e09Smistachkin # include "os_win.h" 19f74b9e09Smistachkin #endif 20f74b9e09Smistachkin 21d9495cd0Sdan #include "vdbeInt.h" 2252b1dbb5Smistachkin #if defined(INCLUDE_SQLITE_TCL_H) 2352b1dbb5Smistachkin # include "sqlite_tcl.h" 2452b1dbb5Smistachkin #else 25d1bf3512Sdrh # include "tcl.h" 2652b1dbb5Smistachkin #endif 27d1bf3512Sdrh #include <stdlib.h> 28d1bf3512Sdrh #include <string.h> 29d1bf3512Sdrh 30dddca286Sdrh /* 31dddca286Sdrh ** This is a copy of the first part of the SqliteDb structure in 32dddca286Sdrh ** tclsqlite.c. We need it here so that the get_sqlite_pointer routine 33dddca286Sdrh ** can extract the sqlite3* pointer from an existing Tcl SQLite 34dddca286Sdrh ** connection. 35dddca286Sdrh */ 36dddca286Sdrh struct SqliteDb { 37dddca286Sdrh sqlite3 *db; 38dddca286Sdrh }; 39dddca286Sdrh 40dddca286Sdrh /* 41a3152895Sdrh ** Convert text generated by the "%p" conversion format back into 42a3152895Sdrh ** a pointer. 43a3152895Sdrh */ 44a3152895Sdrh static int testHexToInt(int h){ 45a3152895Sdrh if( h>='0' && h<='9' ){ 46a3152895Sdrh return h - '0'; 47a3152895Sdrh }else if( h>='a' && h<='f' ){ 48a3152895Sdrh return h - 'a' + 10; 49a3152895Sdrh }else{ 50a3152895Sdrh assert( h>='A' && h<='F' ); 51a3152895Sdrh return h - 'A' + 10; 52a3152895Sdrh } 53a3152895Sdrh } 54e8f52c50Sdrh void *sqlite3TestTextToPtr(const char *z){ 55a3152895Sdrh void *p; 56a3152895Sdrh u64 v; 57a3152895Sdrh u32 v2; 58a3152895Sdrh if( z[0]=='0' && z[1]=='x' ){ 59a3152895Sdrh z += 2; 60a3152895Sdrh } 61a3152895Sdrh v = 0; 62a3152895Sdrh while( *z ){ 63a3152895Sdrh v = (v<<4) + testHexToInt(*z); 64a3152895Sdrh z++; 65a3152895Sdrh } 66a3152895Sdrh if( sizeof(p)==sizeof(v) ){ 67a3152895Sdrh memcpy(&p, &v, sizeof(p)); 68a3152895Sdrh }else{ 69a3152895Sdrh assert( sizeof(p)==sizeof(v2) ); 70a3152895Sdrh v2 = (u32)v; 71a3152895Sdrh memcpy(&p, &v2, sizeof(p)); 72a3152895Sdrh } 73a3152895Sdrh return p; 74a3152895Sdrh } 75a3152895Sdrh 76a3152895Sdrh 77a3152895Sdrh /* 78dddca286Sdrh ** A TCL command that returns the address of the sqlite* pointer 79dddca286Sdrh ** for an sqlite connection instance. Bad things happen if the 80dddca286Sdrh ** input is not an sqlite connection. 81dddca286Sdrh */ 827617e4a8Smistachkin static int SQLITE_TCLAPI get_sqlite_pointer( 83dddca286Sdrh void * clientData, 84dddca286Sdrh Tcl_Interp *interp, 85dddca286Sdrh int objc, 86dddca286Sdrh Tcl_Obj *CONST objv[] 87dddca286Sdrh ){ 88dddca286Sdrh struct SqliteDb *p; 89dddca286Sdrh Tcl_CmdInfo cmdInfo; 90dddca286Sdrh char zBuf[100]; 91dddca286Sdrh if( objc!=2 ){ 92dddca286Sdrh Tcl_WrongNumArgs(interp, 1, objv, "SQLITE-CONNECTION"); 93dddca286Sdrh return TCL_ERROR; 94dddca286Sdrh } 95dddca286Sdrh if( !Tcl_GetCommandInfo(interp, Tcl_GetString(objv[1]), &cmdInfo) ){ 96dddca286Sdrh Tcl_AppendResult(interp, "command not found: ", 97dddca286Sdrh Tcl_GetString(objv[1]), (char*)0); 98dddca286Sdrh return TCL_ERROR; 99dddca286Sdrh } 100dddca286Sdrh p = (struct SqliteDb*)cmdInfo.objClientData; 10165545b59Sdrh sqlite3_snprintf(sizeof(zBuf), zBuf, "%p", p->db); 102dddca286Sdrh Tcl_AppendResult(interp, zBuf, 0); 103dddca286Sdrh return TCL_OK; 104dddca286Sdrh } 105dddca286Sdrh 106b62c335eSdrh /* 107b62c335eSdrh ** Decode a pointer to an sqlite3 object. 108b62c335eSdrh */ 10924b58dd7Sdrh int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb){ 110b62c335eSdrh struct SqliteDb *p; 111b62c335eSdrh Tcl_CmdInfo cmdInfo; 112b62c335eSdrh if( Tcl_GetCommandInfo(interp, zA, &cmdInfo) ){ 113b62c335eSdrh p = (struct SqliteDb*)cmdInfo.objClientData; 114b62c335eSdrh *ppDb = p->db; 115b62c335eSdrh }else{ 116e8f52c50Sdrh *ppDb = (sqlite3*)sqlite3TestTextToPtr(zA); 117b62c335eSdrh } 118b62c335eSdrh return TCL_OK; 119b62c335eSdrh } 120b62c335eSdrh 1216b98d67bSmistachkin #if SQLITE_OS_WIN 1226b98d67bSmistachkin /* 1236b98d67bSmistachkin ** Decode a Win32 HANDLE object. 1246b98d67bSmistachkin */ 1256b98d67bSmistachkin int getWin32Handle(Tcl_Interp *interp, const char *zA, LPHANDLE phFile){ 1266b98d67bSmistachkin *phFile = (HANDLE)sqlite3TestTextToPtr(zA); 1276b98d67bSmistachkin return TCL_OK; 1286b98d67bSmistachkin } 1296b98d67bSmistachkin #endif 1306b98d67bSmistachkin 131e84d8d32Smistachkin extern const char *sqlite3ErrName(int); 132e84d8d32Smistachkin #define t1ErrorName sqlite3ErrName 1336622cce3Sdanielk1977 134d1bf3512Sdrh /* 135c60d0446Sdrh ** Convert an sqlite3_stmt* into an sqlite3*. This depends on the 136c60d0446Sdrh ** fact that the sqlite3* is the first field in the Vdbe structure. 137c60d0446Sdrh */ 13851942bc3Sdrh #define StmtToDb(X) sqlite3_db_handle(X) 139c60d0446Sdrh 140c60d0446Sdrh /* 141c60d0446Sdrh ** Check a return value to make sure it agrees with the results 142c60d0446Sdrh ** from sqlite3_errcode. 143c60d0446Sdrh */ 144c60d0446Sdrh int sqlite3TestErrCode(Tcl_Interp *interp, sqlite3 *db, int rc){ 145b8613ab1Sdrh if( sqlite3_threadsafe()==0 && rc!=SQLITE_MISUSE && rc!=SQLITE_OK 146b8613ab1Sdrh && sqlite3_errcode(db)!=rc ){ 147c60d0446Sdrh char zBuf[200]; 148c60d0446Sdrh int r2 = sqlite3_errcode(db); 14965545b59Sdrh sqlite3_snprintf(sizeof(zBuf), zBuf, 15065545b59Sdrh "error code %s (%d) does not match sqlite3_errcode %s (%d)", 1514f0c5878Sdrh t1ErrorName(rc), rc, t1ErrorName(r2), r2); 152c60d0446Sdrh Tcl_ResetResult(interp); 153c60d0446Sdrh Tcl_AppendResult(interp, zBuf, 0); 154c60d0446Sdrh return 1; 155c60d0446Sdrh } 156c60d0446Sdrh return 0; 157c60d0446Sdrh } 158c60d0446Sdrh 159c60d0446Sdrh /* 16051e3d8e2Sdanielk1977 ** Decode a pointer to an sqlite3_stmt object. 16151e3d8e2Sdanielk1977 */ 16251e3d8e2Sdanielk1977 static int getStmtPointer( 16351e3d8e2Sdanielk1977 Tcl_Interp *interp, 16451e3d8e2Sdanielk1977 const char *zArg, 16551e3d8e2Sdanielk1977 sqlite3_stmt **ppStmt 16651e3d8e2Sdanielk1977 ){ 167e8f52c50Sdrh *ppStmt = (sqlite3_stmt*)sqlite3TestTextToPtr(zArg); 16851e3d8e2Sdanielk1977 return TCL_OK; 16951e3d8e2Sdanielk1977 } 17051e3d8e2Sdanielk1977 17151e3d8e2Sdanielk1977 /* 1727d8085a8Sdrh ** Generate a text representation of a pointer that can be understood 1737d8085a8Sdrh ** by the getDbPointer and getVmPointer routines above. 1747d8085a8Sdrh ** 1757d8085a8Sdrh ** The problem is, on some machines (Solaris) if you do a printf with 1767d8085a8Sdrh ** "%p" you cannot turn around and do a scanf with the same "%p" and 1777d8085a8Sdrh ** get your pointer back. You have to prepend a "0x" before it will 1787d8085a8Sdrh ** work. Or at least that is what is reported to me (drh). But this 1797d8085a8Sdrh ** behavior varies from machine to machine. The solution used her is 1807d8085a8Sdrh ** to test the string right after it is generated to see if it can be 1817d8085a8Sdrh ** understood by scanf, and if not, try prepending an "0x" to see if 1827d8085a8Sdrh ** that helps. If nothing works, a fatal error is generated. 1837d8085a8Sdrh */ 18464b1bea3Sdrh int sqlite3TestMakePointerStr(Tcl_Interp *interp, char *zPtr, void *p){ 185fe63d1c9Sdrh sqlite3_snprintf(100, zPtr, "%p", p); 1867d8085a8Sdrh return TCL_OK; 1877d8085a8Sdrh } 1887d8085a8Sdrh 1897d8085a8Sdrh /* 1906f8a503dSdanielk1977 ** The callback routine for sqlite3_exec_printf(). 191d1bf3512Sdrh */ 192d1bf3512Sdrh static int exec_printf_cb(void *pArg, int argc, char **argv, char **name){ 193d1bf3512Sdrh Tcl_DString *str = (Tcl_DString*)pArg; 194d1bf3512Sdrh int i; 195d1bf3512Sdrh 196d1bf3512Sdrh if( Tcl_DStringLength(str)==0 ){ 197d1bf3512Sdrh for(i=0; i<argc; i++){ 198d1bf3512Sdrh Tcl_DStringAppendElement(str, name[i] ? name[i] : "NULL"); 199d1bf3512Sdrh } 200d1bf3512Sdrh } 201d1bf3512Sdrh for(i=0; i<argc; i++){ 202d1bf3512Sdrh Tcl_DStringAppendElement(str, argv[i] ? argv[i] : "NULL"); 203d1bf3512Sdrh } 204d1bf3512Sdrh return 0; 205d1bf3512Sdrh } 206d1bf3512Sdrh 207d1bf3512Sdrh /* 208538f570cSdrh ** The I/O tracing callback. 209538f570cSdrh */ 210afdd23a4Sshane #if !defined(SQLITE_OMIT_TRACE) && defined(SQLITE_ENABLE_IOTRACE) 211538f570cSdrh static FILE *iotrace_file = 0; 212538f570cSdrh static void io_trace_callback(const char *zFormat, ...){ 213538f570cSdrh va_list ap; 214538f570cSdrh va_start(ap, zFormat); 215538f570cSdrh vfprintf(iotrace_file, zFormat, ap); 216538f570cSdrh va_end(ap); 217538f570cSdrh fflush(iotrace_file); 218538f570cSdrh } 219afdd23a4Sshane #endif 220538f570cSdrh 221538f570cSdrh /* 222538f570cSdrh ** Usage: io_trace FILENAME 223538f570cSdrh ** 224538f570cSdrh ** Turn I/O tracing on or off. If FILENAME is not an empty string, 225538f570cSdrh ** I/O tracing begins going into FILENAME. If FILENAME is an empty 226538f570cSdrh ** string, I/O tracing is turned off. 227538f570cSdrh */ 2287617e4a8Smistachkin static int SQLITE_TCLAPI test_io_trace( 229538f570cSdrh void *NotUsed, 230538f570cSdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 231538f570cSdrh int argc, /* Number of arguments */ 232538f570cSdrh char **argv /* Text of each argument */ 233538f570cSdrh ){ 234286d2f4aSdanielk1977 #if !defined(SQLITE_OMIT_TRACE) && defined(SQLITE_ENABLE_IOTRACE) 235538f570cSdrh if( argc!=2 ){ 236538f570cSdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 237538f570cSdrh " FILENAME\"", 0); 238538f570cSdrh return TCL_ERROR; 239538f570cSdrh } 240538f570cSdrh if( iotrace_file ){ 241538f570cSdrh if( iotrace_file!=stdout && iotrace_file!=stderr ){ 242538f570cSdrh fclose(iotrace_file); 243538f570cSdrh } 244538f570cSdrh iotrace_file = 0; 2453a00f907Smlcreech sqlite3IoTrace = 0; 246538f570cSdrh } 247538f570cSdrh if( argv[1][0] ){ 248538f570cSdrh if( strcmp(argv[1],"stdout")==0 ){ 249538f570cSdrh iotrace_file = stdout; 250538f570cSdrh }else if( strcmp(argv[1],"stderr")==0 ){ 251538f570cSdrh iotrace_file = stderr; 252538f570cSdrh }else{ 253538f570cSdrh iotrace_file = fopen(argv[1], "w"); 254538f570cSdrh } 2553a00f907Smlcreech sqlite3IoTrace = io_trace_callback; 256538f570cSdrh } 257286d2f4aSdanielk1977 #endif 258286d2f4aSdanielk1977 return TCL_OK; 259538f570cSdrh } 260538f570cSdrh 261afcf9bd8Sdan /* 262afcf9bd8Sdan ** Usage: clang_sanitize_address 263afcf9bd8Sdan ** 264afcf9bd8Sdan ** Returns true if the program was compiled using clang with the 265afcf9bd8Sdan ** -fsanitize=address switch on the command line. False otherwise. 26632e1f279Sdrh ** 26732e1f279Sdrh ** Also return true if the OMIT_MISUSE environment variable exists. 268afcf9bd8Sdan */ 2697617e4a8Smistachkin static int SQLITE_TCLAPI clang_sanitize_address( 270afcf9bd8Sdan void *NotUsed, 271afcf9bd8Sdan Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 272afcf9bd8Sdan int argc, /* Number of arguments */ 273afcf9bd8Sdan char **argv /* Text of each argument */ 274afcf9bd8Sdan ){ 275afcf9bd8Sdan int res = 0; 276afcf9bd8Sdan #if defined(__has_feature) 277afcf9bd8Sdan # if __has_feature(address_sanitizer) 278afcf9bd8Sdan res = 1; 279afcf9bd8Sdan # endif 280afcf9bd8Sdan #endif 281618ee61eSdrh #ifdef __SANITIZE_ADDRESS__ 282618ee61eSdrh res = 1; 283618ee61eSdrh #endif 28432e1f279Sdrh if( res==0 && getenv("OMIT_MISUSE")!=0 ) res = 1; 285afcf9bd8Sdan Tcl_SetObjResult(interp, Tcl_NewIntObj(res)); 286afcf9bd8Sdan return TCL_OK; 287afcf9bd8Sdan } 288538f570cSdrh 289538f570cSdrh /* 2906f8a503dSdanielk1977 ** Usage: sqlite3_exec_printf DB FORMAT STRING 291d1bf3512Sdrh ** 2926f8a503dSdanielk1977 ** Invoke the sqlite3_exec_printf() interface using the open database 293d1bf3512Sdrh ** DB. The SQL is the string FORMAT. The format string should contain 294d1bf3512Sdrh ** one %s or %q. STRING is the value inserted into %s or %q. 295d1bf3512Sdrh */ 2967617e4a8Smistachkin static int SQLITE_TCLAPI test_exec_printf( 297d1bf3512Sdrh void *NotUsed, 298d1bf3512Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 299d1bf3512Sdrh int argc, /* Number of arguments */ 300d1bf3512Sdrh char **argv /* Text of each argument */ 301d1bf3512Sdrh ){ 3029bb575fdSdrh sqlite3 *db; 303d1bf3512Sdrh Tcl_DString str; 304d1bf3512Sdrh int rc; 305d1bf3512Sdrh char *zErr = 0; 3061211de37Sdrh char *zSql; 307d1bf3512Sdrh char zBuf[30]; 308d1bf3512Sdrh if( argc!=4 ){ 309d1bf3512Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 310d1bf3512Sdrh " DB FORMAT STRING", 0); 311d1bf3512Sdrh return TCL_ERROR; 312d1bf3512Sdrh } 313b86ccfb2Sdrh if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; 314d1bf3512Sdrh Tcl_DStringInit(&str); 3151211de37Sdrh zSql = sqlite3_mprintf(argv[2], argv[3]); 3161211de37Sdrh rc = sqlite3_exec(db, zSql, exec_printf_cb, &str, &zErr); 3171211de37Sdrh sqlite3_free(zSql); 31865545b59Sdrh sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", rc); 319d1bf3512Sdrh Tcl_AppendElement(interp, zBuf); 320d1bf3512Sdrh Tcl_AppendElement(interp, rc==SQLITE_OK ? Tcl_DStringValue(&str) : zErr); 321d1bf3512Sdrh Tcl_DStringFree(&str); 322926aab22Sdanielk1977 if( zErr ) sqlite3_free(zErr); 323c60d0446Sdrh if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; 324d1bf3512Sdrh return TCL_OK; 325d1bf3512Sdrh } 326d1bf3512Sdrh 327d1bf3512Sdrh /* 3285bd98aefSdrh ** Usage: sqlite3_exec_hex DB HEX 3295bd98aefSdrh ** 3305bd98aefSdrh ** Invoke the sqlite3_exec() on a string that is obtained by translating 3315bd98aefSdrh ** HEX into ASCII. Most characters are translated as is. %HH becomes 3325bd98aefSdrh ** a hex character. 3335bd98aefSdrh */ 3347617e4a8Smistachkin static int SQLITE_TCLAPI test_exec_hex( 3355bd98aefSdrh void *NotUsed, 3365bd98aefSdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 3375bd98aefSdrh int argc, /* Number of arguments */ 3385bd98aefSdrh char **argv /* Text of each argument */ 3395bd98aefSdrh ){ 3405bd98aefSdrh sqlite3 *db; 3415bd98aefSdrh Tcl_DString str; 3425bd98aefSdrh int rc, i, j; 3435bd98aefSdrh char *zErr = 0; 3445bd98aefSdrh char *zHex; 345dca92904Sdan char zSql[501]; 3465bd98aefSdrh char zBuf[30]; 3475bd98aefSdrh if( argc!=3 ){ 3485bd98aefSdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 3495bd98aefSdrh " DB HEX", 0); 3505bd98aefSdrh return TCL_ERROR; 3515bd98aefSdrh } 3525bd98aefSdrh if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; 3535bd98aefSdrh zHex = argv[2]; 354dca92904Sdan for(i=j=0; i<(sizeof(zSql)-1) && zHex[j]; i++, j++){ 3555bd98aefSdrh if( zHex[j]=='%' && zHex[j+2] && zHex[j+2] ){ 3565bd98aefSdrh zSql[i] = (testHexToInt(zHex[j+1])<<4) + testHexToInt(zHex[j+2]); 3575bd98aefSdrh j += 2; 3585bd98aefSdrh }else{ 3595bd98aefSdrh zSql[i] = zHex[j]; 3605bd98aefSdrh } 3615bd98aefSdrh } 3625bd98aefSdrh zSql[i] = 0; 3635bd98aefSdrh Tcl_DStringInit(&str); 3645bd98aefSdrh rc = sqlite3_exec(db, zSql, exec_printf_cb, &str, &zErr); 36565545b59Sdrh sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", rc); 3665bd98aefSdrh Tcl_AppendElement(interp, zBuf); 3675bd98aefSdrh Tcl_AppendElement(interp, rc==SQLITE_OK ? Tcl_DStringValue(&str) : zErr); 3685bd98aefSdrh Tcl_DStringFree(&str); 3695bd98aefSdrh if( zErr ) sqlite3_free(zErr); 3705bd98aefSdrh if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; 3715bd98aefSdrh return TCL_OK; 3725bd98aefSdrh } 3735bd98aefSdrh 3745bd98aefSdrh /* 37527641703Sdrh ** Usage: db_enter DB 37627641703Sdrh ** db_leave DB 37727641703Sdrh ** 37827641703Sdrh ** Enter or leave the mutex on a database connection. 37927641703Sdrh */ 3807617e4a8Smistachkin static int SQLITE_TCLAPI db_enter( 38127641703Sdrh void *NotUsed, 38227641703Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 38327641703Sdrh int argc, /* Number of arguments */ 38427641703Sdrh char **argv /* Text of each argument */ 38527641703Sdrh ){ 38627641703Sdrh sqlite3 *db; 38727641703Sdrh if( argc!=2 ){ 38827641703Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 38927641703Sdrh " DB", 0); 39027641703Sdrh return TCL_ERROR; 39127641703Sdrh } 39227641703Sdrh if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; 39327641703Sdrh sqlite3_mutex_enter(db->mutex); 39427641703Sdrh return TCL_OK; 39527641703Sdrh } 3967617e4a8Smistachkin static int SQLITE_TCLAPI db_leave( 39727641703Sdrh void *NotUsed, 39827641703Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 39927641703Sdrh int argc, /* Number of arguments */ 40027641703Sdrh char **argv /* Text of each argument */ 40127641703Sdrh ){ 40227641703Sdrh sqlite3 *db; 40327641703Sdrh if( argc!=2 ){ 40427641703Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 40527641703Sdrh " DB", 0); 40627641703Sdrh return TCL_ERROR; 40727641703Sdrh } 40827641703Sdrh if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; 40927641703Sdrh sqlite3_mutex_leave(db->mutex); 41027641703Sdrh return TCL_OK; 41127641703Sdrh } 41227641703Sdrh 41327641703Sdrh /* 414b62c335eSdrh ** Usage: sqlite3_exec DB SQL 415b62c335eSdrh ** 416b62c335eSdrh ** Invoke the sqlite3_exec interface using the open database DB 417b62c335eSdrh */ 4187617e4a8Smistachkin static int SQLITE_TCLAPI test_exec( 419b62c335eSdrh void *NotUsed, 420b62c335eSdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 421b62c335eSdrh int argc, /* Number of arguments */ 422b62c335eSdrh char **argv /* Text of each argument */ 423b62c335eSdrh ){ 424b62c335eSdrh sqlite3 *db; 425b62c335eSdrh Tcl_DString str; 426b62c335eSdrh int rc; 427b62c335eSdrh char *zErr = 0; 4284e5dd851Sdrh char *zSql; 4294e5dd851Sdrh int i, j; 430b62c335eSdrh char zBuf[30]; 431b62c335eSdrh if( argc!=3 ){ 432b62c335eSdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 433b62c335eSdrh " DB SQL", 0); 434b62c335eSdrh return TCL_ERROR; 435b62c335eSdrh } 436b62c335eSdrh if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; 437b62c335eSdrh Tcl_DStringInit(&str); 4384e5dd851Sdrh zSql = sqlite3_mprintf("%s", argv[2]); 4394e5dd851Sdrh for(i=j=0; zSql[i];){ 4404e5dd851Sdrh if( zSql[i]=='%' ){ 4414e5dd851Sdrh zSql[j++] = (testHexToInt(zSql[i+1])<<4) + testHexToInt(zSql[i+2]); 4424e5dd851Sdrh i += 3; 4434e5dd851Sdrh }else{ 4444e5dd851Sdrh zSql[j++] = zSql[i++]; 4454e5dd851Sdrh } 4464e5dd851Sdrh } 4474e5dd851Sdrh zSql[j] = 0; 4484e5dd851Sdrh rc = sqlite3_exec(db, zSql, exec_printf_cb, &str, &zErr); 4494e5dd851Sdrh sqlite3_free(zSql); 45065545b59Sdrh sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", rc); 451b62c335eSdrh Tcl_AppendElement(interp, zBuf); 452b62c335eSdrh Tcl_AppendElement(interp, rc==SQLITE_OK ? Tcl_DStringValue(&str) : zErr); 453b62c335eSdrh Tcl_DStringFree(&str); 454b62c335eSdrh if( zErr ) sqlite3_free(zErr); 455b62c335eSdrh if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; 456b62c335eSdrh return TCL_OK; 457b62c335eSdrh } 458b62c335eSdrh 459b62c335eSdrh /* 460b62c335eSdrh ** Usage: sqlite3_exec_nr DB SQL 461b62c335eSdrh ** 462b62c335eSdrh ** Invoke the sqlite3_exec interface using the open database DB. Discard 463b62c335eSdrh ** all results 464b62c335eSdrh */ 4657617e4a8Smistachkin static int SQLITE_TCLAPI test_exec_nr( 466b62c335eSdrh void *NotUsed, 467b62c335eSdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 468b62c335eSdrh int argc, /* Number of arguments */ 469b62c335eSdrh char **argv /* Text of each argument */ 470b62c335eSdrh ){ 471b62c335eSdrh sqlite3 *db; 472b62c335eSdrh int rc; 473b62c335eSdrh char *zErr = 0; 474b62c335eSdrh if( argc!=3 ){ 475b62c335eSdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 476b62c335eSdrh " DB SQL", 0); 477b62c335eSdrh return TCL_ERROR; 478b62c335eSdrh } 479b62c335eSdrh if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; 480b62c335eSdrh rc = sqlite3_exec(db, argv[2], 0, 0, &zErr); 481b62c335eSdrh if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; 482b62c335eSdrh return TCL_OK; 483b62c335eSdrh } 484b62c335eSdrh 485b62c335eSdrh /* 4866f8a503dSdanielk1977 ** Usage: sqlite3_mprintf_z_test SEPARATOR ARG0 ARG1 ... 487d93d8a81Sdrh ** 488bc6160b0Sdrh ** Test the %z format of sqlite_mprintf(). Use multiple mprintf() calls to 489d93d8a81Sdrh ** concatenate arg0 through argn using separator as the separator. 490d93d8a81Sdrh ** Return the result. 491d93d8a81Sdrh */ 4927617e4a8Smistachkin static int SQLITE_TCLAPI test_mprintf_z( 493d93d8a81Sdrh void *NotUsed, 494d93d8a81Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 495d93d8a81Sdrh int argc, /* Number of arguments */ 496d93d8a81Sdrh char **argv /* Text of each argument */ 497d93d8a81Sdrh ){ 498d93d8a81Sdrh char *zResult = 0; 499d93d8a81Sdrh int i; 500d93d8a81Sdrh 501ca0c8971Sdanielk1977 for(i=2; i<argc && (i==2 || zResult); i++){ 502bc6160b0Sdrh zResult = sqlite3_mprintf("%z%s%s", zResult, argv[1], argv[i]); 503d93d8a81Sdrh } 504d93d8a81Sdrh Tcl_AppendResult(interp, zResult, 0); 50517435752Sdrh sqlite3_free(zResult); 506d93d8a81Sdrh return TCL_OK; 507d93d8a81Sdrh } 508d93d8a81Sdrh 509d93d8a81Sdrh /* 51005a82983Sdrh ** Usage: sqlite3_mprintf_n_test STRING 51105a82983Sdrh ** 512bc6160b0Sdrh ** Test the %n format of sqlite_mprintf(). Return the length of the 51305a82983Sdrh ** input string. 51405a82983Sdrh */ 5157617e4a8Smistachkin static int SQLITE_TCLAPI test_mprintf_n( 51605a82983Sdrh void *NotUsed, 51705a82983Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 51805a82983Sdrh int argc, /* Number of arguments */ 51905a82983Sdrh char **argv /* Text of each argument */ 52005a82983Sdrh ){ 52105a82983Sdrh char *zStr; 52205a82983Sdrh int n = 0; 523bc6160b0Sdrh zStr = sqlite3_mprintf("%s%n", argv[1], &n); 52417435752Sdrh sqlite3_free(zStr); 52505a82983Sdrh Tcl_SetObjResult(interp, Tcl_NewIntObj(n)); 52605a82983Sdrh return TCL_OK; 52705a82983Sdrh } 52805a82983Sdrh 52905a82983Sdrh /* 53068853907Sdrh ** Usage: sqlite3_snprintf_int SIZE FORMAT INT 53168853907Sdrh ** 53268853907Sdrh ** Test the of sqlite3_snprintf() routine. SIZE is the size of the 53368853907Sdrh ** output buffer in bytes. The maximum size is 100. FORMAT is the 53468853907Sdrh ** format string. INT is a single integer argument. The FORMAT 53568853907Sdrh ** string must require no more than this one integer argument. If 53668853907Sdrh ** You pass in a format string that requires more than one argument, 53768853907Sdrh ** bad things will happen. 53868853907Sdrh */ 5397617e4a8Smistachkin static int SQLITE_TCLAPI test_snprintf_int( 54068853907Sdrh void *NotUsed, 54168853907Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 54268853907Sdrh int argc, /* Number of arguments */ 54368853907Sdrh char **argv /* Text of each argument */ 54468853907Sdrh ){ 54568853907Sdrh char zStr[100]; 54668853907Sdrh int n = atoi(argv[1]); 54768853907Sdrh const char *zFormat = argv[2]; 54868853907Sdrh int a1 = atoi(argv[3]); 549daf276d4Sdrh if( n>sizeof(zStr) ) n = sizeof(zStr); 5507694574aSdrh sqlite3_snprintf(sizeof(zStr), zStr, "abcdefghijklmnopqrstuvwxyz"); 55168853907Sdrh sqlite3_snprintf(n, zStr, zFormat, a1); 55268853907Sdrh Tcl_AppendResult(interp, zStr, 0); 55368853907Sdrh return TCL_OK; 55468853907Sdrh } 55568853907Sdrh 5568225f5acSshane #ifndef SQLITE_OMIT_GET_TABLE 5578225f5acSshane 55868853907Sdrh /* 559d2b3e23bSdrh ** Usage: sqlite3_get_table_printf DB FORMAT STRING ?--no-counts? 560d1bf3512Sdrh ** 5616f8a503dSdanielk1977 ** Invoke the sqlite3_get_table_printf() interface using the open database 562d1bf3512Sdrh ** DB. The SQL is the string FORMAT. The format string should contain 563d1bf3512Sdrh ** one %s or %q. STRING is the value inserted into %s or %q. 564d1bf3512Sdrh */ 5657617e4a8Smistachkin static int SQLITE_TCLAPI test_get_table_printf( 566d1bf3512Sdrh void *NotUsed, 567d1bf3512Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 568d1bf3512Sdrh int argc, /* Number of arguments */ 569d1bf3512Sdrh char **argv /* Text of each argument */ 570d1bf3512Sdrh ){ 5719bb575fdSdrh sqlite3 *db; 572d1bf3512Sdrh Tcl_DString str; 573d1bf3512Sdrh int rc; 574d1bf3512Sdrh char *zErr = 0; 57527b2f053Smistachkin int nRow = 0, nCol = 0; 576d1bf3512Sdrh char **aResult; 577d1bf3512Sdrh int i; 578d1bf3512Sdrh char zBuf[30]; 5791211de37Sdrh char *zSql; 580d2b3e23bSdrh int resCount = -1; 581d2b3e23bSdrh if( argc==5 ){ 582d2b3e23bSdrh if( Tcl_GetInt(interp, argv[4], &resCount) ) return TCL_ERROR; 583d2b3e23bSdrh } 584d2b3e23bSdrh if( argc!=4 && argc!=5 ){ 585d1bf3512Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 586d2b3e23bSdrh " DB FORMAT STRING ?COUNT?", 0); 587d1bf3512Sdrh return TCL_ERROR; 588d1bf3512Sdrh } 589b86ccfb2Sdrh if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; 590d1bf3512Sdrh Tcl_DStringInit(&str); 5911211de37Sdrh zSql = sqlite3_mprintf(argv[2],argv[3]); 592d2b3e23bSdrh if( argc==5 ){ 593d2b3e23bSdrh rc = sqlite3_get_table(db, zSql, &aResult, 0, 0, &zErr); 594d2b3e23bSdrh }else{ 5951211de37Sdrh rc = sqlite3_get_table(db, zSql, &aResult, &nRow, &nCol, &zErr); 596d2b3e23bSdrh resCount = (nRow+1)*nCol; 597d2b3e23bSdrh } 5981211de37Sdrh sqlite3_free(zSql); 59965545b59Sdrh sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", rc); 600d1bf3512Sdrh Tcl_AppendElement(interp, zBuf); 601d1bf3512Sdrh if( rc==SQLITE_OK ){ 602d2b3e23bSdrh if( argc==4 ){ 60365545b59Sdrh sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", nRow); 604d1bf3512Sdrh Tcl_AppendElement(interp, zBuf); 60565545b59Sdrh sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", nCol); 606d1bf3512Sdrh Tcl_AppendElement(interp, zBuf); 607d2b3e23bSdrh } 608d2b3e23bSdrh for(i=0; i<resCount; i++){ 609d1bf3512Sdrh Tcl_AppendElement(interp, aResult[i] ? aResult[i] : "NULL"); 610d1bf3512Sdrh } 611d1bf3512Sdrh }else{ 612d1bf3512Sdrh Tcl_AppendElement(interp, zErr); 613d1bf3512Sdrh } 6146f8a503dSdanielk1977 sqlite3_free_table(aResult); 615926aab22Sdanielk1977 if( zErr ) sqlite3_free(zErr); 616c60d0446Sdrh if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; 617d1bf3512Sdrh return TCL_OK; 618d1bf3512Sdrh } 619d1bf3512Sdrh 6208225f5acSshane #endif /* SQLITE_OMIT_GET_TABLE */ 6218225f5acSshane 622af9ff33aSdrh 623af9ff33aSdrh /* 6246f8a503dSdanielk1977 ** Usage: sqlite3_last_insert_rowid DB 625af9ff33aSdrh ** 626af9ff33aSdrh ** Returns the integer ROWID of the most recent insert. 627af9ff33aSdrh */ 6287617e4a8Smistachkin static int SQLITE_TCLAPI test_last_rowid( 629af9ff33aSdrh void *NotUsed, 630af9ff33aSdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 631af9ff33aSdrh int argc, /* Number of arguments */ 632af9ff33aSdrh char **argv /* Text of each argument */ 633af9ff33aSdrh ){ 6349bb575fdSdrh sqlite3 *db; 635af9ff33aSdrh char zBuf[30]; 636af9ff33aSdrh 637af9ff33aSdrh if( argc!=2 ){ 638af9ff33aSdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " DB\"", 0); 639af9ff33aSdrh return TCL_ERROR; 640af9ff33aSdrh } 641b86ccfb2Sdrh if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; 64265545b59Sdrh sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", sqlite3_last_insert_rowid(db)); 643af9ff33aSdrh Tcl_AppendResult(interp, zBuf, 0); 644af9ff33aSdrh return SQLITE_OK; 645af9ff33aSdrh } 646af9ff33aSdrh 647d1bf3512Sdrh /* 64825d6543dSdrh ** Usage: sqlite3_key DB KEY 64925d6543dSdrh ** 65025d6543dSdrh ** Set the codec key. 65125d6543dSdrh */ 6527617e4a8Smistachkin static int SQLITE_TCLAPI test_key( 65325d6543dSdrh void *NotUsed, 65425d6543dSdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 65525d6543dSdrh int argc, /* Number of arguments */ 65625d6543dSdrh char **argv /* Text of each argument */ 65725d6543dSdrh ){ 65832f57d4cSdrh #if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_CODEC_FROM_TCL) 6599bb575fdSdrh sqlite3 *db; 66025d6543dSdrh const char *zKey; 66125d6543dSdrh int nKey; 66225d6543dSdrh if( argc!=3 ){ 66325d6543dSdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 66425d6543dSdrh " FILENAME\"", 0); 66525d6543dSdrh return TCL_ERROR; 66625d6543dSdrh } 66725d6543dSdrh if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; 66825d6543dSdrh zKey = argv[2]; 66925d6543dSdrh nKey = strlen(zKey); 67025d6543dSdrh sqlite3_key(db, zKey, nKey); 67125d6543dSdrh #endif 67225d6543dSdrh return TCL_OK; 67325d6543dSdrh } 67425d6543dSdrh 67525d6543dSdrh /* 67625d6543dSdrh ** Usage: sqlite3_rekey DB KEY 67725d6543dSdrh ** 67825d6543dSdrh ** Change the codec key. 67925d6543dSdrh */ 6807617e4a8Smistachkin static int SQLITE_TCLAPI test_rekey( 68125d6543dSdrh void *NotUsed, 68225d6543dSdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 68325d6543dSdrh int argc, /* Number of arguments */ 68425d6543dSdrh char **argv /* Text of each argument */ 68525d6543dSdrh ){ 686caffb1a5Sdrh #ifdef SQLITE_HAS_CODEC 6879bb575fdSdrh sqlite3 *db; 68825d6543dSdrh const char *zKey; 68925d6543dSdrh int nKey; 69025d6543dSdrh if( argc!=3 ){ 69125d6543dSdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 69225d6543dSdrh " FILENAME\"", 0); 69325d6543dSdrh return TCL_ERROR; 69425d6543dSdrh } 69525d6543dSdrh if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; 69625d6543dSdrh zKey = argv[2]; 69725d6543dSdrh nKey = strlen(zKey); 69825d6543dSdrh sqlite3_rekey(db, zKey, nKey); 69925d6543dSdrh #endif 70025d6543dSdrh return TCL_OK; 70125d6543dSdrh } 70225d6543dSdrh 70325d6543dSdrh /* 7046f8a503dSdanielk1977 ** Usage: sqlite3_close DB 705d1bf3512Sdrh ** 7066f8a503dSdanielk1977 ** Closes the database opened by sqlite3_open. 707d1bf3512Sdrh */ 7087617e4a8Smistachkin static int SQLITE_TCLAPI sqlite_test_close( 709d1bf3512Sdrh void *NotUsed, 710d1bf3512Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 711d1bf3512Sdrh int argc, /* Number of arguments */ 712d1bf3512Sdrh char **argv /* Text of each argument */ 713d1bf3512Sdrh ){ 7149bb575fdSdrh sqlite3 *db; 71596d81f99Sdanielk1977 int rc; 716d1bf3512Sdrh if( argc!=2 ){ 717d1bf3512Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 718d1bf3512Sdrh " FILENAME\"", 0); 719d1bf3512Sdrh return TCL_ERROR; 720d1bf3512Sdrh } 721b86ccfb2Sdrh if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; 72296d81f99Sdanielk1977 rc = sqlite3_close(db); 7234f0c5878Sdrh Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC); 724d1bf3512Sdrh return TCL_OK; 725d1bf3512Sdrh } 726d1bf3512Sdrh 727d1bf3512Sdrh /* 728617dc860Sdan ** Usage: sqlite3_close_v2 DB 729617dc860Sdan ** 730617dc860Sdan ** Closes the database opened by sqlite3_open. 731617dc860Sdan */ 7327617e4a8Smistachkin static int SQLITE_TCLAPI sqlite_test_close_v2( 733617dc860Sdan void *NotUsed, 734617dc860Sdan Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 735617dc860Sdan int argc, /* Number of arguments */ 736617dc860Sdan char **argv /* Text of each argument */ 737617dc860Sdan ){ 738617dc860Sdan sqlite3 *db; 739617dc860Sdan int rc; 740617dc860Sdan if( argc!=2 ){ 741617dc860Sdan Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 742617dc860Sdan " FILENAME\"", 0); 743617dc860Sdan return TCL_ERROR; 744617dc860Sdan } 745617dc860Sdan if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; 746617dc860Sdan rc = sqlite3_close_v2(db); 747617dc860Sdan Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC); 748617dc860Sdan return TCL_OK; 749617dc860Sdan } 750617dc860Sdan 751617dc860Sdan /* 752c22bd47dSdrh ** Implementation of the x_coalesce() function. 753c22bd47dSdrh ** Return the first argument non-NULL argument. 754c22bd47dSdrh */ 7554f0c5878Sdrh static void t1_ifnullFunc( 7564f0c5878Sdrh sqlite3_context *context, 7574f0c5878Sdrh int argc, 7584f0c5878Sdrh sqlite3_value **argv 7594f0c5878Sdrh ){ 760c22bd47dSdrh int i; 761c22bd47dSdrh for(i=0; i<argc; i++){ 7629c054830Sdrh if( SQLITE_NULL!=sqlite3_value_type(argv[i]) ){ 7639310ef23Sdrh int n = sqlite3_value_bytes(argv[i]); 76403d847eaSdrh sqlite3_result_text(context, (char*)sqlite3_value_text(argv[i]), 7659310ef23Sdrh n, SQLITE_TRANSIENT); 766c22bd47dSdrh break; 767c22bd47dSdrh } 768c22bd47dSdrh } 769c22bd47dSdrh } 770c22bd47dSdrh 771c22bd47dSdrh /* 772f0313813Sdrh ** These are test functions. hex8() interprets its argument as 773f0313813Sdrh ** UTF8 and returns a hex encoding. hex16le() interprets its argument 774f0313813Sdrh ** as UTF16le and returns a hex encoding. 775f0313813Sdrh */ 776f0313813Sdrh static void hex8Func(sqlite3_context *p, int argc, sqlite3_value **argv){ 777f0313813Sdrh const unsigned char *z; 778f0313813Sdrh int i; 779f0313813Sdrh char zBuf[200]; 780f0313813Sdrh z = sqlite3_value_text(argv[0]); 781f0313813Sdrh for(i=0; i<sizeof(zBuf)/2 - 2 && z[i]; i++){ 78265545b59Sdrh sqlite3_snprintf(sizeof(zBuf)-i*2, &zBuf[i*2], "%02x", z[i]); 783f0313813Sdrh } 784f0313813Sdrh zBuf[i*2] = 0; 785f0313813Sdrh sqlite3_result_text(p, (char*)zBuf, -1, SQLITE_TRANSIENT); 786f0313813Sdrh } 787af30469dSdrh #ifndef SQLITE_OMIT_UTF16 788f0313813Sdrh static void hex16Func(sqlite3_context *p, int argc, sqlite3_value **argv){ 789f0313813Sdrh const unsigned short int *z; 790f0313813Sdrh int i; 791f0313813Sdrh char zBuf[400]; 792f0313813Sdrh z = sqlite3_value_text16(argv[0]); 793f0313813Sdrh for(i=0; i<sizeof(zBuf)/4 - 4 && z[i]; i++){ 79465545b59Sdrh sqlite3_snprintf(sizeof(zBuf)-i*4, &zBuf[i*4],"%04x", z[i]&0xff); 795f0313813Sdrh } 796f0313813Sdrh zBuf[i*4] = 0; 797f0313813Sdrh sqlite3_result_text(p, (char*)zBuf, -1, SQLITE_TRANSIENT); 798f0313813Sdrh } 799af30469dSdrh #endif 800f0313813Sdrh 801f0313813Sdrh /* 802d1d9fc33Sdrh ** A structure into which to accumulate text. 803d1d9fc33Sdrh */ 804d1d9fc33Sdrh struct dstr { 805d1d9fc33Sdrh int nAlloc; /* Space allocated */ 806d1d9fc33Sdrh int nUsed; /* Space used */ 807d1d9fc33Sdrh char *z; /* The space */ 808d1d9fc33Sdrh }; 809d1d9fc33Sdrh 810d1d9fc33Sdrh /* 811d1d9fc33Sdrh ** Append text to a dstr 812d1d9fc33Sdrh */ 813d1d9fc33Sdrh static void dstrAppend(struct dstr *p, const char *z, int divider){ 81483cc1392Sdrh int n = (int)strlen(z); 815d1d9fc33Sdrh if( p->nUsed + n + 2 > p->nAlloc ){ 816d1d9fc33Sdrh char *zNew; 817d1d9fc33Sdrh p->nAlloc = p->nAlloc*2 + n + 200; 81817435752Sdrh zNew = sqlite3_realloc(p->z, p->nAlloc); 819d1d9fc33Sdrh if( zNew==0 ){ 82017435752Sdrh sqlite3_free(p->z); 821d1d9fc33Sdrh memset(p, 0, sizeof(*p)); 822d1d9fc33Sdrh return; 823d1d9fc33Sdrh } 824d1d9fc33Sdrh p->z = zNew; 825d1d9fc33Sdrh } 826d1d9fc33Sdrh if( divider && p->nUsed>0 ){ 827d1d9fc33Sdrh p->z[p->nUsed++] = divider; 828d1d9fc33Sdrh } 829d1d9fc33Sdrh memcpy(&p->z[p->nUsed], z, n+1); 830d1d9fc33Sdrh p->nUsed += n; 831d1d9fc33Sdrh } 832d1d9fc33Sdrh 833d1d9fc33Sdrh /* 8344adee20fSdanielk1977 ** Invoked for each callback from sqlite3ExecFunc 835d1d9fc33Sdrh */ 836d1d9fc33Sdrh static int execFuncCallback(void *pData, int argc, char **argv, char **NotUsed){ 837d1d9fc33Sdrh struct dstr *p = (struct dstr*)pData; 838d1d9fc33Sdrh int i; 839d1d9fc33Sdrh for(i=0; i<argc; i++){ 840d1d9fc33Sdrh if( argv[i]==0 ){ 841d1d9fc33Sdrh dstrAppend(p, "NULL", ' '); 842d1d9fc33Sdrh }else{ 843d1d9fc33Sdrh dstrAppend(p, argv[i], ' '); 844d1d9fc33Sdrh } 845d1d9fc33Sdrh } 846d1d9fc33Sdrh return 0; 847d1d9fc33Sdrh } 848d1d9fc33Sdrh 849d1d9fc33Sdrh /* 850e35ee196Sdanielk1977 ** Implementation of the x_sqlite_exec() function. This function takes 851c22bd47dSdrh ** a single argument and attempts to execute that argument as SQL code. 8526cbe1f1bSdrh ** This is illegal and should set the SQLITE_MISUSE flag on the database. 853c22bd47dSdrh ** 8546f8a503dSdanielk1977 ** 2004-Jan-07: We have changed this to make it legal to call sqlite3_exec() 855d1d9fc33Sdrh ** from within a function call. 856d1d9fc33Sdrh ** 857c22bd47dSdrh ** This routine simulates the effect of having two threads attempt to 858c22bd47dSdrh ** use the same database at the same time. 859c22bd47dSdrh */ 86051ad0ecdSdanielk1977 static void sqlite3ExecFunc( 8610ae8b831Sdanielk1977 sqlite3_context *context, 86251ad0ecdSdanielk1977 int argc, 86351ad0ecdSdanielk1977 sqlite3_value **argv 86451ad0ecdSdanielk1977 ){ 865d1d9fc33Sdrh struct dstr x; 866d1d9fc33Sdrh memset(&x, 0, sizeof(x)); 8673752785fSdrh (void)sqlite3_exec((sqlite3*)sqlite3_user_data(context), 86803d847eaSdrh (char*)sqlite3_value_text(argv[0]), 869d1d9fc33Sdrh execFuncCallback, &x, 0); 870d8123366Sdanielk1977 sqlite3_result_text(context, x.z, x.nUsed, SQLITE_TRANSIENT); 87117435752Sdrh sqlite3_free(x.z); 872c22bd47dSdrh } 873c22bd47dSdrh 874c22bd47dSdrh /* 875d7263927Sdanielk1977 ** Implementation of tkt2213func(), a scalar function that takes exactly 876d7263927Sdanielk1977 ** one argument. It has two interesting features: 877d7263927Sdanielk1977 ** 878d7263927Sdanielk1977 ** * It calls sqlite3_value_text() 3 times on the argument sqlite3_value*. 879d7263927Sdanielk1977 ** If the three pointers returned are not the same an SQL error is raised. 880d7263927Sdanielk1977 ** 88185b623f2Sdrh ** * Otherwise it returns a copy of the text representation of its 882d7263927Sdanielk1977 ** argument in such a way as the VDBE representation is a Mem* cell 883d7263927Sdanielk1977 ** with the MEM_Term flag clear. 884d7263927Sdanielk1977 ** 885d7263927Sdanielk1977 ** Ticket #2213 can therefore be tested by evaluating the following 886d7263927Sdanielk1977 ** SQL expression: 887d7263927Sdanielk1977 ** 888d7263927Sdanielk1977 ** tkt2213func(tkt2213func('a string')); 889d7263927Sdanielk1977 */ 890d7263927Sdanielk1977 static void tkt2213Function( 891d7263927Sdanielk1977 sqlite3_context *context, 892d7263927Sdanielk1977 int argc, 893d7263927Sdanielk1977 sqlite3_value **argv 894d7263927Sdanielk1977 ){ 895d7263927Sdanielk1977 int nText; 896d7263927Sdanielk1977 unsigned char const *zText1; 897d7263927Sdanielk1977 unsigned char const *zText2; 898d7263927Sdanielk1977 unsigned char const *zText3; 899d7263927Sdanielk1977 900d7263927Sdanielk1977 nText = sqlite3_value_bytes(argv[0]); 901d7263927Sdanielk1977 zText1 = sqlite3_value_text(argv[0]); 902d7263927Sdanielk1977 zText2 = sqlite3_value_text(argv[0]); 903d7263927Sdanielk1977 zText3 = sqlite3_value_text(argv[0]); 904d7263927Sdanielk1977 905d7263927Sdanielk1977 if( zText1!=zText2 || zText2!=zText3 ){ 906d7263927Sdanielk1977 sqlite3_result_error(context, "tkt2213 is not fixed", -1); 907d7263927Sdanielk1977 }else{ 908d7263927Sdanielk1977 char *zCopy = (char *)sqlite3_malloc(nText); 909d7263927Sdanielk1977 memcpy(zCopy, zText1, nText); 910d7263927Sdanielk1977 sqlite3_result_text(context, zCopy, nText, sqlite3_free); 911d7263927Sdanielk1977 } 912d7263927Sdanielk1977 } 913d7263927Sdanielk1977 914d7263927Sdanielk1977 /* 9159310ef23Sdrh ** The following SQL function takes 4 arguments. The 2nd and 9169310ef23Sdrh ** 4th argument must be one of these strings: 'text', 'text16', 9179310ef23Sdrh ** or 'blob' corresponding to API functions 9189310ef23Sdrh ** 9199310ef23Sdrh ** sqlite3_value_text() 9209310ef23Sdrh ** sqlite3_value_text16() 9219310ef23Sdrh ** sqlite3_value_blob() 9229310ef23Sdrh ** 9239310ef23Sdrh ** The third argument is a string, either 'bytes' or 'bytes16' or 'noop', 9249310ef23Sdrh ** corresponding to APIs: 9259310ef23Sdrh ** 9269310ef23Sdrh ** sqlite3_value_bytes() 9279310ef23Sdrh ** sqlite3_value_bytes16() 9289310ef23Sdrh ** noop 9299310ef23Sdrh ** 9309310ef23Sdrh ** The APIs designated by the 2nd through 4th arguments are applied 9319310ef23Sdrh ** to the first argument in order. If the pointers returned by the 9329310ef23Sdrh ** second and fourth are different, this routine returns 1. Otherwise, 9339310ef23Sdrh ** this routine returns 0. 9349310ef23Sdrh ** 9359310ef23Sdrh ** This function is used to test to see when returned pointers from 9369310ef23Sdrh ** the _text(), _text16() and _blob() APIs become invalidated. 9379310ef23Sdrh */ 9389310ef23Sdrh static void ptrChngFunction( 9399310ef23Sdrh sqlite3_context *context, 9409310ef23Sdrh int argc, 9419310ef23Sdrh sqlite3_value **argv 9429310ef23Sdrh ){ 9439310ef23Sdrh const void *p1, *p2; 9449310ef23Sdrh const char *zCmd; 9459310ef23Sdrh if( argc!=4 ) return; 9469310ef23Sdrh zCmd = (const char*)sqlite3_value_text(argv[1]); 9479310ef23Sdrh if( zCmd==0 ) return; 9489310ef23Sdrh if( strcmp(zCmd,"text")==0 ){ 9499310ef23Sdrh p1 = (const void*)sqlite3_value_text(argv[0]); 9509310ef23Sdrh #ifndef SQLITE_OMIT_UTF16 9519310ef23Sdrh }else if( strcmp(zCmd, "text16")==0 ){ 9529310ef23Sdrh p1 = (const void*)sqlite3_value_text16(argv[0]); 9539310ef23Sdrh #endif 9549310ef23Sdrh }else if( strcmp(zCmd, "blob")==0 ){ 9559310ef23Sdrh p1 = (const void*)sqlite3_value_blob(argv[0]); 9569310ef23Sdrh }else{ 9579310ef23Sdrh return; 9589310ef23Sdrh } 9599310ef23Sdrh zCmd = (const char*)sqlite3_value_text(argv[2]); 9609310ef23Sdrh if( zCmd==0 ) return; 9619310ef23Sdrh if( strcmp(zCmd,"bytes")==0 ){ 9629310ef23Sdrh sqlite3_value_bytes(argv[0]); 9639310ef23Sdrh #ifndef SQLITE_OMIT_UTF16 9649310ef23Sdrh }else if( strcmp(zCmd, "bytes16")==0 ){ 9659310ef23Sdrh sqlite3_value_bytes16(argv[0]); 9669310ef23Sdrh #endif 9679310ef23Sdrh }else if( strcmp(zCmd, "noop")==0 ){ 9689310ef23Sdrh /* do nothing */ 9699310ef23Sdrh }else{ 9709310ef23Sdrh return; 9719310ef23Sdrh } 9729310ef23Sdrh zCmd = (const char*)sqlite3_value_text(argv[3]); 9739310ef23Sdrh if( zCmd==0 ) return; 9749310ef23Sdrh if( strcmp(zCmd,"text")==0 ){ 9759310ef23Sdrh p2 = (const void*)sqlite3_value_text(argv[0]); 9769310ef23Sdrh #ifndef SQLITE_OMIT_UTF16 9779310ef23Sdrh }else if( strcmp(zCmd, "text16")==0 ){ 9789310ef23Sdrh p2 = (const void*)sqlite3_value_text16(argv[0]); 9799310ef23Sdrh #endif 9809310ef23Sdrh }else if( strcmp(zCmd, "blob")==0 ){ 9819310ef23Sdrh p2 = (const void*)sqlite3_value_blob(argv[0]); 9829310ef23Sdrh }else{ 9839310ef23Sdrh return; 9849310ef23Sdrh } 9859310ef23Sdrh sqlite3_result_int(context, p1!=p2); 9869310ef23Sdrh } 9879310ef23Sdrh 9884a8ee3dfSdrh /* 9894a8ee3dfSdrh ** This SQL function returns a different answer each time it is called, even if 9904a8ee3dfSdrh ** the arguments are the same. 9914a8ee3dfSdrh */ 9924a8ee3dfSdrh static void nondeterministicFunction( 9934a8ee3dfSdrh sqlite3_context *context, 9944a8ee3dfSdrh int argc, 9954a8ee3dfSdrh sqlite3_value **argv 9964a8ee3dfSdrh ){ 9974a8ee3dfSdrh static int cnt = 0; 9984a8ee3dfSdrh sqlite3_result_int(context, cnt++); 9994a8ee3dfSdrh } 10009310ef23Sdrh 10019310ef23Sdrh /* 10024a8ee3dfSdrh ** Usage: sqlite3_create_function DB 1003c22bd47dSdrh ** 10046f8a503dSdanielk1977 ** Call the sqlite3_create_function API on the given database in order 1005c22bd47dSdrh ** to create a function named "x_coalesce". This function does the same thing 1006c22bd47dSdrh ** as the "coalesce" function. This function also registers an SQL function 1007e35ee196Sdanielk1977 ** named "x_sqlite_exec" that invokes sqlite3_exec(). Invoking sqlite3_exec() 1008c22bd47dSdrh ** in this way is illegal recursion and should raise an SQLITE_MISUSE error. 1009c22bd47dSdrh ** The effect is similar to trying to use the same database connection from 1010c22bd47dSdrh ** two threads at the same time. 1011c22bd47dSdrh ** 1012c22bd47dSdrh ** The original motivation for this routine was to be able to call the 10136f8a503dSdanielk1977 ** sqlite3_create_function function while a query is in progress in order 1014c22bd47dSdrh ** to test the SQLITE_MISUSE detection logic. 1015c22bd47dSdrh */ 10167617e4a8Smistachkin static int SQLITE_TCLAPI test_create_function( 1017c22bd47dSdrh void *NotUsed, 1018c22bd47dSdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 1019c22bd47dSdrh int argc, /* Number of arguments */ 1020c22bd47dSdrh char **argv /* Text of each argument */ 1021c22bd47dSdrh ){ 1022c60d0446Sdrh int rc; 10239bb575fdSdrh sqlite3 *db; 1024312d6b36Sdanielk1977 1025c22bd47dSdrh if( argc!=2 ){ 1026c22bd47dSdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 10274397de57Sdanielk1977 " DB\"", 0); 1028c22bd47dSdrh return TCL_ERROR; 1029c22bd47dSdrh } 1030b86ccfb2Sdrh if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; 10314a8ee3dfSdrh rc = sqlite3_create_function(db, "x_coalesce", -1, SQLITE_UTF8, 0, 10324f0c5878Sdrh t1_ifnullFunc, 0, 0); 1033235a818eSdrh if( rc==SQLITE_OK ){ 10344a8ee3dfSdrh rc = sqlite3_create_function(db, "hex8", 1, SQLITE_UTF8 | SQLITE_DETERMINISTIC, 10354a8ee3dfSdrh 0, hex8Func, 0, 0); 1036235a818eSdrh } 1037af30469dSdrh #ifndef SQLITE_OMIT_UTF16 1038235a818eSdrh if( rc==SQLITE_OK ){ 10394a8ee3dfSdrh rc = sqlite3_create_function(db, "hex16", 1, SQLITE_UTF16 | SQLITE_DETERMINISTIC, 10404a8ee3dfSdrh 0, hex16Func, 0, 0); 1041235a818eSdrh } 1042af30469dSdrh #endif 1043d7263927Sdanielk1977 if( rc==SQLITE_OK ){ 1044d7263927Sdanielk1977 rc = sqlite3_create_function(db, "tkt2213func", 1, SQLITE_ANY, 0, 1045d7263927Sdanielk1977 tkt2213Function, 0, 0); 1046d7263927Sdanielk1977 } 10479310ef23Sdrh if( rc==SQLITE_OK ){ 10489310ef23Sdrh rc = sqlite3_create_function(db, "pointer_change", 4, SQLITE_ANY, 0, 10499310ef23Sdrh ptrChngFunction, 0, 0); 10509310ef23Sdrh } 1051312d6b36Sdanielk1977 10524a8ee3dfSdrh /* Functions counter1() and counter2() have the same implementation - they 10534a8ee3dfSdrh ** both return an ascending integer with each call. But counter1() is marked 10544a8ee3dfSdrh ** as non-deterministic and counter2() is marked as deterministic. 10554a8ee3dfSdrh */ 10564a8ee3dfSdrh if( rc==SQLITE_OK ){ 10574a8ee3dfSdrh rc = sqlite3_create_function(db, "counter1", -1, SQLITE_UTF8, 10584a8ee3dfSdrh 0, nondeterministicFunction, 0, 0); 10594a8ee3dfSdrh } 10604a8ee3dfSdrh if( rc==SQLITE_OK ){ 10614a8ee3dfSdrh rc = sqlite3_create_function(db, "counter2", -1, SQLITE_UTF8|SQLITE_DETERMINISTIC, 10624a8ee3dfSdrh 0, nondeterministicFunction, 0, 0); 10634a8ee3dfSdrh } 10644a8ee3dfSdrh 10655436dc2dSdrh #ifndef SQLITE_OMIT_UTF16 1066312d6b36Sdanielk1977 /* Use the sqlite3_create_function16() API here. Mainly for fun, but also 1067312d6b36Sdanielk1977 ** because it is not tested anywhere else. */ 1068c60d0446Sdrh if( rc==SQLITE_OK ){ 1069eee4c8caSdrh const void *zUtf16; 1070576ec6b3Sdanielk1977 sqlite3_value *pVal; 1071f3a65f7eSdrh sqlite3_mutex_enter(db->mutex); 1072f3a65f7eSdrh pVal = sqlite3ValueNew(db); 1073b21c8cd4Sdrh sqlite3ValueSetStr(pVal, -1, "x_sqlite_exec", SQLITE_UTF8, SQLITE_STATIC); 1074a7a8e14bSdanielk1977 zUtf16 = sqlite3ValueText(pVal, SQLITE_UTF16NATIVE); 1075f3a65f7eSdrh if( db->mallocFailed ){ 1076f3a65f7eSdrh rc = SQLITE_NOMEM; 1077f3a65f7eSdrh }else{ 1078a7a8e14bSdanielk1977 rc = sqlite3_create_function16(db, zUtf16, 1079312d6b36Sdanielk1977 1, SQLITE_UTF16, db, sqlite3ExecFunc, 0, 0); 1080f3a65f7eSdrh } 1081312d6b36Sdanielk1977 sqlite3ValueFree(pVal); 1082f3a65f7eSdrh sqlite3_mutex_leave(db->mutex); 1083c60d0446Sdrh } 10845436dc2dSdrh #endif 10855436dc2dSdrh 1086c60d0446Sdrh if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; 10874f0c5878Sdrh Tcl_SetResult(interp, (char *)t1ErrorName(rc), 0); 1088c22bd47dSdrh return TCL_OK; 1089c22bd47dSdrh } 1090c22bd47dSdrh 1091c22bd47dSdrh /* 1092c22bd47dSdrh ** Routines to implement the x_count() aggregate function. 109390669c1dSdrh ** 109490669c1dSdrh ** x_count() counts the number of non-null arguments. But there are 109590669c1dSdrh ** some twists for testing purposes. 109690669c1dSdrh ** 109790669c1dSdrh ** If the argument to x_count() is 40 then a UTF-8 error is reported 109890669c1dSdrh ** on the step function. If x_count(41) is seen, then a UTF-16 error 109990669c1dSdrh ** is reported on the step function. If the total count is 42, then 110090669c1dSdrh ** a UTF-8 error is reported on the finalize function. 1101c22bd47dSdrh */ 11024f0c5878Sdrh typedef struct t1CountCtx t1CountCtx; 11034f0c5878Sdrh struct t1CountCtx { 1104c22bd47dSdrh int n; 1105c22bd47dSdrh }; 11064f0c5878Sdrh static void t1CountStep( 11074f0c5878Sdrh sqlite3_context *context, 11084f0c5878Sdrh int argc, 11094f0c5878Sdrh sqlite3_value **argv 11104f0c5878Sdrh ){ 11114f0c5878Sdrh t1CountCtx *p; 11124f26d6c4Sdrh p = sqlite3_aggregate_context(context, sizeof(*p)); 11139c054830Sdrh if( (argc==0 || SQLITE_NULL!=sqlite3_value_type(argv[0]) ) && p ){ 1114c22bd47dSdrh p->n++; 1115c22bd47dSdrh } 111690669c1dSdrh if( argc>0 ){ 111790669c1dSdrh int v = sqlite3_value_int(argv[0]); 111890669c1dSdrh if( v==40 ){ 111990669c1dSdrh sqlite3_result_error(context, "value of 40 handed to x_count", -1); 1120a1686c9aSdanielk1977 #ifndef SQLITE_OMIT_UTF16 112190669c1dSdrh }else if( v==41 ){ 112290669c1dSdrh const char zUtf16ErrMsg[] = { 0, 0x61, 0, 0x62, 0, 0x63, 0, 0, 0}; 112390669c1dSdrh sqlite3_result_error16(context, &zUtf16ErrMsg[1-SQLITE_BIGENDIAN], -1); 1124a1686c9aSdanielk1977 #endif 112590669c1dSdrh } 112690669c1dSdrh } 1127c22bd47dSdrh } 11284f0c5878Sdrh static void t1CountFinalize(sqlite3_context *context){ 11294f0c5878Sdrh t1CountCtx *p; 11304f26d6c4Sdrh p = sqlite3_aggregate_context(context, sizeof(*p)); 113190669c1dSdrh if( p ){ 113290669c1dSdrh if( p->n==42 ){ 113390669c1dSdrh sqlite3_result_error(context, "x_count totals to 42", -1); 113490669c1dSdrh }else{ 1135c572ef7fSdanielk1977 sqlite3_result_int(context, p ? p->n : 0); 1136c22bd47dSdrh } 113790669c1dSdrh } 113890669c1dSdrh } 1139c22bd47dSdrh 1140c5512882Sdanielk1977 #ifndef SQLITE_OMIT_DEPRECATED 1141fa18beceSdanielk1977 static void legacyCountStep( 1142fa18beceSdanielk1977 sqlite3_context *context, 1143fa18beceSdanielk1977 int argc, 1144fa18beceSdanielk1977 sqlite3_value **argv 1145fa18beceSdanielk1977 ){ 1146fa18beceSdanielk1977 /* no-op */ 1147fa18beceSdanielk1977 } 1148eec556d3Sshane 1149fa18beceSdanielk1977 static void legacyCountFinalize(sqlite3_context *context){ 1150fa18beceSdanielk1977 sqlite3_result_int(context, sqlite3_aggregate_count(context)); 1151fa18beceSdanielk1977 } 1152eec556d3Sshane #endif 1153fa18beceSdanielk1977 1154c22bd47dSdrh /* 1155fa18beceSdanielk1977 ** Usage: sqlite3_create_aggregate DB 1156c22bd47dSdrh ** 11576f8a503dSdanielk1977 ** Call the sqlite3_create_function API on the given database in order 1158fa18beceSdanielk1977 ** to create a function named "x_count". This function is similar 1159fa18beceSdanielk1977 ** to the built-in count() function, with a few special quirks 1160fa18beceSdanielk1977 ** for testing the sqlite3_result_error() APIs. 1161c22bd47dSdrh ** 1162c22bd47dSdrh ** The original motivation for this routine was to be able to call the 11636f8a503dSdanielk1977 ** sqlite3_create_aggregate function while a query is in progress in order 116490669c1dSdrh ** to test the SQLITE_MISUSE detection logic. See misuse.test. 116590669c1dSdrh ** 116690669c1dSdrh ** This routine was later extended to test the use of sqlite3_result_error() 116790669c1dSdrh ** within aggregate functions. 1168fa18beceSdanielk1977 ** 1169fa18beceSdanielk1977 ** Later: It is now also extended to register the aggregate function 1170fa18beceSdanielk1977 ** "legacy_count()" with the supplied database handle. This is used 1171fa18beceSdanielk1977 ** to test the deprecated sqlite3_aggregate_count() API. 1172c22bd47dSdrh */ 11737617e4a8Smistachkin static int SQLITE_TCLAPI test_create_aggregate( 1174c22bd47dSdrh void *NotUsed, 1175c22bd47dSdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 1176c22bd47dSdrh int argc, /* Number of arguments */ 1177c22bd47dSdrh char **argv /* Text of each argument */ 1178c22bd47dSdrh ){ 11799bb575fdSdrh sqlite3 *db; 1180c60d0446Sdrh int rc; 1181c22bd47dSdrh if( argc!=2 ){ 1182c22bd47dSdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 1183c22bd47dSdrh " FILENAME\"", 0); 1184c22bd47dSdrh return TCL_ERROR; 1185c22bd47dSdrh } 1186b86ccfb2Sdrh if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; 1187c60d0446Sdrh rc = sqlite3_create_function(db, "x_count", 0, SQLITE_UTF8, 0, 0, 11884f0c5878Sdrh t1CountStep,t1CountFinalize); 1189c60d0446Sdrh if( rc==SQLITE_OK ){ 1190fa18beceSdanielk1977 rc = sqlite3_create_function(db, "x_count", 1, SQLITE_UTF8, 0, 0, 11914f0c5878Sdrh t1CountStep,t1CountFinalize); 1192c60d0446Sdrh } 1193eec556d3Sshane #ifndef SQLITE_OMIT_DEPRECATED 1194fa18beceSdanielk1977 if( rc==SQLITE_OK ){ 1195fa18beceSdanielk1977 rc = sqlite3_create_function(db, "legacy_count", 0, SQLITE_ANY, 0, 0, 1196fa18beceSdanielk1977 legacyCountStep, legacyCountFinalize 1197fa18beceSdanielk1977 ); 1198fa18beceSdanielk1977 } 1199eec556d3Sshane #endif 1200c60d0446Sdrh if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; 1201fa18beceSdanielk1977 Tcl_SetResult(interp, (char *)t1ErrorName(rc), 0); 1202c22bd47dSdrh return TCL_OK; 1203c22bd47dSdrh } 1204c22bd47dSdrh 1205c22bd47dSdrh 12063c23a885Sdrh /* 12073c23a885Sdrh ** Usage: printf TEXT 12083c23a885Sdrh ** 12093c23a885Sdrh ** Send output to printf. Use this rather than puts to merge the output 12103c23a885Sdrh ** in the correct sequence with debugging printfs inserted into C code. 12113c23a885Sdrh ** Puts uses a separate buffer and debugging statements will be out of 12123c23a885Sdrh ** sequence if it is used. 12133c23a885Sdrh */ 12147617e4a8Smistachkin static int SQLITE_TCLAPI test_printf( 12153c23a885Sdrh void *NotUsed, 12163c23a885Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 12173c23a885Sdrh int argc, /* Number of arguments */ 12183c23a885Sdrh char **argv /* Text of each argument */ 12193c23a885Sdrh ){ 12203c23a885Sdrh if( argc!=2 ){ 12213c23a885Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 12223c23a885Sdrh " TEXT\"", 0); 12233c23a885Sdrh return TCL_ERROR; 12243c23a885Sdrh } 12253c23a885Sdrh printf("%s\n", argv[1]); 12263c23a885Sdrh return TCL_OK; 12273c23a885Sdrh } 12283c23a885Sdrh 12293c23a885Sdrh 1230c22bd47dSdrh 1231c22bd47dSdrh /* 12326f8a503dSdanielk1977 ** Usage: sqlite3_mprintf_int FORMAT INTEGER INTEGER INTEGER 1233d1bf3512Sdrh ** 1234d1bf3512Sdrh ** Call mprintf with three integer arguments 1235d1bf3512Sdrh */ 12367617e4a8Smistachkin static int SQLITE_TCLAPI sqlite3_mprintf_int( 1237d1bf3512Sdrh void *NotUsed, 1238d1bf3512Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 1239d1bf3512Sdrh int argc, /* Number of arguments */ 1240d1bf3512Sdrh char **argv /* Text of each argument */ 1241d1bf3512Sdrh ){ 1242d1bf3512Sdrh int a[3], i; 1243d1bf3512Sdrh char *z; 1244d1bf3512Sdrh if( argc!=5 ){ 1245d1bf3512Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 1246d1bf3512Sdrh " FORMAT INT INT INT\"", 0); 1247d1bf3512Sdrh return TCL_ERROR; 1248d1bf3512Sdrh } 1249d1bf3512Sdrh for(i=2; i<5; i++){ 1250d1bf3512Sdrh if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR; 1251d1bf3512Sdrh } 12526f8a503dSdanielk1977 z = sqlite3_mprintf(argv[1], a[0], a[1], a[2]); 1253d1bf3512Sdrh Tcl_AppendResult(interp, z, 0); 12543f4fedb2Sdrh sqlite3_free(z); 1255d1bf3512Sdrh return TCL_OK; 1256d1bf3512Sdrh } 1257d1bf3512Sdrh 1258d1bf3512Sdrh /* 1259e9707671Sdrh ** Usage: sqlite3_mprintf_int64 FORMAT INTEGER INTEGER INTEGER 1260e9707671Sdrh ** 1261e9707671Sdrh ** Call mprintf with three 64-bit integer arguments 1262e9707671Sdrh */ 12637617e4a8Smistachkin static int SQLITE_TCLAPI sqlite3_mprintf_int64( 1264e9707671Sdrh void *NotUsed, 1265e9707671Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 1266e9707671Sdrh int argc, /* Number of arguments */ 1267e9707671Sdrh char **argv /* Text of each argument */ 1268e9707671Sdrh ){ 1269e9707671Sdrh int i; 1270e9707671Sdrh sqlite_int64 a[3]; 1271e9707671Sdrh char *z; 1272e9707671Sdrh if( argc!=5 ){ 1273e9707671Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 1274e9707671Sdrh " FORMAT INT INT INT\"", 0); 1275e9707671Sdrh return TCL_ERROR; 1276e9707671Sdrh } 1277e9707671Sdrh for(i=2; i<5; i++){ 1278609d5846Sdrh if( sqlite3Atoi64(argv[i], &a[i-2], sqlite3Strlen30(argv[i]), SQLITE_UTF8) ){ 1279e9707671Sdrh Tcl_AppendResult(interp, "argument is not a valid 64-bit integer", 0); 1280e9707671Sdrh return TCL_ERROR; 1281e9707671Sdrh } 1282e9707671Sdrh } 1283e9707671Sdrh z = sqlite3_mprintf(argv[1], a[0], a[1], a[2]); 1284e9707671Sdrh Tcl_AppendResult(interp, z, 0); 1285e9707671Sdrh sqlite3_free(z); 1286e9707671Sdrh return TCL_OK; 1287e9707671Sdrh } 1288e9707671Sdrh 1289e9707671Sdrh /* 1290c5cad1e3Sdrh ** Usage: sqlite3_mprintf_long FORMAT INTEGER INTEGER INTEGER 1291c5cad1e3Sdrh ** 1292c5cad1e3Sdrh ** Call mprintf with three long integer arguments. This might be the 1293c5cad1e3Sdrh ** same as sqlite3_mprintf_int or sqlite3_mprintf_int64, depending on 1294c5cad1e3Sdrh ** platform. 1295c5cad1e3Sdrh */ 12967617e4a8Smistachkin static int SQLITE_TCLAPI sqlite3_mprintf_long( 1297c5cad1e3Sdrh void *NotUsed, 1298c5cad1e3Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 1299c5cad1e3Sdrh int argc, /* Number of arguments */ 1300c5cad1e3Sdrh char **argv /* Text of each argument */ 1301c5cad1e3Sdrh ){ 1302c5cad1e3Sdrh int i; 1303c5cad1e3Sdrh long int a[3]; 1304c5cad1e3Sdrh int b[3]; 1305c5cad1e3Sdrh char *z; 1306c5cad1e3Sdrh if( argc!=5 ){ 1307c5cad1e3Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 1308c5cad1e3Sdrh " FORMAT INT INT INT\"", 0); 1309c5cad1e3Sdrh return TCL_ERROR; 1310c5cad1e3Sdrh } 1311c5cad1e3Sdrh for(i=2; i<5; i++){ 1312c5cad1e3Sdrh if( Tcl_GetInt(interp, argv[i], &b[i-2]) ) return TCL_ERROR; 1313c5cad1e3Sdrh a[i-2] = (long int)b[i-2]; 13147ed0cae2Sdrh a[i-2] &= (((u64)1)<<(sizeof(int)*8))-1; 1315c5cad1e3Sdrh } 1316c5cad1e3Sdrh z = sqlite3_mprintf(argv[1], a[0], a[1], a[2]); 1317c5cad1e3Sdrh Tcl_AppendResult(interp, z, 0); 1318c5cad1e3Sdrh sqlite3_free(z); 1319c5cad1e3Sdrh return TCL_OK; 1320c5cad1e3Sdrh } 1321c5cad1e3Sdrh 1322c5cad1e3Sdrh /* 13236f8a503dSdanielk1977 ** Usage: sqlite3_mprintf_str FORMAT INTEGER INTEGER STRING 1324d1bf3512Sdrh ** 1325d1bf3512Sdrh ** Call mprintf with two integer arguments and one string argument 1326d1bf3512Sdrh */ 13277617e4a8Smistachkin static int SQLITE_TCLAPI sqlite3_mprintf_str( 1328d1bf3512Sdrh void *NotUsed, 1329d1bf3512Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 1330d1bf3512Sdrh int argc, /* Number of arguments */ 1331d1bf3512Sdrh char **argv /* Text of each argument */ 1332d1bf3512Sdrh ){ 1333d1bf3512Sdrh int a[3], i; 1334d1bf3512Sdrh char *z; 1335f220b24fSchw if( argc<4 || argc>5 ){ 1336d1bf3512Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 1337f220b24fSchw " FORMAT INT INT ?STRING?\"", 0); 1338d1bf3512Sdrh return TCL_ERROR; 1339d1bf3512Sdrh } 1340d1bf3512Sdrh for(i=2; i<4; i++){ 1341d1bf3512Sdrh if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR; 1342d1bf3512Sdrh } 13436f8a503dSdanielk1977 z = sqlite3_mprintf(argv[1], a[0], a[1], argc>4 ? argv[4] : NULL); 1344d1bf3512Sdrh Tcl_AppendResult(interp, z, 0); 13453f4fedb2Sdrh sqlite3_free(z); 1346d1bf3512Sdrh return TCL_OK; 1347d1bf3512Sdrh } 1348d1bf3512Sdrh 1349d1bf3512Sdrh /* 1350b3738b6cSdrh ** Usage: sqlite3_snprintf_str INTEGER FORMAT INTEGER INTEGER STRING 1351b3738b6cSdrh ** 1352b3738b6cSdrh ** Call mprintf with two integer arguments and one string argument 1353b3738b6cSdrh */ 13547617e4a8Smistachkin static int SQLITE_TCLAPI sqlite3_snprintf_str( 1355b3738b6cSdrh void *NotUsed, 1356b3738b6cSdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 1357b3738b6cSdrh int argc, /* Number of arguments */ 1358b3738b6cSdrh char **argv /* Text of each argument */ 1359b3738b6cSdrh ){ 1360b3738b6cSdrh int a[3], i; 1361b3738b6cSdrh int n; 1362b3738b6cSdrh char *z; 1363b3738b6cSdrh if( argc<5 || argc>6 ){ 1364b3738b6cSdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 1365b3738b6cSdrh " INT FORMAT INT INT ?STRING?\"", 0); 1366b3738b6cSdrh return TCL_ERROR; 1367b3738b6cSdrh } 1368b3738b6cSdrh if( Tcl_GetInt(interp, argv[1], &n) ) return TCL_ERROR; 1369b3738b6cSdrh if( n<0 ){ 1370b3738b6cSdrh Tcl_AppendResult(interp, "N must be non-negative", 0); 1371b3738b6cSdrh return TCL_ERROR; 1372b3738b6cSdrh } 1373b3738b6cSdrh for(i=3; i<5; i++){ 1374b3738b6cSdrh if( Tcl_GetInt(interp, argv[i], &a[i-3]) ) return TCL_ERROR; 1375b3738b6cSdrh } 1376b3738b6cSdrh z = sqlite3_malloc( n+1 ); 1377b3738b6cSdrh sqlite3_snprintf(n, z, argv[2], a[0], a[1], argc>4 ? argv[5] : NULL); 1378b3738b6cSdrh Tcl_AppendResult(interp, z, 0); 1379b3738b6cSdrh sqlite3_free(z); 1380b3738b6cSdrh return TCL_OK; 1381b3738b6cSdrh } 1382b3738b6cSdrh 1383b3738b6cSdrh /* 138463782855Sdrh ** Usage: sqlite3_mprintf_double FORMAT INTEGER INTEGER DOUBLE 1385d1bf3512Sdrh ** 1386d1bf3512Sdrh ** Call mprintf with two integer arguments and one double argument 1387d1bf3512Sdrh */ 13887617e4a8Smistachkin static int SQLITE_TCLAPI sqlite3_mprintf_double( 1389d1bf3512Sdrh void *NotUsed, 1390d1bf3512Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 1391d1bf3512Sdrh int argc, /* Number of arguments */ 1392d1bf3512Sdrh char **argv /* Text of each argument */ 1393d1bf3512Sdrh ){ 1394d1bf3512Sdrh int a[3], i; 1395d1bf3512Sdrh double r; 1396d1bf3512Sdrh char *z; 1397d1bf3512Sdrh if( argc!=5 ){ 1398d1bf3512Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 139963782855Sdrh " FORMAT INT INT DOUBLE\"", 0); 1400d1bf3512Sdrh return TCL_ERROR; 1401d1bf3512Sdrh } 1402d1bf3512Sdrh for(i=2; i<4; i++){ 1403d1bf3512Sdrh if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR; 1404d1bf3512Sdrh } 1405d1bf3512Sdrh if( Tcl_GetDouble(interp, argv[4], &r) ) return TCL_ERROR; 14066f8a503dSdanielk1977 z = sqlite3_mprintf(argv[1], a[0], a[1], r); 1407d1bf3512Sdrh Tcl_AppendResult(interp, z, 0); 14083f4fedb2Sdrh sqlite3_free(z); 1409d1bf3512Sdrh return TCL_OK; 1410d1bf3512Sdrh } 1411d1bf3512Sdrh 1412d1bf3512Sdrh /* 141363782855Sdrh ** Usage: sqlite3_mprintf_scaled FORMAT DOUBLE DOUBLE 1414b621c237Sdrh ** 1415b621c237Sdrh ** Call mprintf with a single double argument which is the product of the 1416b621c237Sdrh ** two arguments given above. This is used to generate overflow and underflow 1417b621c237Sdrh ** doubles to test that they are converted properly. 1418b621c237Sdrh */ 14197617e4a8Smistachkin static int SQLITE_TCLAPI sqlite3_mprintf_scaled( 1420b621c237Sdrh void *NotUsed, 1421b621c237Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 1422b621c237Sdrh int argc, /* Number of arguments */ 1423b621c237Sdrh char **argv /* Text of each argument */ 1424b621c237Sdrh ){ 1425b621c237Sdrh int i; 1426b621c237Sdrh double r[2]; 1427b621c237Sdrh char *z; 1428b621c237Sdrh if( argc!=4 ){ 1429b621c237Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 1430b621c237Sdrh " FORMAT DOUBLE DOUBLE\"", 0); 1431b621c237Sdrh return TCL_ERROR; 1432b621c237Sdrh } 1433b621c237Sdrh for(i=2; i<4; i++){ 1434b621c237Sdrh if( Tcl_GetDouble(interp, argv[i], &r[i-2]) ) return TCL_ERROR; 1435b621c237Sdrh } 14366f8a503dSdanielk1977 z = sqlite3_mprintf(argv[1], r[0]*r[1]); 1437b621c237Sdrh Tcl_AppendResult(interp, z, 0); 14383f4fedb2Sdrh sqlite3_free(z); 1439b621c237Sdrh return TCL_OK; 1440b621c237Sdrh } 1441b621c237Sdrh 1442b621c237Sdrh /* 1443e29b1a05Sdrh ** Usage: sqlite3_mprintf_stronly FORMAT STRING 1444e29b1a05Sdrh ** 1445e29b1a05Sdrh ** Call mprintf with a single double argument which is the product of the 1446e29b1a05Sdrh ** two arguments given above. This is used to generate overflow and underflow 1447e29b1a05Sdrh ** doubles to test that they are converted properly. 1448e29b1a05Sdrh */ 14497617e4a8Smistachkin static int SQLITE_TCLAPI sqlite3_mprintf_stronly( 1450e29b1a05Sdrh void *NotUsed, 1451e29b1a05Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 1452e29b1a05Sdrh int argc, /* Number of arguments */ 1453e29b1a05Sdrh char **argv /* Text of each argument */ 1454e29b1a05Sdrh ){ 1455e29b1a05Sdrh char *z; 1456e29b1a05Sdrh if( argc!=3 ){ 1457e29b1a05Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 1458e29b1a05Sdrh " FORMAT STRING\"", 0); 1459e29b1a05Sdrh return TCL_ERROR; 1460e29b1a05Sdrh } 1461e29b1a05Sdrh z = sqlite3_mprintf(argv[1], argv[2]); 1462e29b1a05Sdrh Tcl_AppendResult(interp, z, 0); 1463e29b1a05Sdrh sqlite3_free(z); 1464e29b1a05Sdrh return TCL_OK; 1465e29b1a05Sdrh } 1466e29b1a05Sdrh 1467e29b1a05Sdrh /* 146863782855Sdrh ** Usage: sqlite3_mprintf_hexdouble FORMAT HEX 146963782855Sdrh ** 147063782855Sdrh ** Call mprintf with a single double argument which is derived from the 147163782855Sdrh ** hexadecimal encoding of an IEEE double. 147263782855Sdrh */ 14737617e4a8Smistachkin static int SQLITE_TCLAPI sqlite3_mprintf_hexdouble( 147463782855Sdrh void *NotUsed, 147563782855Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 147663782855Sdrh int argc, /* Number of arguments */ 147763782855Sdrh char **argv /* Text of each argument */ 147863782855Sdrh ){ 147963782855Sdrh char *z; 148063782855Sdrh double r; 14815e73db36Sshane unsigned int x1, x2; 14825e73db36Sshane sqlite_uint64 d; 148363782855Sdrh if( argc!=3 ){ 148463782855Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 148563782855Sdrh " FORMAT STRING\"", 0); 148663782855Sdrh return TCL_ERROR; 148763782855Sdrh } 148863782855Sdrh if( sscanf(argv[2], "%08x%08x", &x2, &x1)!=2 ){ 148963782855Sdrh Tcl_AppendResult(interp, "2nd argument should be 16-characters of hex", 0); 149063782855Sdrh return TCL_ERROR; 149163782855Sdrh } 149263782855Sdrh d = x2; 149363782855Sdrh d = (d<<32) + x1; 149463782855Sdrh memcpy(&r, &d, sizeof(r)); 149563782855Sdrh z = sqlite3_mprintf(argv[1], r); 149663782855Sdrh Tcl_AppendResult(interp, z, 0); 149763782855Sdrh sqlite3_free(z); 149863782855Sdrh return TCL_OK; 149963782855Sdrh } 150063782855Sdrh 150163782855Sdrh /* 1502c1def3e0Sdanielk1977 ** Usage: sqlite3_enable_shared_cache ?BOOLEAN? 1503aef0bf64Sdanielk1977 ** 1504aef0bf64Sdanielk1977 */ 15056f7adc8aSdrh #if !defined(SQLITE_OMIT_SHARED_CACHE) 15067617e4a8Smistachkin static int SQLITE_TCLAPI test_enable_shared( 150752622828Sdanielk1977 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ 1508aef0bf64Sdanielk1977 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 1509aef0bf64Sdanielk1977 int objc, /* Number of arguments */ 1510aef0bf64Sdanielk1977 Tcl_Obj *CONST objv[] /* Command arguments */ 1511aef0bf64Sdanielk1977 ){ 1512aef0bf64Sdanielk1977 int rc; 1513aef0bf64Sdanielk1977 int enable; 151452622828Sdanielk1977 int ret = 0; 1515aef0bf64Sdanielk1977 1516c1def3e0Sdanielk1977 if( objc!=2 && objc!=1 ){ 1517c1def3e0Sdanielk1977 Tcl_WrongNumArgs(interp, 1, objv, "?BOOLEAN?"); 1518aef0bf64Sdanielk1977 return TCL_ERROR; 1519aef0bf64Sdanielk1977 } 1520502b4e00Sdanielk1977 ret = sqlite3GlobalConfig.sharedCacheEnabled; 1521c1def3e0Sdanielk1977 1522c1def3e0Sdanielk1977 if( objc==2 ){ 1523c1def3e0Sdanielk1977 if( Tcl_GetBooleanFromObj(interp, objv[1], &enable) ){ 1524c1def3e0Sdanielk1977 return TCL_ERROR; 1525c1def3e0Sdanielk1977 } 15266f7adc8aSdrh rc = sqlite3_enable_shared_cache(enable); 1527aef0bf64Sdanielk1977 if( rc!=SQLITE_OK ){ 1528aef0bf64Sdanielk1977 Tcl_SetResult(interp, (char *)sqlite3ErrStr(rc), TCL_STATIC); 1529aef0bf64Sdanielk1977 return TCL_ERROR; 1530aef0bf64Sdanielk1977 } 1531c1def3e0Sdanielk1977 } 153252622828Sdanielk1977 Tcl_SetObjResult(interp, Tcl_NewBooleanObj(ret)); 1533aef0bf64Sdanielk1977 return TCL_OK; 1534aef0bf64Sdanielk1977 } 1535aef0bf64Sdanielk1977 #endif 1536aef0bf64Sdanielk1977 153716a9b836Sdrh 153816a9b836Sdrh 1539aef0bf64Sdanielk1977 /* 15404ac285a1Sdrh ** Usage: sqlite3_extended_result_codes DB BOOLEAN 15414ac285a1Sdrh ** 15424ac285a1Sdrh */ 15437617e4a8Smistachkin static int SQLITE_TCLAPI test_extended_result_codes( 15444ac285a1Sdrh ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ 15454ac285a1Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 15464ac285a1Sdrh int objc, /* Number of arguments */ 15474ac285a1Sdrh Tcl_Obj *CONST objv[] /* Command arguments */ 15484ac285a1Sdrh ){ 15494ac285a1Sdrh int enable; 15504ac285a1Sdrh sqlite3 *db; 15514ac285a1Sdrh 15524ac285a1Sdrh if( objc!=3 ){ 15534ac285a1Sdrh Tcl_WrongNumArgs(interp, 1, objv, "DB BOOLEAN"); 15544ac285a1Sdrh return TCL_ERROR; 15554ac285a1Sdrh } 15564ac285a1Sdrh if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 15574ac285a1Sdrh if( Tcl_GetBooleanFromObj(interp, objv[2], &enable) ) return TCL_ERROR; 15584ac285a1Sdrh sqlite3_extended_result_codes(db, enable); 15594ac285a1Sdrh return TCL_OK; 15604ac285a1Sdrh } 15614ac285a1Sdrh 15624ac285a1Sdrh /* 1563161fb796Sdanielk1977 ** Usage: sqlite3_libversion_number 1564161fb796Sdanielk1977 ** 1565161fb796Sdanielk1977 */ 15667617e4a8Smistachkin static int SQLITE_TCLAPI test_libversion_number( 1567161fb796Sdanielk1977 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ 1568161fb796Sdanielk1977 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 1569161fb796Sdanielk1977 int objc, /* Number of arguments */ 1570161fb796Sdanielk1977 Tcl_Obj *CONST objv[] /* Command arguments */ 1571161fb796Sdanielk1977 ){ 1572161fb796Sdanielk1977 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_libversion_number())); 1573161fb796Sdanielk1977 return TCL_OK; 1574161fb796Sdanielk1977 } 1575161fb796Sdanielk1977 1576161fb796Sdanielk1977 /* 1577deb802cdSdanielk1977 ** Usage: sqlite3_table_column_metadata DB dbname tblname colname 1578deb802cdSdanielk1977 ** 1579deb802cdSdanielk1977 */ 15807617e4a8Smistachkin static int SQLITE_TCLAPI test_table_column_metadata( 1581deb802cdSdanielk1977 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ 1582deb802cdSdanielk1977 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 1583deb802cdSdanielk1977 int objc, /* Number of arguments */ 1584deb802cdSdanielk1977 Tcl_Obj *CONST objv[] /* Command arguments */ 1585deb802cdSdanielk1977 ){ 1586deb802cdSdanielk1977 sqlite3 *db; 1587deb802cdSdanielk1977 const char *zDb; 1588deb802cdSdanielk1977 const char *zTbl; 1589deb802cdSdanielk1977 const char *zCol; 1590deb802cdSdanielk1977 int rc; 1591deb802cdSdanielk1977 Tcl_Obj *pRet; 1592deb802cdSdanielk1977 1593deb802cdSdanielk1977 const char *zDatatype; 1594deb802cdSdanielk1977 const char *zCollseq; 1595deb802cdSdanielk1977 int notnull; 1596deb802cdSdanielk1977 int primarykey; 1597deb802cdSdanielk1977 int autoincrement; 1598deb802cdSdanielk1977 159945d1b206Sdrh if( objc!=5 && objc!=4 ){ 1600deb802cdSdanielk1977 Tcl_WrongNumArgs(interp, 1, objv, "DB dbname tblname colname"); 1601deb802cdSdanielk1977 return TCL_ERROR; 1602deb802cdSdanielk1977 } 1603deb802cdSdanielk1977 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 1604deb802cdSdanielk1977 zDb = Tcl_GetString(objv[2]); 1605deb802cdSdanielk1977 zTbl = Tcl_GetString(objv[3]); 160645d1b206Sdrh zCol = objc==5 ? Tcl_GetString(objv[4]) : 0; 1607deb802cdSdanielk1977 1608deb802cdSdanielk1977 if( strlen(zDb)==0 ) zDb = 0; 1609deb802cdSdanielk1977 1610deb802cdSdanielk1977 rc = sqlite3_table_column_metadata(db, zDb, zTbl, zCol, 1611deb802cdSdanielk1977 &zDatatype, &zCollseq, ¬null, &primarykey, &autoincrement); 1612deb802cdSdanielk1977 1613deb802cdSdanielk1977 if( rc!=SQLITE_OK ){ 1614deb802cdSdanielk1977 Tcl_AppendResult(interp, sqlite3_errmsg(db), 0); 1615deb802cdSdanielk1977 return TCL_ERROR; 1616deb802cdSdanielk1977 } 1617deb802cdSdanielk1977 1618deb802cdSdanielk1977 pRet = Tcl_NewObj(); 1619deb802cdSdanielk1977 Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zDatatype, -1)); 1620deb802cdSdanielk1977 Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zCollseq, -1)); 1621deb802cdSdanielk1977 Tcl_ListObjAppendElement(0, pRet, Tcl_NewIntObj(notnull)); 1622deb802cdSdanielk1977 Tcl_ListObjAppendElement(0, pRet, Tcl_NewIntObj(primarykey)); 1623deb802cdSdanielk1977 Tcl_ListObjAppendElement(0, pRet, Tcl_NewIntObj(autoincrement)); 1624deb802cdSdanielk1977 Tcl_SetObjResult(interp, pRet); 1625deb802cdSdanielk1977 1626deb802cdSdanielk1977 return TCL_OK; 1627deb802cdSdanielk1977 } 1628deb802cdSdanielk1977 1629dcbb5d3fSdanielk1977 #ifndef SQLITE_OMIT_INCRBLOB 1630dcbb5d3fSdanielk1977 16317617e4a8Smistachkin static int SQLITE_TCLAPI blobHandleFromObj( 163261c7f59cSdan Tcl_Interp *interp, 163361c7f59cSdan Tcl_Obj *pObj, 163461c7f59cSdan sqlite3_blob **ppBlob 163561c7f59cSdan ){ 163661c7f59cSdan char *z; 163761c7f59cSdan int n; 163861c7f59cSdan 163961c7f59cSdan z = Tcl_GetStringFromObj(pObj, &n); 164061c7f59cSdan if( n==0 ){ 164161c7f59cSdan *ppBlob = 0; 164261c7f59cSdan }else{ 164361c7f59cSdan int notUsed; 164461c7f59cSdan Tcl_Channel channel; 164561c7f59cSdan ClientData instanceData; 164661c7f59cSdan 164761c7f59cSdan channel = Tcl_GetChannel(interp, z, ¬Used); 164861c7f59cSdan if( !channel ) return TCL_ERROR; 164961c7f59cSdan 165061c7f59cSdan Tcl_Flush(channel); 165161c7f59cSdan Tcl_Seek(channel, 0, SEEK_SET); 165261c7f59cSdan 165361c7f59cSdan instanceData = Tcl_GetChannelInstanceData(channel); 165461c7f59cSdan *ppBlob = *((sqlite3_blob **)instanceData); 165561c7f59cSdan } 165661c7f59cSdan 165761c7f59cSdan return TCL_OK; 165861c7f59cSdan } 165961c7f59cSdan 16607617e4a8Smistachkin static int SQLITE_TCLAPI test_blob_reopen( 16614e76cc36Sdan ClientData clientData, /* Not used */ 16624e76cc36Sdan Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 16634e76cc36Sdan int objc, /* Number of arguments */ 16644e76cc36Sdan Tcl_Obj *CONST objv[] /* Command arguments */ 16654e76cc36Sdan ){ 16664e76cc36Sdan Tcl_WideInt iRowid; 16674e76cc36Sdan sqlite3_blob *pBlob; 16684e76cc36Sdan int rc; 16694e76cc36Sdan 16704e76cc36Sdan if( objc!=3 ){ 16714e76cc36Sdan Tcl_WrongNumArgs(interp, 1, objv, "CHANNEL ROWID"); 16724e76cc36Sdan return TCL_ERROR; 16734e76cc36Sdan } 16744e76cc36Sdan 167561c7f59cSdan if( blobHandleFromObj(interp, objv[1], &pBlob) ) return TCL_ERROR; 167661c7f59cSdan if( Tcl_GetWideIntFromObj(interp, objv[2], &iRowid) ) return TCL_ERROR; 16774e76cc36Sdan 16784e76cc36Sdan rc = sqlite3_blob_reopen(pBlob, iRowid); 16794e76cc36Sdan if( rc!=SQLITE_OK ){ 1680e84d8d32Smistachkin Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE); 16814e76cc36Sdan } 16824e76cc36Sdan 16834e76cc36Sdan return (rc==SQLITE_OK ? TCL_OK : TCL_ERROR); 16844e76cc36Sdan } 16854e76cc36Sdan 1686dcbb5d3fSdanielk1977 #endif 1687c2e87a3eSdrh 1688deb802cdSdanielk1977 /* 1689a393c036Sdanielk1977 ** Usage: sqlite3_create_collation_v2 DB-HANDLE NAME CMP-PROC DEL-PROC 1690a9808b31Sdanielk1977 ** 1691a9808b31Sdanielk1977 ** This Tcl proc is used for testing the experimental 1692a393c036Sdanielk1977 ** sqlite3_create_collation_v2() interface. 1693a9808b31Sdanielk1977 */ 1694a9808b31Sdanielk1977 struct TestCollationX { 1695a9808b31Sdanielk1977 Tcl_Interp *interp; 1696a9808b31Sdanielk1977 Tcl_Obj *pCmp; 1697a9808b31Sdanielk1977 Tcl_Obj *pDel; 1698a9808b31Sdanielk1977 }; 1699a9808b31Sdanielk1977 typedef struct TestCollationX TestCollationX; 1700a9808b31Sdanielk1977 static void testCreateCollationDel(void *pCtx){ 1701a9808b31Sdanielk1977 TestCollationX *p = (TestCollationX *)pCtx; 1702a9808b31Sdanielk1977 1703a9808b31Sdanielk1977 int rc = Tcl_EvalObjEx(p->interp, p->pDel, TCL_EVAL_DIRECT|TCL_EVAL_GLOBAL); 1704a9808b31Sdanielk1977 if( rc!=TCL_OK ){ 1705a9808b31Sdanielk1977 Tcl_BackgroundError(p->interp); 1706a9808b31Sdanielk1977 } 1707a9808b31Sdanielk1977 1708a9808b31Sdanielk1977 Tcl_DecrRefCount(p->pCmp); 1709a9808b31Sdanielk1977 Tcl_DecrRefCount(p->pDel); 1710a9808b31Sdanielk1977 sqlite3_free((void *)p); 1711a9808b31Sdanielk1977 } 1712a9808b31Sdanielk1977 static int testCreateCollationCmp( 1713a9808b31Sdanielk1977 void *pCtx, 1714a9808b31Sdanielk1977 int nLeft, 1715a9808b31Sdanielk1977 const void *zLeft, 1716a9808b31Sdanielk1977 int nRight, 1717a9808b31Sdanielk1977 const void *zRight 1718a9808b31Sdanielk1977 ){ 1719a9808b31Sdanielk1977 TestCollationX *p = (TestCollationX *)pCtx; 1720a9808b31Sdanielk1977 Tcl_Obj *pScript = Tcl_DuplicateObj(p->pCmp); 1721a9808b31Sdanielk1977 int iRes = 0; 1722a9808b31Sdanielk1977 1723a9808b31Sdanielk1977 Tcl_IncrRefCount(pScript); 1724a9808b31Sdanielk1977 Tcl_ListObjAppendElement(0, pScript, Tcl_NewStringObj((char *)zLeft, nLeft)); 1725a9808b31Sdanielk1977 Tcl_ListObjAppendElement(0, pScript, Tcl_NewStringObj((char *)zRight,nRight)); 1726a9808b31Sdanielk1977 1727a9808b31Sdanielk1977 if( TCL_OK!=Tcl_EvalObjEx(p->interp, pScript, TCL_EVAL_DIRECT|TCL_EVAL_GLOBAL) 1728a9808b31Sdanielk1977 || TCL_OK!=Tcl_GetIntFromObj(p->interp, Tcl_GetObjResult(p->interp), &iRes) 1729a9808b31Sdanielk1977 ){ 1730a9808b31Sdanielk1977 Tcl_BackgroundError(p->interp); 1731a9808b31Sdanielk1977 } 1732a9808b31Sdanielk1977 Tcl_DecrRefCount(pScript); 1733a9808b31Sdanielk1977 1734a9808b31Sdanielk1977 return iRes; 1735a9808b31Sdanielk1977 } 17367617e4a8Smistachkin static int SQLITE_TCLAPI test_create_collation_v2( 1737a9808b31Sdanielk1977 ClientData clientData, /* Not used */ 1738a9808b31Sdanielk1977 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 1739a9808b31Sdanielk1977 int objc, /* Number of arguments */ 1740a9808b31Sdanielk1977 Tcl_Obj *CONST objv[] /* Command arguments */ 1741a9808b31Sdanielk1977 ){ 1742a9808b31Sdanielk1977 TestCollationX *p; 1743a9808b31Sdanielk1977 sqlite3 *db; 1744d55d57edSdrh int rc; 1745a9808b31Sdanielk1977 1746a9808b31Sdanielk1977 if( objc!=5 ){ 1747a9808b31Sdanielk1977 Tcl_WrongNumArgs(interp, 1, objv, "DB-HANDLE NAME CMP-PROC DEL-PROC"); 1748a9808b31Sdanielk1977 return TCL_ERROR; 1749a9808b31Sdanielk1977 } 1750a9808b31Sdanielk1977 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 1751a9808b31Sdanielk1977 1752a9808b31Sdanielk1977 p = (TestCollationX *)sqlite3_malloc(sizeof(TestCollationX)); 1753a9808b31Sdanielk1977 p->pCmp = objv[3]; 1754a9808b31Sdanielk1977 p->pDel = objv[4]; 1755a9808b31Sdanielk1977 p->interp = interp; 1756a9808b31Sdanielk1977 Tcl_IncrRefCount(p->pCmp); 1757a9808b31Sdanielk1977 Tcl_IncrRefCount(p->pDel); 1758a9808b31Sdanielk1977 1759d55d57edSdrh rc = sqlite3_create_collation_v2(db, Tcl_GetString(objv[2]), 16, 1760d55d57edSdrh (void *)p, testCreateCollationCmp, testCreateCollationDel 1761d55d57edSdrh ); 1762d55d57edSdrh if( rc!=SQLITE_MISUSE ){ 1763d55d57edSdrh Tcl_AppendResult(interp, "sqlite3_create_collate_v2() failed to detect " 1764d55d57edSdrh "an invalid encoding", (char*)0); 1765d55d57edSdrh return TCL_ERROR; 1766d55d57edSdrh } 1767d55d57edSdrh rc = sqlite3_create_collation_v2(db, Tcl_GetString(objv[2]), SQLITE_UTF8, 1768a9808b31Sdanielk1977 (void *)p, testCreateCollationCmp, testCreateCollationDel 1769a9808b31Sdanielk1977 ); 1770a9808b31Sdanielk1977 return TCL_OK; 1771a9808b31Sdanielk1977 } 1772a9808b31Sdanielk1977 1773a9808b31Sdanielk1977 /* 1774d2199f0fSdan ** USAGE: sqlite3_create_function_v2 DB NAME NARG ENC ?SWITCHES? 1775d2199f0fSdan ** 1776d2199f0fSdan ** Available switches are: 1777d2199f0fSdan ** 1778d2199f0fSdan ** -func SCRIPT 1779d2199f0fSdan ** -step SCRIPT 1780d2199f0fSdan ** -final SCRIPT 1781d2199f0fSdan ** -destroy SCRIPT 1782d2199f0fSdan */ 1783d2199f0fSdan typedef struct CreateFunctionV2 CreateFunctionV2; 1784d2199f0fSdan struct CreateFunctionV2 { 1785d2199f0fSdan Tcl_Interp *interp; 1786d2199f0fSdan Tcl_Obj *pFunc; /* Script for function invocation */ 1787d2199f0fSdan Tcl_Obj *pStep; /* Script for agg. step invocation */ 1788d2199f0fSdan Tcl_Obj *pFinal; /* Script for agg. finalization invocation */ 1789d2199f0fSdan Tcl_Obj *pDestroy; /* Destructor script */ 1790d2199f0fSdan }; 1791d2199f0fSdan static void cf2Func(sqlite3_context *ctx, int nArg, sqlite3_value **aArg){ 1792d2199f0fSdan } 1793d2199f0fSdan static void cf2Step(sqlite3_context *ctx, int nArg, sqlite3_value **aArg){ 1794d2199f0fSdan } 1795d2199f0fSdan static void cf2Final(sqlite3_context *ctx){ 1796d2199f0fSdan } 1797d2199f0fSdan static void cf2Destroy(void *pUser){ 1798d2199f0fSdan CreateFunctionV2 *p = (CreateFunctionV2 *)pUser; 1799d2199f0fSdan 1800d2199f0fSdan if( p->interp && p->pDestroy ){ 1801d2199f0fSdan int rc = Tcl_EvalObjEx(p->interp, p->pDestroy, 0); 1802d2199f0fSdan if( rc!=TCL_OK ) Tcl_BackgroundError(p->interp); 1803d2199f0fSdan } 1804d2199f0fSdan 1805d2199f0fSdan if( p->pFunc ) Tcl_DecrRefCount(p->pFunc); 1806d2199f0fSdan if( p->pStep ) Tcl_DecrRefCount(p->pStep); 1807d2199f0fSdan if( p->pFinal ) Tcl_DecrRefCount(p->pFinal); 1808d2199f0fSdan if( p->pDestroy ) Tcl_DecrRefCount(p->pDestroy); 1809d2199f0fSdan sqlite3_free(p); 1810d2199f0fSdan } 18117617e4a8Smistachkin static int SQLITE_TCLAPI test_create_function_v2( 1812d2199f0fSdan ClientData clientData, /* Not used */ 1813d2199f0fSdan Tcl_Interp *interp, /* The invoking TCL interpreter */ 1814d2199f0fSdan int objc, /* Number of arguments */ 1815d2199f0fSdan Tcl_Obj *CONST objv[] /* Command arguments */ 1816d2199f0fSdan ){ 1817d2199f0fSdan sqlite3 *db; 1818d2199f0fSdan const char *zFunc; 1819d2199f0fSdan int nArg; 1820d2199f0fSdan int enc; 1821d2199f0fSdan CreateFunctionV2 *p; 1822d2199f0fSdan int i; 1823d2199f0fSdan int rc; 1824d2199f0fSdan 1825d2199f0fSdan struct EncTable { 1826d2199f0fSdan const char *zEnc; 1827d2199f0fSdan int enc; 1828d2199f0fSdan } aEnc[] = { 1829d2199f0fSdan {"utf8", SQLITE_UTF8 }, 1830d2199f0fSdan {"utf16", SQLITE_UTF16 }, 1831d2199f0fSdan {"utf16le", SQLITE_UTF16LE }, 1832d2199f0fSdan {"utf16be", SQLITE_UTF16BE }, 1833d2199f0fSdan {"any", SQLITE_ANY }, 1834d2199f0fSdan {"0", 0 } 1835d2199f0fSdan }; 1836d2199f0fSdan 1837d2199f0fSdan if( objc<5 || (objc%2)==0 ){ 1838d2199f0fSdan Tcl_WrongNumArgs(interp, 1, objv, "DB NAME NARG ENC SWITCHES..."); 1839d2199f0fSdan return TCL_ERROR; 1840d2199f0fSdan } 1841d2199f0fSdan 1842d2199f0fSdan if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 1843d2199f0fSdan zFunc = Tcl_GetString(objv[2]); 1844d2199f0fSdan if( Tcl_GetIntFromObj(interp, objv[3], &nArg) ) return TCL_ERROR; 1845d2199f0fSdan if( Tcl_GetIndexFromObjStruct(interp, objv[4], aEnc, sizeof(aEnc[0]), 1846d2199f0fSdan "encoding", 0, &enc) 1847d2199f0fSdan ){ 1848d2199f0fSdan return TCL_ERROR; 1849d2199f0fSdan } 1850d2199f0fSdan enc = aEnc[enc].enc; 1851d2199f0fSdan 1852d2199f0fSdan p = sqlite3_malloc(sizeof(CreateFunctionV2)); 1853d2199f0fSdan assert( p ); 1854d2199f0fSdan memset(p, 0, sizeof(CreateFunctionV2)); 1855d2199f0fSdan p->interp = interp; 1856d2199f0fSdan 1857d2199f0fSdan for(i=5; i<objc; i+=2){ 1858d2199f0fSdan int iSwitch; 1859d2199f0fSdan const char *azSwitch[] = {"-func", "-step", "-final", "-destroy", 0}; 1860d2199f0fSdan if( Tcl_GetIndexFromObj(interp, objv[i], azSwitch, "switch", 0, &iSwitch) ){ 1861d2199f0fSdan sqlite3_free(p); 1862d2199f0fSdan return TCL_ERROR; 1863d2199f0fSdan } 1864d2199f0fSdan 1865d2199f0fSdan switch( iSwitch ){ 1866d2199f0fSdan case 0: p->pFunc = objv[i+1]; break; 1867d2199f0fSdan case 1: p->pStep = objv[i+1]; break; 1868d2199f0fSdan case 2: p->pFinal = objv[i+1]; break; 1869d2199f0fSdan case 3: p->pDestroy = objv[i+1]; break; 1870d2199f0fSdan } 1871d2199f0fSdan } 1872d2199f0fSdan if( p->pFunc ) p->pFunc = Tcl_DuplicateObj(p->pFunc); 1873d2199f0fSdan if( p->pStep ) p->pStep = Tcl_DuplicateObj(p->pStep); 1874d2199f0fSdan if( p->pFinal ) p->pFinal = Tcl_DuplicateObj(p->pFinal); 1875d2199f0fSdan if( p->pDestroy ) p->pDestroy = Tcl_DuplicateObj(p->pDestroy); 1876d2199f0fSdan 1877d2199f0fSdan if( p->pFunc ) Tcl_IncrRefCount(p->pFunc); 1878d2199f0fSdan if( p->pStep ) Tcl_IncrRefCount(p->pStep); 1879d2199f0fSdan if( p->pFinal ) Tcl_IncrRefCount(p->pFinal); 1880d2199f0fSdan if( p->pDestroy ) Tcl_IncrRefCount(p->pDestroy); 1881d2199f0fSdan 1882d2199f0fSdan rc = sqlite3_create_function_v2(db, zFunc, nArg, enc, (void *)p, 1883d2199f0fSdan (p->pFunc ? cf2Func : 0), 1884d2199f0fSdan (p->pStep ? cf2Step : 0), 1885d2199f0fSdan (p->pFinal ? cf2Final : 0), 1886d2199f0fSdan cf2Destroy 1887d2199f0fSdan ); 1888d2199f0fSdan if( rc!=SQLITE_OK ){ 1889d2199f0fSdan Tcl_ResetResult(interp); 1890e84d8d32Smistachkin Tcl_AppendResult(interp, sqlite3ErrName(rc), 0); 1891d2199f0fSdan return TCL_ERROR; 1892d2199f0fSdan } 1893d2199f0fSdan return TCL_OK; 1894d2199f0fSdan } 1895d2199f0fSdan 1896d2199f0fSdan /* 189769e777f3Sdanielk1977 ** Usage: sqlite3_load_extension DB-HANDLE FILE ?PROC? 189869e777f3Sdanielk1977 */ 18997617e4a8Smistachkin static int SQLITE_TCLAPI test_load_extension( 190069e777f3Sdanielk1977 ClientData clientData, /* Not used */ 190169e777f3Sdanielk1977 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 190269e777f3Sdanielk1977 int objc, /* Number of arguments */ 190369e777f3Sdanielk1977 Tcl_Obj *CONST objv[] /* Command arguments */ 190469e777f3Sdanielk1977 ){ 190569e777f3Sdanielk1977 Tcl_CmdInfo cmdInfo; 190669e777f3Sdanielk1977 sqlite3 *db; 190769e777f3Sdanielk1977 int rc; 190869e777f3Sdanielk1977 char *zDb; 190969e777f3Sdanielk1977 char *zFile; 191069e777f3Sdanielk1977 char *zProc = 0; 191169e777f3Sdanielk1977 char *zErr = 0; 191269e777f3Sdanielk1977 191369e777f3Sdanielk1977 if( objc!=4 && objc!=3 ){ 191469e777f3Sdanielk1977 Tcl_WrongNumArgs(interp, 1, objv, "DB-HANDLE FILE ?PROC?"); 191569e777f3Sdanielk1977 return TCL_ERROR; 191669e777f3Sdanielk1977 } 191769e777f3Sdanielk1977 zDb = Tcl_GetString(objv[1]); 191869e777f3Sdanielk1977 zFile = Tcl_GetString(objv[2]); 191969e777f3Sdanielk1977 if( objc==4 ){ 192069e777f3Sdanielk1977 zProc = Tcl_GetString(objv[3]); 192169e777f3Sdanielk1977 } 192269e777f3Sdanielk1977 192369e777f3Sdanielk1977 /* Extract the C database handle from the Tcl command name */ 192469e777f3Sdanielk1977 if( !Tcl_GetCommandInfo(interp, zDb, &cmdInfo) ){ 192569e777f3Sdanielk1977 Tcl_AppendResult(interp, "command not found: ", zDb, (char*)0); 192669e777f3Sdanielk1977 return TCL_ERROR; 192769e777f3Sdanielk1977 } 192869e777f3Sdanielk1977 db = ((struct SqliteDb*)cmdInfo.objClientData)->db; 192969e777f3Sdanielk1977 assert(db); 193069e777f3Sdanielk1977 193169e777f3Sdanielk1977 /* Call the underlying C function. If an error occurs, set rc to 193269e777f3Sdanielk1977 ** TCL_ERROR and load any error string into the interpreter. If no 193369e777f3Sdanielk1977 ** error occurs, set rc to TCL_OK. 193469e777f3Sdanielk1977 */ 1935c2e87a3eSdrh #ifdef SQLITE_OMIT_LOAD_EXTENSION 1936c2e87a3eSdrh rc = SQLITE_ERROR; 1937c2e87a3eSdrh zErr = sqlite3_mprintf("this build omits sqlite3_load_extension()"); 19389493cafeSdrh (void)zProc; 19399493cafeSdrh (void)zFile; 1940c2e87a3eSdrh #else 194169e777f3Sdanielk1977 rc = sqlite3_load_extension(db, zFile, zProc, &zErr); 1942c2e87a3eSdrh #endif 194369e777f3Sdanielk1977 if( rc!=SQLITE_OK ){ 194469e777f3Sdanielk1977 Tcl_SetResult(interp, zErr ? zErr : "", TCL_VOLATILE); 194569e777f3Sdanielk1977 rc = TCL_ERROR; 194669e777f3Sdanielk1977 }else{ 194769e777f3Sdanielk1977 rc = TCL_OK; 194869e777f3Sdanielk1977 } 194969e777f3Sdanielk1977 sqlite3_free(zErr); 195069e777f3Sdanielk1977 195169e777f3Sdanielk1977 return rc; 195269e777f3Sdanielk1977 } 195369e777f3Sdanielk1977 195469e777f3Sdanielk1977 /* 1955c2e87a3eSdrh ** Usage: sqlite3_enable_load_extension DB-HANDLE ONOFF 1956c2e87a3eSdrh */ 19577617e4a8Smistachkin static int SQLITE_TCLAPI test_enable_load( 1958c2e87a3eSdrh ClientData clientData, /* Not used */ 1959c2e87a3eSdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 1960c2e87a3eSdrh int objc, /* Number of arguments */ 1961c2e87a3eSdrh Tcl_Obj *CONST objv[] /* Command arguments */ 1962c2e87a3eSdrh ){ 1963c2e87a3eSdrh Tcl_CmdInfo cmdInfo; 1964c2e87a3eSdrh sqlite3 *db; 1965c2e87a3eSdrh char *zDb; 1966c2e87a3eSdrh int onoff; 1967c2e87a3eSdrh 1968c2e87a3eSdrh if( objc!=3 ){ 1969c2e87a3eSdrh Tcl_WrongNumArgs(interp, 1, objv, "DB-HANDLE ONOFF"); 1970c2e87a3eSdrh return TCL_ERROR; 1971c2e87a3eSdrh } 1972c2e87a3eSdrh zDb = Tcl_GetString(objv[1]); 1973c2e87a3eSdrh 1974c2e87a3eSdrh /* Extract the C database handle from the Tcl command name */ 1975c2e87a3eSdrh if( !Tcl_GetCommandInfo(interp, zDb, &cmdInfo) ){ 1976c2e87a3eSdrh Tcl_AppendResult(interp, "command not found: ", zDb, (char*)0); 1977c2e87a3eSdrh return TCL_ERROR; 1978c2e87a3eSdrh } 1979c2e87a3eSdrh db = ((struct SqliteDb*)cmdInfo.objClientData)->db; 1980c2e87a3eSdrh assert(db); 1981c2e87a3eSdrh 1982c2e87a3eSdrh /* Get the onoff parameter */ 1983c2e87a3eSdrh if( Tcl_GetBooleanFromObj(interp, objv[2], &onoff) ){ 1984c2e87a3eSdrh return TCL_ERROR; 1985c2e87a3eSdrh } 1986c2e87a3eSdrh 1987c2e87a3eSdrh #ifdef SQLITE_OMIT_LOAD_EXTENSION 1988c2e87a3eSdrh Tcl_AppendResult(interp, "this build omits sqlite3_load_extension()"); 1989c2e87a3eSdrh return TCL_ERROR; 1990c2e87a3eSdrh #else 1991c2e87a3eSdrh sqlite3_enable_load_extension(db, onoff); 1992c2e87a3eSdrh return TCL_OK; 1993c2e87a3eSdrh #endif 1994c2e87a3eSdrh } 1995c2e87a3eSdrh 1996c2e87a3eSdrh /* 199728b4e489Sdrh ** Usage: sqlite_abort 199828b4e489Sdrh ** 199928b4e489Sdrh ** Shutdown the process immediately. This is not a clean shutdown. 200028b4e489Sdrh ** This command is used to test the recoverability of a database in 200128b4e489Sdrh ** the event of a program crash. 200228b4e489Sdrh */ 20037617e4a8Smistachkin static int SQLITE_TCLAPI sqlite_abort( 200428b4e489Sdrh void *NotUsed, 200528b4e489Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 200628b4e489Sdrh int argc, /* Number of arguments */ 200728b4e489Sdrh char **argv /* Text of each argument */ 200828b4e489Sdrh ){ 20092ceced15Sshaneh #if defined(_MSC_VER) 20102ceced15Sshaneh /* We do this, otherwise the test will halt with a popup message 20112ceced15Sshaneh * that we have to click away before the test will continue. 20122ceced15Sshaneh */ 20132ceced15Sshaneh _set_abort_behavior( 0, _CALL_REPORTFAULT ); 20142ceced15Sshaneh #endif 2015d3f6b81aSdan exit(255); 201628b4e489Sdrh assert( interp==0 ); /* This will always fail */ 201728b4e489Sdrh return TCL_OK; 201828b4e489Sdrh } 201928b4e489Sdrh 202028b4e489Sdrh /* 20216cbe1f1bSdrh ** The following routine is a user-defined SQL function whose purpose 20226cbe1f1bSdrh ** is to test the sqlite_set_result() API. 20236cbe1f1bSdrh */ 20240ae8b831Sdanielk1977 static void testFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ 20256cbe1f1bSdrh while( argc>=2 ){ 202603d847eaSdrh const char *zArg0 = (char*)sqlite3_value_text(argv[0]); 20276d88bad4Sdanielk1977 if( zArg0 ){ 20286d88bad4Sdanielk1977 if( 0==sqlite3StrICmp(zArg0, "int") ){ 20296d88bad4Sdanielk1977 sqlite3_result_int(context, sqlite3_value_int(argv[1])); 20306d88bad4Sdanielk1977 }else if( sqlite3StrICmp(zArg0,"int64")==0 ){ 20316d88bad4Sdanielk1977 sqlite3_result_int64(context, sqlite3_value_int64(argv[1])); 203251ad0ecdSdanielk1977 }else if( sqlite3StrICmp(zArg0,"string")==0 ){ 203303d847eaSdrh sqlite3_result_text(context, (char*)sqlite3_value_text(argv[1]), -1, 2034d8123366Sdanielk1977 SQLITE_TRANSIENT); 203551ad0ecdSdanielk1977 }else if( sqlite3StrICmp(zArg0,"double")==0 ){ 20366d88bad4Sdanielk1977 sqlite3_result_double(context, sqlite3_value_double(argv[1])); 20376d88bad4Sdanielk1977 }else if( sqlite3StrICmp(zArg0,"null")==0 ){ 20386d88bad4Sdanielk1977 sqlite3_result_null(context); 20396d88bad4Sdanielk1977 }else if( sqlite3StrICmp(zArg0,"value")==0 ){ 20406d88bad4Sdanielk1977 sqlite3_result_value(context, argv[sqlite3_value_int(argv[1])]); 20416cbe1f1bSdrh }else{ 20426d88bad4Sdanielk1977 goto error_out; 20436d88bad4Sdanielk1977 } 20446d88bad4Sdanielk1977 }else{ 20456d88bad4Sdanielk1977 goto error_out; 20466cbe1f1bSdrh } 20476cbe1f1bSdrh argc -= 2; 20486cbe1f1bSdrh argv += 2; 20496cbe1f1bSdrh } 20506d88bad4Sdanielk1977 return; 20516d88bad4Sdanielk1977 20526d88bad4Sdanielk1977 error_out: 20536d88bad4Sdanielk1977 sqlite3_result_error(context,"first argument should be one of: " 20546d88bad4Sdanielk1977 "int int64 string double null value", -1); 20556cbe1f1bSdrh } 20566cbe1f1bSdrh 20576cbe1f1bSdrh /* 20586cbe1f1bSdrh ** Usage: sqlite_register_test_function DB NAME 20596cbe1f1bSdrh ** 20606cbe1f1bSdrh ** Register the test SQL function on the database DB under the name NAME. 20616cbe1f1bSdrh */ 20627617e4a8Smistachkin static int SQLITE_TCLAPI test_register_func( 20636cbe1f1bSdrh void *NotUsed, 20646cbe1f1bSdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 20656cbe1f1bSdrh int argc, /* Number of arguments */ 20666cbe1f1bSdrh char **argv /* Text of each argument */ 20676cbe1f1bSdrh ){ 20689bb575fdSdrh sqlite3 *db; 20696cbe1f1bSdrh int rc; 20706cbe1f1bSdrh if( argc!=3 ){ 20716cbe1f1bSdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 20726cbe1f1bSdrh " DB FUNCTION-NAME", 0); 20736cbe1f1bSdrh return TCL_ERROR; 20746cbe1f1bSdrh } 2075b86ccfb2Sdrh if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; 2076f9d64d2cSdanielk1977 rc = sqlite3_create_function(db, argv[2], -1, SQLITE_UTF8, 0, 2077d8123366Sdanielk1977 testFunc, 0, 0); 20786cbe1f1bSdrh if( rc!=0 ){ 2079f20b21c8Sdanielk1977 Tcl_AppendResult(interp, sqlite3ErrStr(rc), 0); 20806cbe1f1bSdrh return TCL_ERROR; 20816cbe1f1bSdrh } 2082c60d0446Sdrh if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; 20836cbe1f1bSdrh return TCL_OK; 20846cbe1f1bSdrh } 20856cbe1f1bSdrh 20866cbe1f1bSdrh /* 2087106bb236Sdanielk1977 ** Usage: sqlite3_finalize STMT 2088b86ccfb2Sdrh ** 2089106bb236Sdanielk1977 ** Finalize a statement handle. 2090b86ccfb2Sdrh */ 20917617e4a8Smistachkin static int SQLITE_TCLAPI test_finalize( 2092106bb236Sdanielk1977 void * clientData, 2093106bb236Sdanielk1977 Tcl_Interp *interp, 2094106bb236Sdanielk1977 int objc, 2095106bb236Sdanielk1977 Tcl_Obj *CONST objv[] 2096b86ccfb2Sdrh ){ 2097106bb236Sdanielk1977 sqlite3_stmt *pStmt; 2098b86ccfb2Sdrh int rc; 2099dddb2f23Sdrh sqlite3 *db = 0; 2100106bb236Sdanielk1977 2101106bb236Sdanielk1977 if( objc!=2 ){ 2102106bb236Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 2103106bb236Sdanielk1977 Tcl_GetStringFromObj(objv[0], 0), " <STMT>", 0); 2104b86ccfb2Sdrh return TCL_ERROR; 2105b86ccfb2Sdrh } 2106106bb236Sdanielk1977 2107106bb236Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 2108106bb236Sdanielk1977 21094397de57Sdanielk1977 if( pStmt ){ 2110c60d0446Sdrh db = StmtToDb(pStmt); 21114397de57Sdanielk1977 } 2112fc57d7bfSdanielk1977 rc = sqlite3_finalize(pStmt); 21134f0c5878Sdrh Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC); 21144397de57Sdanielk1977 if( db && sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; 2115106bb236Sdanielk1977 return TCL_OK; 2116106bb236Sdanielk1977 } 2117106bb236Sdanielk1977 2118106bb236Sdanielk1977 /* 2119d1d38488Sdrh ** Usage: sqlite3_stmt_status STMT CODE RESETFLAG 2120d1d38488Sdrh ** 2121d1d38488Sdrh ** Get the value of a status counter from a statement. 2122d1d38488Sdrh */ 21237617e4a8Smistachkin static int SQLITE_TCLAPI test_stmt_status( 2124d1d38488Sdrh void * clientData, 2125d1d38488Sdrh Tcl_Interp *interp, 2126d1d38488Sdrh int objc, 2127d1d38488Sdrh Tcl_Obj *CONST objv[] 2128d1d38488Sdrh ){ 2129d1d38488Sdrh int iValue; 213027b2f053Smistachkin int i, op = 0, resetFlag; 2131d1d38488Sdrh const char *zOpName; 2132d1d38488Sdrh sqlite3_stmt *pStmt; 2133d1d38488Sdrh 2134d1d38488Sdrh static const struct { 2135d1d38488Sdrh const char *zName; 2136d1d38488Sdrh int op; 2137d1d38488Sdrh } aOp[] = { 2138d1d38488Sdrh { "SQLITE_STMTSTATUS_FULLSCAN_STEP", SQLITE_STMTSTATUS_FULLSCAN_STEP }, 2139d1d38488Sdrh { "SQLITE_STMTSTATUS_SORT", SQLITE_STMTSTATUS_SORT }, 2140a21a64ddSdrh { "SQLITE_STMTSTATUS_AUTOINDEX", SQLITE_STMTSTATUS_AUTOINDEX }, 2141bf159fa2Sdrh { "SQLITE_STMTSTATUS_VM_STEP", SQLITE_STMTSTATUS_VM_STEP }, 214200d11d40Sdrh { "SQLITE_STMTSTATUS_REPREPARE", SQLITE_STMTSTATUS_REPREPARE }, 214300d11d40Sdrh { "SQLITE_STMTSTATUS_RUN", SQLITE_STMTSTATUS_RUN }, 214400d11d40Sdrh { "SQLITE_STMTSTATUS_MEMUSED", SQLITE_STMTSTATUS_MEMUSED }, 2145d1d38488Sdrh }; 2146d1d38488Sdrh if( objc!=4 ){ 2147d1d38488Sdrh Tcl_WrongNumArgs(interp, 1, objv, "STMT PARAMETER RESETFLAG"); 2148d1d38488Sdrh return TCL_ERROR; 2149d1d38488Sdrh } 2150d1d38488Sdrh if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 2151d1d38488Sdrh zOpName = Tcl_GetString(objv[2]); 2152d1d38488Sdrh for(i=0; i<ArraySize(aOp); i++){ 2153d1d38488Sdrh if( strcmp(aOp[i].zName, zOpName)==0 ){ 2154d1d38488Sdrh op = aOp[i].op; 2155d1d38488Sdrh break; 2156d1d38488Sdrh } 2157d1d38488Sdrh } 2158d1d38488Sdrh if( i>=ArraySize(aOp) ){ 2159d1d38488Sdrh if( Tcl_GetIntFromObj(interp, objv[2], &op) ) return TCL_ERROR; 2160d1d38488Sdrh } 2161d1d38488Sdrh if( Tcl_GetBooleanFromObj(interp, objv[3], &resetFlag) ) return TCL_ERROR; 2162d1d38488Sdrh iValue = sqlite3_stmt_status(pStmt, op, resetFlag); 2163d1d38488Sdrh Tcl_SetObjResult(interp, Tcl_NewIntObj(iValue)); 2164d1d38488Sdrh return TCL_OK; 2165d1d38488Sdrh } 2166d1d38488Sdrh 216704489b6dSdan #ifdef SQLITE_ENABLE_STMT_SCANSTATUS 216804489b6dSdan /* 216904489b6dSdan ** Usage: sqlite3_stmt_scanstatus STMT IDX 217004489b6dSdan */ 21717617e4a8Smistachkin static int SQLITE_TCLAPI test_stmt_scanstatus( 217204489b6dSdan void * clientData, 217304489b6dSdan Tcl_Interp *interp, 217404489b6dSdan int objc, 217504489b6dSdan Tcl_Obj *CONST objv[] 217604489b6dSdan ){ 217704489b6dSdan sqlite3_stmt *pStmt; /* First argument */ 217804489b6dSdan int idx; /* Second argument */ 217904489b6dSdan 218004489b6dSdan const char *zName; 218104489b6dSdan const char *zExplain; 218204489b6dSdan sqlite3_int64 nLoop; 218304489b6dSdan sqlite3_int64 nVisit; 2184518140edSdrh double rEst; 218504489b6dSdan int res; 218604489b6dSdan 218704489b6dSdan if( objc!=3 ){ 218804489b6dSdan Tcl_WrongNumArgs(interp, 1, objv, "STMT IDX"); 218904489b6dSdan return TCL_ERROR; 219004489b6dSdan } 219104489b6dSdan if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 219204489b6dSdan if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; 219304489b6dSdan 2194d1a1c234Sdrh res = sqlite3_stmt_scanstatus(pStmt, idx, SQLITE_SCANSTAT_NLOOP, (void*)&nLoop); 219504489b6dSdan if( res==0 ){ 219604489b6dSdan Tcl_Obj *pRet = Tcl_NewObj(); 219704489b6dSdan Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("nLoop", -1)); 219804489b6dSdan Tcl_ListObjAppendElement(0, pRet, Tcl_NewWideIntObj(nLoop)); 2199d1a1c234Sdrh sqlite3_stmt_scanstatus(pStmt, idx, SQLITE_SCANSTAT_NVISIT, (void*)&nVisit); 220004489b6dSdan Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("nVisit", -1)); 220104489b6dSdan Tcl_ListObjAppendElement(0, pRet, Tcl_NewWideIntObj(nVisit)); 2202518140edSdrh sqlite3_stmt_scanstatus(pStmt, idx, SQLITE_SCANSTAT_EST, (void*)&rEst); 220304489b6dSdan Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("nEst", -1)); 2204518140edSdrh Tcl_ListObjAppendElement(0, pRet, Tcl_NewDoubleObj(rEst)); 2205d1a1c234Sdrh sqlite3_stmt_scanstatus(pStmt, idx, SQLITE_SCANSTAT_NAME, (void*)&zName); 220604489b6dSdan Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("zName", -1)); 220704489b6dSdan Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zName, -1)); 2208d1a1c234Sdrh sqlite3_stmt_scanstatus(pStmt, idx, SQLITE_SCANSTAT_EXPLAIN, (void*)&zExplain); 220904489b6dSdan Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("zExplain", -1)); 221004489b6dSdan Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zExplain, -1)); 221104489b6dSdan Tcl_SetObjResult(interp, pRet); 221204489b6dSdan }else{ 221304489b6dSdan Tcl_ResetResult(interp); 221404489b6dSdan } 221504489b6dSdan return TCL_OK; 221604489b6dSdan } 221704489b6dSdan 221804489b6dSdan /* 221904489b6dSdan ** Usage: sqlite3_stmt_scanstatus_reset STMT 222004489b6dSdan */ 22217617e4a8Smistachkin static int SQLITE_TCLAPI test_stmt_scanstatus_reset( 222204489b6dSdan void * clientData, 222304489b6dSdan Tcl_Interp *interp, 222404489b6dSdan int objc, 222504489b6dSdan Tcl_Obj *CONST objv[] 222604489b6dSdan ){ 222704489b6dSdan sqlite3_stmt *pStmt; /* First argument */ 222804489b6dSdan if( objc!=2 ){ 222904489b6dSdan Tcl_WrongNumArgs(interp, 1, objv, "STMT"); 223004489b6dSdan return TCL_ERROR; 223104489b6dSdan } 223204489b6dSdan if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 223304489b6dSdan sqlite3_stmt_scanstatus_reset(pStmt); 223404489b6dSdan return TCL_OK; 223504489b6dSdan } 223604489b6dSdan #endif 223704489b6dSdan 2238d83f7ca1Sdan #ifdef SQLITE_ENABLE_SQLLOG 2239d83f7ca1Sdan /* 2240d83f7ca1Sdan ** Usage: sqlite3_config_sqllog 2241d83f7ca1Sdan ** 2242d83f7ca1Sdan ** Zero the SQLITE_CONFIG_SQLLOG configuration 2243d83f7ca1Sdan */ 22447617e4a8Smistachkin static int SQLITE_TCLAPI test_config_sqllog( 2245d83f7ca1Sdan void * clientData, 2246d83f7ca1Sdan Tcl_Interp *interp, 2247d83f7ca1Sdan int objc, 2248d83f7ca1Sdan Tcl_Obj *CONST objv[] 2249d83f7ca1Sdan ){ 2250d83f7ca1Sdan if( objc!=1 ){ 2251d83f7ca1Sdan Tcl_WrongNumArgs(interp, 1, objv, ""); 2252d83f7ca1Sdan return TCL_ERROR; 2253d83f7ca1Sdan } 2254d83f7ca1Sdan sqlite3_config(SQLITE_CONFIG_SQLLOG, 0, 0); 2255d83f7ca1Sdan return TCL_OK; 2256d83f7ca1Sdan } 2257d83f7ca1Sdan #endif 2258d83f7ca1Sdan 2259d1d38488Sdrh /* 22602e3a5a81Sdan ** Usage: sqlite3_config_sorterref 22612e3a5a81Sdan ** 22622e3a5a81Sdan ** Set the SQLITE_CONFIG_SORTERREF_SIZE configuration option 22632e3a5a81Sdan */ 22642e3a5a81Sdan static int SQLITE_TCLAPI test_config_sorterref( 22652e3a5a81Sdan void * clientData, 22662e3a5a81Sdan Tcl_Interp *interp, 22672e3a5a81Sdan int objc, 22682e3a5a81Sdan Tcl_Obj *CONST objv[] 22692e3a5a81Sdan ){ 22702e3a5a81Sdan int iVal; 22712e3a5a81Sdan if( objc!=2 ){ 22722e3a5a81Sdan Tcl_WrongNumArgs(interp, 1, objv, "NBYTE"); 22732e3a5a81Sdan return TCL_ERROR; 22742e3a5a81Sdan } 22752e3a5a81Sdan if( Tcl_GetIntFromObj(interp, objv[1], &iVal) ) return TCL_ERROR; 22762e3a5a81Sdan sqlite3_config(SQLITE_CONFIG_SORTERREF_SIZE, iVal); 22772e3a5a81Sdan return TCL_OK; 22782e3a5a81Sdan } 22792e3a5a81Sdan 22802e3a5a81Sdan /* 2281e4e416e8Sdan ** Usage: vfs_current_time_int64 2282e4e416e8Sdan ** 2283e4e416e8Sdan ** Return the value returned by the default VFS's xCurrentTimeInt64 method. 2284e4e416e8Sdan */ 22857617e4a8Smistachkin static int SQLITE_TCLAPI vfsCurrentTimeInt64( 2286e4e416e8Sdan void * clientData, 2287e4e416e8Sdan Tcl_Interp *interp, 2288e4e416e8Sdan int objc, 2289e4e416e8Sdan Tcl_Obj *CONST objv[] 2290e4e416e8Sdan ){ 2291e4e416e8Sdan i64 t; 2292e4e416e8Sdan sqlite3_vfs *pVfs = sqlite3_vfs_find(0); 2293e4e416e8Sdan if( objc!=1 ){ 2294e4e416e8Sdan Tcl_WrongNumArgs(interp, 1, objv, ""); 2295e4e416e8Sdan return TCL_ERROR; 2296e4e416e8Sdan } 2297e4e416e8Sdan pVfs->xCurrentTimeInt64(pVfs, &t); 2298e4e416e8Sdan Tcl_SetObjResult(interp, Tcl_NewWideIntObj(t)); 2299e4e416e8Sdan return TCL_OK; 2300e4e416e8Sdan } 2301e4e416e8Sdan 2302ee3b7a27Sdrh #ifdef SQLITE_ENABLE_SNAPSHOT 2303e4e416e8Sdan /* 2304fc1acf33Sdan ** Usage: sqlite3_snapshot_get DB DBNAME 2305fc1acf33Sdan */ 23067617e4a8Smistachkin static int SQLITE_TCLAPI test_snapshot_get( 2307fc1acf33Sdan void * clientData, 2308fc1acf33Sdan Tcl_Interp *interp, 2309fc1acf33Sdan int objc, 2310fc1acf33Sdan Tcl_Obj *CONST objv[] 2311fc1acf33Sdan ){ 2312fc1acf33Sdan int rc; 2313fc1acf33Sdan sqlite3 *db; 2314fc1acf33Sdan char *zName; 2315fc1acf33Sdan sqlite3_snapshot *pSnapshot = 0; 2316fc1acf33Sdan 2317fc1acf33Sdan if( objc!=3 ){ 2318fc1acf33Sdan Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME"); 2319fc1acf33Sdan return TCL_ERROR; 2320fc1acf33Sdan } 2321fc1acf33Sdan if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 2322fc1acf33Sdan zName = Tcl_GetString(objv[2]); 2323fc1acf33Sdan 2324fc1acf33Sdan rc = sqlite3_snapshot_get(db, zName, &pSnapshot); 2325fc1acf33Sdan if( rc!=SQLITE_OK ){ 2326fc1acf33Sdan Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1)); 2327fc1acf33Sdan return TCL_ERROR; 2328fc1acf33Sdan }else{ 2329fc1acf33Sdan char zBuf[100]; 2330fc1acf33Sdan if( sqlite3TestMakePointerStr(interp, zBuf, pSnapshot) ) return TCL_ERROR; 2331fc1acf33Sdan Tcl_SetObjResult(interp, Tcl_NewStringObj(zBuf, -1)); 2332fc1acf33Sdan } 2333fc1acf33Sdan return TCL_OK; 2334fc1acf33Sdan } 2335ee3b7a27Sdrh #endif /* SQLITE_ENABLE_SNAPSHOT */ 2336fc1acf33Sdan 2337ee3b7a27Sdrh #ifdef SQLITE_ENABLE_SNAPSHOT 2338fc1acf33Sdan /* 23391158498dSdan ** Usage: sqlite3_snapshot_recover DB DBNAME 23401158498dSdan */ 23411158498dSdan static int SQLITE_TCLAPI test_snapshot_recover( 23421158498dSdan void * clientData, 23431158498dSdan Tcl_Interp *interp, 23441158498dSdan int objc, 23451158498dSdan Tcl_Obj *CONST objv[] 23461158498dSdan ){ 23471158498dSdan int rc; 23481158498dSdan sqlite3 *db; 23491158498dSdan char *zName; 23501158498dSdan 23511158498dSdan if( objc!=3 ){ 23521158498dSdan Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME"); 23531158498dSdan return TCL_ERROR; 23541158498dSdan } 23551158498dSdan if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 23561158498dSdan zName = Tcl_GetString(objv[2]); 23571158498dSdan 23581158498dSdan rc = sqlite3_snapshot_recover(db, zName); 23591158498dSdan if( rc!=SQLITE_OK ){ 23601158498dSdan Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1)); 23611158498dSdan return TCL_ERROR; 23621158498dSdan }else{ 23631158498dSdan Tcl_ResetResult(interp); 23641158498dSdan } 23651158498dSdan return TCL_OK; 23661158498dSdan } 23671158498dSdan #endif /* SQLITE_ENABLE_SNAPSHOT */ 23681158498dSdan 23691158498dSdan #ifdef SQLITE_ENABLE_SNAPSHOT 23701158498dSdan /* 2371fc1acf33Sdan ** Usage: sqlite3_snapshot_open DB DBNAME SNAPSHOT 2372fc1acf33Sdan */ 23737617e4a8Smistachkin static int SQLITE_TCLAPI test_snapshot_open( 2374fc1acf33Sdan void * clientData, 2375fc1acf33Sdan Tcl_Interp *interp, 2376fc1acf33Sdan int objc, 2377fc1acf33Sdan Tcl_Obj *CONST objv[] 2378fc1acf33Sdan ){ 2379fc1acf33Sdan int rc; 2380fc1acf33Sdan sqlite3 *db; 2381fc1acf33Sdan char *zName; 2382fc1acf33Sdan sqlite3_snapshot *pSnapshot; 2383fc1acf33Sdan 2384fc1acf33Sdan if( objc!=4 ){ 2385fc1acf33Sdan Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME SNAPSHOT"); 2386fc1acf33Sdan return TCL_ERROR; 2387fc1acf33Sdan } 2388fc1acf33Sdan if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 2389fc1acf33Sdan zName = Tcl_GetString(objv[2]); 2390fc1acf33Sdan pSnapshot = (sqlite3_snapshot*)sqlite3TestTextToPtr(Tcl_GetString(objv[3])); 2391fc1acf33Sdan 2392fc1acf33Sdan rc = sqlite3_snapshot_open(db, zName, pSnapshot); 2393fc1acf33Sdan if( rc!=SQLITE_OK ){ 2394fc1acf33Sdan Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1)); 2395fc1acf33Sdan return TCL_ERROR; 2396*fa3d4c19Sdan }else{ 2397*fa3d4c19Sdan Tcl_ResetResult(interp); 2398fc1acf33Sdan } 2399fc1acf33Sdan return TCL_OK; 2400fc1acf33Sdan } 2401ee3b7a27Sdrh #endif /* SQLITE_ENABLE_SNAPSHOT */ 2402fc1acf33Sdan 2403ee3b7a27Sdrh #ifdef SQLITE_ENABLE_SNAPSHOT 2404fc1acf33Sdan /* 2405fc1acf33Sdan ** Usage: sqlite3_snapshot_free SNAPSHOT 2406fc1acf33Sdan */ 24077617e4a8Smistachkin static int SQLITE_TCLAPI test_snapshot_free( 2408fc1acf33Sdan void * clientData, 2409fc1acf33Sdan Tcl_Interp *interp, 2410fc1acf33Sdan int objc, 2411fc1acf33Sdan Tcl_Obj *CONST objv[] 2412fc1acf33Sdan ){ 2413fc1acf33Sdan sqlite3_snapshot *pSnapshot; 2414fc1acf33Sdan if( objc!=2 ){ 2415fc1acf33Sdan Tcl_WrongNumArgs(interp, 1, objv, "SNAPSHOT"); 2416fc1acf33Sdan return TCL_ERROR; 2417fc1acf33Sdan } 2418fc1acf33Sdan pSnapshot = (sqlite3_snapshot*)sqlite3TestTextToPtr(Tcl_GetString(objv[1])); 2419fc1acf33Sdan sqlite3_snapshot_free(pSnapshot); 2420fc1acf33Sdan return TCL_OK; 2421fc1acf33Sdan } 2422ee3b7a27Sdrh #endif /* SQLITE_ENABLE_SNAPSHOT */ 2423fc1acf33Sdan 2424ad2d5bafSdan #ifdef SQLITE_ENABLE_SNAPSHOT 2425ad2d5bafSdan /* 2426ad2d5bafSdan ** Usage: sqlite3_snapshot_cmp SNAPSHOT1 SNAPSHOT2 2427ad2d5bafSdan */ 24287617e4a8Smistachkin static int SQLITE_TCLAPI test_snapshot_cmp( 2429ad2d5bafSdan void * clientData, 2430ad2d5bafSdan Tcl_Interp *interp, 2431ad2d5bafSdan int objc, 2432ad2d5bafSdan Tcl_Obj *CONST objv[] 2433ad2d5bafSdan ){ 2434ad2d5bafSdan int res; 2435ad2d5bafSdan sqlite3_snapshot *p1; 2436ad2d5bafSdan sqlite3_snapshot *p2; 2437ad2d5bafSdan if( objc!=3 ){ 2438ad2d5bafSdan Tcl_WrongNumArgs(interp, 1, objv, "SNAPSHOT1 SNAPSHOT2"); 2439ad2d5bafSdan return TCL_ERROR; 2440ad2d5bafSdan } 2441ad2d5bafSdan p1 = (sqlite3_snapshot*)sqlite3TestTextToPtr(Tcl_GetString(objv[1])); 2442ad2d5bafSdan p2 = (sqlite3_snapshot*)sqlite3TestTextToPtr(Tcl_GetString(objv[2])); 2443ad2d5bafSdan res = sqlite3_snapshot_cmp(p1, p2); 2444ad2d5bafSdan Tcl_SetObjResult(interp, Tcl_NewIntObj(res)); 2445ad2d5bafSdan return TCL_OK; 2446ad2d5bafSdan } 2447ad2d5bafSdan #endif /* SQLITE_ENABLE_SNAPSHOT */ 2448ad2d5bafSdan 244925accbcaSdan #ifdef SQLITE_ENABLE_SNAPSHOT 245025accbcaSdan /* 245125accbcaSdan ** Usage: sqlite3_snapshot_get_blob DB DBNAME 245225accbcaSdan */ 245325accbcaSdan static int SQLITE_TCLAPI test_snapshot_get_blob( 245425accbcaSdan void * clientData, 245525accbcaSdan Tcl_Interp *interp, 245625accbcaSdan int objc, 245725accbcaSdan Tcl_Obj *CONST objv[] 245825accbcaSdan ){ 245925accbcaSdan int rc; 246025accbcaSdan sqlite3 *db; 246125accbcaSdan char *zName; 246225accbcaSdan sqlite3_snapshot *pSnapshot = 0; 246325accbcaSdan 246425accbcaSdan if( objc!=3 ){ 246525accbcaSdan Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME"); 246625accbcaSdan return TCL_ERROR; 246725accbcaSdan } 246825accbcaSdan if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 246925accbcaSdan zName = Tcl_GetString(objv[2]); 247025accbcaSdan 247125accbcaSdan rc = sqlite3_snapshot_get(db, zName, &pSnapshot); 247225accbcaSdan if( rc!=SQLITE_OK ){ 247325accbcaSdan Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1)); 247425accbcaSdan return TCL_ERROR; 247525accbcaSdan }else{ 247625accbcaSdan Tcl_SetObjResult(interp, 247725accbcaSdan Tcl_NewByteArrayObj((unsigned char*)pSnapshot, sizeof(sqlite3_snapshot)) 247825accbcaSdan ); 247925accbcaSdan sqlite3_snapshot_free(pSnapshot); 248025accbcaSdan } 248125accbcaSdan return TCL_OK; 248225accbcaSdan } 248325accbcaSdan #endif /* SQLITE_ENABLE_SNAPSHOT */ 248425accbcaSdan 248525accbcaSdan #ifdef SQLITE_ENABLE_SNAPSHOT 248625accbcaSdan /* 248725accbcaSdan ** Usage: sqlite3_snapshot_open_blob DB DBNAME SNAPSHOT 248825accbcaSdan */ 248925accbcaSdan static int SQLITE_TCLAPI test_snapshot_open_blob( 249025accbcaSdan void * clientData, 249125accbcaSdan Tcl_Interp *interp, 249225accbcaSdan int objc, 249325accbcaSdan Tcl_Obj *CONST objv[] 249425accbcaSdan ){ 249525accbcaSdan int rc; 249625accbcaSdan sqlite3 *db; 249725accbcaSdan char *zName; 249825accbcaSdan unsigned char *pBlob; 249925accbcaSdan int nBlob; 250025accbcaSdan 250125accbcaSdan if( objc!=4 ){ 250225accbcaSdan Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME SNAPSHOT"); 250325accbcaSdan return TCL_ERROR; 250425accbcaSdan } 250525accbcaSdan if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 250625accbcaSdan zName = Tcl_GetString(objv[2]); 250725accbcaSdan pBlob = Tcl_GetByteArrayFromObj(objv[3], &nBlob); 250825accbcaSdan if( nBlob!=sizeof(sqlite3_snapshot) ){ 250925accbcaSdan Tcl_AppendResult(interp, "bad SNAPSHOT", 0); 251025accbcaSdan return TCL_ERROR; 251125accbcaSdan } 251225accbcaSdan rc = sqlite3_snapshot_open(db, zName, (sqlite3_snapshot*)pBlob); 251325accbcaSdan if( rc!=SQLITE_OK ){ 251425accbcaSdan Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1)); 251525accbcaSdan return TCL_ERROR; 251625accbcaSdan } 251725accbcaSdan return TCL_OK; 251825accbcaSdan } 251925accbcaSdan #endif /* SQLITE_ENABLE_SNAPSHOT */ 252025accbcaSdan 252125accbcaSdan #ifdef SQLITE_ENABLE_SNAPSHOT 252225accbcaSdan /* 252325accbcaSdan ** Usage: sqlite3_snapshot_cmp_blob SNAPSHOT1 SNAPSHOT2 252425accbcaSdan */ 252525accbcaSdan static int SQLITE_TCLAPI test_snapshot_cmp_blob( 252625accbcaSdan void * clientData, 252725accbcaSdan Tcl_Interp *interp, 252825accbcaSdan int objc, 252925accbcaSdan Tcl_Obj *CONST objv[] 253025accbcaSdan ){ 253125accbcaSdan int res; 253225accbcaSdan unsigned char *p1; 253325accbcaSdan unsigned char *p2; 253425accbcaSdan int n1; 253525accbcaSdan int n2; 253625accbcaSdan 253725accbcaSdan if( objc!=3 ){ 253825accbcaSdan Tcl_WrongNumArgs(interp, 1, objv, "SNAPSHOT1 SNAPSHOT2"); 253925accbcaSdan return TCL_ERROR; 254025accbcaSdan } 254125accbcaSdan 254225accbcaSdan p1 = Tcl_GetByteArrayFromObj(objv[1], &n1); 254325accbcaSdan p2 = Tcl_GetByteArrayFromObj(objv[2], &n2); 254425accbcaSdan 254525accbcaSdan if( n1!=sizeof(sqlite3_snapshot) || n1!=n2 ){ 254625accbcaSdan Tcl_AppendResult(interp, "bad SNAPSHOT", 0); 254725accbcaSdan return TCL_ERROR; 254825accbcaSdan } 254925accbcaSdan 255025accbcaSdan res = sqlite3_snapshot_cmp((sqlite3_snapshot*)p1, (sqlite3_snapshot*)p2); 255125accbcaSdan Tcl_SetObjResult(interp, Tcl_NewIntObj(res)); 255225accbcaSdan return TCL_OK; 255325accbcaSdan } 255425accbcaSdan #endif /* SQLITE_ENABLE_SNAPSHOT */ 255525accbcaSdan 2556fc1acf33Sdan /* 2557000f95b1Sdan ** Usage: sqlite3_delete_database FILENAME 2558000f95b1Sdan */ 2559000f95b1Sdan int sqlite3_delete_database(const char*); /* in test_delete.c */ 2560000f95b1Sdan static int SQLITE_TCLAPI test_delete_database( 2561000f95b1Sdan void * clientData, 2562000f95b1Sdan Tcl_Interp *interp, 2563000f95b1Sdan int objc, 2564000f95b1Sdan Tcl_Obj *CONST objv[] 2565000f95b1Sdan ){ 2566000f95b1Sdan int rc; 2567000f95b1Sdan const char *zFile; 2568000f95b1Sdan if( objc!=2 ){ 2569000f95b1Sdan Tcl_WrongNumArgs(interp, 1, objv, "FILE"); 2570000f95b1Sdan return TCL_ERROR; 2571000f95b1Sdan } 2572000f95b1Sdan zFile = (const char*)Tcl_GetString(objv[1]); 2573000f95b1Sdan rc = sqlite3_delete_database(zFile); 2574000f95b1Sdan 2575000f95b1Sdan Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1)); 2576000f95b1Sdan return TCL_OK; 2577000f95b1Sdan } 2578000f95b1Sdan 2579000f95b1Sdan /* 25804da30f88Sdan ** Usage: atomic_batch_write PATH 25814da30f88Sdan */ 25824da30f88Sdan static int SQLITE_TCLAPI test_atomic_batch_write( 25834da30f88Sdan void * clientData, 25844da30f88Sdan Tcl_Interp *interp, 25854da30f88Sdan int objc, 25864da30f88Sdan Tcl_Obj *CONST objv[] 25874da30f88Sdan ){ 25884da30f88Sdan char *zFile = 0; /* Path to file to test */ 25894da30f88Sdan sqlite3 *db = 0; /* Database handle */ 25904da30f88Sdan sqlite3_file *pFd = 0; /* SQLite fd open on zFile */ 25914da30f88Sdan int bRes = 0; /* Integer result of this command */ 25924da30f88Sdan int dc = 0; /* Device-characteristics mask */ 25934da30f88Sdan int rc; /* sqlite3_open() return code */ 25944da30f88Sdan 25954da30f88Sdan if( objc!=2 ){ 25964da30f88Sdan Tcl_WrongNumArgs(interp, 1, objv, "PATH"); 25974da30f88Sdan return TCL_ERROR; 25984da30f88Sdan } 25994da30f88Sdan zFile = Tcl_GetString(objv[1]); 26004da30f88Sdan 26014da30f88Sdan rc = sqlite3_open(zFile, &db); 26024da30f88Sdan if( rc!=SQLITE_OK ){ 26034da30f88Sdan Tcl_AppendResult(interp, sqlite3_errmsg(db), 0); 26044da30f88Sdan sqlite3_close(db); 26054da30f88Sdan return TCL_ERROR; 26064da30f88Sdan } 26074da30f88Sdan 26084da30f88Sdan rc = sqlite3_file_control(db, "main", SQLITE_FCNTL_FILE_POINTER, (void*)&pFd); 26094da30f88Sdan dc = pFd->pMethods->xDeviceCharacteristics(pFd); 26104da30f88Sdan if( dc & SQLITE_IOCAP_BATCH_ATOMIC ){ 26114da30f88Sdan bRes = 1; 26124da30f88Sdan } 26134da30f88Sdan 26144da30f88Sdan Tcl_SetObjResult(interp, Tcl_NewIntObj(bRes)); 26154da30f88Sdan sqlite3_close(db); 26164da30f88Sdan return TCL_OK; 26174da30f88Sdan } 26184da30f88Sdan 26194da30f88Sdan /* 2620bb5a9c3eSdrh ** Usage: sqlite3_next_stmt DB STMT 2621bb5a9c3eSdrh ** 2622bb5a9c3eSdrh ** Return the next statment in sequence after STMT. 2623bb5a9c3eSdrh */ 26247617e4a8Smistachkin static int SQLITE_TCLAPI test_next_stmt( 2625bb5a9c3eSdrh void * clientData, 2626bb5a9c3eSdrh Tcl_Interp *interp, 2627bb5a9c3eSdrh int objc, 2628bb5a9c3eSdrh Tcl_Obj *CONST objv[] 2629bb5a9c3eSdrh ){ 2630bb5a9c3eSdrh sqlite3_stmt *pStmt; 2631bb5a9c3eSdrh sqlite3 *db = 0; 2632bb5a9c3eSdrh char zBuf[50]; 2633bb5a9c3eSdrh 2634bb5a9c3eSdrh if( objc!=3 ){ 2635bb5a9c3eSdrh Tcl_AppendResult(interp, "wrong # args: should be \"", 2636bb5a9c3eSdrh Tcl_GetStringFromObj(objv[0], 0), " DB STMT", 0); 2637bb5a9c3eSdrh return TCL_ERROR; 2638bb5a9c3eSdrh } 2639bb5a9c3eSdrh 2640bb5a9c3eSdrh if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 2641bb5a9c3eSdrh if( getStmtPointer(interp, Tcl_GetString(objv[2]), &pStmt) ) return TCL_ERROR; 2642bb5a9c3eSdrh pStmt = sqlite3_next_stmt(db, pStmt); 2643bb5a9c3eSdrh if( pStmt ){ 2644bb5a9c3eSdrh if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR; 2645bb5a9c3eSdrh Tcl_AppendResult(interp, zBuf, 0); 2646bb5a9c3eSdrh } 2647bb5a9c3eSdrh return TCL_OK; 2648bb5a9c3eSdrh } 2649bb5a9c3eSdrh 2650f03d9cccSdrh /* 2651f03d9cccSdrh ** Usage: sqlite3_stmt_readonly STMT 2652f03d9cccSdrh ** 2653f03d9cccSdrh ** Return true if STMT is a NULL pointer or a pointer to a statement 2654f03d9cccSdrh ** that is guaranteed to leave the database unmodified. 2655f03d9cccSdrh */ 26567617e4a8Smistachkin static int SQLITE_TCLAPI test_stmt_readonly( 2657f03d9cccSdrh void * clientData, 2658f03d9cccSdrh Tcl_Interp *interp, 2659f03d9cccSdrh int objc, 2660f03d9cccSdrh Tcl_Obj *CONST objv[] 2661f03d9cccSdrh ){ 2662f03d9cccSdrh sqlite3_stmt *pStmt; 2663f03d9cccSdrh int rc; 2664f03d9cccSdrh 2665f03d9cccSdrh if( objc!=2 ){ 2666f03d9cccSdrh Tcl_AppendResult(interp, "wrong # args: should be \"", 2667f03d9cccSdrh Tcl_GetStringFromObj(objv[0], 0), " STMT", 0); 2668f03d9cccSdrh return TCL_ERROR; 2669f03d9cccSdrh } 2670f03d9cccSdrh 2671f03d9cccSdrh if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 2672f03d9cccSdrh rc = sqlite3_stmt_readonly(pStmt); 2673f03d9cccSdrh Tcl_SetObjResult(interp, Tcl_NewBooleanObj(rc)); 2674f03d9cccSdrh return TCL_OK; 2675f03d9cccSdrh } 2676f03d9cccSdrh 2677d9495cd0Sdan /* 26782fb6693eSdrh ** Usage: sqlite3_stmt_busy STMT 26792fb6693eSdrh ** 26802fb6693eSdrh ** Return true if STMT is a non-NULL pointer to a statement 26812fb6693eSdrh ** that has been stepped but not to completion. 26822fb6693eSdrh */ 26837617e4a8Smistachkin static int SQLITE_TCLAPI test_stmt_busy( 26842fb6693eSdrh void * clientData, 26852fb6693eSdrh Tcl_Interp *interp, 26862fb6693eSdrh int objc, 26872fb6693eSdrh Tcl_Obj *CONST objv[] 26882fb6693eSdrh ){ 26892fb6693eSdrh sqlite3_stmt *pStmt; 26902fb6693eSdrh int rc; 26912fb6693eSdrh 26922fb6693eSdrh if( objc!=2 ){ 26932fb6693eSdrh Tcl_AppendResult(interp, "wrong # args: should be \"", 26942fb6693eSdrh Tcl_GetStringFromObj(objv[0], 0), " STMT", 0); 26952fb6693eSdrh return TCL_ERROR; 26962fb6693eSdrh } 26972fb6693eSdrh 26982fb6693eSdrh if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 26992fb6693eSdrh rc = sqlite3_stmt_busy(pStmt); 27002fb6693eSdrh Tcl_SetObjResult(interp, Tcl_NewBooleanObj(rc)); 27012fb6693eSdrh return TCL_OK; 27022fb6693eSdrh } 27032fb6693eSdrh 27042fb6693eSdrh /* 2705d9495cd0Sdan ** Usage: uses_stmt_journal STMT 2706d9495cd0Sdan ** 2707d9495cd0Sdan ** Return true if STMT uses a statement journal. 2708d9495cd0Sdan */ 27097617e4a8Smistachkin static int SQLITE_TCLAPI uses_stmt_journal( 2710d9495cd0Sdan void * clientData, 2711d9495cd0Sdan Tcl_Interp *interp, 2712d9495cd0Sdan int objc, 2713d9495cd0Sdan Tcl_Obj *CONST objv[] 2714d9495cd0Sdan ){ 2715d9495cd0Sdan sqlite3_stmt *pStmt; 2716d9495cd0Sdan 2717d9495cd0Sdan if( objc!=2 ){ 2718d9495cd0Sdan Tcl_AppendResult(interp, "wrong # args: should be \"", 2719d9495cd0Sdan Tcl_GetStringFromObj(objv[0], 0), " STMT", 0); 2720d9495cd0Sdan return TCL_ERROR; 2721d9495cd0Sdan } 2722d9495cd0Sdan 2723d9495cd0Sdan if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 2724caffb1a5Sdrh sqlite3_stmt_readonly(pStmt); 2725d9495cd0Sdan Tcl_SetObjResult(interp, Tcl_NewBooleanObj(((Vdbe *)pStmt)->usesStmtJournal)); 2726d9495cd0Sdan return TCL_OK; 2727d9495cd0Sdan } 2728d9495cd0Sdan 2729bb5a9c3eSdrh 2730bb5a9c3eSdrh /* 2731106bb236Sdanielk1977 ** Usage: sqlite3_reset STMT 2732106bb236Sdanielk1977 ** 2733261919ccSdanielk1977 ** Reset a statement handle. 2734106bb236Sdanielk1977 */ 27357617e4a8Smistachkin static int SQLITE_TCLAPI test_reset( 2736106bb236Sdanielk1977 void * clientData, 2737106bb236Sdanielk1977 Tcl_Interp *interp, 2738106bb236Sdanielk1977 int objc, 2739106bb236Sdanielk1977 Tcl_Obj *CONST objv[] 2740106bb236Sdanielk1977 ){ 2741106bb236Sdanielk1977 sqlite3_stmt *pStmt; 2742106bb236Sdanielk1977 int rc; 2743106bb236Sdanielk1977 2744106bb236Sdanielk1977 if( objc!=2 ){ 2745106bb236Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 2746106bb236Sdanielk1977 Tcl_GetStringFromObj(objv[0], 0), " <STMT>", 0); 2747106bb236Sdanielk1977 return TCL_ERROR; 2748106bb236Sdanielk1977 } 2749106bb236Sdanielk1977 2750106bb236Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 2751106bb236Sdanielk1977 2752fc57d7bfSdanielk1977 rc = sqlite3_reset(pStmt); 2753261919ccSdanielk1977 if( pStmt && sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ){ 2754261919ccSdanielk1977 return TCL_ERROR; 2755261919ccSdanielk1977 } 27564f0c5878Sdrh Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC); 2757261919ccSdanielk1977 /* 2758106bb236Sdanielk1977 if( rc ){ 2759b86ccfb2Sdrh return TCL_ERROR; 2760b86ccfb2Sdrh } 2761261919ccSdanielk1977 */ 2762b86ccfb2Sdrh return TCL_OK; 2763b86ccfb2Sdrh } 2764b86ccfb2Sdrh 27655a38705eSdrh /* 2766d89bd007Sdrh ** Usage: sqlite3_expired STMT 2767d89bd007Sdrh ** 2768d89bd007Sdrh ** Return TRUE if a recompilation of the statement is recommended. 2769d89bd007Sdrh */ 27707617e4a8Smistachkin static int SQLITE_TCLAPI test_expired( 2771d89bd007Sdrh void * clientData, 2772d89bd007Sdrh Tcl_Interp *interp, 2773d89bd007Sdrh int objc, 2774d89bd007Sdrh Tcl_Obj *CONST objv[] 2775d89bd007Sdrh ){ 2776eec556d3Sshane #ifndef SQLITE_OMIT_DEPRECATED 2777d89bd007Sdrh sqlite3_stmt *pStmt; 2778d89bd007Sdrh if( objc!=2 ){ 2779d89bd007Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", 2780d89bd007Sdrh Tcl_GetStringFromObj(objv[0], 0), " <STMT>", 0); 2781d89bd007Sdrh return TCL_ERROR; 2782d89bd007Sdrh } 2783d89bd007Sdrh if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 2784d89bd007Sdrh Tcl_SetObjResult(interp, Tcl_NewBooleanObj(sqlite3_expired(pStmt))); 2785eec556d3Sshane #endif 2786d89bd007Sdrh return TCL_OK; 2787d89bd007Sdrh } 2788d89bd007Sdrh 2789d89bd007Sdrh /* 2790f8db1bc0Sdrh ** Usage: sqlite3_transfer_bindings FROMSTMT TOSTMT 2791f8db1bc0Sdrh ** 2792f8db1bc0Sdrh ** Transfer all bindings from FROMSTMT over to TOSTMT 2793f8db1bc0Sdrh */ 27947617e4a8Smistachkin static int SQLITE_TCLAPI test_transfer_bind( 2795f8db1bc0Sdrh void * clientData, 2796f8db1bc0Sdrh Tcl_Interp *interp, 2797f8db1bc0Sdrh int objc, 2798f8db1bc0Sdrh Tcl_Obj *CONST objv[] 2799f8db1bc0Sdrh ){ 2800eec556d3Sshane #ifndef SQLITE_OMIT_DEPRECATED 2801f8db1bc0Sdrh sqlite3_stmt *pStmt1, *pStmt2; 2802f8db1bc0Sdrh if( objc!=3 ){ 2803f8db1bc0Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", 2804f8db1bc0Sdrh Tcl_GetStringFromObj(objv[0], 0), " FROM-STMT TO-STMT", 0); 2805f8db1bc0Sdrh return TCL_ERROR; 2806f8db1bc0Sdrh } 2807f8db1bc0Sdrh if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt1)) return TCL_ERROR; 2808f8db1bc0Sdrh if( getStmtPointer(interp, Tcl_GetString(objv[2]), &pStmt2)) return TCL_ERROR; 2809f8db1bc0Sdrh Tcl_SetObjResult(interp, 2810f8db1bc0Sdrh Tcl_NewIntObj(sqlite3_transfer_bindings(pStmt1,pStmt2))); 2811eec556d3Sshane #endif 2812f8db1bc0Sdrh return TCL_OK; 2813f8db1bc0Sdrh } 2814f8db1bc0Sdrh 2815f8db1bc0Sdrh /* 2816fbcd585fSdanielk1977 ** Usage: sqlite3_changes DB 281750457896Sdrh ** 2818fbcd585fSdanielk1977 ** Return the number of changes made to the database by the last SQL 2819fbcd585fSdanielk1977 ** execution. 282050457896Sdrh */ 28217617e4a8Smistachkin static int SQLITE_TCLAPI test_changes( 2822fbcd585fSdanielk1977 void * clientData, 2823fbcd585fSdanielk1977 Tcl_Interp *interp, 2824fbcd585fSdanielk1977 int objc, 2825fbcd585fSdanielk1977 Tcl_Obj *CONST objv[] 2826fbcd585fSdanielk1977 ){ 2827fbcd585fSdanielk1977 sqlite3 *db; 2828fbcd585fSdanielk1977 if( objc!=2 ){ 2829fbcd585fSdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 2830fbcd585fSdanielk1977 Tcl_GetString(objv[0]), " DB", 0); 2831fbcd585fSdanielk1977 return TCL_ERROR; 2832fbcd585fSdanielk1977 } 2833fbcd585fSdanielk1977 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 2834fbcd585fSdanielk1977 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_changes(db))); 2835fbcd585fSdanielk1977 return TCL_OK; 2836fbcd585fSdanielk1977 } 283750457896Sdrh 283850457896Sdrh /* 28397c972decSdrh ** This is the "static_bind_value" that variables are bound to when 28406f8a503dSdanielk1977 ** the FLAG option of sqlite3_bind is "static" 284150457896Sdrh */ 28427c972decSdrh static char *sqlite_static_bind_value = 0; 2843f0313813Sdrh static int sqlite_static_bind_nbyte = 0; 28447c972decSdrh 28457c972decSdrh /* 28466f8a503dSdanielk1977 ** Usage: sqlite3_bind VM IDX VALUE FLAGS 28477c972decSdrh ** 2848f7b5496eSdrh ** Sets the value of the IDX-th occurrence of "?" in the original SQL 28497c972decSdrh ** string. VALUE is the new value. If FLAGS=="null" then VALUE is 28507c972decSdrh ** ignored and the value is set to NULL. If FLAGS=="static" then 28517c972decSdrh ** the value is set to the value of a static variable named 28527c972decSdrh ** "sqlite_static_bind_value". If FLAGS=="normal" then a copy 2853bf8aa2a6Sdrh ** of the VALUE is made. If FLAGS=="blob10" then a VALUE is ignored 2854bf8aa2a6Sdrh ** an a 10-byte blob "abc\000xyz\000pq" is inserted. 28557c972decSdrh */ 28567617e4a8Smistachkin static int SQLITE_TCLAPI test_bind( 285750457896Sdrh void *NotUsed, 285850457896Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 285950457896Sdrh int argc, /* Number of arguments */ 286050457896Sdrh char **argv /* Text of each argument */ 286150457896Sdrh ){ 2862fc57d7bfSdanielk1977 sqlite3_stmt *pStmt; 286350457896Sdrh int rc; 28647c972decSdrh int idx; 28657c972decSdrh if( argc!=5 ){ 286650457896Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 28677c972decSdrh " VM IDX VALUE (null|static|normal)\"", 0); 286850457896Sdrh return TCL_ERROR; 286950457896Sdrh } 2870fc57d7bfSdanielk1977 if( getStmtPointer(interp, argv[1], &pStmt) ) return TCL_ERROR; 28717c972decSdrh if( Tcl_GetInt(interp, argv[2], &idx) ) return TCL_ERROR; 28727c972decSdrh if( strcmp(argv[4],"null")==0 ){ 2873fc57d7bfSdanielk1977 rc = sqlite3_bind_null(pStmt, idx); 28747c972decSdrh }else if( strcmp(argv[4],"static")==0 ){ 2875fc57d7bfSdanielk1977 rc = sqlite3_bind_text(pStmt, idx, sqlite_static_bind_value, -1, 0); 2876f0313813Sdrh }else if( strcmp(argv[4],"static-nbytes")==0 ){ 2877f0313813Sdrh rc = sqlite3_bind_text(pStmt, idx, sqlite_static_bind_value, 2878f0313813Sdrh sqlite_static_bind_nbyte, 0); 28797c972decSdrh }else if( strcmp(argv[4],"normal")==0 ){ 2880d8123366Sdanielk1977 rc = sqlite3_bind_text(pStmt, idx, argv[3], -1, SQLITE_TRANSIENT); 2881bf8aa2a6Sdrh }else if( strcmp(argv[4],"blob10")==0 ){ 2882bf8aa2a6Sdrh rc = sqlite3_bind_text(pStmt, idx, "abc\000xyz\000pq", 10, SQLITE_STATIC); 28837c972decSdrh }else{ 28847c972decSdrh Tcl_AppendResult(interp, "4th argument should be " 28857c972decSdrh "\"null\" or \"static\" or \"normal\"", 0); 28867c972decSdrh return TCL_ERROR; 28877c972decSdrh } 2888c60d0446Sdrh if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR; 288950457896Sdrh if( rc ){ 289050457896Sdrh char zBuf[50]; 289165545b59Sdrh sqlite3_snprintf(sizeof(zBuf), zBuf, "(%d) ", rc); 2892f20b21c8Sdanielk1977 Tcl_AppendResult(interp, zBuf, sqlite3ErrStr(rc), 0); 289350457896Sdrh return TCL_ERROR; 289450457896Sdrh } 289550457896Sdrh return TCL_OK; 289650457896Sdrh } 289750457896Sdrh 28985436dc2dSdrh #ifndef SQLITE_OMIT_UTF16 28994e6af134Sdanielk1977 /* 29004e6af134Sdanielk1977 ** Usage: add_test_collate <db ptr> <utf8> <utf16le> <utf16be> 29014e6af134Sdanielk1977 ** 29024e6af134Sdanielk1977 ** This function is used to test that SQLite selects the correct collation 29034e6af134Sdanielk1977 ** sequence callback when multiple versions (for different text encodings) 29044e6af134Sdanielk1977 ** are available. 29054e6af134Sdanielk1977 ** 29064e6af134Sdanielk1977 ** Calling this routine registers the collation sequence "test_collate" 29074e6af134Sdanielk1977 ** with database handle <db>. The second argument must be a list of three 29084e6af134Sdanielk1977 ** boolean values. If the first is true, then a version of test_collate is 29094e6af134Sdanielk1977 ** registered for UTF-8, if the second is true, a version is registered for 29104e6af134Sdanielk1977 ** UTF-16le, if the third is true, a UTF-16be version is available. 29114e6af134Sdanielk1977 ** Previous versions of test_collate are deleted. 29124e6af134Sdanielk1977 ** 29134e6af134Sdanielk1977 ** The collation sequence test_collate is implemented by calling the 29144e6af134Sdanielk1977 ** following TCL script: 29154e6af134Sdanielk1977 ** 29164e6af134Sdanielk1977 ** "test_collate <enc> <lhs> <rhs>" 29174e6af134Sdanielk1977 ** 29184e6af134Sdanielk1977 ** The <lhs> and <rhs> are the two values being compared, encoded in UTF-8. 29194e6af134Sdanielk1977 ** The <enc> parameter is the encoding of the collation function that 29204e6af134Sdanielk1977 ** SQLite selected to call. The TCL test script implements the 29214e6af134Sdanielk1977 ** "test_collate" proc. 29224e6af134Sdanielk1977 ** 292360ec914cSpeter.d.reid ** Note that this will only work with one interpreter at a time, as the 29244e6af134Sdanielk1977 ** interp pointer to use when evaluating the TCL script is stored in 29254e6af134Sdanielk1977 ** pTestCollateInterp. 29264e6af134Sdanielk1977 */ 29274e6af134Sdanielk1977 static Tcl_Interp* pTestCollateInterp; 29284e6af134Sdanielk1977 static int test_collate_func( 29294e6af134Sdanielk1977 void *pCtx, 29304e6af134Sdanielk1977 int nA, const void *zA, 29314e6af134Sdanielk1977 int nB, const void *zB 29324e6af134Sdanielk1977 ){ 29334e6af134Sdanielk1977 Tcl_Interp *i = pTestCollateInterp; 2934d2199f0fSdan int encin = SQLITE_PTR_TO_INT(pCtx); 29354e6af134Sdanielk1977 int res; 29364db38a70Sdrh int n; 29374e6af134Sdanielk1977 29384e6af134Sdanielk1977 sqlite3_value *pVal; 29394e6af134Sdanielk1977 Tcl_Obj *pX; 29404e6af134Sdanielk1977 29414e6af134Sdanielk1977 pX = Tcl_NewStringObj("test_collate", -1); 29424e6af134Sdanielk1977 Tcl_IncrRefCount(pX); 29434e6af134Sdanielk1977 29444e6af134Sdanielk1977 switch( encin ){ 29454e6af134Sdanielk1977 case SQLITE_UTF8: 29464e6af134Sdanielk1977 Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-8",-1)); 29474e6af134Sdanielk1977 break; 29484e6af134Sdanielk1977 case SQLITE_UTF16LE: 29494e6af134Sdanielk1977 Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-16LE",-1)); 29504e6af134Sdanielk1977 break; 29514e6af134Sdanielk1977 case SQLITE_UTF16BE: 29524e6af134Sdanielk1977 Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-16BE",-1)); 29534e6af134Sdanielk1977 break; 29544e6af134Sdanielk1977 default: 29554e6af134Sdanielk1977 assert(0); 29564e6af134Sdanielk1977 } 29574e6af134Sdanielk1977 295802fa4696Sdan sqlite3BeginBenignMalloc(); 29591e536953Sdanielk1977 pVal = sqlite3ValueNew(0); 296002fa4696Sdan if( pVal ){ 2961b21c8cd4Sdrh sqlite3ValueSetStr(pVal, nA, zA, encin, SQLITE_STATIC); 29624db38a70Sdrh n = sqlite3_value_bytes(pVal); 296303d847eaSdrh Tcl_ListObjAppendElement(i,pX, 296403d847eaSdrh Tcl_NewStringObj((char*)sqlite3_value_text(pVal),n)); 2965b21c8cd4Sdrh sqlite3ValueSetStr(pVal, nB, zB, encin, SQLITE_STATIC); 29664db38a70Sdrh n = sqlite3_value_bytes(pVal); 296703d847eaSdrh Tcl_ListObjAppendElement(i,pX, 296803d847eaSdrh Tcl_NewStringObj((char*)sqlite3_value_text(pVal),n)); 29694e6af134Sdanielk1977 sqlite3ValueFree(pVal); 297002fa4696Sdan } 297102fa4696Sdan sqlite3EndBenignMalloc(); 29724e6af134Sdanielk1977 29734e6af134Sdanielk1977 Tcl_EvalObjEx(i, pX, 0); 29744e6af134Sdanielk1977 Tcl_DecrRefCount(pX); 29754e6af134Sdanielk1977 Tcl_GetIntFromObj(i, Tcl_GetObjResult(i), &res); 29764e6af134Sdanielk1977 return res; 29774e6af134Sdanielk1977 } 29787617e4a8Smistachkin static int SQLITE_TCLAPI test_collate( 29794e6af134Sdanielk1977 void * clientData, 29804e6af134Sdanielk1977 Tcl_Interp *interp, 29814e6af134Sdanielk1977 int objc, 29824e6af134Sdanielk1977 Tcl_Obj *CONST objv[] 29834e6af134Sdanielk1977 ){ 29844e6af134Sdanielk1977 sqlite3 *db; 29854e6af134Sdanielk1977 int val; 2986312d6b36Sdanielk1977 sqlite3_value *pVal; 2987c60d0446Sdrh int rc; 29884e6af134Sdanielk1977 29894e6af134Sdanielk1977 if( objc!=5 ) goto bad_args; 29904e6af134Sdanielk1977 pTestCollateInterp = interp; 29914e6af134Sdanielk1977 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 29924e6af134Sdanielk1977 29934e6af134Sdanielk1977 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[2], &val) ) return TCL_ERROR; 2994c60d0446Sdrh rc = sqlite3_create_collation(db, "test_collate", SQLITE_UTF8, 29954e6af134Sdanielk1977 (void *)SQLITE_UTF8, val?test_collate_func:0); 2996c60d0446Sdrh if( rc==SQLITE_OK ){ 2997eee4c8caSdrh const void *zUtf16; 29984e6af134Sdanielk1977 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[3], &val) ) return TCL_ERROR; 2999c60d0446Sdrh rc = sqlite3_create_collation(db, "test_collate", SQLITE_UTF16LE, 30004e6af134Sdanielk1977 (void *)SQLITE_UTF16LE, val?test_collate_func:0); 30014e6af134Sdanielk1977 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[4], &val) ) return TCL_ERROR; 3002312d6b36Sdanielk1977 300386f8c197Sdrh #if 0 30049a30cf65Sdanielk1977 if( sqlite3_iMallocFail>0 ){ 30059a30cf65Sdanielk1977 sqlite3_iMallocFail++; 30069a30cf65Sdanielk1977 } 30079a30cf65Sdanielk1977 #endif 3008f3a65f7eSdrh sqlite3_mutex_enter(db->mutex); 3009f3a65f7eSdrh pVal = sqlite3ValueNew(db); 3010b21c8cd4Sdrh sqlite3ValueSetStr(pVal, -1, "test_collate", SQLITE_UTF8, SQLITE_STATIC); 3011a7a8e14bSdanielk1977 zUtf16 = sqlite3ValueText(pVal, SQLITE_UTF16NATIVE); 3012f3a65f7eSdrh if( db->mallocFailed ){ 3013f3a65f7eSdrh rc = SQLITE_NOMEM; 3014f3a65f7eSdrh }else{ 3015a7a8e14bSdanielk1977 rc = sqlite3_create_collation16(db, zUtf16, SQLITE_UTF16BE, 30169a30cf65Sdanielk1977 (void *)SQLITE_UTF16BE, val?test_collate_func:0); 3017f3a65f7eSdrh } 3018312d6b36Sdanielk1977 sqlite3ValueFree(pVal); 3019f3a65f7eSdrh sqlite3_mutex_leave(db->mutex); 3020c60d0446Sdrh } 3021c60d0446Sdrh if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; 30229a30cf65Sdanielk1977 30239a30cf65Sdanielk1977 if( rc!=SQLITE_OK ){ 3024e84d8d32Smistachkin Tcl_AppendResult(interp, sqlite3ErrName(rc), 0); 30259a30cf65Sdanielk1977 return TCL_ERROR; 30269a30cf65Sdanielk1977 } 30274e6af134Sdanielk1977 return TCL_OK; 30284e6af134Sdanielk1977 30294e6af134Sdanielk1977 bad_args: 30304e6af134Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 30314e6af134Sdanielk1977 Tcl_GetStringFromObj(objv[0], 0), " <DB> <utf8> <utf16le> <utf16be>", 0); 30324e6af134Sdanielk1977 return TCL_ERROR; 30334e6af134Sdanielk1977 } 30344e6af134Sdanielk1977 3035268803a9Sdrh /* 303638fdead8Sdan ** Usage: add_test_utf16bin_collate <db ptr> 303738fdead8Sdan ** 303838fdead8Sdan ** Add a utf-16 collation sequence named "utf16bin" to the database 303938fdead8Sdan ** handle. This collation sequence compares arguments in the same way as the 304038fdead8Sdan ** built-in collation "binary". 304138fdead8Sdan */ 304238fdead8Sdan static int test_utf16bin_collate_func( 304338fdead8Sdan void *pCtx, 304438fdead8Sdan int nA, const void *zA, 304538fdead8Sdan int nB, const void *zB 304638fdead8Sdan ){ 304738fdead8Sdan int nCmp = (nA>nB ? nB : nA); 304838fdead8Sdan int res = memcmp(zA, zB, nCmp); 304938fdead8Sdan if( res==0 ) res = nA - nB; 305038fdead8Sdan return res; 305138fdead8Sdan } 30527617e4a8Smistachkin static int SQLITE_TCLAPI test_utf16bin_collate( 305338fdead8Sdan void * clientData, 305438fdead8Sdan Tcl_Interp *interp, 305538fdead8Sdan int objc, 305638fdead8Sdan Tcl_Obj *CONST objv[] 305738fdead8Sdan ){ 305838fdead8Sdan sqlite3 *db; 305938fdead8Sdan int rc; 306038fdead8Sdan 306138fdead8Sdan if( objc!=2 ) goto bad_args; 306238fdead8Sdan if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 306338fdead8Sdan 306438fdead8Sdan rc = sqlite3_create_collation(db, "utf16bin", SQLITE_UTF16, 0, 306538fdead8Sdan test_utf16bin_collate_func 306638fdead8Sdan ); 306738fdead8Sdan if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; 306838fdead8Sdan return TCL_OK; 306938fdead8Sdan 307038fdead8Sdan bad_args: 307138fdead8Sdan Tcl_WrongNumArgs(interp, 1, objv, "DB"); 307238fdead8Sdan return TCL_ERROR; 307338fdead8Sdan } 307438fdead8Sdan 307538fdead8Sdan /* 3076268803a9Sdrh ** When the collation needed callback is invoked, record the name of 3077268803a9Sdrh ** the requested collating function here. The recorded name is linked 3078268803a9Sdrh ** to a TCL variable and used to make sure that the requested collation 3079268803a9Sdrh ** name is correct. 3080268803a9Sdrh */ 3081268803a9Sdrh static char zNeededCollation[200]; 3082268803a9Sdrh static char *pzNeededCollation = zNeededCollation; 3083268803a9Sdrh 3084268803a9Sdrh 3085268803a9Sdrh /* 3086268803a9Sdrh ** Called when a collating sequence is needed. Registered using 3087268803a9Sdrh ** sqlite3_collation_needed16(). 3088268803a9Sdrh */ 3089312d6b36Sdanielk1977 static void test_collate_needed_cb( 3090312d6b36Sdanielk1977 void *pCtx, 3091312d6b36Sdanielk1977 sqlite3 *db, 3092312d6b36Sdanielk1977 int eTextRep, 3093268803a9Sdrh const void *pName 3094312d6b36Sdanielk1977 ){ 309514db2665Sdanielk1977 int enc = ENC(db); 3096268803a9Sdrh int i; 3097268803a9Sdrh char *z; 3098268803a9Sdrh for(z = (char*)pName, i=0; *z || z[1]; z++){ 3099268803a9Sdrh if( *z ) zNeededCollation[i++] = *z; 3100268803a9Sdrh } 3101268803a9Sdrh zNeededCollation[i] = 0; 3102312d6b36Sdanielk1977 sqlite3_create_collation( 3103d2199f0fSdan db, "test_collate", ENC(db), SQLITE_INT_TO_PTR(enc), test_collate_func); 3104312d6b36Sdanielk1977 } 3105312d6b36Sdanielk1977 3106312d6b36Sdanielk1977 /* 3107312d6b36Sdanielk1977 ** Usage: add_test_collate_needed DB 3108312d6b36Sdanielk1977 */ 31097617e4a8Smistachkin static int SQLITE_TCLAPI test_collate_needed( 3110312d6b36Sdanielk1977 void * clientData, 3111312d6b36Sdanielk1977 Tcl_Interp *interp, 3112312d6b36Sdanielk1977 int objc, 3113312d6b36Sdanielk1977 Tcl_Obj *CONST objv[] 3114312d6b36Sdanielk1977 ){ 3115312d6b36Sdanielk1977 sqlite3 *db; 3116c60d0446Sdrh int rc; 3117312d6b36Sdanielk1977 3118312d6b36Sdanielk1977 if( objc!=2 ) goto bad_args; 3119312d6b36Sdanielk1977 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 3120c60d0446Sdrh rc = sqlite3_collation_needed16(db, 0, test_collate_needed_cb); 3121268803a9Sdrh zNeededCollation[0] = 0; 3122c60d0446Sdrh if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; 3123312d6b36Sdanielk1977 return TCL_OK; 3124312d6b36Sdanielk1977 3125312d6b36Sdanielk1977 bad_args: 3126312d6b36Sdanielk1977 Tcl_WrongNumArgs(interp, 1, objv, "DB"); 3127312d6b36Sdanielk1977 return TCL_ERROR; 3128312d6b36Sdanielk1977 } 31297d9bd4e1Sdrh 31307d9bd4e1Sdrh /* 31317d9bd4e1Sdrh ** tclcmd: add_alignment_test_collations DB 31327d9bd4e1Sdrh ** 31337d9bd4e1Sdrh ** Add two new collating sequences to the database DB 31347d9bd4e1Sdrh ** 31357d9bd4e1Sdrh ** utf16_aligned 31367d9bd4e1Sdrh ** utf16_unaligned 31377d9bd4e1Sdrh ** 31387d9bd4e1Sdrh ** Both collating sequences use the same sort order as BINARY. 31397d9bd4e1Sdrh ** The only difference is that the utf16_aligned collating 31407d9bd4e1Sdrh ** sequence is declared with the SQLITE_UTF16_ALIGNED flag. 31417d9bd4e1Sdrh ** Both collating functions increment the unaligned utf16 counter 31427d9bd4e1Sdrh ** whenever they see a string that begins on an odd byte boundary. 31437d9bd4e1Sdrh */ 31447d9bd4e1Sdrh static int unaligned_string_counter = 0; 31457d9bd4e1Sdrh static int alignmentCollFunc( 31467d9bd4e1Sdrh void *NotUsed, 31477d9bd4e1Sdrh int nKey1, const void *pKey1, 31487d9bd4e1Sdrh int nKey2, const void *pKey2 31497d9bd4e1Sdrh ){ 31507d9bd4e1Sdrh int rc, n; 31517d9bd4e1Sdrh n = nKey1<nKey2 ? nKey1 : nKey2; 3152d2199f0fSdan if( nKey1>0 && 1==(1&(SQLITE_PTR_TO_INT(pKey1))) ) unaligned_string_counter++; 3153d2199f0fSdan if( nKey2>0 && 1==(1&(SQLITE_PTR_TO_INT(pKey2))) ) unaligned_string_counter++; 31547d9bd4e1Sdrh rc = memcmp(pKey1, pKey2, n); 31557d9bd4e1Sdrh if( rc==0 ){ 31567d9bd4e1Sdrh rc = nKey1 - nKey2; 31577d9bd4e1Sdrh } 31587d9bd4e1Sdrh return rc; 31597d9bd4e1Sdrh } 31607617e4a8Smistachkin static int SQLITE_TCLAPI add_alignment_test_collations( 31617d9bd4e1Sdrh void * clientData, 31627d9bd4e1Sdrh Tcl_Interp *interp, 31637d9bd4e1Sdrh int objc, 31647d9bd4e1Sdrh Tcl_Obj *CONST objv[] 31657d9bd4e1Sdrh ){ 31667d9bd4e1Sdrh sqlite3 *db; 31677d9bd4e1Sdrh if( objc>=2 ){ 31687d9bd4e1Sdrh if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 3169ebb32939Sdanielk1977 sqlite3_create_collation(db, "utf16_unaligned", SQLITE_UTF16, 31707d9bd4e1Sdrh 0, alignmentCollFunc); 3171ebb32939Sdanielk1977 sqlite3_create_collation(db, "utf16_aligned", SQLITE_UTF16_ALIGNED, 31727d9bd4e1Sdrh 0, alignmentCollFunc); 31737d9bd4e1Sdrh } 31747d9bd4e1Sdrh return SQLITE_OK; 31757d9bd4e1Sdrh } 31767d9bd4e1Sdrh #endif /* !defined(SQLITE_OMIT_UTF16) */ 3177312d6b36Sdanielk1977 3178c8e9a2dfSdanielk1977 /* 3179c8e9a2dfSdanielk1977 ** Usage: add_test_function <db ptr> <utf8> <utf16le> <utf16be> 3180c8e9a2dfSdanielk1977 ** 3181c8e9a2dfSdanielk1977 ** This function is used to test that SQLite selects the correct user 3182c8e9a2dfSdanielk1977 ** function callback when multiple versions (for different text encodings) 3183c8e9a2dfSdanielk1977 ** are available. 3184c8e9a2dfSdanielk1977 ** 3185c8e9a2dfSdanielk1977 ** Calling this routine registers up to three versions of the user function 3186c8e9a2dfSdanielk1977 ** "test_function" with database handle <db>. If the second argument is 3187c8e9a2dfSdanielk1977 ** true, then a version of test_function is registered for UTF-8, if the 3188c8e9a2dfSdanielk1977 ** third is true, a version is registered for UTF-16le, if the fourth is 3189c8e9a2dfSdanielk1977 ** true, a UTF-16be version is available. Previous versions of 3190c8e9a2dfSdanielk1977 ** test_function are deleted. 3191c8e9a2dfSdanielk1977 ** 3192c8e9a2dfSdanielk1977 ** The user function is implemented by calling the following TCL script: 3193c8e9a2dfSdanielk1977 ** 3194c8e9a2dfSdanielk1977 ** "test_function <enc> <arg>" 3195c8e9a2dfSdanielk1977 ** 3196c8e9a2dfSdanielk1977 ** Where <enc> is one of UTF-8, UTF-16LE or UTF16BE, and <arg> is the 3197c8e9a2dfSdanielk1977 ** single argument passed to the SQL function. The value returned by 3198c8e9a2dfSdanielk1977 ** the TCL script is used as the return value of the SQL function. It 3199c8e9a2dfSdanielk1977 ** is passed to SQLite using UTF-16BE for a UTF-8 test_function(), UTF-8 3200c8e9a2dfSdanielk1977 ** for a UTF-16LE test_function(), and UTF-16LE for an implementation that 3201c8e9a2dfSdanielk1977 ** prefers UTF-16BE. 3202c8e9a2dfSdanielk1977 */ 32035436dc2dSdrh #ifndef SQLITE_OMIT_UTF16 3204c8e9a2dfSdanielk1977 static void test_function_utf8( 3205c8e9a2dfSdanielk1977 sqlite3_context *pCtx, 3206c8e9a2dfSdanielk1977 int nArg, 3207c8e9a2dfSdanielk1977 sqlite3_value **argv 3208c8e9a2dfSdanielk1977 ){ 3209c8e9a2dfSdanielk1977 Tcl_Interp *interp; 3210c8e9a2dfSdanielk1977 Tcl_Obj *pX; 3211c8e9a2dfSdanielk1977 sqlite3_value *pVal; 3212c8e9a2dfSdanielk1977 interp = (Tcl_Interp *)sqlite3_user_data(pCtx); 3213c8e9a2dfSdanielk1977 pX = Tcl_NewStringObj("test_function", -1); 3214c8e9a2dfSdanielk1977 Tcl_IncrRefCount(pX); 3215c8e9a2dfSdanielk1977 Tcl_ListObjAppendElement(interp, pX, Tcl_NewStringObj("UTF-8", -1)); 3216c8e9a2dfSdanielk1977 Tcl_ListObjAppendElement(interp, pX, 321703d847eaSdrh Tcl_NewStringObj((char*)sqlite3_value_text(argv[0]), -1)); 3218c8e9a2dfSdanielk1977 Tcl_EvalObjEx(interp, pX, 0); 3219c8e9a2dfSdanielk1977 Tcl_DecrRefCount(pX); 3220c8e9a2dfSdanielk1977 sqlite3_result_text(pCtx, Tcl_GetStringResult(interp), -1, SQLITE_TRANSIENT); 32211e536953Sdanielk1977 pVal = sqlite3ValueNew(0); 3222b21c8cd4Sdrh sqlite3ValueSetStr(pVal, -1, Tcl_GetStringResult(interp), 3223c8e9a2dfSdanielk1977 SQLITE_UTF8, SQLITE_STATIC); 3224c8e9a2dfSdanielk1977 sqlite3_result_text16be(pCtx, sqlite3_value_text16be(pVal), 3225c8e9a2dfSdanielk1977 -1, SQLITE_TRANSIENT); 3226c8e9a2dfSdanielk1977 sqlite3ValueFree(pVal); 3227c8e9a2dfSdanielk1977 } 3228c8e9a2dfSdanielk1977 static void test_function_utf16le( 3229c8e9a2dfSdanielk1977 sqlite3_context *pCtx, 3230c8e9a2dfSdanielk1977 int nArg, 3231c8e9a2dfSdanielk1977 sqlite3_value **argv 3232c8e9a2dfSdanielk1977 ){ 3233c8e9a2dfSdanielk1977 Tcl_Interp *interp; 3234c8e9a2dfSdanielk1977 Tcl_Obj *pX; 3235c8e9a2dfSdanielk1977 sqlite3_value *pVal; 3236c8e9a2dfSdanielk1977 interp = (Tcl_Interp *)sqlite3_user_data(pCtx); 3237c8e9a2dfSdanielk1977 pX = Tcl_NewStringObj("test_function", -1); 3238c8e9a2dfSdanielk1977 Tcl_IncrRefCount(pX); 3239c8e9a2dfSdanielk1977 Tcl_ListObjAppendElement(interp, pX, Tcl_NewStringObj("UTF-16LE", -1)); 3240c8e9a2dfSdanielk1977 Tcl_ListObjAppendElement(interp, pX, 324103d847eaSdrh Tcl_NewStringObj((char*)sqlite3_value_text(argv[0]), -1)); 3242c8e9a2dfSdanielk1977 Tcl_EvalObjEx(interp, pX, 0); 3243c8e9a2dfSdanielk1977 Tcl_DecrRefCount(pX); 32441e536953Sdanielk1977 pVal = sqlite3ValueNew(0); 3245b21c8cd4Sdrh sqlite3ValueSetStr(pVal, -1, Tcl_GetStringResult(interp), 3246c8e9a2dfSdanielk1977 SQLITE_UTF8, SQLITE_STATIC); 324703d847eaSdrh sqlite3_result_text(pCtx,(char*)sqlite3_value_text(pVal),-1,SQLITE_TRANSIENT); 3248c8e9a2dfSdanielk1977 sqlite3ValueFree(pVal); 3249c8e9a2dfSdanielk1977 } 3250c8e9a2dfSdanielk1977 static void test_function_utf16be( 3251c8e9a2dfSdanielk1977 sqlite3_context *pCtx, 3252c8e9a2dfSdanielk1977 int nArg, 3253c8e9a2dfSdanielk1977 sqlite3_value **argv 3254c8e9a2dfSdanielk1977 ){ 3255c8e9a2dfSdanielk1977 Tcl_Interp *interp; 3256c8e9a2dfSdanielk1977 Tcl_Obj *pX; 3257c8e9a2dfSdanielk1977 sqlite3_value *pVal; 3258c8e9a2dfSdanielk1977 interp = (Tcl_Interp *)sqlite3_user_data(pCtx); 3259c8e9a2dfSdanielk1977 pX = Tcl_NewStringObj("test_function", -1); 3260c8e9a2dfSdanielk1977 Tcl_IncrRefCount(pX); 3261c8e9a2dfSdanielk1977 Tcl_ListObjAppendElement(interp, pX, Tcl_NewStringObj("UTF-16BE", -1)); 3262c8e9a2dfSdanielk1977 Tcl_ListObjAppendElement(interp, pX, 326303d847eaSdrh Tcl_NewStringObj((char*)sqlite3_value_text(argv[0]), -1)); 3264c8e9a2dfSdanielk1977 Tcl_EvalObjEx(interp, pX, 0); 3265c8e9a2dfSdanielk1977 Tcl_DecrRefCount(pX); 32661e536953Sdanielk1977 pVal = sqlite3ValueNew(0); 3267b21c8cd4Sdrh sqlite3ValueSetStr(pVal, -1, Tcl_GetStringResult(interp), 3268c8e9a2dfSdanielk1977 SQLITE_UTF8, SQLITE_STATIC); 3269de4fcfddSdrh sqlite3_result_text16(pCtx, sqlite3_value_text16le(pVal), 3270de4fcfddSdrh -1, SQLITE_TRANSIENT); 3271de4fcfddSdrh sqlite3_result_text16be(pCtx, sqlite3_value_text16le(pVal), 3272de4fcfddSdrh -1, SQLITE_TRANSIENT); 3273c8e9a2dfSdanielk1977 sqlite3_result_text16le(pCtx, sqlite3_value_text16le(pVal), 3274c8e9a2dfSdanielk1977 -1, SQLITE_TRANSIENT); 3275c8e9a2dfSdanielk1977 sqlite3ValueFree(pVal); 3276c8e9a2dfSdanielk1977 } 32775436dc2dSdrh #endif /* SQLITE_OMIT_UTF16 */ 32787617e4a8Smistachkin static int SQLITE_TCLAPI test_function( 3279c8e9a2dfSdanielk1977 void * clientData, 3280c8e9a2dfSdanielk1977 Tcl_Interp *interp, 3281c8e9a2dfSdanielk1977 int objc, 3282c8e9a2dfSdanielk1977 Tcl_Obj *CONST objv[] 3283c8e9a2dfSdanielk1977 ){ 32845436dc2dSdrh #ifndef SQLITE_OMIT_UTF16 3285c8e9a2dfSdanielk1977 sqlite3 *db; 3286c8e9a2dfSdanielk1977 int val; 3287c8e9a2dfSdanielk1977 3288c8e9a2dfSdanielk1977 if( objc!=5 ) goto bad_args; 3289c8e9a2dfSdanielk1977 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 3290c8e9a2dfSdanielk1977 3291c8e9a2dfSdanielk1977 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[2], &val) ) return TCL_ERROR; 3292c8e9a2dfSdanielk1977 if( val ){ 3293c8e9a2dfSdanielk1977 sqlite3_create_function(db, "test_function", 1, SQLITE_UTF8, 3294c8e9a2dfSdanielk1977 interp, test_function_utf8, 0, 0); 3295c8e9a2dfSdanielk1977 } 3296c8e9a2dfSdanielk1977 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[3], &val) ) return TCL_ERROR; 3297c8e9a2dfSdanielk1977 if( val ){ 3298c8e9a2dfSdanielk1977 sqlite3_create_function(db, "test_function", 1, SQLITE_UTF16LE, 3299c8e9a2dfSdanielk1977 interp, test_function_utf16le, 0, 0); 3300c8e9a2dfSdanielk1977 } 3301c8e9a2dfSdanielk1977 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[4], &val) ) return TCL_ERROR; 3302c8e9a2dfSdanielk1977 if( val ){ 3303c8e9a2dfSdanielk1977 sqlite3_create_function(db, "test_function", 1, SQLITE_UTF16BE, 3304c8e9a2dfSdanielk1977 interp, test_function_utf16be, 0, 0); 3305c8e9a2dfSdanielk1977 } 3306c8e9a2dfSdanielk1977 3307c8e9a2dfSdanielk1977 return TCL_OK; 3308c8e9a2dfSdanielk1977 bad_args: 3309c8e9a2dfSdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 3310c8e9a2dfSdanielk1977 Tcl_GetStringFromObj(objv[0], 0), " <DB> <utf8> <utf16le> <utf16be>", 0); 33115436dc2dSdrh #endif /* SQLITE_OMIT_UTF16 */ 3312c8e9a2dfSdanielk1977 return TCL_ERROR; 3313c8e9a2dfSdanielk1977 } 3314c8e9a2dfSdanielk1977 3315312d6b36Sdanielk1977 /* 3316ba3cbf3dSdan ** Usage: sqlite3_test_errstr <err code> 3317312d6b36Sdanielk1977 ** 3318312d6b36Sdanielk1977 ** Test that the english language string equivalents for sqlite error codes 3319312d6b36Sdanielk1977 ** are sane. The parameter is an integer representing an sqlite error code. 3320312d6b36Sdanielk1977 ** The result is a list of two elements, the string representation of the 3321312d6b36Sdanielk1977 ** error code and the english language explanation. 3322312d6b36Sdanielk1977 */ 33237617e4a8Smistachkin static int SQLITE_TCLAPI test_errstr( 3324312d6b36Sdanielk1977 void * clientData, 3325312d6b36Sdanielk1977 Tcl_Interp *interp, 3326312d6b36Sdanielk1977 int objc, 3327312d6b36Sdanielk1977 Tcl_Obj *CONST objv[] 3328312d6b36Sdanielk1977 ){ 3329312d6b36Sdanielk1977 char *zCode; 3330312d6b36Sdanielk1977 int i; 3331312d6b36Sdanielk1977 if( objc!=1 ){ 3332312d6b36Sdanielk1977 Tcl_WrongNumArgs(interp, 1, objv, "<error code>"); 3333312d6b36Sdanielk1977 } 3334312d6b36Sdanielk1977 3335312d6b36Sdanielk1977 zCode = Tcl_GetString(objv[1]); 3336312d6b36Sdanielk1977 for(i=0; i<200; i++){ 33374f0c5878Sdrh if( 0==strcmp(t1ErrorName(i), zCode) ) break; 3338312d6b36Sdanielk1977 } 3339312d6b36Sdanielk1977 Tcl_SetResult(interp, (char *)sqlite3ErrStr(i), 0); 3340312d6b36Sdanielk1977 return TCL_OK; 3341312d6b36Sdanielk1977 } 3342312d6b36Sdanielk1977 334350457896Sdrh /* 334499ee3600Sdrh ** Usage: breakpoint 334599ee3600Sdrh ** 334699ee3600Sdrh ** This routine exists for one purpose - to provide a place to put a 334799ee3600Sdrh ** breakpoint with GDB that can be triggered using TCL code. The use 334899ee3600Sdrh ** for this is when a particular test fails on (say) the 1485th iteration. 334999ee3600Sdrh ** In the TCL test script, we can add code like this: 335099ee3600Sdrh ** 335199ee3600Sdrh ** if {$i==1485} breakpoint 335299ee3600Sdrh ** 335399ee3600Sdrh ** Then run testfixture in the debugger and wait for the breakpoint to 335499ee3600Sdrh ** fire. Then additional breakpoints can be set to trace down the bug. 335599ee3600Sdrh */ 33567617e4a8Smistachkin static int SQLITE_TCLAPI test_breakpoint( 335799ee3600Sdrh void *NotUsed, 335899ee3600Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 335999ee3600Sdrh int argc, /* Number of arguments */ 336099ee3600Sdrh char **argv /* Text of each argument */ 336199ee3600Sdrh ){ 336299ee3600Sdrh return TCL_OK; /* Do nothing */ 336399ee3600Sdrh } 336499ee3600Sdrh 3365241db313Sdrh /* 3366b026e05eSdrh ** Usage: sqlite3_bind_zeroblob STMT IDX N 3367b026e05eSdrh ** 3368b026e05eSdrh ** Test the sqlite3_bind_zeroblob interface. STMT is a prepared statement. 3369b026e05eSdrh ** IDX is the index of a wildcard in the prepared statement. This command 3370b026e05eSdrh ** binds a N-byte zero-filled BLOB to the wildcard. 3371b026e05eSdrh */ 33727617e4a8Smistachkin static int SQLITE_TCLAPI test_bind_zeroblob( 3373b026e05eSdrh void * clientData, 3374b026e05eSdrh Tcl_Interp *interp, 3375b026e05eSdrh int objc, 3376b026e05eSdrh Tcl_Obj *CONST objv[] 3377b026e05eSdrh ){ 3378b026e05eSdrh sqlite3_stmt *pStmt; 3379b026e05eSdrh int idx; 3380b026e05eSdrh int n; 3381b026e05eSdrh int rc; 3382b026e05eSdrh 3383b026e05eSdrh if( objc!=4 ){ 338428c66307Sdanielk1977 Tcl_WrongNumArgs(interp, 1, objv, "STMT IDX N"); 3385b026e05eSdrh return TCL_ERROR; 3386b026e05eSdrh } 3387b026e05eSdrh 3388b026e05eSdrh if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 3389b026e05eSdrh if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; 3390b026e05eSdrh if( Tcl_GetIntFromObj(interp, objv[3], &n) ) return TCL_ERROR; 3391b026e05eSdrh 3392b026e05eSdrh rc = sqlite3_bind_zeroblob(pStmt, idx, n); 3393b026e05eSdrh if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR; 3394b026e05eSdrh if( rc!=SQLITE_OK ){ 3395b026e05eSdrh return TCL_ERROR; 3396b026e05eSdrh } 3397b026e05eSdrh 3398b026e05eSdrh return TCL_OK; 3399b026e05eSdrh } 3400b026e05eSdrh 3401b026e05eSdrh /* 340280c03022Sdan ** Usage: sqlite3_bind_zeroblob64 STMT IDX N 340380c03022Sdan ** 340480c03022Sdan ** Test the sqlite3_bind_zeroblob64 interface. STMT is a prepared statement. 340580c03022Sdan ** IDX is the index of a wildcard in the prepared statement. This command 340680c03022Sdan ** binds a N-byte zero-filled BLOB to the wildcard. 340780c03022Sdan */ 34087617e4a8Smistachkin static int SQLITE_TCLAPI test_bind_zeroblob64( 340980c03022Sdan void * clientData, 341080c03022Sdan Tcl_Interp *interp, 341180c03022Sdan int objc, 341280c03022Sdan Tcl_Obj *CONST objv[] 341380c03022Sdan ){ 341480c03022Sdan sqlite3_stmt *pStmt; 341580c03022Sdan int idx; 34169a1e85eeSdrh Tcl_WideInt n; 341780c03022Sdan int rc; 341880c03022Sdan 341980c03022Sdan if( objc!=4 ){ 342080c03022Sdan Tcl_WrongNumArgs(interp, 1, objv, "STMT IDX N"); 342180c03022Sdan return TCL_ERROR; 342280c03022Sdan } 342380c03022Sdan 342480c03022Sdan if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 342580c03022Sdan if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; 342680c03022Sdan if( Tcl_GetWideIntFromObj(interp, objv[3], &n) ) return TCL_ERROR; 342780c03022Sdan 342880c03022Sdan rc = sqlite3_bind_zeroblob64(pStmt, idx, n); 342980c03022Sdan if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR; 343080c03022Sdan if( rc!=SQLITE_OK ){ 343180c03022Sdan Tcl_AppendResult(interp, sqlite3ErrName(rc), 0); 343280c03022Sdan return TCL_ERROR; 343380c03022Sdan } 343480c03022Sdan 343580c03022Sdan return TCL_OK; 343680c03022Sdan } 343780c03022Sdan 343880c03022Sdan /* 3439241db313Sdrh ** Usage: sqlite3_bind_int STMT N VALUE 3440241db313Sdrh ** 3441241db313Sdrh ** Test the sqlite3_bind_int interface. STMT is a prepared statement. 3442241db313Sdrh ** N is the index of a wildcard in the prepared statement. This command 3443241db313Sdrh ** binds a 32-bit integer VALUE to that wildcard. 3444241db313Sdrh */ 34457617e4a8Smistachkin static int SQLITE_TCLAPI test_bind_int( 344651e3d8e2Sdanielk1977 void * clientData, 344751e3d8e2Sdanielk1977 Tcl_Interp *interp, 344851e3d8e2Sdanielk1977 int objc, 344951e3d8e2Sdanielk1977 Tcl_Obj *CONST objv[] 345051e3d8e2Sdanielk1977 ){ 345151e3d8e2Sdanielk1977 sqlite3_stmt *pStmt; 345251e3d8e2Sdanielk1977 int idx; 345351e3d8e2Sdanielk1977 int value; 345451e3d8e2Sdanielk1977 int rc; 345551e3d8e2Sdanielk1977 345651e3d8e2Sdanielk1977 if( objc!=4 ){ 345751e3d8e2Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 3458241db313Sdrh Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE", 0); 345951e3d8e2Sdanielk1977 return TCL_ERROR; 346051e3d8e2Sdanielk1977 } 346151e3d8e2Sdanielk1977 346251e3d8e2Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 346351e3d8e2Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; 346451e3d8e2Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[3], &value) ) return TCL_ERROR; 346551e3d8e2Sdanielk1977 3466c572ef7fSdanielk1977 rc = sqlite3_bind_int(pStmt, idx, value); 3467c60d0446Sdrh if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR; 346851e3d8e2Sdanielk1977 if( rc!=SQLITE_OK ){ 346951e3d8e2Sdanielk1977 return TCL_ERROR; 347051e3d8e2Sdanielk1977 } 347151e3d8e2Sdanielk1977 347251e3d8e2Sdanielk1977 return TCL_OK; 347351e3d8e2Sdanielk1977 } 347451e3d8e2Sdanielk1977 3475241db313Sdrh 3476241db313Sdrh /* 34772e3f87aeSdrh ** Usage: intarray_addr INT ... 34784841624aSdrh ** 34792e3f87aeSdrh ** Return the address of a C-language array of 32-bit integers. 34802e3f87aeSdrh ** 34812e3f87aeSdrh ** Space to hold the array is obtained from malloc(). Call this procedure once 34822e3f87aeSdrh ** with no arguments in order to release memory. Each call to this procedure 34832e3f87aeSdrh ** overwrites the previous array. 34844841624aSdrh */ 34857617e4a8Smistachkin static int SQLITE_TCLAPI test_intarray_addr( 34864841624aSdrh void * clientData, 34874841624aSdrh Tcl_Interp *interp, 34884841624aSdrh int objc, 34894841624aSdrh Tcl_Obj *CONST objv[] 34904841624aSdrh ){ 34914841624aSdrh int i; 34924841624aSdrh static int *p = 0; 34934841624aSdrh 34944841624aSdrh sqlite3_free(p); 34954841624aSdrh p = 0; 34962e3f87aeSdrh if( objc>1 ){ 34972e3f87aeSdrh p = sqlite3_malloc( sizeof(p[0])*(objc-1) ); 34984841624aSdrh if( p==0 ) return TCL_ERROR; 34992e3f87aeSdrh for(i=0; i<objc-1; i++){ 35002e3f87aeSdrh if( Tcl_GetIntFromObj(interp, objv[1+i], &p[i]) ){ 35014841624aSdrh sqlite3_free(p); 35022e3f87aeSdrh p = 0; 35034841624aSdrh return TCL_ERROR; 35044841624aSdrh } 35054841624aSdrh } 35062e3f87aeSdrh } 35072e3f87aeSdrh Tcl_SetObjResult(interp, Tcl_NewWideIntObj((sqlite3_int64)p)); 35082e3f87aeSdrh return TCL_OK; 35092e3f87aeSdrh } 35102e3f87aeSdrh /* 35112e3f87aeSdrh ** Usage: intarray_addr INT ... 35122e3f87aeSdrh ** 35132e3f87aeSdrh ** Return the address of a C-language array of 32-bit integers. 35142e3f87aeSdrh ** 35152e3f87aeSdrh ** Space to hold the array is obtained from malloc(). Call this procedure once 35162e3f87aeSdrh ** with no arguments in order to release memory. Each call to this procedure 35172e3f87aeSdrh ** overwrites the previous array. 35182e3f87aeSdrh */ 35197617e4a8Smistachkin static int SQLITE_TCLAPI test_int64array_addr( 35202e3f87aeSdrh void * clientData, 35212e3f87aeSdrh Tcl_Interp *interp, 35222e3f87aeSdrh int objc, 35232e3f87aeSdrh Tcl_Obj *CONST objv[] 35242e3f87aeSdrh ){ 35252e3f87aeSdrh int i; 35262e3f87aeSdrh static sqlite3_int64 *p = 0; 35272e3f87aeSdrh 35282e3f87aeSdrh sqlite3_free(p); 35292e3f87aeSdrh p = 0; 35302e3f87aeSdrh if( objc>1 ){ 35312e3f87aeSdrh p = sqlite3_malloc( sizeof(p[0])*(objc-1) ); 35322e3f87aeSdrh if( p==0 ) return TCL_ERROR; 35332e3f87aeSdrh for(i=0; i<objc-1; i++){ 3534a912348aSdrh Tcl_WideInt v; 3535a912348aSdrh if( Tcl_GetWideIntFromObj(interp, objv[1+i], &v) ){ 35362e3f87aeSdrh sqlite3_free(p); 35372e3f87aeSdrh p = 0; 35382e3f87aeSdrh return TCL_ERROR; 35392e3f87aeSdrh } 3540a912348aSdrh p[i] = v; 35412e3f87aeSdrh } 35422e3f87aeSdrh } 35432e3f87aeSdrh Tcl_SetObjResult(interp, Tcl_NewWideIntObj((sqlite3_int64)p)); 35442e3f87aeSdrh return TCL_OK; 35452e3f87aeSdrh } 35462e3f87aeSdrh /* 35472e3f87aeSdrh ** Usage: doublearray_addr INT ... 35482e3f87aeSdrh ** 35492e3f87aeSdrh ** Return the address of a C-language array of doubles. 35502e3f87aeSdrh ** 35512e3f87aeSdrh ** Space to hold the array is obtained from malloc(). Call this procedure once 35522e3f87aeSdrh ** with no arguments in order to release memory. Each call to this procedure 35532e3f87aeSdrh ** overwrites the previous array. 35542e3f87aeSdrh */ 35557617e4a8Smistachkin static int SQLITE_TCLAPI test_doublearray_addr( 35562e3f87aeSdrh void * clientData, 35572e3f87aeSdrh Tcl_Interp *interp, 35582e3f87aeSdrh int objc, 35592e3f87aeSdrh Tcl_Obj *CONST objv[] 35602e3f87aeSdrh ){ 35612e3f87aeSdrh int i; 35622e3f87aeSdrh static double *p = 0; 35632e3f87aeSdrh 35642e3f87aeSdrh sqlite3_free(p); 35652e3f87aeSdrh p = 0; 35662e3f87aeSdrh if( objc>1 ){ 35672e3f87aeSdrh p = sqlite3_malloc( sizeof(p[0])*(objc-1) ); 35682e3f87aeSdrh if( p==0 ) return TCL_ERROR; 35692e3f87aeSdrh for(i=0; i<objc-1; i++){ 35702e3f87aeSdrh if( Tcl_GetDoubleFromObj(interp, objv[1+i], &p[i]) ){ 35712e3f87aeSdrh sqlite3_free(p); 35722e3f87aeSdrh p = 0; 35732e3f87aeSdrh return TCL_ERROR; 35742e3f87aeSdrh } 35752e3f87aeSdrh } 35762e3f87aeSdrh } 35772e3f87aeSdrh Tcl_SetObjResult(interp, Tcl_NewWideIntObj((sqlite3_int64)p)); 35782e3f87aeSdrh return TCL_OK; 35792e3f87aeSdrh } 35802e3f87aeSdrh /* 35812e3f87aeSdrh ** Usage: textarray_addr TEXT ... 35822e3f87aeSdrh ** 35832e3f87aeSdrh ** Return the address of a C-language array of strings. 35842e3f87aeSdrh ** 35852e3f87aeSdrh ** Space to hold the array is obtained from malloc(). Call this procedure once 35862e3f87aeSdrh ** with no arguments in order to release memory. Each call to this procedure 35872e3f87aeSdrh ** overwrites the previous array. 35882e3f87aeSdrh */ 35897617e4a8Smistachkin static int SQLITE_TCLAPI test_textarray_addr( 35902e3f87aeSdrh void * clientData, 35912e3f87aeSdrh Tcl_Interp *interp, 35922e3f87aeSdrh int objc, 35932e3f87aeSdrh Tcl_Obj *CONST objv[] 35942e3f87aeSdrh ){ 35952e3f87aeSdrh int i; 35962e3f87aeSdrh static int n = 0; 35972e3f87aeSdrh static char **p = 0; 35982e3f87aeSdrh 35992e3f87aeSdrh for(i=0; i<n; i++) sqlite3_free(p[i]); 36002e3f87aeSdrh sqlite3_free(p); 36012e3f87aeSdrh p = 0; 36022e3f87aeSdrh if( objc>1 ){ 36032e3f87aeSdrh p = sqlite3_malloc( sizeof(p[0])*(objc-1) ); 36042e3f87aeSdrh if( p==0 ) return TCL_ERROR; 36052e3f87aeSdrh for(i=0; i<objc-1; i++){ 36062e3f87aeSdrh p[i] = sqlite3_mprintf("%s", Tcl_GetString(objv[1+i])); 36072e3f87aeSdrh } 36082e3f87aeSdrh } 360950687436Sdan n = objc-1; 36102e3f87aeSdrh Tcl_SetObjResult(interp, Tcl_NewWideIntObj((sqlite3_int64)p)); 36114841624aSdrh return TCL_OK; 36124841624aSdrh } 36134841624aSdrh 36144841624aSdrh 36154841624aSdrh /* 3616241db313Sdrh ** Usage: sqlite3_bind_int64 STMT N VALUE 3617241db313Sdrh ** 3618241db313Sdrh ** Test the sqlite3_bind_int64 interface. STMT is a prepared statement. 3619241db313Sdrh ** N is the index of a wildcard in the prepared statement. This command 3620241db313Sdrh ** binds a 64-bit integer VALUE to that wildcard. 3621241db313Sdrh */ 36227617e4a8Smistachkin static int SQLITE_TCLAPI test_bind_int64( 362351e3d8e2Sdanielk1977 void * clientData, 362451e3d8e2Sdanielk1977 Tcl_Interp *interp, 362551e3d8e2Sdanielk1977 int objc, 362651e3d8e2Sdanielk1977 Tcl_Obj *CONST objv[] 362751e3d8e2Sdanielk1977 ){ 362851e3d8e2Sdanielk1977 sqlite3_stmt *pStmt; 362951e3d8e2Sdanielk1977 int idx; 3630b3f787f4Sdrh Tcl_WideInt value; 363151e3d8e2Sdanielk1977 int rc; 363251e3d8e2Sdanielk1977 363351e3d8e2Sdanielk1977 if( objc!=4 ){ 363451e3d8e2Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 3635241db313Sdrh Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE", 0); 363651e3d8e2Sdanielk1977 return TCL_ERROR; 363751e3d8e2Sdanielk1977 } 363851e3d8e2Sdanielk1977 363951e3d8e2Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 364051e3d8e2Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; 364151e3d8e2Sdanielk1977 if( Tcl_GetWideIntFromObj(interp, objv[3], &value) ) return TCL_ERROR; 364251e3d8e2Sdanielk1977 364351e3d8e2Sdanielk1977 rc = sqlite3_bind_int64(pStmt, idx, value); 3644c60d0446Sdrh if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR; 364551e3d8e2Sdanielk1977 if( rc!=SQLITE_OK ){ 364651e3d8e2Sdanielk1977 return TCL_ERROR; 364751e3d8e2Sdanielk1977 } 364851e3d8e2Sdanielk1977 364951e3d8e2Sdanielk1977 return TCL_OK; 365051e3d8e2Sdanielk1977 } 365151e3d8e2Sdanielk1977 3652241db313Sdrh 3653241db313Sdrh /* 3654241db313Sdrh ** Usage: sqlite3_bind_double STMT N VALUE 3655241db313Sdrh ** 3656241db313Sdrh ** Test the sqlite3_bind_double interface. STMT is a prepared statement. 3657241db313Sdrh ** N is the index of a wildcard in the prepared statement. This command 3658241db313Sdrh ** binds a 64-bit integer VALUE to that wildcard. 3659241db313Sdrh */ 36607617e4a8Smistachkin static int SQLITE_TCLAPI test_bind_double( 366151e3d8e2Sdanielk1977 void * clientData, 366251e3d8e2Sdanielk1977 Tcl_Interp *interp, 366351e3d8e2Sdanielk1977 int objc, 366451e3d8e2Sdanielk1977 Tcl_Obj *CONST objv[] 366551e3d8e2Sdanielk1977 ){ 366651e3d8e2Sdanielk1977 sqlite3_stmt *pStmt; 366751e3d8e2Sdanielk1977 int idx; 366827b2f053Smistachkin double value = 0; 366951e3d8e2Sdanielk1977 int rc; 3670a06f17feSdrh const char *zVal; 3671a06f17feSdrh int i; 3672a06f17feSdrh static const struct { 3673a06f17feSdrh const char *zName; /* Name of the special floating point value */ 3674a06f17feSdrh unsigned int iUpper; /* Upper 32 bits */ 3675a06f17feSdrh unsigned int iLower; /* Lower 32 bits */ 3676a06f17feSdrh } aSpecialFp[] = { 3677a06f17feSdrh { "NaN", 0x7fffffff, 0xffffffff }, 3678a06f17feSdrh { "SNaN", 0x7ff7ffff, 0xffffffff }, 3679a06f17feSdrh { "-NaN", 0xffffffff, 0xffffffff }, 3680a06f17feSdrh { "-SNaN", 0xfff7ffff, 0xffffffff }, 3681a06f17feSdrh { "+Inf", 0x7ff00000, 0x00000000 }, 3682a06f17feSdrh { "-Inf", 0xfff00000, 0x00000000 }, 3683a06f17feSdrh { "Epsilon", 0x00000000, 0x00000001 }, 3684a06f17feSdrh { "-Epsilon", 0x80000000, 0x00000001 }, 3685a06f17feSdrh { "NaN0", 0x7ff80000, 0x00000000 }, 3686a06f17feSdrh { "-NaN0", 0xfff80000, 0x00000000 }, 3687a06f17feSdrh }; 368851e3d8e2Sdanielk1977 368951e3d8e2Sdanielk1977 if( objc!=4 ){ 369051e3d8e2Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 3691241db313Sdrh Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE", 0); 369251e3d8e2Sdanielk1977 return TCL_ERROR; 369351e3d8e2Sdanielk1977 } 369451e3d8e2Sdanielk1977 369551e3d8e2Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 369651e3d8e2Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; 369751e3d8e2Sdanielk1977 3698394f07efSdrh /* Intercept the string "NaN" and generate a NaN value for it. 3699394f07efSdrh ** All other strings are passed through to Tcl_GetDoubleFromObj(). 3700394f07efSdrh ** Tcl_GetDoubleFromObj() should understand "NaN" but some versions 3701394f07efSdrh ** contain a bug. 3702394f07efSdrh */ 3703a06f17feSdrh zVal = Tcl_GetString(objv[3]); 3704a06f17feSdrh for(i=0; i<sizeof(aSpecialFp)/sizeof(aSpecialFp[0]); i++){ 3705a06f17feSdrh if( strcmp(aSpecialFp[i].zName, zVal)==0 ){ 3706a06f17feSdrh sqlite3_uint64 x; 3707a06f17feSdrh x = aSpecialFp[i].iUpper; 3708a06f17feSdrh x <<= 32; 3709a06f17feSdrh x |= aSpecialFp[i].iLower; 37100a66733aSdrh assert( sizeof(value)==8 ); 37110a66733aSdrh assert( sizeof(x)==8 ); 37120a66733aSdrh memcpy(&value, &x, 8); 3713a06f17feSdrh break; 3714a06f17feSdrh } 3715a06f17feSdrh } 3716a06f17feSdrh if( i>=sizeof(aSpecialFp)/sizeof(aSpecialFp[0]) && 3717a06f17feSdrh Tcl_GetDoubleFromObj(interp, objv[3], &value) ){ 3718394f07efSdrh return TCL_ERROR; 3719394f07efSdrh } 372051e3d8e2Sdanielk1977 rc = sqlite3_bind_double(pStmt, idx, value); 3721c60d0446Sdrh if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR; 372251e3d8e2Sdanielk1977 if( rc!=SQLITE_OK ){ 372351e3d8e2Sdanielk1977 return TCL_ERROR; 372451e3d8e2Sdanielk1977 } 372551e3d8e2Sdanielk1977 372651e3d8e2Sdanielk1977 return TCL_OK; 372751e3d8e2Sdanielk1977 } 372851e3d8e2Sdanielk1977 3729241db313Sdrh /* 3730241db313Sdrh ** Usage: sqlite3_bind_null STMT N 3731241db313Sdrh ** 3732241db313Sdrh ** Test the sqlite3_bind_null interface. STMT is a prepared statement. 3733241db313Sdrh ** N is the index of a wildcard in the prepared statement. This command 3734241db313Sdrh ** binds a NULL to the wildcard. 3735241db313Sdrh */ 37367617e4a8Smistachkin static int SQLITE_TCLAPI test_bind_null( 373751e3d8e2Sdanielk1977 void * clientData, 373851e3d8e2Sdanielk1977 Tcl_Interp *interp, 373951e3d8e2Sdanielk1977 int objc, 374051e3d8e2Sdanielk1977 Tcl_Obj *CONST objv[] 374151e3d8e2Sdanielk1977 ){ 374251e3d8e2Sdanielk1977 sqlite3_stmt *pStmt; 374351e3d8e2Sdanielk1977 int idx; 374451e3d8e2Sdanielk1977 int rc; 374551e3d8e2Sdanielk1977 374651e3d8e2Sdanielk1977 if( objc!=3 ){ 374751e3d8e2Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 3748241db313Sdrh Tcl_GetStringFromObj(objv[0], 0), " STMT N", 0); 374951e3d8e2Sdanielk1977 return TCL_ERROR; 375051e3d8e2Sdanielk1977 } 375151e3d8e2Sdanielk1977 375251e3d8e2Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 375351e3d8e2Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; 375451e3d8e2Sdanielk1977 375551e3d8e2Sdanielk1977 rc = sqlite3_bind_null(pStmt, idx); 3756c60d0446Sdrh if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR; 375751e3d8e2Sdanielk1977 if( rc!=SQLITE_OK ){ 375851e3d8e2Sdanielk1977 return TCL_ERROR; 375951e3d8e2Sdanielk1977 } 376051e3d8e2Sdanielk1977 376151e3d8e2Sdanielk1977 return TCL_OK; 376251e3d8e2Sdanielk1977 } 376351e3d8e2Sdanielk1977 3764241db313Sdrh /* 3765241db313Sdrh ** Usage: sqlite3_bind_text STMT N STRING BYTES 3766241db313Sdrh ** 3767241db313Sdrh ** Test the sqlite3_bind_text interface. STMT is a prepared statement. 3768241db313Sdrh ** N is the index of a wildcard in the prepared statement. This command 3769241db313Sdrh ** binds a UTF-8 string STRING to the wildcard. The string is BYTES bytes 3770241db313Sdrh ** long. 3771241db313Sdrh */ 37727617e4a8Smistachkin static int SQLITE_TCLAPI test_bind_text( 377351e3d8e2Sdanielk1977 void * clientData, 377451e3d8e2Sdanielk1977 Tcl_Interp *interp, 377551e3d8e2Sdanielk1977 int objc, 377651e3d8e2Sdanielk1977 Tcl_Obj *CONST objv[] 377751e3d8e2Sdanielk1977 ){ 377851e3d8e2Sdanielk1977 sqlite3_stmt *pStmt; 377951e3d8e2Sdanielk1977 int idx; 378051e3d8e2Sdanielk1977 int bytes; 378151e3d8e2Sdanielk1977 char *value; 378251e3d8e2Sdanielk1977 int rc; 378351e3d8e2Sdanielk1977 378451e3d8e2Sdanielk1977 if( objc!=5 ){ 378551e3d8e2Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 3786241db313Sdrh Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE BYTES", 0); 378751e3d8e2Sdanielk1977 return TCL_ERROR; 378851e3d8e2Sdanielk1977 } 378951e3d8e2Sdanielk1977 379051e3d8e2Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 379151e3d8e2Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; 379210dfbbb5Sdrh value = (char*)Tcl_GetByteArrayFromObj(objv[3], &bytes); 379351e3d8e2Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[4], &bytes) ) return TCL_ERROR; 379451e3d8e2Sdanielk1977 3795d8123366Sdanielk1977 rc = sqlite3_bind_text(pStmt, idx, value, bytes, SQLITE_TRANSIENT); 3796c60d0446Sdrh if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR; 379751e3d8e2Sdanielk1977 if( rc!=SQLITE_OK ){ 3798e84d8d32Smistachkin Tcl_AppendResult(interp, sqlite3ErrName(rc), 0); 379951e3d8e2Sdanielk1977 return TCL_ERROR; 380051e3d8e2Sdanielk1977 } 380151e3d8e2Sdanielk1977 380251e3d8e2Sdanielk1977 return TCL_OK; 380351e3d8e2Sdanielk1977 } 380451e3d8e2Sdanielk1977 3805241db313Sdrh /* 3806161fb796Sdanielk1977 ** Usage: sqlite3_bind_text16 ?-static? STMT N STRING BYTES 3807241db313Sdrh ** 3808241db313Sdrh ** Test the sqlite3_bind_text16 interface. STMT is a prepared statement. 3809241db313Sdrh ** N is the index of a wildcard in the prepared statement. This command 3810241db313Sdrh ** binds a UTF-16 string STRING to the wildcard. The string is BYTES bytes 3811241db313Sdrh ** long. 3812241db313Sdrh */ 38137617e4a8Smistachkin static int SQLITE_TCLAPI test_bind_text16( 381451e3d8e2Sdanielk1977 void * clientData, 381551e3d8e2Sdanielk1977 Tcl_Interp *interp, 381651e3d8e2Sdanielk1977 int objc, 381751e3d8e2Sdanielk1977 Tcl_Obj *CONST objv[] 381851e3d8e2Sdanielk1977 ){ 38195436dc2dSdrh #ifndef SQLITE_OMIT_UTF16 382051e3d8e2Sdanielk1977 sqlite3_stmt *pStmt; 382151e3d8e2Sdanielk1977 int idx; 382251e3d8e2Sdanielk1977 int bytes; 382351e3d8e2Sdanielk1977 char *value; 382451e3d8e2Sdanielk1977 int rc; 382551e3d8e2Sdanielk1977 38267da5fcb0Sdrh void (*xDel)(void*) = (objc==6?SQLITE_STATIC:SQLITE_TRANSIENT); 3827161fb796Sdanielk1977 Tcl_Obj *oStmt = objv[objc-4]; 3828161fb796Sdanielk1977 Tcl_Obj *oN = objv[objc-3]; 3829161fb796Sdanielk1977 Tcl_Obj *oString = objv[objc-2]; 3830161fb796Sdanielk1977 Tcl_Obj *oBytes = objv[objc-1]; 3831161fb796Sdanielk1977 3832161fb796Sdanielk1977 if( objc!=5 && objc!=6){ 383351e3d8e2Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 3834241db313Sdrh Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE BYTES", 0); 383551e3d8e2Sdanielk1977 return TCL_ERROR; 383651e3d8e2Sdanielk1977 } 383751e3d8e2Sdanielk1977 3838161fb796Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(oStmt), &pStmt) ) return TCL_ERROR; 3839161fb796Sdanielk1977 if( Tcl_GetIntFromObj(interp, oN, &idx) ) return TCL_ERROR; 3840161fb796Sdanielk1977 value = (char*)Tcl_GetByteArrayFromObj(oString, 0); 3841161fb796Sdanielk1977 if( Tcl_GetIntFromObj(interp, oBytes, &bytes) ) return TCL_ERROR; 384251e3d8e2Sdanielk1977 3843161fb796Sdanielk1977 rc = sqlite3_bind_text16(pStmt, idx, (void *)value, bytes, xDel); 3844c60d0446Sdrh if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR; 384551e3d8e2Sdanielk1977 if( rc!=SQLITE_OK ){ 3846e84d8d32Smistachkin Tcl_AppendResult(interp, sqlite3ErrName(rc), 0); 384751e3d8e2Sdanielk1977 return TCL_ERROR; 384851e3d8e2Sdanielk1977 } 384951e3d8e2Sdanielk1977 38505436dc2dSdrh #endif /* SQLITE_OMIT_UTF16 */ 385151e3d8e2Sdanielk1977 return TCL_OK; 385251e3d8e2Sdanielk1977 } 385351e3d8e2Sdanielk1977 3854241db313Sdrh /* 38555b159dc3Sdanielk1977 ** Usage: sqlite3_bind_blob ?-static? STMT N DATA BYTES 3856241db313Sdrh ** 3857241db313Sdrh ** Test the sqlite3_bind_blob interface. STMT is a prepared statement. 3858241db313Sdrh ** N is the index of a wildcard in the prepared statement. This command 3859241db313Sdrh ** binds a BLOB to the wildcard. The BLOB is BYTES bytes in size. 3860241db313Sdrh */ 38617617e4a8Smistachkin static int SQLITE_TCLAPI test_bind_blob( 386251e3d8e2Sdanielk1977 void * clientData, 386351e3d8e2Sdanielk1977 Tcl_Interp *interp, 386451e3d8e2Sdanielk1977 int objc, 386551e3d8e2Sdanielk1977 Tcl_Obj *CONST objv[] 386651e3d8e2Sdanielk1977 ){ 386751e3d8e2Sdanielk1977 sqlite3_stmt *pStmt; 3868de6fde6aSmistachkin int len, idx; 386951e3d8e2Sdanielk1977 int bytes; 387051e3d8e2Sdanielk1977 char *value; 387151e3d8e2Sdanielk1977 int rc; 38725b159dc3Sdanielk1977 sqlite3_destructor_type xDestructor = SQLITE_TRANSIENT; 387351e3d8e2Sdanielk1977 38745b159dc3Sdanielk1977 if( objc!=5 && objc!=6 ){ 387551e3d8e2Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 3876241db313Sdrh Tcl_GetStringFromObj(objv[0], 0), " STMT N DATA BYTES", 0); 387751e3d8e2Sdanielk1977 return TCL_ERROR; 387851e3d8e2Sdanielk1977 } 387951e3d8e2Sdanielk1977 38805b159dc3Sdanielk1977 if( objc==6 ){ 38815b159dc3Sdanielk1977 xDestructor = SQLITE_STATIC; 38825b159dc3Sdanielk1977 objv++; 38835b159dc3Sdanielk1977 } 38845b159dc3Sdanielk1977 388551e3d8e2Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 388651e3d8e2Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; 3887de6fde6aSmistachkin 38888d853642Sdrh value = (char*)Tcl_GetByteArrayFromObj(objv[3], &len); 388949e4643eSdanielk1977 if( Tcl_GetIntFromObj(interp, objv[4], &bytes) ) return TCL_ERROR; 389051e3d8e2Sdanielk1977 3891de6fde6aSmistachkin if( bytes>len ){ 3892de6fde6aSmistachkin char zBuf[200]; 3893de6fde6aSmistachkin sqlite3_snprintf(sizeof(zBuf), zBuf, 3894de6fde6aSmistachkin "cannot use %d blob bytes, have %d", bytes, len); 3895de6fde6aSmistachkin Tcl_AppendResult(interp, zBuf, -1); 3896de6fde6aSmistachkin return TCL_ERROR; 3897de6fde6aSmistachkin } 3898de6fde6aSmistachkin 38995b159dc3Sdanielk1977 rc = sqlite3_bind_blob(pStmt, idx, value, bytes, xDestructor); 3900c60d0446Sdrh if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR; 390151e3d8e2Sdanielk1977 if( rc!=SQLITE_OK ){ 390251e3d8e2Sdanielk1977 return TCL_ERROR; 390351e3d8e2Sdanielk1977 } 390451e3d8e2Sdanielk1977 390551e3d8e2Sdanielk1977 return TCL_OK; 390651e3d8e2Sdanielk1977 } 390751e3d8e2Sdanielk1977 390899ee3600Sdrh /* 390975f6a032Sdrh ** Usage: sqlite3_bind_parameter_count STMT 391075f6a032Sdrh ** 391175f6a032Sdrh ** Return the number of wildcards in the given statement. 391275f6a032Sdrh */ 39137617e4a8Smistachkin static int SQLITE_TCLAPI test_bind_parameter_count( 391475f6a032Sdrh void * clientData, 391575f6a032Sdrh Tcl_Interp *interp, 391675f6a032Sdrh int objc, 391775f6a032Sdrh Tcl_Obj *CONST objv[] 391875f6a032Sdrh ){ 391975f6a032Sdrh sqlite3_stmt *pStmt; 392075f6a032Sdrh 392175f6a032Sdrh if( objc!=2 ){ 392275f6a032Sdrh Tcl_WrongNumArgs(interp, 1, objv, "STMT"); 392375f6a032Sdrh return TCL_ERROR; 392475f6a032Sdrh } 392575f6a032Sdrh if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 392675f6a032Sdrh Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_bind_parameter_count(pStmt))); 392775f6a032Sdrh return TCL_OK; 392875f6a032Sdrh } 392975f6a032Sdrh 393075f6a032Sdrh /* 3931895d7472Sdrh ** Usage: sqlite3_bind_parameter_name STMT N 3932895d7472Sdrh ** 3933895d7472Sdrh ** Return the name of the Nth wildcard. The first wildcard is 1. 3934895d7472Sdrh ** An empty string is returned if N is out of range or if the wildcard 3935895d7472Sdrh ** is nameless. 3936895d7472Sdrh */ 39377617e4a8Smistachkin static int SQLITE_TCLAPI test_bind_parameter_name( 3938895d7472Sdrh void * clientData, 3939895d7472Sdrh Tcl_Interp *interp, 3940895d7472Sdrh int objc, 3941895d7472Sdrh Tcl_Obj *CONST objv[] 3942895d7472Sdrh ){ 3943895d7472Sdrh sqlite3_stmt *pStmt; 3944895d7472Sdrh int i; 3945895d7472Sdrh 3946895d7472Sdrh if( objc!=3 ){ 3947895d7472Sdrh Tcl_WrongNumArgs(interp, 1, objv, "STMT N"); 3948895d7472Sdrh return TCL_ERROR; 3949895d7472Sdrh } 3950895d7472Sdrh if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 3951895d7472Sdrh if( Tcl_GetIntFromObj(interp, objv[2], &i) ) return TCL_ERROR; 3952895d7472Sdrh Tcl_SetObjResult(interp, 3953895d7472Sdrh Tcl_NewStringObj(sqlite3_bind_parameter_name(pStmt,i),-1) 3954895d7472Sdrh ); 3955895d7472Sdrh return TCL_OK; 3956895d7472Sdrh } 3957895d7472Sdrh 3958895d7472Sdrh /* 3959fa6bc000Sdrh ** Usage: sqlite3_bind_parameter_index STMT NAME 3960fa6bc000Sdrh ** 3961fa6bc000Sdrh ** Return the index of the wildcard called NAME. Return 0 if there is 3962fa6bc000Sdrh ** no such wildcard. 3963fa6bc000Sdrh */ 39647617e4a8Smistachkin static int SQLITE_TCLAPI test_bind_parameter_index( 3965fa6bc000Sdrh void * clientData, 3966fa6bc000Sdrh Tcl_Interp *interp, 3967fa6bc000Sdrh int objc, 3968fa6bc000Sdrh Tcl_Obj *CONST objv[] 3969fa6bc000Sdrh ){ 3970fa6bc000Sdrh sqlite3_stmt *pStmt; 3971fa6bc000Sdrh 3972fa6bc000Sdrh if( objc!=3 ){ 3973fa6bc000Sdrh Tcl_WrongNumArgs(interp, 1, objv, "STMT NAME"); 3974fa6bc000Sdrh return TCL_ERROR; 3975fa6bc000Sdrh } 3976fa6bc000Sdrh if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 3977fa6bc000Sdrh Tcl_SetObjResult(interp, 3978fa6bc000Sdrh Tcl_NewIntObj( 3979fa6bc000Sdrh sqlite3_bind_parameter_index(pStmt,Tcl_GetString(objv[2])) 3980fa6bc000Sdrh ) 3981fa6bc000Sdrh ); 3982fa6bc000Sdrh return TCL_OK; 3983fa6bc000Sdrh } 3984fa6bc000Sdrh 3985fa6bc000Sdrh /* 3986600dd0baSdanielk1977 ** Usage: sqlite3_clear_bindings STMT 3987600dd0baSdanielk1977 ** 3988600dd0baSdanielk1977 */ 39897617e4a8Smistachkin static int SQLITE_TCLAPI test_clear_bindings( 3990600dd0baSdanielk1977 void * clientData, 3991600dd0baSdanielk1977 Tcl_Interp *interp, 3992600dd0baSdanielk1977 int objc, 3993600dd0baSdanielk1977 Tcl_Obj *CONST objv[] 3994600dd0baSdanielk1977 ){ 3995600dd0baSdanielk1977 sqlite3_stmt *pStmt; 3996600dd0baSdanielk1977 3997600dd0baSdanielk1977 if( objc!=2 ){ 3998600dd0baSdanielk1977 Tcl_WrongNumArgs(interp, 1, objv, "STMT"); 3999600dd0baSdanielk1977 return TCL_ERROR; 4000600dd0baSdanielk1977 } 4001600dd0baSdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 4002600dd0baSdanielk1977 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_clear_bindings(pStmt))); 4003600dd0baSdanielk1977 return TCL_OK; 4004600dd0baSdanielk1977 } 4005f9cb7f58Sdrh 4006f9cb7f58Sdrh /* 4007f9cb7f58Sdrh ** Usage: sqlite3_sleep MILLISECONDS 4008f9cb7f58Sdrh */ 40097617e4a8Smistachkin static int SQLITE_TCLAPI test_sleep( 4010f9cb7f58Sdrh void * clientData, 4011f9cb7f58Sdrh Tcl_Interp *interp, 4012f9cb7f58Sdrh int objc, 4013f9cb7f58Sdrh Tcl_Obj *CONST objv[] 4014f9cb7f58Sdrh ){ 4015f9cb7f58Sdrh int ms; 4016f9cb7f58Sdrh 4017f9cb7f58Sdrh if( objc!=2 ){ 4018f9cb7f58Sdrh Tcl_WrongNumArgs(interp, 1, objv, "MILLISECONDS"); 4019f9cb7f58Sdrh return TCL_ERROR; 4020f9cb7f58Sdrh } 4021f9cb7f58Sdrh if( Tcl_GetIntFromObj(interp, objv[1], &ms) ){ 4022f9cb7f58Sdrh return TCL_ERROR; 4023f9cb7f58Sdrh } 4024f9cb7f58Sdrh Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_sleep(ms))); 4025f9cb7f58Sdrh return TCL_OK; 4026f9cb7f58Sdrh } 4027600dd0baSdanielk1977 4028600dd0baSdanielk1977 /* 402999dfe5ebSdrh ** Usage: sqlite3_extended_errcode DB 403099dfe5ebSdrh ** 403199dfe5ebSdrh ** Return the string representation of the most recent sqlite3_* API 403299dfe5ebSdrh ** error code. e.g. "SQLITE_ERROR". 403399dfe5ebSdrh */ 40347617e4a8Smistachkin static int SQLITE_TCLAPI test_ex_errcode( 403599dfe5ebSdrh void * clientData, 403699dfe5ebSdrh Tcl_Interp *interp, 403799dfe5ebSdrh int objc, 403899dfe5ebSdrh Tcl_Obj *CONST objv[] 403999dfe5ebSdrh ){ 404099dfe5ebSdrh sqlite3 *db; 404199dfe5ebSdrh int rc; 404299dfe5ebSdrh 404399dfe5ebSdrh if( objc!=2 ){ 404499dfe5ebSdrh Tcl_AppendResult(interp, "wrong # args: should be \"", 404599dfe5ebSdrh Tcl_GetString(objv[0]), " DB", 0); 404699dfe5ebSdrh return TCL_ERROR; 404799dfe5ebSdrh } 404899dfe5ebSdrh if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 404999dfe5ebSdrh rc = sqlite3_extended_errcode(db); 405099dfe5ebSdrh Tcl_AppendResult(interp, (char *)t1ErrorName(rc), 0); 405199dfe5ebSdrh return TCL_OK; 405299dfe5ebSdrh } 405399dfe5ebSdrh 405499dfe5ebSdrh 405599dfe5ebSdrh /* 40566622cce3Sdanielk1977 ** Usage: sqlite3_errcode DB 40576622cce3Sdanielk1977 ** 40586622cce3Sdanielk1977 ** Return the string representation of the most recent sqlite3_* API 40596622cce3Sdanielk1977 ** error code. e.g. "SQLITE_ERROR". 40606622cce3Sdanielk1977 */ 40617617e4a8Smistachkin static int SQLITE_TCLAPI test_errcode( 40626622cce3Sdanielk1977 void * clientData, 40636622cce3Sdanielk1977 Tcl_Interp *interp, 40646622cce3Sdanielk1977 int objc, 40656622cce3Sdanielk1977 Tcl_Obj *CONST objv[] 40666622cce3Sdanielk1977 ){ 40676622cce3Sdanielk1977 sqlite3 *db; 40684ac285a1Sdrh int rc; 40696622cce3Sdanielk1977 40706622cce3Sdanielk1977 if( objc!=2 ){ 40716622cce3Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 40726622cce3Sdanielk1977 Tcl_GetString(objv[0]), " DB", 0); 40736622cce3Sdanielk1977 return TCL_ERROR; 40746622cce3Sdanielk1977 } 40756622cce3Sdanielk1977 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 40764ac285a1Sdrh rc = sqlite3_errcode(db); 407799dfe5ebSdrh Tcl_AppendResult(interp, (char *)t1ErrorName(rc), 0); 40786622cce3Sdanielk1977 return TCL_OK; 40796622cce3Sdanielk1977 } 40806622cce3Sdanielk1977 40816622cce3Sdanielk1977 /* 40820410302eSdanielk1977 ** Usage: sqlite3_errmsg DB 40836622cce3Sdanielk1977 ** 40846622cce3Sdanielk1977 ** Returns the UTF-8 representation of the error message string for the 40856622cce3Sdanielk1977 ** most recent sqlite3_* API call. 40866622cce3Sdanielk1977 */ 40877617e4a8Smistachkin static int SQLITE_TCLAPI test_errmsg( 40886622cce3Sdanielk1977 void * clientData, 40896622cce3Sdanielk1977 Tcl_Interp *interp, 40906622cce3Sdanielk1977 int objc, 40916622cce3Sdanielk1977 Tcl_Obj *CONST objv[] 40926622cce3Sdanielk1977 ){ 40939bb575fdSdrh sqlite3 *db; 40946622cce3Sdanielk1977 const char *zErr; 40956622cce3Sdanielk1977 40966622cce3Sdanielk1977 if( objc!=2 ){ 40976622cce3Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 40986622cce3Sdanielk1977 Tcl_GetString(objv[0]), " DB", 0); 40996622cce3Sdanielk1977 return TCL_ERROR; 41006622cce3Sdanielk1977 } 41016622cce3Sdanielk1977 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 41026622cce3Sdanielk1977 41036622cce3Sdanielk1977 zErr = sqlite3_errmsg(db); 41046622cce3Sdanielk1977 Tcl_SetObjResult(interp, Tcl_NewStringObj(zErr, -1)); 41056622cce3Sdanielk1977 return TCL_OK; 41066622cce3Sdanielk1977 } 41076622cce3Sdanielk1977 41086622cce3Sdanielk1977 /* 41096622cce3Sdanielk1977 ** Usage: test_errmsg16 DB 41106622cce3Sdanielk1977 ** 41116622cce3Sdanielk1977 ** Returns the UTF-16 representation of the error message string for the 41126622cce3Sdanielk1977 ** most recent sqlite3_* API call. This is a byte array object at the TCL 41136622cce3Sdanielk1977 ** level, and it includes the 0x00 0x00 terminator bytes at the end of the 41146622cce3Sdanielk1977 ** UTF-16 string. 41156622cce3Sdanielk1977 */ 41167617e4a8Smistachkin static int SQLITE_TCLAPI test_errmsg16( 41176622cce3Sdanielk1977 void * clientData, 41186622cce3Sdanielk1977 Tcl_Interp *interp, 41196622cce3Sdanielk1977 int objc, 41206622cce3Sdanielk1977 Tcl_Obj *CONST objv[] 41216622cce3Sdanielk1977 ){ 41225436dc2dSdrh #ifndef SQLITE_OMIT_UTF16 41239bb575fdSdrh sqlite3 *db; 41246622cce3Sdanielk1977 const void *zErr; 4125aed382f9Sdrh const char *z; 4126950f054cSdanielk1977 int bytes = 0; 41276622cce3Sdanielk1977 41286622cce3Sdanielk1977 if( objc!=2 ){ 41296622cce3Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 41306622cce3Sdanielk1977 Tcl_GetString(objv[0]), " DB", 0); 41316622cce3Sdanielk1977 return TCL_ERROR; 41326622cce3Sdanielk1977 } 41336622cce3Sdanielk1977 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 41346622cce3Sdanielk1977 41356622cce3Sdanielk1977 zErr = sqlite3_errmsg16(db); 4136950f054cSdanielk1977 if( zErr ){ 4137aed382f9Sdrh z = zErr; 4138aed382f9Sdrh for(bytes=0; z[bytes] || z[bytes+1]; bytes+=2){} 4139950f054cSdanielk1977 } 41406622cce3Sdanielk1977 Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(zErr, bytes)); 41415436dc2dSdrh #endif /* SQLITE_OMIT_UTF16 */ 41426622cce3Sdanielk1977 return TCL_OK; 41436622cce3Sdanielk1977 } 41446622cce3Sdanielk1977 41456622cce3Sdanielk1977 /* 41461c767f0dSdrh ** Usage: sqlite3_prepare DB sql bytes ?tailvar? 41476622cce3Sdanielk1977 ** 41486622cce3Sdanielk1977 ** Compile up to <bytes> bytes of the supplied SQL string <sql> using 41496622cce3Sdanielk1977 ** database handle <DB>. The parameter <tailval> is the name of a global 41506622cce3Sdanielk1977 ** variable that is set to the unused portion of <sql> (if any). A 41516622cce3Sdanielk1977 ** STMT handle is returned. 41526622cce3Sdanielk1977 */ 41537617e4a8Smistachkin static int SQLITE_TCLAPI test_prepare( 41546622cce3Sdanielk1977 void * clientData, 41556622cce3Sdanielk1977 Tcl_Interp *interp, 41566622cce3Sdanielk1977 int objc, 41576622cce3Sdanielk1977 Tcl_Obj *CONST objv[] 41586622cce3Sdanielk1977 ){ 41596622cce3Sdanielk1977 sqlite3 *db; 41606622cce3Sdanielk1977 const char *zSql; 41616622cce3Sdanielk1977 int bytes; 41626622cce3Sdanielk1977 const char *zTail = 0; 41636622cce3Sdanielk1977 sqlite3_stmt *pStmt = 0; 41646622cce3Sdanielk1977 char zBuf[50]; 41654ad1713cSdanielk1977 int rc; 41666622cce3Sdanielk1977 41671c767f0dSdrh if( objc!=5 && objc!=4 ){ 41686622cce3Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 41691c767f0dSdrh Tcl_GetString(objv[0]), " DB sql bytes ?tailvar?", 0); 41706622cce3Sdanielk1977 return TCL_ERROR; 41716622cce3Sdanielk1977 } 41726622cce3Sdanielk1977 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 41736622cce3Sdanielk1977 zSql = Tcl_GetString(objv[2]); 41746622cce3Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR; 41756622cce3Sdanielk1977 41761c767f0dSdrh rc = sqlite3_prepare(db, zSql, bytes, &pStmt, objc>=5 ? &zTail : 0); 4177937d0deaSdan Tcl_ResetResult(interp); 4178c60d0446Sdrh if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; 41791c767f0dSdrh if( zTail && objc>=5 ){ 41806622cce3Sdanielk1977 if( bytes>=0 ){ 418183cc1392Sdrh bytes = bytes - (int)(zTail-zSql); 41826622cce3Sdanielk1977 } 41837da5fcb0Sdrh if( (int)strlen(zTail)<bytes ){ 418483cc1392Sdrh bytes = (int)strlen(zTail); 41853a2c8c8bSdanielk1977 } 41866622cce3Sdanielk1977 Tcl_ObjSetVar2(interp, objv[4], 0, Tcl_NewStringObj(zTail, bytes), 0); 41876622cce3Sdanielk1977 } 41884ad1713cSdanielk1977 if( rc!=SQLITE_OK ){ 41894ad1713cSdanielk1977 assert( pStmt==0 ); 419065545b59Sdrh sqlite3_snprintf(sizeof(zBuf), zBuf, "(%d) ", rc); 41914ad1713cSdanielk1977 Tcl_AppendResult(interp, zBuf, sqlite3_errmsg(db), 0); 41924ad1713cSdanielk1977 return TCL_ERROR; 41934ad1713cSdanielk1977 } 41946622cce3Sdanielk1977 41954ad1713cSdanielk1977 if( pStmt ){ 419664b1bea3Sdrh if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR; 41976622cce3Sdanielk1977 Tcl_AppendResult(interp, zBuf, 0); 41984ad1713cSdanielk1977 } 41996622cce3Sdanielk1977 return TCL_OK; 42006622cce3Sdanielk1977 } 42016622cce3Sdanielk1977 42026622cce3Sdanielk1977 /* 42031c767f0dSdrh ** Usage: sqlite3_prepare_v2 DB sql bytes ?tailvar? 4204b900aaf3Sdrh ** 4205b900aaf3Sdrh ** Compile up to <bytes> bytes of the supplied SQL string <sql> using 4206b900aaf3Sdrh ** database handle <DB>. The parameter <tailval> is the name of a global 4207b900aaf3Sdrh ** variable that is set to the unused portion of <sql> (if any). A 4208b900aaf3Sdrh ** STMT handle is returned. 4209b900aaf3Sdrh */ 42107617e4a8Smistachkin static int SQLITE_TCLAPI test_prepare_v2( 4211b900aaf3Sdrh void * clientData, 4212b900aaf3Sdrh Tcl_Interp *interp, 4213b900aaf3Sdrh int objc, 4214b900aaf3Sdrh Tcl_Obj *CONST objv[] 4215b900aaf3Sdrh ){ 4216b900aaf3Sdrh sqlite3 *db; 4217b900aaf3Sdrh const char *zSql; 4218d89b834fSdan char *zCopy = 0; /* malloc() copy of zSql */ 4219b900aaf3Sdrh int bytes; 4220b900aaf3Sdrh const char *zTail = 0; 4221b900aaf3Sdrh sqlite3_stmt *pStmt = 0; 4222b900aaf3Sdrh char zBuf[50]; 4223b900aaf3Sdrh int rc; 4224b900aaf3Sdrh 42251c767f0dSdrh if( objc!=5 && objc!=4 ){ 4226b900aaf3Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", 4227b900aaf3Sdrh Tcl_GetString(objv[0]), " DB sql bytes tailvar", 0); 4228b900aaf3Sdrh return TCL_ERROR; 4229b900aaf3Sdrh } 4230b900aaf3Sdrh if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 4231b900aaf3Sdrh zSql = Tcl_GetString(objv[2]); 4232b900aaf3Sdrh if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR; 4233b900aaf3Sdrh 4234d89b834fSdan /* Instead of using zSql directly, make a copy into a buffer obtained 4235d89b834fSdan ** directly from malloc(). The idea is to make it easier for valgrind 4236d89b834fSdan ** to spot buffer overreads. */ 4237d89b834fSdan if( bytes>=0 ){ 4238d89b834fSdan zCopy = malloc(bytes); 4239d89b834fSdan memcpy(zCopy, zSql, bytes); 4240d89b834fSdan }else{ 42412c3abeb8Sdrh int n = (int)strlen(zSql) + 1; 4242d89b834fSdan zCopy = malloc(n); 4243d89b834fSdan memcpy(zCopy, zSql, n); 4244d89b834fSdan } 4245d89b834fSdan rc = sqlite3_prepare_v2(db, zCopy, bytes, &pStmt, objc>=5 ? &zTail : 0); 4246d89b834fSdan free(zCopy); 4247d89b834fSdan zTail = &zSql[(zTail - zCopy)]; 4248d89b834fSdan 42497e29e956Sdanielk1977 assert(rc==SQLITE_OK || pStmt==0); 4250937d0deaSdan Tcl_ResetResult(interp); 4251b900aaf3Sdrh if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; 4252e5d7bf1eSdrh if( rc==SQLITE_OK && zTail && objc>=5 ){ 4253b900aaf3Sdrh if( bytes>=0 ){ 425483cc1392Sdrh bytes = bytes - (int)(zTail-zSql); 4255b900aaf3Sdrh } 4256b900aaf3Sdrh Tcl_ObjSetVar2(interp, objv[4], 0, Tcl_NewStringObj(zTail, bytes), 0); 4257b900aaf3Sdrh } 4258b900aaf3Sdrh if( rc!=SQLITE_OK ){ 4259b900aaf3Sdrh assert( pStmt==0 ); 426065545b59Sdrh sqlite3_snprintf(sizeof(zBuf), zBuf, "(%d) ", rc); 4261b900aaf3Sdrh Tcl_AppendResult(interp, zBuf, sqlite3_errmsg(db), 0); 4262b900aaf3Sdrh return TCL_ERROR; 4263b900aaf3Sdrh } 4264b900aaf3Sdrh 4265b900aaf3Sdrh if( pStmt ){ 4266b900aaf3Sdrh if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR; 4267b900aaf3Sdrh Tcl_AppendResult(interp, zBuf, 0); 4268b900aaf3Sdrh } 4269b900aaf3Sdrh return TCL_OK; 4270b900aaf3Sdrh } 4271b900aaf3Sdrh 4272b900aaf3Sdrh /* 42734837f531Sdrh ** Usage: sqlite3_prepare_tkt3134 DB 42744837f531Sdrh ** 42754837f531Sdrh ** Generate a prepared statement for a zero-byte string as a test 427660ec914cSpeter.d.reid ** for ticket #3134. The string should be preceded by a zero byte. 42774837f531Sdrh */ 42787617e4a8Smistachkin static int SQLITE_TCLAPI test_prepare_tkt3134( 42794837f531Sdrh void * clientData, 42804837f531Sdrh Tcl_Interp *interp, 42814837f531Sdrh int objc, 42824837f531Sdrh Tcl_Obj *CONST objv[] 42834837f531Sdrh ){ 42844837f531Sdrh sqlite3 *db; 42854837f531Sdrh static const char zSql[] = "\000SELECT 1"; 42864837f531Sdrh sqlite3_stmt *pStmt = 0; 42874837f531Sdrh char zBuf[50]; 42884837f531Sdrh int rc; 42894837f531Sdrh 42904837f531Sdrh if( objc!=2 ){ 42914837f531Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", 42924837f531Sdrh Tcl_GetString(objv[0]), " DB sql bytes tailvar", 0); 42934837f531Sdrh return TCL_ERROR; 42944837f531Sdrh } 42954837f531Sdrh if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 42964837f531Sdrh rc = sqlite3_prepare_v2(db, &zSql[1], 0, &pStmt, 0); 42974837f531Sdrh assert(rc==SQLITE_OK || pStmt==0); 42984837f531Sdrh if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; 42994837f531Sdrh if( rc!=SQLITE_OK ){ 43004837f531Sdrh assert( pStmt==0 ); 430165545b59Sdrh sqlite3_snprintf(sizeof(zBuf), zBuf, "(%d) ", rc); 43024837f531Sdrh Tcl_AppendResult(interp, zBuf, sqlite3_errmsg(db), 0); 43034837f531Sdrh return TCL_ERROR; 43044837f531Sdrh } 43054837f531Sdrh 43064837f531Sdrh if( pStmt ){ 43074837f531Sdrh if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR; 43084837f531Sdrh Tcl_AppendResult(interp, zBuf, 0); 43094837f531Sdrh } 43104837f531Sdrh return TCL_OK; 43114837f531Sdrh } 43124837f531Sdrh 43134837f531Sdrh /* 4314b900aaf3Sdrh ** Usage: sqlite3_prepare16 DB sql bytes tailvar 43156622cce3Sdanielk1977 ** 43166622cce3Sdanielk1977 ** Compile up to <bytes> bytes of the supplied SQL string <sql> using 43176622cce3Sdanielk1977 ** database handle <DB>. The parameter <tailval> is the name of a global 43186622cce3Sdanielk1977 ** variable that is set to the unused portion of <sql> (if any). A 43196622cce3Sdanielk1977 ** STMT handle is returned. 43206622cce3Sdanielk1977 */ 43217617e4a8Smistachkin static int SQLITE_TCLAPI test_prepare16( 43226622cce3Sdanielk1977 void * clientData, 43236622cce3Sdanielk1977 Tcl_Interp *interp, 43246622cce3Sdanielk1977 int objc, 43256622cce3Sdanielk1977 Tcl_Obj *CONST objv[] 43266622cce3Sdanielk1977 ){ 43275436dc2dSdrh #ifndef SQLITE_OMIT_UTF16 43286622cce3Sdanielk1977 sqlite3 *db; 43296622cce3Sdanielk1977 const void *zSql; 43306622cce3Sdanielk1977 const void *zTail = 0; 43316622cce3Sdanielk1977 Tcl_Obj *pTail = 0; 43326622cce3Sdanielk1977 sqlite3_stmt *pStmt = 0; 43336622cce3Sdanielk1977 char zBuf[50]; 4334c60d0446Sdrh int rc; 43356622cce3Sdanielk1977 int bytes; /* The integer specified as arg 3 */ 43366622cce3Sdanielk1977 int objlen; /* The byte-array length of arg 2 */ 43376622cce3Sdanielk1977 43381c767f0dSdrh if( objc!=5 && objc!=4 ){ 43396622cce3Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 43401c767f0dSdrh Tcl_GetString(objv[0]), " DB sql bytes ?tailvar?", 0); 43416622cce3Sdanielk1977 return TCL_ERROR; 43426622cce3Sdanielk1977 } 43436622cce3Sdanielk1977 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 43446622cce3Sdanielk1977 zSql = Tcl_GetByteArrayFromObj(objv[2], &objlen); 43456622cce3Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR; 43466622cce3Sdanielk1977 43471c767f0dSdrh rc = sqlite3_prepare16(db, zSql, bytes, &pStmt, objc>=5 ? &zTail : 0); 4348c60d0446Sdrh if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; 4349c60d0446Sdrh if( rc ){ 43506622cce3Sdanielk1977 return TCL_ERROR; 43516622cce3Sdanielk1977 } 43526622cce3Sdanielk1977 43531c767f0dSdrh if( objc>=5 ){ 43546622cce3Sdanielk1977 if( zTail ){ 435583cc1392Sdrh objlen = objlen - (int)((u8 *)zTail-(u8 *)zSql); 43566622cce3Sdanielk1977 }else{ 43576622cce3Sdanielk1977 objlen = 0; 43586622cce3Sdanielk1977 } 43596622cce3Sdanielk1977 pTail = Tcl_NewByteArrayObj((u8 *)zTail, objlen); 43606622cce3Sdanielk1977 Tcl_IncrRefCount(pTail); 43616622cce3Sdanielk1977 Tcl_ObjSetVar2(interp, objv[4], 0, pTail, 0); 43624ad1713cSdanielk1977 Tcl_DecrRefCount(pTail); 43631c767f0dSdrh } 43646622cce3Sdanielk1977 43654ad1713cSdanielk1977 if( pStmt ){ 436664b1bea3Sdrh if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR; 43674ad1713cSdanielk1977 } 43686622cce3Sdanielk1977 Tcl_AppendResult(interp, zBuf, 0); 43695436dc2dSdrh #endif /* SQLITE_OMIT_UTF16 */ 43706622cce3Sdanielk1977 return TCL_OK; 43716622cce3Sdanielk1977 } 43726622cce3Sdanielk1977 43734ad1713cSdanielk1977 /* 43741c767f0dSdrh ** Usage: sqlite3_prepare16_v2 DB sql bytes ?tailvar? 4375b900aaf3Sdrh ** 4376b900aaf3Sdrh ** Compile up to <bytes> bytes of the supplied SQL string <sql> using 4377b900aaf3Sdrh ** database handle <DB>. The parameter <tailval> is the name of a global 4378b900aaf3Sdrh ** variable that is set to the unused portion of <sql> (if any). A 4379b900aaf3Sdrh ** STMT handle is returned. 4380b900aaf3Sdrh */ 43817617e4a8Smistachkin static int SQLITE_TCLAPI test_prepare16_v2( 4382b900aaf3Sdrh void * clientData, 4383b900aaf3Sdrh Tcl_Interp *interp, 4384b900aaf3Sdrh int objc, 4385b900aaf3Sdrh Tcl_Obj *CONST objv[] 4386b900aaf3Sdrh ){ 4387b900aaf3Sdrh #ifndef SQLITE_OMIT_UTF16 4388b900aaf3Sdrh sqlite3 *db; 4389b900aaf3Sdrh const void *zSql; 4390b900aaf3Sdrh const void *zTail = 0; 4391b900aaf3Sdrh Tcl_Obj *pTail = 0; 4392b900aaf3Sdrh sqlite3_stmt *pStmt = 0; 4393b900aaf3Sdrh char zBuf[50]; 4394b900aaf3Sdrh int rc; 4395b900aaf3Sdrh int bytes; /* The integer specified as arg 3 */ 4396b900aaf3Sdrh int objlen; /* The byte-array length of arg 2 */ 4397b900aaf3Sdrh 43981c767f0dSdrh if( objc!=5 && objc!=4 ){ 4399b900aaf3Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", 44001c767f0dSdrh Tcl_GetString(objv[0]), " DB sql bytes ?tailvar?", 0); 4401b900aaf3Sdrh return TCL_ERROR; 4402b900aaf3Sdrh } 4403b900aaf3Sdrh if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 4404b900aaf3Sdrh zSql = Tcl_GetByteArrayFromObj(objv[2], &objlen); 4405b900aaf3Sdrh if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR; 4406b900aaf3Sdrh 44071c767f0dSdrh rc = sqlite3_prepare16_v2(db, zSql, bytes, &pStmt, objc>=5 ? &zTail : 0); 4408b900aaf3Sdrh if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; 4409b900aaf3Sdrh if( rc ){ 4410b900aaf3Sdrh return TCL_ERROR; 4411b900aaf3Sdrh } 4412b900aaf3Sdrh 44131c767f0dSdrh if( objc>=5 ){ 4414b900aaf3Sdrh if( zTail ){ 441583cc1392Sdrh objlen = objlen - (int)((u8 *)zTail-(u8 *)zSql); 4416b900aaf3Sdrh }else{ 4417b900aaf3Sdrh objlen = 0; 4418b900aaf3Sdrh } 4419b900aaf3Sdrh pTail = Tcl_NewByteArrayObj((u8 *)zTail, objlen); 4420b900aaf3Sdrh Tcl_IncrRefCount(pTail); 4421b900aaf3Sdrh Tcl_ObjSetVar2(interp, objv[4], 0, pTail, 0); 4422b900aaf3Sdrh Tcl_DecrRefCount(pTail); 44231c767f0dSdrh } 4424b900aaf3Sdrh 4425b900aaf3Sdrh if( pStmt ){ 4426b900aaf3Sdrh if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR; 4427b900aaf3Sdrh } 4428b900aaf3Sdrh Tcl_AppendResult(interp, zBuf, 0); 4429b900aaf3Sdrh #endif /* SQLITE_OMIT_UTF16 */ 4430b900aaf3Sdrh return TCL_OK; 4431b900aaf3Sdrh } 4432b900aaf3Sdrh 4433b900aaf3Sdrh /* 44344ad1713cSdanielk1977 ** Usage: sqlite3_open filename ?options-list? 44354ad1713cSdanielk1977 */ 44367617e4a8Smistachkin static int SQLITE_TCLAPI test_open( 44374ad1713cSdanielk1977 void * clientData, 44384ad1713cSdanielk1977 Tcl_Interp *interp, 44394ad1713cSdanielk1977 int objc, 44404ad1713cSdanielk1977 Tcl_Obj *CONST objv[] 44414ad1713cSdanielk1977 ){ 44424ad1713cSdanielk1977 const char *zFilename; 44434ad1713cSdanielk1977 sqlite3 *db; 44444ad1713cSdanielk1977 char zBuf[100]; 44454ad1713cSdanielk1977 4446afc91047Sdrh if( objc!=3 && objc!=2 && objc!=1 ){ 44474ad1713cSdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 44484ad1713cSdanielk1977 Tcl_GetString(objv[0]), " filename options-list", 0); 44494ad1713cSdanielk1977 return TCL_ERROR; 44504ad1713cSdanielk1977 } 44514ad1713cSdanielk1977 4452afc91047Sdrh zFilename = objc>1 ? Tcl_GetString(objv[1]) : 0; 4453caffb1a5Sdrh sqlite3_open(zFilename, &db); 44544ad1713cSdanielk1977 445564b1bea3Sdrh if( sqlite3TestMakePointerStr(interp, zBuf, db) ) return TCL_ERROR; 44564ad1713cSdanielk1977 Tcl_AppendResult(interp, zBuf, 0); 44574ad1713cSdanielk1977 return TCL_OK; 44584ad1713cSdanielk1977 } 44594ad1713cSdanielk1977 44604ad1713cSdanielk1977 /* 4461286ab7c2Sdan ** Usage: sqlite3_open_v2 FILENAME FLAGS VFS 4462286ab7c2Sdan */ 44637617e4a8Smistachkin static int SQLITE_TCLAPI test_open_v2( 4464286ab7c2Sdan void * clientData, 4465286ab7c2Sdan Tcl_Interp *interp, 4466286ab7c2Sdan int objc, 4467286ab7c2Sdan Tcl_Obj *CONST objv[] 4468286ab7c2Sdan ){ 4469286ab7c2Sdan const char *zFilename; 4470286ab7c2Sdan const char *zVfs; 4471286ab7c2Sdan int flags = 0; 4472286ab7c2Sdan sqlite3 *db; 4473286ab7c2Sdan int rc; 4474286ab7c2Sdan char zBuf[100]; 4475286ab7c2Sdan 4476286ab7c2Sdan int nFlag; 4477286ab7c2Sdan Tcl_Obj **apFlag; 4478286ab7c2Sdan int i; 4479286ab7c2Sdan 4480286ab7c2Sdan if( objc!=4 ){ 4481286ab7c2Sdan Tcl_WrongNumArgs(interp, 1, objv, "FILENAME FLAGS VFS"); 4482286ab7c2Sdan return TCL_ERROR; 4483286ab7c2Sdan } 4484286ab7c2Sdan zFilename = Tcl_GetString(objv[1]); 4485286ab7c2Sdan zVfs = Tcl_GetString(objv[3]); 4486286ab7c2Sdan if( zVfs[0]==0x00 ) zVfs = 0; 4487286ab7c2Sdan 4488286ab7c2Sdan rc = Tcl_ListObjGetElements(interp, objv[2], &nFlag, &apFlag); 4489286ab7c2Sdan if( rc!=TCL_OK ) return rc; 4490286ab7c2Sdan for(i=0; i<nFlag; i++){ 4491286ab7c2Sdan int iFlag; 4492286ab7c2Sdan struct OpenFlag { 4493286ab7c2Sdan const char *zFlag; 4494286ab7c2Sdan int flag; 4495286ab7c2Sdan } aFlag[] = { 4496286ab7c2Sdan { "SQLITE_OPEN_READONLY", SQLITE_OPEN_READONLY }, 4497286ab7c2Sdan { "SQLITE_OPEN_READWRITE", SQLITE_OPEN_READWRITE }, 4498286ab7c2Sdan { "SQLITE_OPEN_CREATE", SQLITE_OPEN_CREATE }, 4499286ab7c2Sdan { "SQLITE_OPEN_DELETEONCLOSE", SQLITE_OPEN_DELETEONCLOSE }, 4500286ab7c2Sdan { "SQLITE_OPEN_EXCLUSIVE", SQLITE_OPEN_EXCLUSIVE }, 4501286ab7c2Sdan { "SQLITE_OPEN_AUTOPROXY", SQLITE_OPEN_AUTOPROXY }, 4502286ab7c2Sdan { "SQLITE_OPEN_MAIN_DB", SQLITE_OPEN_MAIN_DB }, 4503286ab7c2Sdan { "SQLITE_OPEN_TEMP_DB", SQLITE_OPEN_TEMP_DB }, 4504286ab7c2Sdan { "SQLITE_OPEN_TRANSIENT_DB", SQLITE_OPEN_TRANSIENT_DB }, 4505286ab7c2Sdan { "SQLITE_OPEN_MAIN_JOURNAL", SQLITE_OPEN_MAIN_JOURNAL }, 4506286ab7c2Sdan { "SQLITE_OPEN_TEMP_JOURNAL", SQLITE_OPEN_TEMP_JOURNAL }, 4507286ab7c2Sdan { "SQLITE_OPEN_SUBJOURNAL", SQLITE_OPEN_SUBJOURNAL }, 4508286ab7c2Sdan { "SQLITE_OPEN_MASTER_JOURNAL", SQLITE_OPEN_MASTER_JOURNAL }, 4509286ab7c2Sdan { "SQLITE_OPEN_NOMUTEX", SQLITE_OPEN_NOMUTEX }, 4510286ab7c2Sdan { "SQLITE_OPEN_FULLMUTEX", SQLITE_OPEN_FULLMUTEX }, 4511286ab7c2Sdan { "SQLITE_OPEN_SHAREDCACHE", SQLITE_OPEN_SHAREDCACHE }, 4512286ab7c2Sdan { "SQLITE_OPEN_PRIVATECACHE", SQLITE_OPEN_PRIVATECACHE }, 4513286ab7c2Sdan { "SQLITE_OPEN_WAL", SQLITE_OPEN_WAL }, 4514286ab7c2Sdan { "SQLITE_OPEN_URI", SQLITE_OPEN_URI }, 4515286ab7c2Sdan { 0, 0 } 4516286ab7c2Sdan }; 4517286ab7c2Sdan rc = Tcl_GetIndexFromObjStruct(interp, apFlag[i], aFlag, sizeof(aFlag[0]), 4518286ab7c2Sdan "flag", 0, &iFlag 4519286ab7c2Sdan ); 4520286ab7c2Sdan if( rc!=TCL_OK ) return rc; 4521286ab7c2Sdan flags |= aFlag[iFlag].flag; 4522286ab7c2Sdan } 4523286ab7c2Sdan 4524286ab7c2Sdan rc = sqlite3_open_v2(zFilename, &db, flags, zVfs); 4525286ab7c2Sdan if( sqlite3TestMakePointerStr(interp, zBuf, db) ) return TCL_ERROR; 4526286ab7c2Sdan Tcl_AppendResult(interp, zBuf, 0); 4527286ab7c2Sdan return TCL_OK; 4528286ab7c2Sdan } 4529286ab7c2Sdan 4530286ab7c2Sdan /* 45314ad1713cSdanielk1977 ** Usage: sqlite3_open16 filename options 45324ad1713cSdanielk1977 */ 45337617e4a8Smistachkin static int SQLITE_TCLAPI test_open16( 45344ad1713cSdanielk1977 void * clientData, 45354ad1713cSdanielk1977 Tcl_Interp *interp, 45364ad1713cSdanielk1977 int objc, 45374ad1713cSdanielk1977 Tcl_Obj *CONST objv[] 45384ad1713cSdanielk1977 ){ 45395436dc2dSdrh #ifndef SQLITE_OMIT_UTF16 45404ad1713cSdanielk1977 const void *zFilename; 45414ad1713cSdanielk1977 sqlite3 *db; 45424ad1713cSdanielk1977 char zBuf[100]; 45434ad1713cSdanielk1977 45444ad1713cSdanielk1977 if( objc!=3 ){ 45454ad1713cSdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 45464ad1713cSdanielk1977 Tcl_GetString(objv[0]), " filename options-list", 0); 45474ad1713cSdanielk1977 return TCL_ERROR; 45484ad1713cSdanielk1977 } 45494ad1713cSdanielk1977 45504ad1713cSdanielk1977 zFilename = Tcl_GetByteArrayFromObj(objv[1], 0); 4551caffb1a5Sdrh sqlite3_open16(zFilename, &db); 45524ad1713cSdanielk1977 455364b1bea3Sdrh if( sqlite3TestMakePointerStr(interp, zBuf, db) ) return TCL_ERROR; 45544ad1713cSdanielk1977 Tcl_AppendResult(interp, zBuf, 0); 45555436dc2dSdrh #endif /* SQLITE_OMIT_UTF16 */ 45564ad1713cSdanielk1977 return TCL_OK; 45574ad1713cSdanielk1977 } 4558d3d39e93Sdrh 4559d3d39e93Sdrh /* 4560bc6ada41Sdanielk1977 ** Usage: sqlite3_complete16 <UTF-16 string> 4561bc6ada41Sdanielk1977 ** 4562bc6ada41Sdanielk1977 ** Return 1 if the supplied argument is a complete SQL statement, or zero 4563bc6ada41Sdanielk1977 ** otherwise. 4564bc6ada41Sdanielk1977 */ 45657617e4a8Smistachkin static int SQLITE_TCLAPI test_complete16( 4566bc6ada41Sdanielk1977 void * clientData, 4567bc6ada41Sdanielk1977 Tcl_Interp *interp, 4568bc6ada41Sdanielk1977 int objc, 4569bc6ada41Sdanielk1977 Tcl_Obj *CONST objv[] 4570bc6ada41Sdanielk1977 ){ 4571ccae6026Sdrh #if !defined(SQLITE_OMIT_COMPLETE) && !defined(SQLITE_OMIT_UTF16) 4572bc6ada41Sdanielk1977 char *zBuf; 4573bc6ada41Sdanielk1977 4574bc6ada41Sdanielk1977 if( objc!=2 ){ 4575bc6ada41Sdanielk1977 Tcl_WrongNumArgs(interp, 1, objv, "<utf-16 sql>"); 4576bc6ada41Sdanielk1977 return TCL_ERROR; 4577bc6ada41Sdanielk1977 } 4578bc6ada41Sdanielk1977 457903d847eaSdrh zBuf = (char*)Tcl_GetByteArrayFromObj(objv[1], 0); 4580bc6ada41Sdanielk1977 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_complete16(zBuf))); 4581ccae6026Sdrh #endif /* SQLITE_OMIT_COMPLETE && SQLITE_OMIT_UTF16 */ 4582bc6ada41Sdanielk1977 return TCL_OK; 4583bc6ada41Sdanielk1977 } 4584bc6ada41Sdanielk1977 4585bc6ada41Sdanielk1977 /* 458691694dbdSdrh ** Usage: sqlite3_normalize SQL 458791694dbdSdrh ** 458891694dbdSdrh ** Return the normalized value for an SQL statement. 458991694dbdSdrh */ 459091694dbdSdrh static int SQLITE_TCLAPI test_normalize( 459191694dbdSdrh void * clientData, 459291694dbdSdrh Tcl_Interp *interp, 459391694dbdSdrh int objc, 459491694dbdSdrh Tcl_Obj *CONST objv[] 459591694dbdSdrh ){ 459691694dbdSdrh char *zSql; 459791694dbdSdrh char *zNorm; 459891694dbdSdrh extern char *sqlite3_normalize(const char*); 459991694dbdSdrh 460091694dbdSdrh if( objc!=2 ){ 460191694dbdSdrh Tcl_WrongNumArgs(interp, 1, objv, "SQL"); 460291694dbdSdrh return TCL_ERROR; 460391694dbdSdrh } 460491694dbdSdrh 460591694dbdSdrh zSql = (char*)Tcl_GetString(objv[1]); 460691694dbdSdrh zNorm = sqlite3_normalize(zSql); 460791694dbdSdrh if( zNorm ){ 460891694dbdSdrh Tcl_SetObjResult(interp, Tcl_NewStringObj(zNorm, -1)); 460991694dbdSdrh sqlite3_free(zNorm); 461091694dbdSdrh } 461191694dbdSdrh return TCL_OK; 461291694dbdSdrh } 461391694dbdSdrh 461491694dbdSdrh /* 4615106bb236Sdanielk1977 ** Usage: sqlite3_step STMT 4616106bb236Sdanielk1977 ** 4617106bb236Sdanielk1977 ** Advance the statement to the next row. 4618106bb236Sdanielk1977 */ 46197617e4a8Smistachkin static int SQLITE_TCLAPI test_step( 4620106bb236Sdanielk1977 void * clientData, 4621106bb236Sdanielk1977 Tcl_Interp *interp, 4622106bb236Sdanielk1977 int objc, 4623106bb236Sdanielk1977 Tcl_Obj *CONST objv[] 4624106bb236Sdanielk1977 ){ 4625106bb236Sdanielk1977 sqlite3_stmt *pStmt; 4626106bb236Sdanielk1977 int rc; 4627106bb236Sdanielk1977 4628e1cd9874Sdanielk1977 if( objc!=2 ){ 4629106bb236Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 4630106bb236Sdanielk1977 Tcl_GetString(objv[0]), " STMT", 0); 4631106bb236Sdanielk1977 return TCL_ERROR; 4632106bb236Sdanielk1977 } 4633106bb236Sdanielk1977 4634106bb236Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 463517240fd9Sdanielk1977 rc = sqlite3_step(pStmt); 4636106bb236Sdanielk1977 4637fbcd585fSdanielk1977 /* if( rc!=SQLITE_DONE && rc!=SQLITE_ROW ) return TCL_ERROR; */ 46384f0c5878Sdrh Tcl_SetResult(interp, (char *)t1ErrorName(rc), 0); 4639e1cd9874Sdanielk1977 return TCL_OK; 4640e1cd9874Sdanielk1977 } 4641e1cd9874Sdanielk1977 46427617e4a8Smistachkin static int SQLITE_TCLAPI test_sql( 4643404ca075Sdanielk1977 void * clientData, 4644404ca075Sdanielk1977 Tcl_Interp *interp, 4645404ca075Sdanielk1977 int objc, 4646404ca075Sdanielk1977 Tcl_Obj *CONST objv[] 4647404ca075Sdanielk1977 ){ 4648404ca075Sdanielk1977 sqlite3_stmt *pStmt; 4649404ca075Sdanielk1977 4650404ca075Sdanielk1977 if( objc!=2 ){ 4651404ca075Sdanielk1977 Tcl_WrongNumArgs(interp, 1, objv, "STMT"); 4652404ca075Sdanielk1977 return TCL_ERROR; 4653404ca075Sdanielk1977 } 4654404ca075Sdanielk1977 4655404ca075Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 4656404ca075Sdanielk1977 Tcl_SetResult(interp, (char *)sqlite3_sql(pStmt), TCL_VOLATILE); 4657404ca075Sdanielk1977 return TCL_OK; 4658404ca075Sdanielk1977 } 46597617e4a8Smistachkin static int SQLITE_TCLAPI test_ex_sql( 4660fca760c8Sdrh void * clientData, 4661fca760c8Sdrh Tcl_Interp *interp, 4662fca760c8Sdrh int objc, 4663fca760c8Sdrh Tcl_Obj *CONST objv[] 4664fca760c8Sdrh ){ 4665fca760c8Sdrh sqlite3_stmt *pStmt; 4666fca760c8Sdrh char *z; 4667fca760c8Sdrh 4668fca760c8Sdrh if( objc!=2 ){ 4669fca760c8Sdrh Tcl_WrongNumArgs(interp, 1, objv, "STMT"); 4670fca760c8Sdrh return TCL_ERROR; 4671fca760c8Sdrh } 4672fca760c8Sdrh 4673fca760c8Sdrh if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 4674fca760c8Sdrh z = sqlite3_expanded_sql(pStmt); 4675fca760c8Sdrh Tcl_SetResult(interp, z, TCL_VOLATILE); 4676fca760c8Sdrh sqlite3_free(z); 4677fca760c8Sdrh return TCL_OK; 4678fca760c8Sdrh } 4679404ca075Sdanielk1977 4680e1cd9874Sdanielk1977 /* 468117240fd9Sdanielk1977 ** Usage: sqlite3_column_count STMT 468217240fd9Sdanielk1977 ** 468317240fd9Sdanielk1977 ** Return the number of columns returned by the sql statement STMT. 468417240fd9Sdanielk1977 */ 46857617e4a8Smistachkin static int SQLITE_TCLAPI test_column_count( 468617240fd9Sdanielk1977 void * clientData, 468717240fd9Sdanielk1977 Tcl_Interp *interp, 468817240fd9Sdanielk1977 int objc, 468917240fd9Sdanielk1977 Tcl_Obj *CONST objv[] 469017240fd9Sdanielk1977 ){ 469117240fd9Sdanielk1977 sqlite3_stmt *pStmt; 469217240fd9Sdanielk1977 469317240fd9Sdanielk1977 if( objc!=2 ){ 469417240fd9Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 469517240fd9Sdanielk1977 Tcl_GetString(objv[0]), " STMT column", 0); 469617240fd9Sdanielk1977 return TCL_ERROR; 469717240fd9Sdanielk1977 } 469817240fd9Sdanielk1977 469917240fd9Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 470017240fd9Sdanielk1977 470117240fd9Sdanielk1977 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_column_count(pStmt))); 470217240fd9Sdanielk1977 return TCL_OK; 470317240fd9Sdanielk1977 } 470417240fd9Sdanielk1977 470517240fd9Sdanielk1977 /* 47063cf86063Sdanielk1977 ** Usage: sqlite3_column_type STMT column 47073cf86063Sdanielk1977 ** 47083cf86063Sdanielk1977 ** Return the type of the data in column 'column' of the current row. 47093cf86063Sdanielk1977 */ 47107617e4a8Smistachkin static int SQLITE_TCLAPI test_column_type( 47113cf86063Sdanielk1977 void * clientData, 47123cf86063Sdanielk1977 Tcl_Interp *interp, 47133cf86063Sdanielk1977 int objc, 47143cf86063Sdanielk1977 Tcl_Obj *CONST objv[] 47153cf86063Sdanielk1977 ){ 47163cf86063Sdanielk1977 sqlite3_stmt *pStmt; 47173cf86063Sdanielk1977 int col; 47183cf86063Sdanielk1977 int tp; 47193cf86063Sdanielk1977 47203cf86063Sdanielk1977 if( objc!=3 ){ 47213cf86063Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 47223cf86063Sdanielk1977 Tcl_GetString(objv[0]), " STMT column", 0); 47233cf86063Sdanielk1977 return TCL_ERROR; 47243cf86063Sdanielk1977 } 47253cf86063Sdanielk1977 47263cf86063Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 47273cf86063Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; 47283cf86063Sdanielk1977 47293cf86063Sdanielk1977 tp = sqlite3_column_type(pStmt, col); 47303cf86063Sdanielk1977 switch( tp ){ 47319c054830Sdrh case SQLITE_INTEGER: 47323cf86063Sdanielk1977 Tcl_SetResult(interp, "INTEGER", TCL_STATIC); 47333cf86063Sdanielk1977 break; 47349c054830Sdrh case SQLITE_NULL: 47353cf86063Sdanielk1977 Tcl_SetResult(interp, "NULL", TCL_STATIC); 47363cf86063Sdanielk1977 break; 47379c054830Sdrh case SQLITE_FLOAT: 47383cf86063Sdanielk1977 Tcl_SetResult(interp, "FLOAT", TCL_STATIC); 47393cf86063Sdanielk1977 break; 47409c054830Sdrh case SQLITE_TEXT: 47413cf86063Sdanielk1977 Tcl_SetResult(interp, "TEXT", TCL_STATIC); 47423cf86063Sdanielk1977 break; 47439c054830Sdrh case SQLITE_BLOB: 47443cf86063Sdanielk1977 Tcl_SetResult(interp, "BLOB", TCL_STATIC); 47453cf86063Sdanielk1977 break; 47463cf86063Sdanielk1977 default: 47473cf86063Sdanielk1977 assert(0); 47483cf86063Sdanielk1977 } 47493cf86063Sdanielk1977 47503cf86063Sdanielk1977 return TCL_OK; 47513cf86063Sdanielk1977 } 47523cf86063Sdanielk1977 47533cf86063Sdanielk1977 /* 475404f2e68dSdanielk1977 ** Usage: sqlite3_column_int64 STMT column 47553cf86063Sdanielk1977 ** 47563cf86063Sdanielk1977 ** Return the data in column 'column' of the current row cast as an 475704f2e68dSdanielk1977 ** wide (64-bit) integer. 47583cf86063Sdanielk1977 */ 47597617e4a8Smistachkin static int SQLITE_TCLAPI test_column_int64( 47603cf86063Sdanielk1977 void * clientData, 47613cf86063Sdanielk1977 Tcl_Interp *interp, 47623cf86063Sdanielk1977 int objc, 47633cf86063Sdanielk1977 Tcl_Obj *CONST objv[] 47643cf86063Sdanielk1977 ){ 47653cf86063Sdanielk1977 sqlite3_stmt *pStmt; 47663cf86063Sdanielk1977 int col; 476704f2e68dSdanielk1977 i64 iVal; 47683cf86063Sdanielk1977 47693cf86063Sdanielk1977 if( objc!=3 ){ 47703cf86063Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 47713cf86063Sdanielk1977 Tcl_GetString(objv[0]), " STMT column", 0); 47723cf86063Sdanielk1977 return TCL_ERROR; 47733cf86063Sdanielk1977 } 47743cf86063Sdanielk1977 47753cf86063Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 47763cf86063Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; 47773cf86063Sdanielk1977 477804f2e68dSdanielk1977 iVal = sqlite3_column_int64(pStmt, col); 477904f2e68dSdanielk1977 Tcl_SetObjResult(interp, Tcl_NewWideIntObj(iVal)); 478004f2e68dSdanielk1977 return TCL_OK; 478104f2e68dSdanielk1977 } 478204f2e68dSdanielk1977 478304f2e68dSdanielk1977 /* 4784ea61b2c4Sdanielk1977 ** Usage: sqlite3_column_blob STMT column 4785ea61b2c4Sdanielk1977 */ 47867617e4a8Smistachkin static int SQLITE_TCLAPI test_column_blob( 4787ea61b2c4Sdanielk1977 void * clientData, 4788ea61b2c4Sdanielk1977 Tcl_Interp *interp, 4789ea61b2c4Sdanielk1977 int objc, 4790ea61b2c4Sdanielk1977 Tcl_Obj *CONST objv[] 4791ea61b2c4Sdanielk1977 ){ 4792ea61b2c4Sdanielk1977 sqlite3_stmt *pStmt; 4793ea61b2c4Sdanielk1977 int col; 4794ea61b2c4Sdanielk1977 4795ea61b2c4Sdanielk1977 int len; 4796c572ef7fSdanielk1977 const void *pBlob; 4797ea61b2c4Sdanielk1977 4798ea61b2c4Sdanielk1977 if( objc!=3 ){ 4799ea61b2c4Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 4800ea61b2c4Sdanielk1977 Tcl_GetString(objv[0]), " STMT column", 0); 4801ea61b2c4Sdanielk1977 return TCL_ERROR; 4802ea61b2c4Sdanielk1977 } 4803ea61b2c4Sdanielk1977 4804ea61b2c4Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 4805ea61b2c4Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; 4806ea61b2c4Sdanielk1977 4807ea61b2c4Sdanielk1977 len = sqlite3_column_bytes(pStmt, col); 48089310ef23Sdrh pBlob = sqlite3_column_blob(pStmt, col); 4809ea61b2c4Sdanielk1977 Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(pBlob, len)); 4810ea61b2c4Sdanielk1977 return TCL_OK; 4811ea61b2c4Sdanielk1977 } 4812ea61b2c4Sdanielk1977 4813ea61b2c4Sdanielk1977 /* 481404f2e68dSdanielk1977 ** Usage: sqlite3_column_double STMT column 481504f2e68dSdanielk1977 ** 481604f2e68dSdanielk1977 ** Return the data in column 'column' of the current row cast as a double. 481704f2e68dSdanielk1977 */ 48187617e4a8Smistachkin static int SQLITE_TCLAPI test_column_double( 481904f2e68dSdanielk1977 void * clientData, 482004f2e68dSdanielk1977 Tcl_Interp *interp, 482104f2e68dSdanielk1977 int objc, 482204f2e68dSdanielk1977 Tcl_Obj *CONST objv[] 482304f2e68dSdanielk1977 ){ 482404f2e68dSdanielk1977 sqlite3_stmt *pStmt; 482504f2e68dSdanielk1977 int col; 482604f2e68dSdanielk1977 double rVal; 482704f2e68dSdanielk1977 482804f2e68dSdanielk1977 if( objc!=3 ){ 482904f2e68dSdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 483004f2e68dSdanielk1977 Tcl_GetString(objv[0]), " STMT column", 0); 483104f2e68dSdanielk1977 return TCL_ERROR; 483204f2e68dSdanielk1977 } 483304f2e68dSdanielk1977 483404f2e68dSdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 483504f2e68dSdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; 483604f2e68dSdanielk1977 483704f2e68dSdanielk1977 rVal = sqlite3_column_double(pStmt, col); 4838c572ef7fSdanielk1977 Tcl_SetObjResult(interp, Tcl_NewDoubleObj(rVal)); 48393cf86063Sdanielk1977 return TCL_OK; 48403cf86063Sdanielk1977 } 48413cf86063Sdanielk1977 48423cf86063Sdanielk1977 /* 484317240fd9Sdanielk1977 ** Usage: sqlite3_data_count STMT 484417240fd9Sdanielk1977 ** 484517240fd9Sdanielk1977 ** Return the number of columns returned by the sql statement STMT. 484617240fd9Sdanielk1977 */ 48477617e4a8Smistachkin static int SQLITE_TCLAPI test_data_count( 484817240fd9Sdanielk1977 void * clientData, 484917240fd9Sdanielk1977 Tcl_Interp *interp, 485017240fd9Sdanielk1977 int objc, 485117240fd9Sdanielk1977 Tcl_Obj *CONST objv[] 485217240fd9Sdanielk1977 ){ 485317240fd9Sdanielk1977 sqlite3_stmt *pStmt; 485417240fd9Sdanielk1977 485517240fd9Sdanielk1977 if( objc!=2 ){ 485617240fd9Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 485717240fd9Sdanielk1977 Tcl_GetString(objv[0]), " STMT column", 0); 485817240fd9Sdanielk1977 return TCL_ERROR; 485917240fd9Sdanielk1977 } 486017240fd9Sdanielk1977 486117240fd9Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 486217240fd9Sdanielk1977 486317240fd9Sdanielk1977 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_data_count(pStmt))); 486417240fd9Sdanielk1977 return TCL_OK; 486517240fd9Sdanielk1977 } 486617240fd9Sdanielk1977 486717240fd9Sdanielk1977 /* 486804f2e68dSdanielk1977 ** Usage: sqlite3_column_text STMT column 486904f2e68dSdanielk1977 ** 487004f2e68dSdanielk1977 ** Usage: sqlite3_column_decltype STMT column 487104f2e68dSdanielk1977 ** 487204f2e68dSdanielk1977 ** Usage: sqlite3_column_name STMT column 487304f2e68dSdanielk1977 */ 48747617e4a8Smistachkin static int SQLITE_TCLAPI test_stmt_utf8( 4875241db313Sdrh void * clientData, /* Pointer to SQLite API function to be invoke */ 487604f2e68dSdanielk1977 Tcl_Interp *interp, 487704f2e68dSdanielk1977 int objc, 487804f2e68dSdanielk1977 Tcl_Obj *CONST objv[] 487904f2e68dSdanielk1977 ){ 488004f2e68dSdanielk1977 sqlite3_stmt *pStmt; 488104f2e68dSdanielk1977 int col; 488244a376f6Sdanielk1977 const char *(*xFunc)(sqlite3_stmt*, int); 4883f93bbbeaSdanielk1977 const char *zRet; 488404f2e68dSdanielk1977 488544a376f6Sdanielk1977 xFunc = (const char *(*)(sqlite3_stmt*, int))clientData; 488604f2e68dSdanielk1977 if( objc!=3 ){ 488704f2e68dSdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 488804f2e68dSdanielk1977 Tcl_GetString(objv[0]), " STMT column", 0); 488904f2e68dSdanielk1977 return TCL_ERROR; 489004f2e68dSdanielk1977 } 489104f2e68dSdanielk1977 489204f2e68dSdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 489304f2e68dSdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; 4894f93bbbeaSdanielk1977 zRet = xFunc(pStmt, col); 4895f93bbbeaSdanielk1977 if( zRet ){ 4896f93bbbeaSdanielk1977 Tcl_SetResult(interp, (char *)zRet, 0); 4897f93bbbeaSdanielk1977 } 489804f2e68dSdanielk1977 return TCL_OK; 489904f2e68dSdanielk1977 } 490004f2e68dSdanielk1977 49017617e4a8Smistachkin static int SQLITE_TCLAPI test_global_recover( 49026b456a2bSdanielk1977 void * clientData, 49036b456a2bSdanielk1977 Tcl_Interp *interp, 49046b456a2bSdanielk1977 int objc, 49056b456a2bSdanielk1977 Tcl_Obj *CONST objv[] 49066b456a2bSdanielk1977 ){ 4907eec556d3Sshane #ifndef SQLITE_OMIT_DEPRECATED 49086b456a2bSdanielk1977 int rc; 49096b456a2bSdanielk1977 if( objc!=1 ){ 49106b456a2bSdanielk1977 Tcl_WrongNumArgs(interp, 1, objv, ""); 49116b456a2bSdanielk1977 return TCL_ERROR; 49126b456a2bSdanielk1977 } 49136b456a2bSdanielk1977 rc = sqlite3_global_recover(); 49144f0c5878Sdrh Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC); 49156b456a2bSdanielk1977 #endif 49166b456a2bSdanielk1977 return TCL_OK; 49176b456a2bSdanielk1977 } 49186b456a2bSdanielk1977 491904f2e68dSdanielk1977 /* 492004f2e68dSdanielk1977 ** Usage: sqlite3_column_text STMT column 492104f2e68dSdanielk1977 ** 492204f2e68dSdanielk1977 ** Usage: sqlite3_column_decltype STMT column 492304f2e68dSdanielk1977 ** 492404f2e68dSdanielk1977 ** Usage: sqlite3_column_name STMT column 492504f2e68dSdanielk1977 */ 49267617e4a8Smistachkin static int SQLITE_TCLAPI test_stmt_utf16( 4927241db313Sdrh void * clientData, /* Pointer to SQLite API function to be invoked */ 492804f2e68dSdanielk1977 Tcl_Interp *interp, 492904f2e68dSdanielk1977 int objc, 493004f2e68dSdanielk1977 Tcl_Obj *CONST objv[] 493104f2e68dSdanielk1977 ){ 49325436dc2dSdrh #ifndef SQLITE_OMIT_UTF16 493304f2e68dSdanielk1977 sqlite3_stmt *pStmt; 493404f2e68dSdanielk1977 int col; 493504f2e68dSdanielk1977 Tcl_Obj *pRet; 493604f2e68dSdanielk1977 const void *zName16; 493744a376f6Sdanielk1977 const void *(*xFunc)(sqlite3_stmt*, int); 493804f2e68dSdanielk1977 493944a376f6Sdanielk1977 xFunc = (const void *(*)(sqlite3_stmt*, int))clientData; 494004f2e68dSdanielk1977 if( objc!=3 ){ 494104f2e68dSdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 494204f2e68dSdanielk1977 Tcl_GetString(objv[0]), " STMT column", 0); 494304f2e68dSdanielk1977 return TCL_ERROR; 494404f2e68dSdanielk1977 } 494504f2e68dSdanielk1977 494604f2e68dSdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 494704f2e68dSdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; 494804f2e68dSdanielk1977 494904f2e68dSdanielk1977 zName16 = xFunc(pStmt, col); 4950f93bbbeaSdanielk1977 if( zName16 ){ 4951aed382f9Sdrh int n; 4952aed382f9Sdrh const char *z = zName16; 4953aed382f9Sdrh for(n=0; z[n] || z[n+1]; n+=2){} 4954aed382f9Sdrh pRet = Tcl_NewByteArrayObj(zName16, n+2); 495504f2e68dSdanielk1977 Tcl_SetObjResult(interp, pRet); 4956f93bbbeaSdanielk1977 } 49575436dc2dSdrh #endif /* SQLITE_OMIT_UTF16 */ 495804f2e68dSdanielk1977 495904f2e68dSdanielk1977 return TCL_OK; 496004f2e68dSdanielk1977 } 496104f2e68dSdanielk1977 496204f2e68dSdanielk1977 /* 496304f2e68dSdanielk1977 ** Usage: sqlite3_column_int STMT column 496404f2e68dSdanielk1977 ** 496504f2e68dSdanielk1977 ** Usage: sqlite3_column_bytes STMT column 496604f2e68dSdanielk1977 ** 496704f2e68dSdanielk1977 ** Usage: sqlite3_column_bytes16 STMT column 496804f2e68dSdanielk1977 ** 496904f2e68dSdanielk1977 */ 49707617e4a8Smistachkin static int SQLITE_TCLAPI test_stmt_int( 4971241db313Sdrh void * clientData, /* Pointer to SQLite API function to be invoked */ 497204f2e68dSdanielk1977 Tcl_Interp *interp, 497304f2e68dSdanielk1977 int objc, 497404f2e68dSdanielk1977 Tcl_Obj *CONST objv[] 497504f2e68dSdanielk1977 ){ 497604f2e68dSdanielk1977 sqlite3_stmt *pStmt; 497704f2e68dSdanielk1977 int col; 497844a376f6Sdanielk1977 int (*xFunc)(sqlite3_stmt*, int); 497904f2e68dSdanielk1977 498055a25a12Sdanielk1977 xFunc = (int (*)(sqlite3_stmt*, int))clientData; 498104f2e68dSdanielk1977 if( objc!=3 ){ 498204f2e68dSdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", 498304f2e68dSdanielk1977 Tcl_GetString(objv[0]), " STMT column", 0); 498404f2e68dSdanielk1977 return TCL_ERROR; 498504f2e68dSdanielk1977 } 498604f2e68dSdanielk1977 498704f2e68dSdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 498804f2e68dSdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; 498904f2e68dSdanielk1977 499004f2e68dSdanielk1977 Tcl_SetObjResult(interp, Tcl_NewIntObj(xFunc(pStmt, col))); 499104f2e68dSdanielk1977 return TCL_OK; 499204f2e68dSdanielk1977 } 499304f2e68dSdanielk1977 49946622cce3Sdanielk1977 /* 4995cacb208eSdrh ** Usage: sqlite_set_magic DB MAGIC-NUMBER 4996cacb208eSdrh ** 4997cacb208eSdrh ** Set the db->magic value. This is used to test error recovery logic. 4998cacb208eSdrh */ 49997617e4a8Smistachkin static int SQLITE_TCLAPI sqlite_set_magic( 5000cacb208eSdrh void * clientData, 5001cacb208eSdrh Tcl_Interp *interp, 5002cacb208eSdrh int argc, 5003cacb208eSdrh char **argv 5004cacb208eSdrh ){ 5005cacb208eSdrh sqlite3 *db; 5006cacb208eSdrh if( argc!=3 ){ 5007cacb208eSdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 5008cacb208eSdrh " DB MAGIC", 0); 5009cacb208eSdrh return TCL_ERROR; 5010cacb208eSdrh } 5011cacb208eSdrh if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; 5012cacb208eSdrh if( strcmp(argv[2], "SQLITE_MAGIC_OPEN")==0 ){ 5013cacb208eSdrh db->magic = SQLITE_MAGIC_OPEN; 5014cacb208eSdrh }else if( strcmp(argv[2], "SQLITE_MAGIC_CLOSED")==0 ){ 5015cacb208eSdrh db->magic = SQLITE_MAGIC_CLOSED; 5016cacb208eSdrh }else if( strcmp(argv[2], "SQLITE_MAGIC_BUSY")==0 ){ 5017cacb208eSdrh db->magic = SQLITE_MAGIC_BUSY; 5018cacb208eSdrh }else if( strcmp(argv[2], "SQLITE_MAGIC_ERROR")==0 ){ 5019cacb208eSdrh db->magic = SQLITE_MAGIC_ERROR; 5020902b9ee4Sdrh }else if( Tcl_GetInt(interp, argv[2], (int*)&db->magic) ){ 5021cacb208eSdrh return TCL_ERROR; 5022cacb208eSdrh } 5023cacb208eSdrh return TCL_OK; 5024cacb208eSdrh } 5025cacb208eSdrh 5026cacb208eSdrh /* 5027c5cdca61Sdrh ** Usage: sqlite3_interrupt DB 5028c5cdca61Sdrh ** 5029c5cdca61Sdrh ** Trigger an interrupt on DB 5030c5cdca61Sdrh */ 50317617e4a8Smistachkin static int SQLITE_TCLAPI test_interrupt( 5032c5cdca61Sdrh void * clientData, 5033c5cdca61Sdrh Tcl_Interp *interp, 5034c5cdca61Sdrh int argc, 5035c5cdca61Sdrh char **argv 5036c5cdca61Sdrh ){ 5037c5cdca61Sdrh sqlite3 *db; 5038c5cdca61Sdrh if( argc!=2 ){ 5039c5cdca61Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " DB", 0); 5040c5cdca61Sdrh return TCL_ERROR; 5041c5cdca61Sdrh } 5042c5cdca61Sdrh if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; 5043c5cdca61Sdrh sqlite3_interrupt(db); 5044c5cdca61Sdrh return TCL_OK; 5045c5cdca61Sdrh } 5046c5cdca61Sdrh 5047600dd0baSdanielk1977 /* 50489636c4e1Sdanielk1977 ** Usage: sqlite_delete_function DB function-name 50499636c4e1Sdanielk1977 ** 50509636c4e1Sdanielk1977 ** Delete the user function 'function-name' from database handle DB. It 50519636c4e1Sdanielk1977 ** is assumed that the user function was created as UTF8, any number of 50529636c4e1Sdanielk1977 ** arguments (the way the TCL interface does it). 50539636c4e1Sdanielk1977 */ 50547617e4a8Smistachkin static int SQLITE_TCLAPI delete_function( 50559636c4e1Sdanielk1977 void * clientData, 50569636c4e1Sdanielk1977 Tcl_Interp *interp, 50579636c4e1Sdanielk1977 int argc, 50589636c4e1Sdanielk1977 char **argv 50599636c4e1Sdanielk1977 ){ 50609636c4e1Sdanielk1977 int rc; 50619636c4e1Sdanielk1977 sqlite3 *db; 50629636c4e1Sdanielk1977 if( argc!=3 ){ 50639636c4e1Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 50649636c4e1Sdanielk1977 " DB function-name", 0); 50659636c4e1Sdanielk1977 return TCL_ERROR; 50669636c4e1Sdanielk1977 } 50679636c4e1Sdanielk1977 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; 50689636c4e1Sdanielk1977 rc = sqlite3_create_function(db, argv[2], -1, SQLITE_UTF8, 0, 0, 0, 0); 50694f0c5878Sdrh Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC); 50709636c4e1Sdanielk1977 return TCL_OK; 50719636c4e1Sdanielk1977 } 50729636c4e1Sdanielk1977 50739636c4e1Sdanielk1977 /* 50749636c4e1Sdanielk1977 ** Usage: sqlite_delete_collation DB collation-name 50759636c4e1Sdanielk1977 ** 50769636c4e1Sdanielk1977 ** Delete the collation sequence 'collation-name' from database handle 50779636c4e1Sdanielk1977 ** DB. It is assumed that the collation sequence was created as UTF8 (the 50789636c4e1Sdanielk1977 ** way the TCL interface does it). 50799636c4e1Sdanielk1977 */ 50807617e4a8Smistachkin static int SQLITE_TCLAPI delete_collation( 50819636c4e1Sdanielk1977 void * clientData, 50829636c4e1Sdanielk1977 Tcl_Interp *interp, 50839636c4e1Sdanielk1977 int argc, 50849636c4e1Sdanielk1977 char **argv 50859636c4e1Sdanielk1977 ){ 50869636c4e1Sdanielk1977 int rc; 50879636c4e1Sdanielk1977 sqlite3 *db; 50889636c4e1Sdanielk1977 if( argc!=3 ){ 50899636c4e1Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 50909636c4e1Sdanielk1977 " DB function-name", 0); 50919636c4e1Sdanielk1977 return TCL_ERROR; 50929636c4e1Sdanielk1977 } 50939636c4e1Sdanielk1977 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; 50949636c4e1Sdanielk1977 rc = sqlite3_create_collation(db, argv[2], SQLITE_UTF8, 0, 0); 50954f0c5878Sdrh Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC); 50969636c4e1Sdanielk1977 return TCL_OK; 50979636c4e1Sdanielk1977 } 50989636c4e1Sdanielk1977 50999636c4e1Sdanielk1977 /* 51003e1d8e63Sdrh ** Usage: sqlite3_get_autocommit DB 51013e1d8e63Sdrh ** 51023e1d8e63Sdrh ** Return true if the database DB is currently in auto-commit mode. 51033e1d8e63Sdrh ** Return false if not. 51043e1d8e63Sdrh */ 51057617e4a8Smistachkin static int SQLITE_TCLAPI get_autocommit( 51063e1d8e63Sdrh void * clientData, 51073e1d8e63Sdrh Tcl_Interp *interp, 51083e1d8e63Sdrh int argc, 51093e1d8e63Sdrh char **argv 51103e1d8e63Sdrh ){ 51113e1d8e63Sdrh char zBuf[30]; 51123e1d8e63Sdrh sqlite3 *db; 51133e1d8e63Sdrh if( argc!=2 ){ 51143e1d8e63Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 51153e1d8e63Sdrh " DB", 0); 51163e1d8e63Sdrh return TCL_ERROR; 51173e1d8e63Sdrh } 51183e1d8e63Sdrh if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; 511965545b59Sdrh sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", sqlite3_get_autocommit(db)); 51203e1d8e63Sdrh Tcl_AppendResult(interp, zBuf, 0); 51213e1d8e63Sdrh return TCL_OK; 51223e1d8e63Sdrh } 51233e1d8e63Sdrh 51243e1d8e63Sdrh /* 51253086765bSdrh ** Usage: sqlite3_busy_timeout DB MS 51263086765bSdrh ** 51273086765bSdrh ** Set the busy timeout. This is more easily done using the timeout 51283086765bSdrh ** method of the TCL interface. But we need a way to test the case 51293086765bSdrh ** where it returns SQLITE_MISUSE. 51303086765bSdrh */ 51317617e4a8Smistachkin static int SQLITE_TCLAPI test_busy_timeout( 51323086765bSdrh void * clientData, 51333086765bSdrh Tcl_Interp *interp, 51343086765bSdrh int argc, 51353086765bSdrh char **argv 51363086765bSdrh ){ 51373086765bSdrh int rc, ms; 51383086765bSdrh sqlite3 *db; 51393086765bSdrh if( argc!=3 ){ 51403086765bSdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 51413086765bSdrh " DB", 0); 51423086765bSdrh return TCL_ERROR; 51433086765bSdrh } 51443086765bSdrh if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; 51453086765bSdrh if( Tcl_GetInt(interp, argv[2], &ms) ) return TCL_ERROR; 51463086765bSdrh rc = sqlite3_busy_timeout(db, ms); 5147e84d8d32Smistachkin Tcl_AppendResult(interp, sqlite3ErrName(rc), 0); 51483086765bSdrh return TCL_OK; 51493086765bSdrh } 51503086765bSdrh 51513086765bSdrh /* 515292febd92Sdrh ** Usage: tcl_variable_type VARIABLENAME 515392febd92Sdrh ** 515492febd92Sdrh ** Return the name of the internal representation for the 515592febd92Sdrh ** value of the given variable. 515692febd92Sdrh */ 51577617e4a8Smistachkin static int SQLITE_TCLAPI tcl_variable_type( 515892febd92Sdrh void * clientData, 515992febd92Sdrh Tcl_Interp *interp, 516092febd92Sdrh int objc, 516192febd92Sdrh Tcl_Obj *CONST objv[] 516292febd92Sdrh ){ 516392febd92Sdrh Tcl_Obj *pVar; 516492febd92Sdrh if( objc!=2 ){ 516592febd92Sdrh Tcl_WrongNumArgs(interp, 1, objv, "VARIABLE"); 516692febd92Sdrh return TCL_ERROR; 516792febd92Sdrh } 516892febd92Sdrh pVar = Tcl_GetVar2Ex(interp, Tcl_GetString(objv[1]), 0, TCL_LEAVE_ERR_MSG); 516992febd92Sdrh if( pVar==0 ) return TCL_ERROR; 517092febd92Sdrh if( pVar->typePtr ){ 517192febd92Sdrh Tcl_SetObjResult(interp, Tcl_NewStringObj(pVar->typePtr->name, -1)); 517292febd92Sdrh } 517392febd92Sdrh return TCL_OK; 517492febd92Sdrh } 517592febd92Sdrh 517692febd92Sdrh /* 51776aafc29bSdrh ** Usage: sqlite3_release_memory ?N? 51786aafc29bSdrh ** 51796aafc29bSdrh ** Attempt to release memory currently held but not actually required. 51806aafc29bSdrh ** The integer N is the number of bytes we are trying to release. The 51816aafc29bSdrh ** return value is the amount of memory actually released. 51826aafc29bSdrh */ 51837617e4a8Smistachkin static int SQLITE_TCLAPI test_release_memory( 51846aafc29bSdrh void * clientData, 51856aafc29bSdrh Tcl_Interp *interp, 51866aafc29bSdrh int objc, 51876aafc29bSdrh Tcl_Obj *CONST objv[] 51886aafc29bSdrh ){ 51896f7adc8aSdrh #if defined(SQLITE_ENABLE_MEMORY_MANAGEMENT) && !defined(SQLITE_OMIT_DISKIO) 51906aafc29bSdrh int N; 51916aafc29bSdrh int amt; 51926aafc29bSdrh if( objc!=1 && objc!=2 ){ 51936aafc29bSdrh Tcl_WrongNumArgs(interp, 1, objv, "?N?"); 51946aafc29bSdrh return TCL_ERROR; 51956aafc29bSdrh } 51966aafc29bSdrh if( objc==2 ){ 51976aafc29bSdrh if( Tcl_GetIntFromObj(interp, objv[1], &N) ) return TCL_ERROR; 51986aafc29bSdrh }else{ 51996aafc29bSdrh N = -1; 52006aafc29bSdrh } 52016aafc29bSdrh amt = sqlite3_release_memory(N); 52026aafc29bSdrh Tcl_SetObjResult(interp, Tcl_NewIntObj(amt)); 52036aafc29bSdrh #endif 52046aafc29bSdrh return TCL_OK; 52056aafc29bSdrh } 52066aafc29bSdrh 520709419b4bSdrh 520809419b4bSdrh /* 520909419b4bSdrh ** Usage: sqlite3_db_release_memory DB 521009419b4bSdrh ** 521109419b4bSdrh ** Attempt to release memory currently held by database DB. Return the 521209419b4bSdrh ** result code (which in the current implementation is always zero). 521309419b4bSdrh */ 52147617e4a8Smistachkin static int SQLITE_TCLAPI test_db_release_memory( 521509419b4bSdrh void * clientData, 521609419b4bSdrh Tcl_Interp *interp, 521709419b4bSdrh int objc, 521809419b4bSdrh Tcl_Obj *CONST objv[] 521909419b4bSdrh ){ 522009419b4bSdrh sqlite3 *db; 522109419b4bSdrh int rc; 522209419b4bSdrh if( objc!=2 ){ 522309419b4bSdrh Tcl_WrongNumArgs(interp, 1, objv, "DB"); 522409419b4bSdrh return TCL_ERROR; 522509419b4bSdrh } 522609419b4bSdrh if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 522709419b4bSdrh rc = sqlite3_db_release_memory(db); 522809419b4bSdrh Tcl_SetObjResult(interp, Tcl_NewIntObj(rc)); 522909419b4bSdrh return TCL_OK; 523009419b4bSdrh } 523109419b4bSdrh 52326aafc29bSdrh /* 52336fa255fdSdan ** Usage: sqlite3_db_cacheflush DB 52346fa255fdSdan ** 52356fa255fdSdan ** Attempt to flush any dirty pages to disk. 52366fa255fdSdan */ 52377617e4a8Smistachkin static int SQLITE_TCLAPI test_db_cacheflush( 52386fa255fdSdan void * clientData, 52396fa255fdSdan Tcl_Interp *interp, 52406fa255fdSdan int objc, 52416fa255fdSdan Tcl_Obj *CONST objv[] 52426fa255fdSdan ){ 52436fa255fdSdan sqlite3 *db; 52446fa255fdSdan int rc; 52456fa255fdSdan if( objc!=2 ){ 52466fa255fdSdan Tcl_WrongNumArgs(interp, 1, objv, "DB"); 52476fa255fdSdan return TCL_ERROR; 52486fa255fdSdan } 52496fa255fdSdan if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 52506fa255fdSdan rc = sqlite3_db_cacheflush(db); 52516fa255fdSdan if( rc ){ 52526fa255fdSdan Tcl_SetResult(interp, (char *)sqlite3ErrStr(rc), TCL_STATIC); 52536fa255fdSdan return TCL_ERROR; 52546fa255fdSdan } 52556fa255fdSdan 52566fa255fdSdan Tcl_ResetResult(interp); 52576fa255fdSdan return TCL_OK; 52586fa255fdSdan } 52596fa255fdSdan 52606fa255fdSdan /* 52610e80e509Sdrh ** Usage: sqlite3_system_errno DB 52620e80e509Sdrh ** 52630e80e509Sdrh ** Return the low-level system errno value. 52640e80e509Sdrh */ 52657617e4a8Smistachkin static int SQLITE_TCLAPI test_system_errno( 52660e80e509Sdrh void * clientData, 52670e80e509Sdrh Tcl_Interp *interp, 52680e80e509Sdrh int objc, 52690e80e509Sdrh Tcl_Obj *CONST objv[] 52700e80e509Sdrh ){ 52710e80e509Sdrh sqlite3 *db; 52720e80e509Sdrh int iErrno; 52730e80e509Sdrh if( objc!=2 ){ 52740e80e509Sdrh Tcl_WrongNumArgs(interp, 1, objv, "DB"); 52750e80e509Sdrh return TCL_ERROR; 52760e80e509Sdrh } 52770e80e509Sdrh if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 52780e80e509Sdrh iErrno = sqlite3_system_errno(db); 52790e80e509Sdrh Tcl_SetObjResult(interp, Tcl_NewIntObj(iErrno)); 52800e80e509Sdrh return TCL_OK; 52810e80e509Sdrh } 52820e80e509Sdrh 52830e80e509Sdrh /* 5284283829cbSdrh ** Usage: sqlite3_db_filename DB DBNAME 5285283829cbSdrh ** 5286283829cbSdrh ** Return the name of a file associated with a database. 5287283829cbSdrh */ 52887617e4a8Smistachkin static int SQLITE_TCLAPI test_db_filename( 5289283829cbSdrh void * clientData, 5290283829cbSdrh Tcl_Interp *interp, 5291283829cbSdrh int objc, 5292283829cbSdrh Tcl_Obj *CONST objv[] 5293283829cbSdrh ){ 5294283829cbSdrh sqlite3 *db; 5295283829cbSdrh const char *zDbName; 5296283829cbSdrh if( objc!=3 ){ 5297283829cbSdrh Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME"); 5298283829cbSdrh return TCL_ERROR; 5299283829cbSdrh } 5300283829cbSdrh if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 5301283829cbSdrh zDbName = Tcl_GetString(objv[2]); 5302283829cbSdrh Tcl_AppendResult(interp, sqlite3_db_filename(db, zDbName), (void*)0); 5303283829cbSdrh return TCL_OK; 5304283829cbSdrh } 5305283829cbSdrh 5306283829cbSdrh /* 5307421377e6Sdrh ** Usage: sqlite3_db_readonly DB DBNAME 5308421377e6Sdrh ** 5309421377e6Sdrh ** Return 1 or 0 if DBNAME is readonly or not. Return -1 if DBNAME does 5310421377e6Sdrh ** not exist. 5311421377e6Sdrh */ 53127617e4a8Smistachkin static int SQLITE_TCLAPI test_db_readonly( 5313421377e6Sdrh void * clientData, 5314421377e6Sdrh Tcl_Interp *interp, 5315421377e6Sdrh int objc, 5316421377e6Sdrh Tcl_Obj *CONST objv[] 5317421377e6Sdrh ){ 5318421377e6Sdrh sqlite3 *db; 5319421377e6Sdrh const char *zDbName; 5320421377e6Sdrh if( objc!=3 ){ 5321421377e6Sdrh Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME"); 5322421377e6Sdrh return TCL_ERROR; 5323421377e6Sdrh } 5324421377e6Sdrh if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 5325421377e6Sdrh zDbName = Tcl_GetString(objv[2]); 5326421377e6Sdrh Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_db_readonly(db, zDbName))); 5327421377e6Sdrh return TCL_OK; 5328421377e6Sdrh } 5329421377e6Sdrh 5330421377e6Sdrh /* 53316aafc29bSdrh ** Usage: sqlite3_soft_heap_limit ?N? 53326aafc29bSdrh ** 53336aafc29bSdrh ** Query or set the soft heap limit for the current thread. The 53346aafc29bSdrh ** limit is only changed if the N is present. The previous limit 53356aafc29bSdrh ** is returned. 53366aafc29bSdrh */ 53377617e4a8Smistachkin static int SQLITE_TCLAPI test_soft_heap_limit( 53386aafc29bSdrh void * clientData, 53396aafc29bSdrh Tcl_Interp *interp, 53406aafc29bSdrh int objc, 53416aafc29bSdrh Tcl_Obj *CONST objv[] 53426aafc29bSdrh ){ 5343f82ccf64Sdrh sqlite3_int64 amt; 5344b3f787f4Sdrh Tcl_WideInt N = -1; 53456aafc29bSdrh if( objc!=1 && objc!=2 ){ 53466aafc29bSdrh Tcl_WrongNumArgs(interp, 1, objv, "?N?"); 53476aafc29bSdrh return TCL_ERROR; 53486aafc29bSdrh } 53496aafc29bSdrh if( objc==2 ){ 5350f82ccf64Sdrh if( Tcl_GetWideIntFromObj(interp, objv[1], &N) ) return TCL_ERROR; 53516aafc29bSdrh } 5352f82ccf64Sdrh amt = sqlite3_soft_heap_limit64(N); 5353f82ccf64Sdrh Tcl_SetObjResult(interp, Tcl_NewWideIntObj(amt)); 53546aafc29bSdrh return TCL_OK; 53556aafc29bSdrh } 53566aafc29bSdrh 53576aafc29bSdrh /* 5358b4bc7057Sdrh ** Usage: sqlite3_thread_cleanup 5359b4bc7057Sdrh ** 5360b4bc7057Sdrh ** Call the sqlite3_thread_cleanup API. 5361b4bc7057Sdrh */ 53627617e4a8Smistachkin static int SQLITE_TCLAPI test_thread_cleanup( 5363b4bc7057Sdrh void * clientData, 5364b4bc7057Sdrh Tcl_Interp *interp, 5365b4bc7057Sdrh int objc, 5366b4bc7057Sdrh Tcl_Obj *CONST objv[] 5367b4bc7057Sdrh ){ 5368eec556d3Sshane #ifndef SQLITE_OMIT_DEPRECATED 5369b4bc7057Sdrh sqlite3_thread_cleanup(); 5370eec556d3Sshane #endif 5371b4bc7057Sdrh return TCL_OK; 5372b4bc7057Sdrh } 5373b4bc7057Sdrh 5374b4bc7057Sdrh /* 5375c6ba55f4Sdrh ** Usage: sqlite3_pager_refcounts DB 5376c6ba55f4Sdrh ** 5377f5345443Sdrh ** Return a list of numbers which are the PagerRefcount for all 5378f5345443Sdrh ** pagers on each database connection. 5379c6ba55f4Sdrh */ 53807617e4a8Smistachkin static int SQLITE_TCLAPI test_pager_refcounts( 5381c6ba55f4Sdrh void * clientData, 5382c6ba55f4Sdrh Tcl_Interp *interp, 5383c6ba55f4Sdrh int objc, 5384c6ba55f4Sdrh Tcl_Obj *CONST objv[] 5385c6ba55f4Sdrh ){ 5386c6ba55f4Sdrh sqlite3 *db; 5387c6ba55f4Sdrh int i; 5388c6ba55f4Sdrh int v, *a; 5389c6ba55f4Sdrh Tcl_Obj *pResult; 5390c6ba55f4Sdrh 5391c6ba55f4Sdrh if( objc!=2 ){ 5392c6ba55f4Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", 5393f5345443Sdrh Tcl_GetStringFromObj(objv[0], 0), " DB", 0); 5394c6ba55f4Sdrh return TCL_ERROR; 5395c6ba55f4Sdrh } 5396c6ba55f4Sdrh if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 5397c6ba55f4Sdrh pResult = Tcl_NewObj(); 5398c6ba55f4Sdrh for(i=0; i<db->nDb; i++){ 5399c6ba55f4Sdrh if( db->aDb[i].pBt==0 ){ 5400c6ba55f4Sdrh v = -1; 5401c6ba55f4Sdrh }else{ 540227641703Sdrh sqlite3_mutex_enter(db->mutex); 5403c6ba55f4Sdrh a = sqlite3PagerStats(sqlite3BtreePager(db->aDb[i].pBt)); 5404c6ba55f4Sdrh v = a[0]; 540527641703Sdrh sqlite3_mutex_leave(db->mutex); 5406c6ba55f4Sdrh } 5407c6ba55f4Sdrh Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(v)); 5408c6ba55f4Sdrh } 5409c6ba55f4Sdrh Tcl_SetObjResult(interp, pResult); 5410c6ba55f4Sdrh return TCL_OK; 5411c6ba55f4Sdrh } 5412c6ba55f4Sdrh 5413c6ba55f4Sdrh 5414c6ba55f4Sdrh /* 541580788d8bSdrh ** tclcmd: working_64bit_int 541680788d8bSdrh ** 541780788d8bSdrh ** Some TCL builds (ex: cygwin) do not support 64-bit integers. This 541880788d8bSdrh ** leads to a number of test failures. The present command checks the 541980788d8bSdrh ** TCL build to see whether or not it supports 64-bit integers. It 542080788d8bSdrh ** returns TRUE if it does and FALSE if not. 542180788d8bSdrh ** 542280788d8bSdrh ** This command is used to warn users that their TCL build is defective 542380788d8bSdrh ** and that the errors they are seeing in the test scripts might be 542480788d8bSdrh ** a result of their defective TCL rather than problems in SQLite. 542580788d8bSdrh */ 54267617e4a8Smistachkin static int SQLITE_TCLAPI working_64bit_int( 542780788d8bSdrh ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ 542880788d8bSdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 542980788d8bSdrh int objc, /* Number of arguments */ 543080788d8bSdrh Tcl_Obj *CONST objv[] /* Command arguments */ 543180788d8bSdrh ){ 543280788d8bSdrh Tcl_Obj *pTestObj; 543380788d8bSdrh int working = 0; 543480788d8bSdrh 543580788d8bSdrh pTestObj = Tcl_NewWideIntObj(1000000*(i64)1234567890); 543680788d8bSdrh working = strcmp(Tcl_GetString(pTestObj), "1234567890000000")==0; 543780788d8bSdrh Tcl_DecrRefCount(pTestObj); 543880788d8bSdrh Tcl_SetObjResult(interp, Tcl_NewBooleanObj(working)); 543980788d8bSdrh return TCL_OK; 544080788d8bSdrh } 544180788d8bSdrh 544280788d8bSdrh 544380788d8bSdrh /* 54449bc5449fSdrh ** tclcmd: vfs_unlink_test 54459bc5449fSdrh ** 54469bc5449fSdrh ** This TCL command unregisters the primary VFS and then registers 54479bc5449fSdrh ** it back again. This is used to test the ability to register a 54489bc5449fSdrh ** VFS when none are previously registered, and the ability to 54499bc5449fSdrh ** unregister the only available VFS. Ticket #2738 54509bc5449fSdrh */ 54517617e4a8Smistachkin static int SQLITE_TCLAPI vfs_unlink_test( 54529bc5449fSdrh ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ 54539bc5449fSdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 54549bc5449fSdrh int objc, /* Number of arguments */ 54559bc5449fSdrh Tcl_Obj *CONST objv[] /* Command arguments */ 54569bc5449fSdrh ){ 54579bc5449fSdrh int i; 545891fd4d46Sdrh sqlite3_vfs *pMain; 54599bc5449fSdrh sqlite3_vfs *apVfs[20]; 546091fd4d46Sdrh sqlite3_vfs one, two; 54619bc5449fSdrh 546291fd4d46Sdrh sqlite3_vfs_unregister(0); /* Unregister of NULL is harmless */ 546391fd4d46Sdrh one.zName = "__one"; 546491fd4d46Sdrh two.zName = "__two"; 546591fd4d46Sdrh 546691fd4d46Sdrh /* Calling sqlite3_vfs_register with 2nd argument of 0 does not 546791fd4d46Sdrh ** change the default VFS 546891fd4d46Sdrh */ 546991fd4d46Sdrh pMain = sqlite3_vfs_find(0); 547091fd4d46Sdrh sqlite3_vfs_register(&one, 0); 547191fd4d46Sdrh assert( pMain==0 || pMain==sqlite3_vfs_find(0) ); 547291fd4d46Sdrh sqlite3_vfs_register(&two, 0); 547391fd4d46Sdrh assert( pMain==0 || pMain==sqlite3_vfs_find(0) ); 547491fd4d46Sdrh 547591fd4d46Sdrh /* We can find a VFS by its name */ 547691fd4d46Sdrh assert( sqlite3_vfs_find("__one")==&one ); 547791fd4d46Sdrh assert( sqlite3_vfs_find("__two")==&two ); 547891fd4d46Sdrh 547991fd4d46Sdrh /* Calling sqlite_vfs_register with non-zero second parameter changes the 548091fd4d46Sdrh ** default VFS, even if the 1st parameter is an existig VFS that is 548191fd4d46Sdrh ** previously registered as the non-default. 548291fd4d46Sdrh */ 548391fd4d46Sdrh sqlite3_vfs_register(&one, 1); 548491fd4d46Sdrh assert( sqlite3_vfs_find("__one")==&one ); 548591fd4d46Sdrh assert( sqlite3_vfs_find("__two")==&two ); 548691fd4d46Sdrh assert( sqlite3_vfs_find(0)==&one ); 548791fd4d46Sdrh sqlite3_vfs_register(&two, 1); 548891fd4d46Sdrh assert( sqlite3_vfs_find("__one")==&one ); 548991fd4d46Sdrh assert( sqlite3_vfs_find("__two")==&two ); 549091fd4d46Sdrh assert( sqlite3_vfs_find(0)==&two ); 549191fd4d46Sdrh if( pMain ){ 549291fd4d46Sdrh sqlite3_vfs_register(pMain, 1); 549391fd4d46Sdrh assert( sqlite3_vfs_find("__one")==&one ); 549491fd4d46Sdrh assert( sqlite3_vfs_find("__two")==&two ); 549591fd4d46Sdrh assert( sqlite3_vfs_find(0)==pMain ); 549691fd4d46Sdrh } 549791fd4d46Sdrh 549891fd4d46Sdrh /* Unlink the default VFS. Repeat until there are no more VFSes 549991fd4d46Sdrh ** registered. 550091fd4d46Sdrh */ 55019bc5449fSdrh for(i=0; i<sizeof(apVfs)/sizeof(apVfs[0]); i++){ 55029bc5449fSdrh apVfs[i] = sqlite3_vfs_find(0); 55039bc5449fSdrh if( apVfs[i] ){ 55049bc5449fSdrh assert( apVfs[i]==sqlite3_vfs_find(apVfs[i]->zName) ); 55059bc5449fSdrh sqlite3_vfs_unregister(apVfs[i]); 55069bc5449fSdrh assert( 0==sqlite3_vfs_find(apVfs[i]->zName) ); 55079bc5449fSdrh } 55089bc5449fSdrh } 55099bc5449fSdrh assert( 0==sqlite3_vfs_find(0) ); 551091fd4d46Sdrh 55111f045330Smlcreech /* Register the main VFS as non-default (will be made default, since 55121f045330Smlcreech ** it'll be the only one in existence). 55131f045330Smlcreech */ 55141f045330Smlcreech sqlite3_vfs_register(pMain, 0); 55151f045330Smlcreech assert( sqlite3_vfs_find(0)==pMain ); 55161f045330Smlcreech 55171f045330Smlcreech /* Un-register the main VFS again to restore an empty VFS list */ 55181f045330Smlcreech sqlite3_vfs_unregister(pMain); 55191f045330Smlcreech assert( 0==sqlite3_vfs_find(0) ); 55201f045330Smlcreech 552191fd4d46Sdrh /* Relink all VFSes in reverse order. */ 55229bc5449fSdrh for(i=sizeof(apVfs)/sizeof(apVfs[0])-1; i>=0; i--){ 55239bc5449fSdrh if( apVfs[i] ){ 55249bc5449fSdrh sqlite3_vfs_register(apVfs[i], 1); 55259bc5449fSdrh assert( apVfs[i]==sqlite3_vfs_find(0) ); 55269bc5449fSdrh assert( apVfs[i]==sqlite3_vfs_find(apVfs[i]->zName) ); 55279bc5449fSdrh } 55289bc5449fSdrh } 552991fd4d46Sdrh 553091fd4d46Sdrh /* Unregister out sample VFSes. */ 553191fd4d46Sdrh sqlite3_vfs_unregister(&one); 553291fd4d46Sdrh sqlite3_vfs_unregister(&two); 553391fd4d46Sdrh 553491fd4d46Sdrh /* Unregistering a VFS that is not currently registered is harmless */ 553591fd4d46Sdrh sqlite3_vfs_unregister(&one); 553691fd4d46Sdrh sqlite3_vfs_unregister(&two); 553791fd4d46Sdrh assert( sqlite3_vfs_find("__one")==0 ); 553891fd4d46Sdrh assert( sqlite3_vfs_find("__two")==0 ); 553991fd4d46Sdrh 554091fd4d46Sdrh /* We should be left with the original default VFS back as the 554191fd4d46Sdrh ** original */ 554291fd4d46Sdrh assert( sqlite3_vfs_find(0)==pMain ); 554391fd4d46Sdrh 55449bc5449fSdrh return TCL_OK; 55459bc5449fSdrh } 55469bc5449fSdrh 554793aed5a1Sdrh /* 5548c8d75674Sdrh ** tclcmd: vfs_initfail_test 5549c8d75674Sdrh ** 5550c8d75674Sdrh ** This TCL command attempts to vfs_find and vfs_register when the 5551c8d75674Sdrh ** sqlite3_initialize() interface is failing. All calls should fail. 5552c8d75674Sdrh */ 55537617e4a8Smistachkin static int SQLITE_TCLAPI vfs_initfail_test( 5554c8d75674Sdrh ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ 5555c8d75674Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 5556c8d75674Sdrh int objc, /* Number of arguments */ 5557c8d75674Sdrh Tcl_Obj *CONST objv[] /* Command arguments */ 5558c8d75674Sdrh ){ 5559c8d75674Sdrh sqlite3_vfs one; 5560c8d75674Sdrh one.zName = "__one"; 5561c8d75674Sdrh 5562c8d75674Sdrh if( sqlite3_vfs_find(0) ) return TCL_ERROR; 5563c8d75674Sdrh sqlite3_vfs_register(&one, 0); 5564c8d75674Sdrh if( sqlite3_vfs_find(0) ) return TCL_ERROR; 5565c8d75674Sdrh sqlite3_vfs_register(&one, 1); 5566c8d75674Sdrh if( sqlite3_vfs_find(0) ) return TCL_ERROR; 5567c8d75674Sdrh return TCL_OK; 5568c8d75674Sdrh } 5569c8d75674Sdrh 5570c8d75674Sdrh /* 5571a2820970Sdrh ** Saved VFSes 5572a2820970Sdrh */ 5573a2820970Sdrh static sqlite3_vfs *apVfs[20]; 5574a2820970Sdrh static int nVfs = 0; 5575a2820970Sdrh 5576a2820970Sdrh /* 5577a2820970Sdrh ** tclcmd: vfs_unregister_all 5578a2820970Sdrh ** 5579a2820970Sdrh ** Unregister all VFSes. 5580a2820970Sdrh */ 55817617e4a8Smistachkin static int SQLITE_TCLAPI vfs_unregister_all( 5582a2820970Sdrh ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ 5583a2820970Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 5584a2820970Sdrh int objc, /* Number of arguments */ 5585a2820970Sdrh Tcl_Obj *CONST objv[] /* Command arguments */ 5586a2820970Sdrh ){ 5587a2820970Sdrh int i; 5588a2820970Sdrh for(i=0; i<ArraySize(apVfs); i++){ 5589a2820970Sdrh apVfs[i] = sqlite3_vfs_find(0); 5590a2820970Sdrh if( apVfs[i]==0 ) break; 5591a2820970Sdrh sqlite3_vfs_unregister(apVfs[i]); 5592a2820970Sdrh } 5593a2820970Sdrh nVfs = i; 5594a2820970Sdrh return TCL_OK; 5595a2820970Sdrh } 5596a2820970Sdrh /* 5597a2820970Sdrh ** tclcmd: vfs_reregister_all 5598a2820970Sdrh ** 559905accd22Sdan ** Restore all VFSes that were removed using vfs_unregister_all. Taking 560005accd22Sdan ** care to put the linked list back together in the same order as it was 560105accd22Sdan ** in before vfs_unregister_all was invoked. 5602a2820970Sdrh */ 56037617e4a8Smistachkin static int SQLITE_TCLAPI vfs_reregister_all( 5604a2820970Sdrh ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ 5605a2820970Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 5606a2820970Sdrh int objc, /* Number of arguments */ 5607a2820970Sdrh Tcl_Obj *CONST objv[] /* Command arguments */ 5608a2820970Sdrh ){ 5609a2820970Sdrh int i; 561005accd22Sdan for(i=nVfs-1; i>=0; i--){ 561105accd22Sdan sqlite3_vfs_register(apVfs[i], 1); 5612a2820970Sdrh } 5613a2820970Sdrh return TCL_OK; 5614a2820970Sdrh } 5615a2820970Sdrh 5616a2820970Sdrh 5617a2820970Sdrh /* 561855176259Sdrh ** tclcmd: file_control_test DB 561955176259Sdrh ** 562055176259Sdrh ** This TCL command runs the sqlite3_file_control interface and 562155176259Sdrh ** verifies correct operation of the same. 562255176259Sdrh */ 56237617e4a8Smistachkin static int SQLITE_TCLAPI file_control_test( 562455176259Sdrh ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ 562555176259Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 562655176259Sdrh int objc, /* Number of arguments */ 562755176259Sdrh Tcl_Obj *CONST objv[] /* Command arguments */ 562855176259Sdrh ){ 562955176259Sdrh int iArg = 0; 563055176259Sdrh sqlite3 *db; 563155176259Sdrh int rc; 563255176259Sdrh 563355176259Sdrh if( objc!=2 ){ 563455176259Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", 563555176259Sdrh Tcl_GetStringFromObj(objv[0], 0), " DB", 0); 563655176259Sdrh return TCL_ERROR; 563755176259Sdrh } 563855176259Sdrh if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 563955176259Sdrh rc = sqlite3_file_control(db, 0, 0, &iArg); 56400b52b7d0Sdrh assert( rc==SQLITE_NOTFOUND ); 564155176259Sdrh rc = sqlite3_file_control(db, "notadatabase", SQLITE_FCNTL_LOCKSTATE, &iArg); 564255176259Sdrh assert( rc==SQLITE_ERROR ); 564355176259Sdrh rc = sqlite3_file_control(db, "main", -1, &iArg); 56440b52b7d0Sdrh assert( rc==SQLITE_NOTFOUND ); 564555176259Sdrh rc = sqlite3_file_control(db, "temp", -1, &iArg); 56460b52b7d0Sdrh assert( rc==SQLITE_NOTFOUND || rc==SQLITE_ERROR ); 5647aebf413dSaswift 564855176259Sdrh return TCL_OK; 564955176259Sdrh } 565055176259Sdrh 5651aebf413dSaswift 5652aebf413dSaswift /* 5653aebf413dSaswift ** tclcmd: file_control_lasterrno_test DB 5654aebf413dSaswift ** 5655aebf413dSaswift ** This TCL command runs the sqlite3_file_control interface and 5656aebf413dSaswift ** verifies correct operation of the SQLITE_LAST_ERRNO verb. 5657aebf413dSaswift */ 56587617e4a8Smistachkin static int SQLITE_TCLAPI file_control_lasterrno_test( 5659aebf413dSaswift ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ 5660aebf413dSaswift Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 5661aebf413dSaswift int objc, /* Number of arguments */ 5662aebf413dSaswift Tcl_Obj *CONST objv[] /* Command arguments */ 5663aebf413dSaswift ){ 5664aebf413dSaswift int iArg = 0; 5665aebf413dSaswift sqlite3 *db; 5666aebf413dSaswift int rc; 5667aebf413dSaswift 5668aebf413dSaswift if( objc!=2 ){ 5669aebf413dSaswift Tcl_AppendResult(interp, "wrong # args: should be \"", 5670aebf413dSaswift Tcl_GetStringFromObj(objv[0], 0), " DB", 0); 5671aebf413dSaswift return TCL_ERROR; 5672aebf413dSaswift } 56739db299fbSshane if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){ 56749db299fbSshane return TCL_ERROR; 56759db299fbSshane } 5676aebf413dSaswift rc = sqlite3_file_control(db, NULL, SQLITE_LAST_ERRNO, &iArg); 56779db299fbSshane if( rc ){ 56789db299fbSshane Tcl_SetObjResult(interp, Tcl_NewIntObj(rc)); 56799db299fbSshane return TCL_ERROR; 56809db299fbSshane } 5681aebf413dSaswift if( iArg!=0 ) { 5682aebf413dSaswift Tcl_AppendResult(interp, "Unexpected non-zero errno: ", 5683aebf413dSaswift Tcl_GetStringFromObj(Tcl_NewIntObj(iArg), 0), " ", 0); 5684aebf413dSaswift return TCL_ERROR; 5685aebf413dSaswift } 5686aebf413dSaswift return TCL_OK; 5687aebf413dSaswift } 5688aebf413dSaswift 5689aebf413dSaswift /* 5690ea99a31cSdrh ** tclcmd: file_control_data_version DB DBNAME 5691ea99a31cSdrh ** 5692ea99a31cSdrh ** This TCL command runs the sqlite3_file_control with the 5693ea99a31cSdrh ** SQLITE_FCNTL_DATA_VERSION opcode, returning the result. 5694ea99a31cSdrh */ 5695ea99a31cSdrh static int SQLITE_TCLAPI file_control_data_version( 5696ea99a31cSdrh ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ 5697ea99a31cSdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 5698ea99a31cSdrh int objc, /* Number of arguments */ 5699ea99a31cSdrh Tcl_Obj *CONST objv[] /* Command arguments */ 5700ea99a31cSdrh ){ 5701ea99a31cSdrh unsigned int iVers; /* data version */ 5702ea99a31cSdrh char *zDb; /* Db name ("main", "temp" etc.) */ 5703ea99a31cSdrh sqlite3 *db; /* Database handle */ 5704ea99a31cSdrh int rc; /* file_control() return code */ 5705ea99a31cSdrh char zBuf[100]; 5706ea99a31cSdrh 5707ea99a31cSdrh if( objc!=3 && objc!=2 ){ 5708ea99a31cSdrh Tcl_WrongNumArgs(interp, 1, objv, "DB [DBNAME]"); 5709ea99a31cSdrh return TCL_ERROR; 5710ea99a31cSdrh } 5711ea99a31cSdrh if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){ 5712ea99a31cSdrh return TCL_ERROR; 5713ea99a31cSdrh } 5714ea99a31cSdrh zDb = objc==3 ? Tcl_GetString(objv[2]) : NULL; 5715ea99a31cSdrh 5716ea99a31cSdrh rc = sqlite3_file_control(db, zDb, SQLITE_FCNTL_DATA_VERSION, (void *)&iVers); 5717ea99a31cSdrh if( rc ){ 5718ea99a31cSdrh Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_STATIC); 5719ea99a31cSdrh return TCL_ERROR; 5720ea99a31cSdrh }else{ 5721ea99a31cSdrh sqlite3_snprintf(sizeof(zBuf),zBuf,"%u",iVers); 5722ea99a31cSdrh Tcl_SetResult(interp, (char *)zBuf, TCL_VOLATILE); 5723ea99a31cSdrh return TCL_OK; 5724ea99a31cSdrh } 5725ea99a31cSdrh } 5726ea99a31cSdrh 5727ea99a31cSdrh /* 57286e09d69cSdan ** tclcmd: file_control_chunksize_test DB DBNAME SIZE 57296e09d69cSdan ** 57306e09d69cSdan ** This TCL command runs the sqlite3_file_control interface and 57316e09d69cSdan ** verifies correct operation of the SQLITE_GET_LOCKPROXYFILE and 57326e09d69cSdan ** SQLITE_SET_LOCKPROXYFILE verbs. 57336e09d69cSdan */ 57347617e4a8Smistachkin static int SQLITE_TCLAPI file_control_chunksize_test( 57356e09d69cSdan ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ 57366e09d69cSdan Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 57376e09d69cSdan int objc, /* Number of arguments */ 57386e09d69cSdan Tcl_Obj *CONST objv[] /* Command arguments */ 57396e09d69cSdan ){ 57406e09d69cSdan int nSize; /* New chunk size */ 57416e09d69cSdan char *zDb; /* Db name ("main", "temp" etc.) */ 57426e09d69cSdan sqlite3 *db; /* Database handle */ 57436e09d69cSdan int rc; /* file_control() return code */ 57446e09d69cSdan 57456e09d69cSdan if( objc!=4 ){ 57466e09d69cSdan Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME SIZE"); 57476e09d69cSdan return TCL_ERROR; 57486e09d69cSdan } 57496e09d69cSdan if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) 57506e09d69cSdan || Tcl_GetIntFromObj(interp, objv[3], &nSize) 57516e09d69cSdan ){ 57526e09d69cSdan return TCL_ERROR; 57536e09d69cSdan } 57546e09d69cSdan zDb = Tcl_GetString(objv[2]); 57556e09d69cSdan if( zDb[0]=='\0' ) zDb = NULL; 57566e09d69cSdan 57576e09d69cSdan rc = sqlite3_file_control(db, zDb, SQLITE_FCNTL_CHUNK_SIZE, (void *)&nSize); 57586e09d69cSdan if( rc ){ 5759e84d8d32Smistachkin Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_STATIC); 57606e09d69cSdan return TCL_ERROR; 57616e09d69cSdan } 57626e09d69cSdan return TCL_OK; 57636e09d69cSdan } 57646e09d69cSdan 57656e09d69cSdan /* 5766661d71afSdan ** tclcmd: file_control_sizehint_test DB DBNAME SIZE 5767661d71afSdan ** 5768fdd7f71eSdrh ** This TCL command runs the sqlite3_file_control interface 5769fdd7f71eSdrh ** with SQLITE_FCNTL_SIZE_HINT 5770661d71afSdan */ 57717617e4a8Smistachkin static int SQLITE_TCLAPI file_control_sizehint_test( 5772661d71afSdan ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ 5773661d71afSdan Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 5774661d71afSdan int objc, /* Number of arguments */ 5775661d71afSdan Tcl_Obj *CONST objv[] /* Command arguments */ 5776661d71afSdan ){ 5777b3f787f4Sdrh Tcl_WideInt nSize; /* Hinted size */ 5778661d71afSdan char *zDb; /* Db name ("main", "temp" etc.) */ 5779661d71afSdan sqlite3 *db; /* Database handle */ 5780661d71afSdan int rc; /* file_control() return code */ 5781661d71afSdan 5782661d71afSdan if( objc!=4 ){ 5783661d71afSdan Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME SIZE"); 5784661d71afSdan return TCL_ERROR; 5785661d71afSdan } 5786661d71afSdan if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) 5787661d71afSdan || Tcl_GetWideIntFromObj(interp, objv[3], &nSize) 5788661d71afSdan ){ 5789661d71afSdan return TCL_ERROR; 5790661d71afSdan } 5791661d71afSdan zDb = Tcl_GetString(objv[2]); 5792661d71afSdan if( zDb[0]=='\0' ) zDb = NULL; 5793661d71afSdan 5794661d71afSdan rc = sqlite3_file_control(db, zDb, SQLITE_FCNTL_SIZE_HINT, (void *)&nSize); 5795661d71afSdan if( rc ){ 5796e84d8d32Smistachkin Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_STATIC); 5797661d71afSdan return TCL_ERROR; 5798661d71afSdan } 5799661d71afSdan return TCL_OK; 5800661d71afSdan } 5801661d71afSdan 5802661d71afSdan /* 5803ad24581eSdrh ** tclcmd: file_control_lockproxy_test DB PWD 5804aebf413dSaswift ** 5805aebf413dSaswift ** This TCL command runs the sqlite3_file_control interface and 5806aebf413dSaswift ** verifies correct operation of the SQLITE_GET_LOCKPROXYFILE and 5807aebf413dSaswift ** SQLITE_SET_LOCKPROXYFILE verbs. 5808aebf413dSaswift */ 58097617e4a8Smistachkin static int SQLITE_TCLAPI file_control_lockproxy_test( 5810aebf413dSaswift ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ 5811aebf413dSaswift Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 5812aebf413dSaswift int objc, /* Number of arguments */ 5813aebf413dSaswift Tcl_Obj *CONST objv[] /* Command arguments */ 5814aebf413dSaswift ){ 5815aebf413dSaswift sqlite3 *db; 5816aebf413dSaswift 5817ad24581eSdrh if( objc!=3 ){ 5818aebf413dSaswift Tcl_AppendResult(interp, "wrong # args: should be \"", 5819ad24581eSdrh Tcl_GetStringFromObj(objv[0], 0), " DB PWD", 0); 5820aebf413dSaswift return TCL_ERROR; 5821aebf413dSaswift } 58229db299fbSshane if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){ 58239db299fbSshane return TCL_ERROR; 58249db299fbSshane } 5825aebf413dSaswift 58269b35ea62Sdrh #if !defined(SQLITE_ENABLE_LOCKING_STYLE) 5827d2cb50b7Sdrh # if defined(__APPLE__) 58289b35ea62Sdrh # define SQLITE_ENABLE_LOCKING_STYLE 1 58299b35ea62Sdrh # else 58309b35ea62Sdrh # define SQLITE_ENABLE_LOCKING_STYLE 0 58319b35ea62Sdrh # endif 58329b35ea62Sdrh #endif 5833d2cb50b7Sdrh #if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) 5834aebf413dSaswift { 5835aebf413dSaswift char *testPath; 5836103fe743Sdrh int rc; 5837caffb1a5Sdrh int nPwd; 5838caffb1a5Sdrh const char *zPwd; 5839ad24581eSdrh char proxyPath[400]; 5840ad24581eSdrh 5841caffb1a5Sdrh zPwd = Tcl_GetStringFromObj(objv[2], &nPwd); 5842ad24581eSdrh if( sizeof(proxyPath)<nPwd+20 ){ 5843ad24581eSdrh Tcl_AppendResult(interp, "PWD too big", (void*)0); 5844ad24581eSdrh return TCL_ERROR; 5845ad24581eSdrh } 584665545b59Sdrh sqlite3_snprintf(sizeof(proxyPath), proxyPath, "%s/test.proxy", zPwd); 5847aebf413dSaswift rc = sqlite3_file_control(db, NULL, SQLITE_SET_LOCKPROXYFILE, proxyPath); 58487708e972Sdrh if( rc ){ 58499db299fbSshane Tcl_SetObjResult(interp, Tcl_NewIntObj(rc)); 58509db299fbSshane return TCL_ERROR; 58517708e972Sdrh } 5852aebf413dSaswift rc = sqlite3_file_control(db, NULL, SQLITE_GET_LOCKPROXYFILE, &testPath); 5853aebf413dSaswift if( strncmp(proxyPath,testPath,11) ){ 58547708e972Sdrh Tcl_AppendResult(interp, "Lock proxy file did not match the " 58557708e972Sdrh "previously assigned value", 0); 5856aebf413dSaswift return TCL_ERROR; 5857aebf413dSaswift } 58587708e972Sdrh if( rc ){ 58597708e972Sdrh Tcl_SetObjResult(interp, Tcl_NewIntObj(rc)); 58607708e972Sdrh return TCL_ERROR; 58617708e972Sdrh } 5862aebf413dSaswift rc = sqlite3_file_control(db, NULL, SQLITE_SET_LOCKPROXYFILE, proxyPath); 58637708e972Sdrh if( rc ){ 58647708e972Sdrh Tcl_SetObjResult(interp, Tcl_NewIntObj(rc)); 58657708e972Sdrh return TCL_ERROR; 58667708e972Sdrh } 5867aebf413dSaswift } 5868aebf413dSaswift #endif 5869aebf413dSaswift return TCL_OK; 5870aebf413dSaswift } 5871aebf413dSaswift 58726b98d67bSmistachkin #if SQLITE_OS_WIN 5873d0cdf012Sdrh /* 5874d0cdf012Sdrh ** tclcmd: file_control_win32_av_retry DB NRETRY DELAY 5875d0cdf012Sdrh ** 5876d0cdf012Sdrh ** This TCL command runs the sqlite3_file_control interface with 5877d0cdf012Sdrh ** the SQLITE_FCNTL_WIN32_AV_RETRY opcode. 5878d0cdf012Sdrh */ 58797617e4a8Smistachkin static int SQLITE_TCLAPI file_control_win32_av_retry( 5880d0cdf012Sdrh ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ 5881d0cdf012Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 5882d0cdf012Sdrh int objc, /* Number of arguments */ 5883d0cdf012Sdrh Tcl_Obj *CONST objv[] /* Command arguments */ 5884d0cdf012Sdrh ){ 5885d0cdf012Sdrh sqlite3 *db; 5886d0cdf012Sdrh int rc; 5887d0cdf012Sdrh int a[2]; 5888d0cdf012Sdrh char z[100]; 5889d0cdf012Sdrh 5890d0cdf012Sdrh if( objc!=4 ){ 5891d0cdf012Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", 5892d0cdf012Sdrh Tcl_GetStringFromObj(objv[0], 0), " DB NRETRY DELAY", 0); 5893d0cdf012Sdrh return TCL_ERROR; 5894d0cdf012Sdrh } 5895d0cdf012Sdrh if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){ 5896d0cdf012Sdrh return TCL_ERROR; 5897d0cdf012Sdrh } 5898d0cdf012Sdrh if( Tcl_GetIntFromObj(interp, objv[2], &a[0]) ) return TCL_ERROR; 5899d0cdf012Sdrh if( Tcl_GetIntFromObj(interp, objv[3], &a[1]) ) return TCL_ERROR; 5900d0cdf012Sdrh rc = sqlite3_file_control(db, NULL, SQLITE_FCNTL_WIN32_AV_RETRY, (void*)a); 5901d0cdf012Sdrh sqlite3_snprintf(sizeof(z), z, "%d %d %d", rc, a[0], a[1]); 5902d0cdf012Sdrh Tcl_AppendResult(interp, z, (char*)0); 5903d0cdf012Sdrh return TCL_OK; 5904d0cdf012Sdrh } 5905d0cdf012Sdrh 5906253cea5cSdrh /* 59071b361ff3Smistachkin ** tclcmd: file_control_win32_get_handle DB 59081b361ff3Smistachkin ** 59091b361ff3Smistachkin ** This TCL command runs the sqlite3_file_control interface with 59101b361ff3Smistachkin ** the SQLITE_FCNTL_WIN32_GET_HANDLE opcode. 59111b361ff3Smistachkin */ 59121b361ff3Smistachkin static int file_control_win32_get_handle( 59131b361ff3Smistachkin ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ 59141b361ff3Smistachkin Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 59151b361ff3Smistachkin int objc, /* Number of arguments */ 59161b361ff3Smistachkin Tcl_Obj *CONST objv[] /* Command arguments */ 59171b361ff3Smistachkin ){ 59181b361ff3Smistachkin sqlite3 *db; 59191b361ff3Smistachkin int rc; 59201b361ff3Smistachkin HANDLE hFile = NULL; 59211b361ff3Smistachkin char z[100]; 59221b361ff3Smistachkin 59231b361ff3Smistachkin if( objc!=2 ){ 59241b361ff3Smistachkin Tcl_AppendResult(interp, "wrong # args: should be \"", 59251b361ff3Smistachkin Tcl_GetStringFromObj(objv[0], 0), " DB", 0); 59261b361ff3Smistachkin return TCL_ERROR; 59271b361ff3Smistachkin } 59281b361ff3Smistachkin if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){ 59291b361ff3Smistachkin return TCL_ERROR; 59301b361ff3Smistachkin } 59311b361ff3Smistachkin rc = sqlite3_file_control(db, NULL, SQLITE_FCNTL_WIN32_GET_HANDLE, 59321b361ff3Smistachkin (void*)&hFile); 59331b361ff3Smistachkin sqlite3_snprintf(sizeof(z), z, "%d %p", rc, (void*)hFile); 59341b361ff3Smistachkin Tcl_AppendResult(interp, z, (char*)0); 59351b361ff3Smistachkin return TCL_OK; 59361b361ff3Smistachkin } 59371b361ff3Smistachkin 59381b361ff3Smistachkin /* 59396b98d67bSmistachkin ** tclcmd: file_control_win32_set_handle DB HANDLE 59406b98d67bSmistachkin ** 59416b98d67bSmistachkin ** This TCL command runs the sqlite3_file_control interface with 59426b98d67bSmistachkin ** the SQLITE_FCNTL_WIN32_SET_HANDLE opcode. 59436b98d67bSmistachkin */ 59447617e4a8Smistachkin static int SQLITE_TCLAPI file_control_win32_set_handle( 59456b98d67bSmistachkin ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ 59466b98d67bSmistachkin Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 59476b98d67bSmistachkin int objc, /* Number of arguments */ 59486b98d67bSmistachkin Tcl_Obj *CONST objv[] /* Command arguments */ 59496b98d67bSmistachkin ){ 59506b98d67bSmistachkin sqlite3 *db; 59516b98d67bSmistachkin int rc; 59526b98d67bSmistachkin HANDLE hFile = NULL; 59536b98d67bSmistachkin char z[100]; 59546b98d67bSmistachkin 59556b98d67bSmistachkin if( objc!=3 ){ 59566b98d67bSmistachkin Tcl_AppendResult(interp, "wrong # args: should be \"", 59576b98d67bSmistachkin Tcl_GetStringFromObj(objv[0], 0), " DB HANDLE", 0); 59586b98d67bSmistachkin return TCL_ERROR; 59596b98d67bSmistachkin } 59606b98d67bSmistachkin if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){ 59616b98d67bSmistachkin return TCL_ERROR; 59626b98d67bSmistachkin } 59636b98d67bSmistachkin if( getWin32Handle(interp, Tcl_GetString(objv[2]), &hFile) ){ 59646b98d67bSmistachkin return TCL_ERROR; 59656b98d67bSmistachkin } 59666b98d67bSmistachkin rc = sqlite3_file_control(db, NULL, SQLITE_FCNTL_WIN32_SET_HANDLE, 59676b98d67bSmistachkin (void*)&hFile); 59686b98d67bSmistachkin sqlite3_snprintf(sizeof(z), z, "%d %p", rc, (void*)hFile); 59696b98d67bSmistachkin Tcl_AppendResult(interp, z, (char*)0); 59706b98d67bSmistachkin return TCL_OK; 59716b98d67bSmistachkin } 59726b98d67bSmistachkin #endif 59736b98d67bSmistachkin 59746b98d67bSmistachkin /* 5975253cea5cSdrh ** tclcmd: file_control_persist_wal DB PERSIST-FLAG 5976253cea5cSdrh ** 5977253cea5cSdrh ** This TCL command runs the sqlite3_file_control interface with 5978253cea5cSdrh ** the SQLITE_FCNTL_PERSIST_WAL opcode. 5979253cea5cSdrh */ 59807617e4a8Smistachkin static int SQLITE_TCLAPI file_control_persist_wal( 5981253cea5cSdrh ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ 5982253cea5cSdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 5983253cea5cSdrh int objc, /* Number of arguments */ 5984253cea5cSdrh Tcl_Obj *CONST objv[] /* Command arguments */ 5985253cea5cSdrh ){ 5986253cea5cSdrh sqlite3 *db; 5987253cea5cSdrh int rc; 5988253cea5cSdrh int bPersist; 5989253cea5cSdrh char z[100]; 5990253cea5cSdrh 5991253cea5cSdrh if( objc!=3 ){ 5992253cea5cSdrh Tcl_AppendResult(interp, "wrong # args: should be \"", 5993253cea5cSdrh Tcl_GetStringFromObj(objv[0], 0), " DB FLAG", 0); 5994253cea5cSdrh return TCL_ERROR; 5995253cea5cSdrh } 5996253cea5cSdrh if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){ 5997253cea5cSdrh return TCL_ERROR; 5998253cea5cSdrh } 5999253cea5cSdrh if( Tcl_GetIntFromObj(interp, objv[2], &bPersist) ) return TCL_ERROR; 6000253cea5cSdrh rc = sqlite3_file_control(db, NULL, SQLITE_FCNTL_PERSIST_WAL, (void*)&bPersist); 6001253cea5cSdrh sqlite3_snprintf(sizeof(z), z, "%d %d", rc, bPersist); 6002253cea5cSdrh Tcl_AppendResult(interp, z, (char*)0); 6003253cea5cSdrh return TCL_OK; 6004253cea5cSdrh } 6005253cea5cSdrh 6006f12b3f60Sdrh /* 6007cb15f35fSdrh ** tclcmd: file_control_powersafe_overwrite DB PSOW-FLAG 6008f12b3f60Sdrh ** 6009f12b3f60Sdrh ** This TCL command runs the sqlite3_file_control interface with 6010cb15f35fSdrh ** the SQLITE_FCNTL_POWERSAFE_OVERWRITE opcode. 6011f12b3f60Sdrh */ 60127617e4a8Smistachkin static int SQLITE_TCLAPI file_control_powersafe_overwrite( 6013f12b3f60Sdrh ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ 6014f12b3f60Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 6015f12b3f60Sdrh int objc, /* Number of arguments */ 6016f12b3f60Sdrh Tcl_Obj *CONST objv[] /* Command arguments */ 6017f12b3f60Sdrh ){ 6018f12b3f60Sdrh sqlite3 *db; 6019f12b3f60Sdrh int rc; 6020cb15f35fSdrh int b; 6021f12b3f60Sdrh char z[100]; 6022f12b3f60Sdrh 6023f12b3f60Sdrh if( objc!=3 ){ 6024f12b3f60Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", 6025f12b3f60Sdrh Tcl_GetStringFromObj(objv[0], 0), " DB FLAG", 0); 6026f12b3f60Sdrh return TCL_ERROR; 6027f12b3f60Sdrh } 6028f12b3f60Sdrh if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){ 6029f12b3f60Sdrh return TCL_ERROR; 6030f12b3f60Sdrh } 6031cb15f35fSdrh if( Tcl_GetIntFromObj(interp, objv[2], &b) ) return TCL_ERROR; 6032cb15f35fSdrh rc = sqlite3_file_control(db,NULL,SQLITE_FCNTL_POWERSAFE_OVERWRITE,(void*)&b); 6033cb15f35fSdrh sqlite3_snprintf(sizeof(z), z, "%d %d", rc, b); 6034f12b3f60Sdrh Tcl_AppendResult(interp, z, (char*)0); 6035f12b3f60Sdrh return TCL_OK; 6036f12b3f60Sdrh } 6037f12b3f60Sdrh 6038aebf413dSaswift 603955176259Sdrh /* 6040de60fc2dSdrh ** tclcmd: file_control_vfsname DB ?AUXDB? 6041de60fc2dSdrh ** 6042de60fc2dSdrh ** Return a string that describes the stack of VFSes. 6043de60fc2dSdrh */ 60447617e4a8Smistachkin static int SQLITE_TCLAPI file_control_vfsname( 6045de60fc2dSdrh ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ 6046de60fc2dSdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 6047de60fc2dSdrh int objc, /* Number of arguments */ 6048de60fc2dSdrh Tcl_Obj *CONST objv[] /* Command arguments */ 6049de60fc2dSdrh ){ 6050de60fc2dSdrh sqlite3 *db; 6051de60fc2dSdrh const char *zDbName = "main"; 6052de60fc2dSdrh char *zVfsName = 0; 6053de60fc2dSdrh 6054de60fc2dSdrh if( objc!=2 && objc!=3 ){ 6055de60fc2dSdrh Tcl_AppendResult(interp, "wrong # args: should be \"", 6056de60fc2dSdrh Tcl_GetStringFromObj(objv[0], 0), " DB ?AUXDB?", 0); 6057de60fc2dSdrh return TCL_ERROR; 6058de60fc2dSdrh } 6059de60fc2dSdrh if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){ 6060de60fc2dSdrh return TCL_ERROR; 6061de60fc2dSdrh } 6062de60fc2dSdrh if( objc==3 ){ 6063de60fc2dSdrh zDbName = Tcl_GetString(objv[2]); 6064de60fc2dSdrh } 6065de60fc2dSdrh sqlite3_file_control(db, zDbName, SQLITE_FCNTL_VFSNAME,(void*)&zVfsName); 6066de60fc2dSdrh Tcl_AppendResult(interp, zVfsName, (char*)0); 6067de60fc2dSdrh sqlite3_free(zVfsName); 6068de60fc2dSdrh return TCL_OK; 6069de60fc2dSdrh } 6070de60fc2dSdrh 6071696b33e6Sdrh /* 6072696b33e6Sdrh ** tclcmd: file_control_tempfilename DB ?AUXDB? 6073696b33e6Sdrh ** 6074696b33e6Sdrh ** Return a string that is a temporary filename 6075696b33e6Sdrh */ 60767617e4a8Smistachkin static int SQLITE_TCLAPI file_control_tempfilename( 6077696b33e6Sdrh ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ 6078696b33e6Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 6079696b33e6Sdrh int objc, /* Number of arguments */ 6080696b33e6Sdrh Tcl_Obj *CONST objv[] /* Command arguments */ 6081696b33e6Sdrh ){ 6082696b33e6Sdrh sqlite3 *db; 6083696b33e6Sdrh const char *zDbName = "main"; 6084696b33e6Sdrh char *zTName = 0; 6085696b33e6Sdrh 6086696b33e6Sdrh if( objc!=2 && objc!=3 ){ 6087696b33e6Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", 6088696b33e6Sdrh Tcl_GetStringFromObj(objv[0], 0), " DB ?AUXDB?", 0); 6089696b33e6Sdrh return TCL_ERROR; 6090696b33e6Sdrh } 6091696b33e6Sdrh if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){ 6092696b33e6Sdrh return TCL_ERROR; 6093696b33e6Sdrh } 6094696b33e6Sdrh if( objc==3 ){ 6095696b33e6Sdrh zDbName = Tcl_GetString(objv[2]); 6096696b33e6Sdrh } 6097696b33e6Sdrh sqlite3_file_control(db, zDbName, SQLITE_FCNTL_TEMPFILENAME, (void*)&zTName); 6098696b33e6Sdrh Tcl_AppendResult(interp, zTName, (char*)0); 6099696b33e6Sdrh sqlite3_free(zTName); 6100696b33e6Sdrh return TCL_OK; 6101696b33e6Sdrh } 6102696b33e6Sdrh 6103de60fc2dSdrh 6104de60fc2dSdrh /* 6105e339d65aSdanielk1977 ** tclcmd: sqlite3_vfs_list 6106e339d65aSdanielk1977 ** 6107e339d65aSdanielk1977 ** Return a tcl list containing the names of all registered vfs's. 6108e339d65aSdanielk1977 */ 61097617e4a8Smistachkin static int SQLITE_TCLAPI vfs_list( 6110e339d65aSdanielk1977 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ 6111e339d65aSdanielk1977 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 6112e339d65aSdanielk1977 int objc, /* Number of arguments */ 6113e339d65aSdanielk1977 Tcl_Obj *CONST objv[] /* Command arguments */ 6114e339d65aSdanielk1977 ){ 6115e339d65aSdanielk1977 sqlite3_vfs *pVfs; 6116e339d65aSdanielk1977 Tcl_Obj *pRet = Tcl_NewObj(); 6117e339d65aSdanielk1977 if( objc!=1 ){ 6118e339d65aSdanielk1977 Tcl_WrongNumArgs(interp, 1, objv, ""); 6119e339d65aSdanielk1977 return TCL_ERROR; 6120e339d65aSdanielk1977 } 6121e339d65aSdanielk1977 for(pVfs=sqlite3_vfs_find(0); pVfs; pVfs=pVfs->pNext){ 6122e339d65aSdanielk1977 Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj(pVfs->zName, -1)); 6123e339d65aSdanielk1977 } 6124e339d65aSdanielk1977 Tcl_SetObjResult(interp, pRet); 6125e339d65aSdanielk1977 return TCL_OK; 6126e339d65aSdanielk1977 } 6127e339d65aSdanielk1977 6128e339d65aSdanielk1977 /* 6129b1a6c3c1Sdrh ** tclcmd: sqlite3_limit DB ID VALUE 6130b1a6c3c1Sdrh ** 6131b1a6c3c1Sdrh ** This TCL command runs the sqlite3_limit interface and 6132b1a6c3c1Sdrh ** verifies correct operation of the same. 6133b1a6c3c1Sdrh */ 61347617e4a8Smistachkin static int SQLITE_TCLAPI test_limit( 6135b1a6c3c1Sdrh ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ 6136b1a6c3c1Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 6137b1a6c3c1Sdrh int objc, /* Number of arguments */ 6138b1a6c3c1Sdrh Tcl_Obj *CONST objv[] /* Command arguments */ 6139b1a6c3c1Sdrh ){ 6140b1a6c3c1Sdrh sqlite3 *db; 6141b1a6c3c1Sdrh int rc; 6142b1a6c3c1Sdrh static const struct { 6143b1a6c3c1Sdrh char *zName; 6144b1a6c3c1Sdrh int id; 6145b1a6c3c1Sdrh } aId[] = { 6146b1a6c3c1Sdrh { "SQLITE_LIMIT_LENGTH", SQLITE_LIMIT_LENGTH }, 6147b1a6c3c1Sdrh { "SQLITE_LIMIT_SQL_LENGTH", SQLITE_LIMIT_SQL_LENGTH }, 6148b1a6c3c1Sdrh { "SQLITE_LIMIT_COLUMN", SQLITE_LIMIT_COLUMN }, 6149b1a6c3c1Sdrh { "SQLITE_LIMIT_EXPR_DEPTH", SQLITE_LIMIT_EXPR_DEPTH }, 6150b1a6c3c1Sdrh { "SQLITE_LIMIT_COMPOUND_SELECT", SQLITE_LIMIT_COMPOUND_SELECT }, 6151b1a6c3c1Sdrh { "SQLITE_LIMIT_VDBE_OP", SQLITE_LIMIT_VDBE_OP }, 6152b1a6c3c1Sdrh { "SQLITE_LIMIT_FUNCTION_ARG", SQLITE_LIMIT_FUNCTION_ARG }, 6153b1a6c3c1Sdrh { "SQLITE_LIMIT_ATTACHED", SQLITE_LIMIT_ATTACHED }, 6154b1a6c3c1Sdrh { "SQLITE_LIMIT_LIKE_PATTERN_LENGTH", SQLITE_LIMIT_LIKE_PATTERN_LENGTH }, 6155b1a6c3c1Sdrh { "SQLITE_LIMIT_VARIABLE_NUMBER", SQLITE_LIMIT_VARIABLE_NUMBER }, 6156417168adSdrh { "SQLITE_LIMIT_TRIGGER_DEPTH", SQLITE_LIMIT_TRIGGER_DEPTH }, 61573705ef6aSdrh { "SQLITE_LIMIT_WORKER_THREADS", SQLITE_LIMIT_WORKER_THREADS }, 6158521cc849Sdrh 6159521cc849Sdrh /* Out of range test cases */ 6160521cc849Sdrh { "SQLITE_LIMIT_TOOSMALL", -1, }, 61613705ef6aSdrh { "SQLITE_LIMIT_TOOBIG", SQLITE_LIMIT_WORKER_THREADS+1 }, 6162b1a6c3c1Sdrh }; 616327b2f053Smistachkin int i, id = 0; 6164b1a6c3c1Sdrh int val; 6165b1a6c3c1Sdrh const char *zId; 6166b1a6c3c1Sdrh 6167b1a6c3c1Sdrh if( objc!=4 ){ 6168b1a6c3c1Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", 6169b1a6c3c1Sdrh Tcl_GetStringFromObj(objv[0], 0), " DB ID VALUE", 0); 6170b1a6c3c1Sdrh return TCL_ERROR; 6171b1a6c3c1Sdrh } 6172b1a6c3c1Sdrh if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 6173b1a6c3c1Sdrh zId = Tcl_GetString(objv[2]); 6174b1a6c3c1Sdrh for(i=0; i<sizeof(aId)/sizeof(aId[0]); i++){ 6175b1a6c3c1Sdrh if( strcmp(zId, aId[i].zName)==0 ){ 6176b1a6c3c1Sdrh id = aId[i].id; 6177b1a6c3c1Sdrh break; 6178b1a6c3c1Sdrh } 6179b1a6c3c1Sdrh } 6180b1a6c3c1Sdrh if( i>=sizeof(aId)/sizeof(aId[0]) ){ 6181b1a6c3c1Sdrh Tcl_AppendResult(interp, "unknown limit type: ", zId, (char*)0); 6182b1a6c3c1Sdrh return TCL_ERROR; 6183b1a6c3c1Sdrh } 6184b1a6c3c1Sdrh if( Tcl_GetIntFromObj(interp, objv[3], &val) ) return TCL_ERROR; 6185b1a6c3c1Sdrh rc = sqlite3_limit(db, id, val); 6186b1a6c3c1Sdrh Tcl_SetObjResult(interp, Tcl_NewIntObj(rc)); 6187b1a6c3c1Sdrh return TCL_OK; 6188b1a6c3c1Sdrh } 6189b1a6c3c1Sdrh 6190b1a6c3c1Sdrh /* 619193aed5a1Sdrh ** tclcmd: save_prng_state 6192a2820970Sdrh ** 6193a2820970Sdrh ** Save the state of the pseudo-random number generator. 6194a2820970Sdrh ** At the same time, verify that sqlite3_test_control works even when 6195a2820970Sdrh ** called with an out-of-range opcode. 619693aed5a1Sdrh */ 61977617e4a8Smistachkin static int SQLITE_TCLAPI save_prng_state( 619893aed5a1Sdrh ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ 619993aed5a1Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 620093aed5a1Sdrh int objc, /* Number of arguments */ 620193aed5a1Sdrh Tcl_Obj *CONST objv[] /* Command arguments */ 620293aed5a1Sdrh ){ 6203a2820970Sdrh int rc = sqlite3_test_control(9999); 6204a2820970Sdrh assert( rc==0 ); 6205a2820970Sdrh rc = sqlite3_test_control(-1); 6206a2820970Sdrh assert( rc==0 ); 62072fa1868fSdrh sqlite3_test_control(SQLITE_TESTCTRL_PRNG_SAVE); 620893aed5a1Sdrh return TCL_OK; 620993aed5a1Sdrh } 621093aed5a1Sdrh /* 621193aed5a1Sdrh ** tclcmd: restore_prng_state 621293aed5a1Sdrh */ 62137617e4a8Smistachkin static int SQLITE_TCLAPI restore_prng_state( 621493aed5a1Sdrh ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ 621593aed5a1Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 621693aed5a1Sdrh int objc, /* Number of arguments */ 621793aed5a1Sdrh Tcl_Obj *CONST objv[] /* Command arguments */ 621893aed5a1Sdrh ){ 62192fa1868fSdrh sqlite3_test_control(SQLITE_TESTCTRL_PRNG_RESTORE); 622093aed5a1Sdrh return TCL_OK; 622193aed5a1Sdrh } 622293aed5a1Sdrh /* 622393aed5a1Sdrh ** tclcmd: reset_prng_state 622493aed5a1Sdrh */ 62257617e4a8Smistachkin static int SQLITE_TCLAPI reset_prng_state( 622693aed5a1Sdrh ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ 622793aed5a1Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 622893aed5a1Sdrh int objc, /* Number of arguments */ 622993aed5a1Sdrh Tcl_Obj *CONST objv[] /* Command arguments */ 623093aed5a1Sdrh ){ 62312fa1868fSdrh sqlite3_test_control(SQLITE_TESTCTRL_PRNG_RESET); 623293aed5a1Sdrh return TCL_OK; 623393aed5a1Sdrh } 623493aed5a1Sdrh 6235062d4cb0Sdanielk1977 /* 623609fe6143Sdrh ** tclcmd: database_may_be_corrupt 623709fe6143Sdrh ** 623809fe6143Sdrh ** Indicate that database files might be corrupt. In other words, set the normal 623909fe6143Sdrh ** state of operation. 624009fe6143Sdrh */ 62417617e4a8Smistachkin static int SQLITE_TCLAPI database_may_be_corrupt( 624209fe6143Sdrh ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ 624309fe6143Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 624409fe6143Sdrh int objc, /* Number of arguments */ 624509fe6143Sdrh Tcl_Obj *CONST objv[] /* Command arguments */ 624609fe6143Sdrh ){ 624709fe6143Sdrh sqlite3_test_control(SQLITE_TESTCTRL_NEVER_CORRUPT, 0); 624809fe6143Sdrh return TCL_OK; 624909fe6143Sdrh } 625009fe6143Sdrh /* 625109fe6143Sdrh ** tclcmd: database_never_corrupt 625209fe6143Sdrh ** 625309fe6143Sdrh ** Indicate that database files are always well-formed. This enables extra assert() 625409fe6143Sdrh ** statements that test conditions that are always true for well-formed databases. 625509fe6143Sdrh */ 62567617e4a8Smistachkin static int SQLITE_TCLAPI database_never_corrupt( 625709fe6143Sdrh ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ 625809fe6143Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 625909fe6143Sdrh int objc, /* Number of arguments */ 626009fe6143Sdrh Tcl_Obj *CONST objv[] /* Command arguments */ 626109fe6143Sdrh ){ 626209fe6143Sdrh sqlite3_test_control(SQLITE_TESTCTRL_NEVER_CORRUPT, 1); 626309fe6143Sdrh return TCL_OK; 626409fe6143Sdrh } 626509fe6143Sdrh 626609fe6143Sdrh /* 6267062d4cb0Sdanielk1977 ** tclcmd: pcache_stats 6268062d4cb0Sdanielk1977 */ 62697617e4a8Smistachkin static int SQLITE_TCLAPI test_pcache_stats( 6270062d4cb0Sdanielk1977 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ 6271062d4cb0Sdanielk1977 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 6272062d4cb0Sdanielk1977 int objc, /* Number of arguments */ 6273062d4cb0Sdanielk1977 Tcl_Obj *CONST objv[] /* Command arguments */ 6274062d4cb0Sdanielk1977 ){ 6275062d4cb0Sdanielk1977 int nMin; 6276062d4cb0Sdanielk1977 int nMax; 6277062d4cb0Sdanielk1977 int nCurrent; 6278062d4cb0Sdanielk1977 int nRecyclable; 6279062d4cb0Sdanielk1977 Tcl_Obj *pRet; 6280062d4cb0Sdanielk1977 6281062d4cb0Sdanielk1977 sqlite3PcacheStats(&nCurrent, &nMax, &nMin, &nRecyclable); 6282062d4cb0Sdanielk1977 6283062d4cb0Sdanielk1977 pRet = Tcl_NewObj(); 6284062d4cb0Sdanielk1977 Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj("current", -1)); 6285062d4cb0Sdanielk1977 Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(nCurrent)); 6286062d4cb0Sdanielk1977 Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj("max", -1)); 6287062d4cb0Sdanielk1977 Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(nMax)); 6288062d4cb0Sdanielk1977 Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj("min", -1)); 6289062d4cb0Sdanielk1977 Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(nMin)); 6290062d4cb0Sdanielk1977 Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj("recyclable", -1)); 6291062d4cb0Sdanielk1977 Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(nRecyclable)); 6292062d4cb0Sdanielk1977 6293062d4cb0Sdanielk1977 Tcl_SetObjResult(interp, pRet); 6294062d4cb0Sdanielk1977 6295062d4cb0Sdanielk1977 return TCL_OK; 6296062d4cb0Sdanielk1977 } 6297062d4cb0Sdanielk1977 629869910da9Sdrh #ifdef SQLITE_ENABLE_UNLOCK_NOTIFY 6299404ca075Sdanielk1977 static void test_unlock_notify_cb(void **aArg, int nArg){ 6300404ca075Sdanielk1977 int ii; 6301404ca075Sdanielk1977 for(ii=0; ii<nArg; ii++){ 6302404ca075Sdanielk1977 Tcl_EvalEx((Tcl_Interp *)aArg[ii], "unlock_notify", -1, TCL_EVAL_GLOBAL); 6303404ca075Sdanielk1977 } 6304404ca075Sdanielk1977 } 630569910da9Sdrh #endif /* SQLITE_ENABLE_UNLOCK_NOTIFY */ 6306404ca075Sdanielk1977 6307404ca075Sdanielk1977 /* 6308404ca075Sdanielk1977 ** tclcmd: sqlite3_unlock_notify db 6309404ca075Sdanielk1977 */ 6310404ca075Sdanielk1977 #ifdef SQLITE_ENABLE_UNLOCK_NOTIFY 63117617e4a8Smistachkin static int SQLITE_TCLAPI test_unlock_notify( 6312404ca075Sdanielk1977 ClientData clientData, /* Unused */ 6313404ca075Sdanielk1977 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 6314404ca075Sdanielk1977 int objc, /* Number of arguments */ 6315404ca075Sdanielk1977 Tcl_Obj *CONST objv[] /* Command arguments */ 6316404ca075Sdanielk1977 ){ 6317404ca075Sdanielk1977 sqlite3 *db; 6318404ca075Sdanielk1977 int rc; 6319404ca075Sdanielk1977 6320404ca075Sdanielk1977 if( objc!=2 ){ 6321404ca075Sdanielk1977 Tcl_WrongNumArgs(interp, 1, objv, "DB"); 6322404ca075Sdanielk1977 return TCL_ERROR; 6323404ca075Sdanielk1977 } 6324404ca075Sdanielk1977 6325404ca075Sdanielk1977 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){ 6326404ca075Sdanielk1977 return TCL_ERROR; 6327404ca075Sdanielk1977 } 6328404ca075Sdanielk1977 rc = sqlite3_unlock_notify(db, test_unlock_notify_cb, (void *)interp); 6329404ca075Sdanielk1977 Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC); 6330404ca075Sdanielk1977 return TCL_OK; 6331404ca075Sdanielk1977 } 6332404ca075Sdanielk1977 #endif 6333404ca075Sdanielk1977 633487c1fe1bSdan /* 633587c1fe1bSdan ** tclcmd: sqlite3_wal_checkpoint db ?NAME? 633687c1fe1bSdan */ 63377617e4a8Smistachkin static int SQLITE_TCLAPI test_wal_checkpoint( 633887c1fe1bSdan ClientData clientData, /* Unused */ 633987c1fe1bSdan Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 634087c1fe1bSdan int objc, /* Number of arguments */ 634187c1fe1bSdan Tcl_Obj *CONST objv[] /* Command arguments */ 634287c1fe1bSdan ){ 634387c1fe1bSdan char *zDb = 0; 634487c1fe1bSdan sqlite3 *db; 634587c1fe1bSdan int rc; 634687c1fe1bSdan 634787c1fe1bSdan if( objc!=3 && objc!=2 ){ 634887c1fe1bSdan Tcl_WrongNumArgs(interp, 1, objv, "DB ?NAME?"); 634987c1fe1bSdan return TCL_ERROR; 635087c1fe1bSdan } 635187c1fe1bSdan 635287c1fe1bSdan if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){ 635387c1fe1bSdan return TCL_ERROR; 635487c1fe1bSdan } 635587c1fe1bSdan if( objc==3 ){ 635687c1fe1bSdan zDb = Tcl_GetString(objv[2]); 635787c1fe1bSdan } 635887c1fe1bSdan rc = sqlite3_wal_checkpoint(db, zDb); 635987c1fe1bSdan Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC); 636087c1fe1bSdan return TCL_OK; 636187c1fe1bSdan } 636287c1fe1bSdan 6363eb8763d7Sdan /* 63649c5e3680Sdan ** tclcmd: sqlite3_wal_checkpoint_v2 db MODE ?NAME? 63659c5e3680Sdan ** 63669c5e3680Sdan ** This command calls the wal_checkpoint_v2() function with the specified 63679c5e3680Sdan ** mode argument (passive, full or restart). If present, the database name 63689c5e3680Sdan ** NAME is passed as the second argument to wal_checkpoint_v2(). If it the 63699c5e3680Sdan ** NAME argument is not present, a NULL pointer is passed instead. 63709c5e3680Sdan ** 63719c5e3680Sdan ** If wal_checkpoint_v2() returns any value other than SQLITE_BUSY or 63729c5e3680Sdan ** SQLITE_OK, then this command returns TCL_ERROR. The Tcl result is set 63739c5e3680Sdan ** to the error message obtained from sqlite3_errmsg(). 63749c5e3680Sdan ** 63759c5e3680Sdan ** Otherwise, this command returns a list of three integers. The first integer 63769c5e3680Sdan ** is 1 if SQLITE_BUSY was returned, or 0 otherwise. The following two integers 6377f7b5496eSdrh ** are the values returned via the output parameters by wal_checkpoint_v2() - 63789c5e3680Sdan ** the number of frames in the log and the number of frames in the log 63799c5e3680Sdan ** that have been checkpointed. 63809c5e3680Sdan */ 63817617e4a8Smistachkin static int SQLITE_TCLAPI test_wal_checkpoint_v2( 63829c5e3680Sdan ClientData clientData, /* Unused */ 63839c5e3680Sdan Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 63849c5e3680Sdan int objc, /* Number of arguments */ 63859c5e3680Sdan Tcl_Obj *CONST objv[] /* Command arguments */ 63869c5e3680Sdan ){ 63879c5e3680Sdan char *zDb = 0; 63889c5e3680Sdan sqlite3 *db; 63899c5e3680Sdan int rc; 63909c5e3680Sdan 63919c5e3680Sdan int eMode; 63929c5e3680Sdan int nLog = -555; 63939c5e3680Sdan int nCkpt = -555; 63949c5e3680Sdan Tcl_Obj *pRet; 63959c5e3680Sdan 6396f26a1549Sdan const char * aMode[] = { "passive", "full", "restart", "truncate", 0 }; 63979c5e3680Sdan assert( SQLITE_CHECKPOINT_PASSIVE==0 ); 63989c5e3680Sdan assert( SQLITE_CHECKPOINT_FULL==1 ); 63999c5e3680Sdan assert( SQLITE_CHECKPOINT_RESTART==2 ); 6400f26a1549Sdan assert( SQLITE_CHECKPOINT_TRUNCATE==3 ); 64019c5e3680Sdan 64029c5e3680Sdan if( objc!=3 && objc!=4 ){ 64039c5e3680Sdan Tcl_WrongNumArgs(interp, 1, objv, "DB MODE ?NAME?"); 64049c5e3680Sdan return TCL_ERROR; 64059c5e3680Sdan } 64069c5e3680Sdan 64079c5e3680Sdan if( objc==4 ){ 64089c5e3680Sdan zDb = Tcl_GetString(objv[3]); 64099c5e3680Sdan } 64102928d327Sdan if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) || ( 64112928d327Sdan TCL_OK!=Tcl_GetIntFromObj(0, objv[2], &eMode) 64122928d327Sdan && TCL_OK!=Tcl_GetIndexFromObj(interp, objv[2], aMode, "mode", 0, &eMode) 64132928d327Sdan )){ 64149c5e3680Sdan return TCL_ERROR; 64159c5e3680Sdan } 64169c5e3680Sdan 64179c5e3680Sdan rc = sqlite3_wal_checkpoint_v2(db, zDb, eMode, &nLog, &nCkpt); 64189c5e3680Sdan if( rc!=SQLITE_OK && rc!=SQLITE_BUSY ){ 64192928d327Sdan const char *zErrCode = sqlite3ErrName(rc); 64209778bd72Sdan Tcl_ResetResult(interp); 64212928d327Sdan Tcl_AppendResult(interp, zErrCode, " - ", (char *)sqlite3_errmsg(db), 0); 64229c5e3680Sdan return TCL_ERROR; 64239c5e3680Sdan } 64249c5e3680Sdan 64259c5e3680Sdan pRet = Tcl_NewObj(); 64269c5e3680Sdan Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(rc==SQLITE_BUSY?1:0)); 64279c5e3680Sdan Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(nLog)); 64289c5e3680Sdan Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(nCkpt)); 64299c5e3680Sdan Tcl_SetObjResult(interp, pRet); 64309c5e3680Sdan 64319c5e3680Sdan return TCL_OK; 64329c5e3680Sdan } 64339c5e3680Sdan 64349c5e3680Sdan /* 64359af10620Sdan ** tclcmd: sqlite3_wal_autocheckpoint db VALUE 64369af10620Sdan */ 64377617e4a8Smistachkin static int SQLITE_TCLAPI test_wal_autocheckpoint( 64389af10620Sdan ClientData clientData, /* Unused */ 64399af10620Sdan Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 64409af10620Sdan int objc, /* Number of arguments */ 64419af10620Sdan Tcl_Obj *CONST objv[] /* Command arguments */ 64429af10620Sdan ){ 64439af10620Sdan sqlite3 *db; 64449af10620Sdan int rc; 64459af10620Sdan int iVal; 64469af10620Sdan 64479af10620Sdan 64489af10620Sdan if( objc!=3 ){ 64499af10620Sdan Tcl_WrongNumArgs(interp, 1, objv, "DB VALUE"); 64509af10620Sdan return TCL_ERROR; 64519af10620Sdan } 64529af10620Sdan 64539af10620Sdan if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) 64549af10620Sdan || Tcl_GetIntFromObj(0, objv[2], &iVal) 64559af10620Sdan ){ 64569af10620Sdan return TCL_ERROR; 64579af10620Sdan } 64589af10620Sdan 64599af10620Sdan rc = sqlite3_wal_autocheckpoint(db, iVal); 64609af10620Sdan Tcl_ResetResult(interp); 64619af10620Sdan if( rc!=SQLITE_OK ){ 64629af10620Sdan const char *zErrCode = sqlite3ErrName(rc); 64639af10620Sdan Tcl_SetObjResult(interp, Tcl_NewStringObj(zErrCode, -1)); 64649af10620Sdan return TCL_ERROR; 64659af10620Sdan } 64669af10620Sdan 64679af10620Sdan return TCL_OK; 64689af10620Sdan } 64699af10620Sdan 64709af10620Sdan 64719af10620Sdan /* 6472eb8763d7Sdan ** tclcmd: test_sqlite3_log ?SCRIPT? 6473eb8763d7Sdan */ 6474eb8763d7Sdan static struct LogCallback { 6475eb8763d7Sdan Tcl_Interp *pInterp; 6476eb8763d7Sdan Tcl_Obj *pObj; 6477eb8763d7Sdan } logcallback = {0, 0}; 6478eb8763d7Sdan static void xLogcallback(void *unused, int err, char *zMsg){ 6479eb8763d7Sdan Tcl_Obj *pNew = Tcl_DuplicateObj(logcallback.pObj); 6480eb8763d7Sdan Tcl_IncrRefCount(pNew); 6481eb8763d7Sdan Tcl_ListObjAppendElement( 6482e84d8d32Smistachkin 0, pNew, Tcl_NewStringObj(sqlite3ErrName(err), -1) 6483eb8763d7Sdan ); 6484eb8763d7Sdan Tcl_ListObjAppendElement(0, pNew, Tcl_NewStringObj(zMsg, -1)); 6485eb8763d7Sdan Tcl_EvalObjEx(logcallback.pInterp, pNew, TCL_EVAL_GLOBAL|TCL_EVAL_DIRECT); 6486eb8763d7Sdan Tcl_DecrRefCount(pNew); 6487eb8763d7Sdan } 64887617e4a8Smistachkin static int SQLITE_TCLAPI test_sqlite3_log( 6489eb8763d7Sdan ClientData clientData, 6490eb8763d7Sdan Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 6491eb8763d7Sdan int objc, /* Number of arguments */ 6492eb8763d7Sdan Tcl_Obj *CONST objv[] /* Command arguments */ 6493eb8763d7Sdan ){ 6494eb8763d7Sdan if( objc>2 ){ 6495eb8763d7Sdan Tcl_WrongNumArgs(interp, 1, objv, "SCRIPT"); 6496eb8763d7Sdan return TCL_ERROR; 6497eb8763d7Sdan } 6498eb8763d7Sdan if( logcallback.pObj ){ 6499eb8763d7Sdan Tcl_DecrRefCount(logcallback.pObj); 6500eb8763d7Sdan logcallback.pObj = 0; 6501eb8763d7Sdan logcallback.pInterp = 0; 6502d797a9b5Sdrh sqlite3_config(SQLITE_CONFIG_LOG, (void*)0, (void*)0); 6503eb8763d7Sdan } 6504eb8763d7Sdan if( objc>1 ){ 6505eb8763d7Sdan logcallback.pObj = objv[1]; 6506eb8763d7Sdan Tcl_IncrRefCount(logcallback.pObj); 6507eb8763d7Sdan logcallback.pInterp = interp; 6508d797a9b5Sdrh sqlite3_config(SQLITE_CONFIG_LOG, xLogcallback, (void*)0); 6509eb8763d7Sdan } 6510eb8763d7Sdan return TCL_OK; 6511eb8763d7Sdan } 65129bc5449fSdrh 65139bc5449fSdrh /* 6514a2c8a95bSdrh ** tcl_objproc COMMANDNAME ARGS... 6515a2c8a95bSdrh ** 6516a2c8a95bSdrh ** Run a TCL command using its objProc interface. Throw an error if 6517a2c8a95bSdrh ** the command has no objProc interface. 6518a2c8a95bSdrh */ 65197617e4a8Smistachkin static int SQLITE_TCLAPI runAsObjProc( 6520a2c8a95bSdrh void * clientData, 6521a2c8a95bSdrh Tcl_Interp *interp, 6522a2c8a95bSdrh int objc, 6523a2c8a95bSdrh Tcl_Obj *CONST objv[] 6524a2c8a95bSdrh ){ 6525a2c8a95bSdrh Tcl_CmdInfo cmdInfo; 6526a2c8a95bSdrh if( objc<2 ){ 6527a2c8a95bSdrh Tcl_WrongNumArgs(interp, 1, objv, "COMMAND ..."); 6528a2c8a95bSdrh return TCL_ERROR; 6529a2c8a95bSdrh } 6530a2c8a95bSdrh if( !Tcl_GetCommandInfo(interp, Tcl_GetString(objv[1]), &cmdInfo) ){ 6531a2c8a95bSdrh Tcl_AppendResult(interp, "command not found: ", 6532a2c8a95bSdrh Tcl_GetString(objv[1]), (char*)0); 6533a2c8a95bSdrh return TCL_ERROR; 6534a2c8a95bSdrh } 6535a2c8a95bSdrh if( cmdInfo.objProc==0 ){ 6536a2c8a95bSdrh Tcl_AppendResult(interp, "command has no objProc: ", 6537a2c8a95bSdrh Tcl_GetString(objv[1]), (char*)0); 6538a2c8a95bSdrh return TCL_ERROR; 6539a2c8a95bSdrh } 6540a2c8a95bSdrh return cmdInfo.objProc(cmdInfo.objClientData, interp, objc-1, objv+1); 6541a2c8a95bSdrh } 6542a2c8a95bSdrh 654391da6b83Sdan #ifndef SQLITE_OMIT_EXPLAIN 654491da6b83Sdan /* 654591da6b83Sdan ** WARNING: The following function, printExplainQueryPlan() is an exact 654691da6b83Sdan ** copy of example code from eqp.in (eqp.html). If this code is modified, 654791da6b83Sdan ** then the documentation copy needs to be modified as well. 654891da6b83Sdan */ 654991da6b83Sdan /* 655091da6b83Sdan ** Argument pStmt is a prepared SQL statement. This function compiles 655191da6b83Sdan ** an EXPLAIN QUERY PLAN command to report on the prepared statement, 655291da6b83Sdan ** and prints the report to stdout using printf(). 655391da6b83Sdan */ 655491da6b83Sdan int printExplainQueryPlan(sqlite3_stmt *pStmt){ 655591da6b83Sdan const char *zSql; /* Input SQL */ 655691da6b83Sdan char *zExplain; /* SQL with EXPLAIN QUERY PLAN prepended */ 655791da6b83Sdan sqlite3_stmt *pExplain; /* Compiled EXPLAIN QUERY PLAN command */ 655891da6b83Sdan int rc; /* Return code from sqlite3_prepare_v2() */ 655991da6b83Sdan 656091da6b83Sdan zSql = sqlite3_sql(pStmt); 656191da6b83Sdan if( zSql==0 ) return SQLITE_ERROR; 656291da6b83Sdan 656391da6b83Sdan zExplain = sqlite3_mprintf("EXPLAIN QUERY PLAN %s", zSql); 656491da6b83Sdan if( zExplain==0 ) return SQLITE_NOMEM; 656591da6b83Sdan 656691da6b83Sdan rc = sqlite3_prepare_v2(sqlite3_db_handle(pStmt), zExplain, -1, &pExplain, 0); 656791da6b83Sdan sqlite3_free(zExplain); 656891da6b83Sdan if( rc!=SQLITE_OK ) return rc; 656991da6b83Sdan 657091da6b83Sdan while( SQLITE_ROW==sqlite3_step(pExplain) ){ 657191da6b83Sdan int iSelectid = sqlite3_column_int(pExplain, 0); 657291da6b83Sdan int iOrder = sqlite3_column_int(pExplain, 1); 657391da6b83Sdan int iFrom = sqlite3_column_int(pExplain, 2); 657491da6b83Sdan const char *zDetail = (const char *)sqlite3_column_text(pExplain, 3); 657591da6b83Sdan 657691da6b83Sdan printf("%d %d %d %s\n", iSelectid, iOrder, iFrom, zDetail); 657791da6b83Sdan } 657891da6b83Sdan 657991da6b83Sdan return sqlite3_finalize(pExplain); 658091da6b83Sdan } 658191da6b83Sdan 65827617e4a8Smistachkin static int SQLITE_TCLAPI test_print_eqp( 658391da6b83Sdan void * clientData, 658491da6b83Sdan Tcl_Interp *interp, 658591da6b83Sdan int objc, 658691da6b83Sdan Tcl_Obj *CONST objv[] 658791da6b83Sdan ){ 658891da6b83Sdan int rc; 658991da6b83Sdan sqlite3_stmt *pStmt; 659091da6b83Sdan 659191da6b83Sdan if( objc!=2 ){ 659291da6b83Sdan Tcl_WrongNumArgs(interp, 1, objv, "STMT"); 659391da6b83Sdan return TCL_ERROR; 659491da6b83Sdan } 659591da6b83Sdan if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 659691da6b83Sdan rc = printExplainQueryPlan(pStmt); 65977c5d8fb7Sshaneh /* This is needed on Windows so that a test case using this 65987c5d8fb7Sshaneh ** function can open a read pipe and get the output of 65997c5d8fb7Sshaneh ** printExplainQueryPlan() immediately. 66007c5d8fb7Sshaneh */ 66017c5d8fb7Sshaneh fflush(stdout); 660291da6b83Sdan Tcl_SetResult(interp, (char *)t1ErrorName(rc), 0); 660391da6b83Sdan return TCL_OK; 660491da6b83Sdan } 660591da6b83Sdan #endif /* SQLITE_OMIT_EXPLAIN */ 6606a2c8a95bSdrh 6607a2c8a95bSdrh /* 6608c17d696cSdan ** sqlite3_test_control VERB ARGS... 6609c17d696cSdan */ 66107617e4a8Smistachkin static int SQLITE_TCLAPI test_test_control( 6611c17d696cSdan void * clientData, 6612c17d696cSdan Tcl_Interp *interp, 6613c17d696cSdan int objc, 6614c17d696cSdan Tcl_Obj *CONST objv[] 6615c17d696cSdan ){ 6616c17d696cSdan struct Verb { 6617c17d696cSdan const char *zName; 6618c17d696cSdan int i; 6619c17d696cSdan } aVerb[] = { 6620c17d696cSdan { "SQLITE_TESTCTRL_LOCALTIME_FAULT", SQLITE_TESTCTRL_LOCALTIME_FAULT }, 66218930c2abSdan { "SQLITE_TESTCTRL_SORTER_MMAP", SQLITE_TESTCTRL_SORTER_MMAP }, 66221ffede8cSdrh { "SQLITE_TESTCTRL_IMPOSTER", SQLITE_TESTCTRL_IMPOSTER }, 6623c17d696cSdan }; 6624c17d696cSdan int iVerb; 6625c17d696cSdan int iFlag; 6626c17d696cSdan int rc; 6627c17d696cSdan 6628c17d696cSdan if( objc<2 ){ 6629c17d696cSdan Tcl_WrongNumArgs(interp, 1, objv, "VERB ARGS..."); 6630c17d696cSdan return TCL_ERROR; 6631c17d696cSdan } 6632c17d696cSdan 6633c17d696cSdan rc = Tcl_GetIndexFromObjStruct( 6634c17d696cSdan interp, objv[1], aVerb, sizeof(aVerb[0]), "VERB", 0, &iVerb 6635c17d696cSdan ); 6636c17d696cSdan if( rc!=TCL_OK ) return rc; 6637c17d696cSdan 6638c17d696cSdan iFlag = aVerb[iVerb].i; 6639c17d696cSdan switch( iFlag ){ 6640c17d696cSdan case SQLITE_TESTCTRL_LOCALTIME_FAULT: { 6641c17d696cSdan int val; 6642c17d696cSdan if( objc!=3 ){ 6643c17d696cSdan Tcl_WrongNumArgs(interp, 2, objv, "ONOFF"); 6644c17d696cSdan return TCL_ERROR; 6645c17d696cSdan } 6646c17d696cSdan if( Tcl_GetBooleanFromObj(interp, objv[2], &val) ) return TCL_ERROR; 6647c17d696cSdan sqlite3_test_control(SQLITE_TESTCTRL_LOCALTIME_FAULT, val); 6648c17d696cSdan break; 6649c17d696cSdan } 66508930c2abSdan 66518930c2abSdan case SQLITE_TESTCTRL_SORTER_MMAP: { 66528930c2abSdan int val; 66538930c2abSdan sqlite3 *db; 66548930c2abSdan if( objc!=4 ){ 66558930c2abSdan Tcl_WrongNumArgs(interp, 2, objv, "DB LIMIT"); 66568930c2abSdan return TCL_ERROR; 66578930c2abSdan } 66588930c2abSdan if( getDbPointer(interp, Tcl_GetString(objv[2]), &db) ) return TCL_ERROR; 66598930c2abSdan if( Tcl_GetIntFromObj(interp, objv[3], &val) ) return TCL_ERROR; 66608930c2abSdan sqlite3_test_control(SQLITE_TESTCTRL_SORTER_MMAP, db, val); 66618930c2abSdan break; 66628930c2abSdan } 6663917682a4Sdrh 66641ffede8cSdrh case SQLITE_TESTCTRL_IMPOSTER: { 66651ffede8cSdrh int onOff, tnum; 66661ffede8cSdrh const char *zDbName; 6667917682a4Sdrh sqlite3 *db; 6668917682a4Sdrh if( objc!=6 ){ 66691ffede8cSdrh Tcl_WrongNumArgs(interp, 2, objv, "DB dbName onOff tnum"); 6670917682a4Sdrh return TCL_ERROR; 6671917682a4Sdrh } 6672917682a4Sdrh if( getDbPointer(interp, Tcl_GetString(objv[2]), &db) ) return TCL_ERROR; 66731ffede8cSdrh zDbName = Tcl_GetString(objv[3]); 66741ffede8cSdrh if( Tcl_GetIntFromObj(interp, objv[4], &onOff) ) return TCL_ERROR; 66751ffede8cSdrh if( Tcl_GetIntFromObj(interp, objv[5], &tnum) ) return TCL_ERROR; 66761ffede8cSdrh sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, db, zDbName, onOff, tnum); 6677917682a4Sdrh break; 6678917682a4Sdrh } 6679c17d696cSdan } 6680c17d696cSdan 6681c17d696cSdan Tcl_ResetResult(interp); 6682c17d696cSdan return TCL_OK; 6683c17d696cSdan } 6684c17d696cSdan 6685daf9a5a4Smistachkin #if SQLITE_OS_UNIX 6686a72014faSdan #include <sys/time.h> 6687a72014faSdan #include <sys/resource.h> 6688a72014faSdan 66897617e4a8Smistachkin static int SQLITE_TCLAPI test_getrusage( 6690a72014faSdan void * clientData, 6691a72014faSdan Tcl_Interp *interp, 6692a72014faSdan int objc, 6693a72014faSdan Tcl_Obj *CONST objv[] 6694a72014faSdan ){ 6695a72014faSdan char buf[1024]; 6696a72014faSdan struct rusage r; 6697a72014faSdan memset(&r, 0, sizeof(r)); 6698a72014faSdan getrusage(RUSAGE_SELF, &r); 6699a72014faSdan 670065545b59Sdrh sqlite3_snprintf(sizeof(buf), buf, 670165545b59Sdrh "ru_utime=%d.%06d ru_stime=%d.%06d ru_minflt=%d ru_majflt=%d", 67025d8a1372Sdan (int)r.ru_utime.tv_sec, (int)r.ru_utime.tv_usec, 67035d8a1372Sdan (int)r.ru_stime.tv_sec, (int)r.ru_stime.tv_usec, 67045d8a1372Sdan (int)r.ru_minflt, (int)r.ru_majflt 6705a72014faSdan ); 6706a72014faSdan Tcl_SetObjResult(interp, Tcl_NewStringObj(buf, -1)); 6707a72014faSdan return TCL_OK; 6708a72014faSdan } 6709daf9a5a4Smistachkin #endif 6710a72014faSdan 671180084ca8Sdrh #if SQLITE_OS_WIN 671280084ca8Sdrh /* 671380084ca8Sdrh ** Information passed from the main thread into the windows file locker 671480084ca8Sdrh ** background thread. 671580084ca8Sdrh */ 671680084ca8Sdrh struct win32FileLocker { 6717176f1b47Smistachkin char *evName; /* Name of event to signal thread startup */ 671880084ca8Sdrh HANDLE h; /* Handle of the file to be locked */ 671980084ca8Sdrh int delay1; /* Delay before locking */ 672080084ca8Sdrh int delay2; /* Delay before unlocking */ 672180084ca8Sdrh int ok; /* Finished ok */ 672280084ca8Sdrh int err; /* True if an error occurs */ 672380084ca8Sdrh }; 672480084ca8Sdrh #endif 672580084ca8Sdrh 672680084ca8Sdrh 672780084ca8Sdrh #if SQLITE_OS_WIN 67287da5fcb0Sdrh #include <process.h> 672980084ca8Sdrh /* 673080084ca8Sdrh ** The background thread that does file locking. 673180084ca8Sdrh */ 673269def7ffSmistachkin static void SQLITE_CDECL win32_file_locker(void *pAppData){ 673380084ca8Sdrh struct win32FileLocker *p = (struct win32FileLocker*)pAppData; 6734176f1b47Smistachkin if( p->evName ){ 6735176f1b47Smistachkin HANDLE ev = OpenEvent(EVENT_MODIFY_STATE, FALSE, p->evName); 6736176f1b47Smistachkin if ( ev ){ 6737176f1b47Smistachkin SetEvent(ev); 6738176f1b47Smistachkin CloseHandle(ev); 6739176f1b47Smistachkin } 6740176f1b47Smistachkin } 674180084ca8Sdrh if( p->delay1 ) Sleep(p->delay1); 674280084ca8Sdrh if( LockFile(p->h, 0, 0, 100000000, 0) ){ 674380084ca8Sdrh Sleep(p->delay2); 674480084ca8Sdrh UnlockFile(p->h, 0, 0, 100000000, 0); 674580084ca8Sdrh p->ok = 1; 674680084ca8Sdrh }else{ 674780084ca8Sdrh p->err = 1; 674880084ca8Sdrh } 674980084ca8Sdrh CloseHandle(p->h); 675080084ca8Sdrh p->h = 0; 675180084ca8Sdrh p->delay1 = 0; 675280084ca8Sdrh p->delay2 = 0; 675380084ca8Sdrh } 675480084ca8Sdrh #endif 675580084ca8Sdrh 675680084ca8Sdrh #if SQLITE_OS_WIN 675780084ca8Sdrh /* 675880084ca8Sdrh ** lock_win32_file FILENAME DELAY1 DELAY2 675980084ca8Sdrh ** 676080084ca8Sdrh ** Get an exclusive manditory lock on file for DELAY2 milliseconds. 676180084ca8Sdrh ** Wait DELAY1 milliseconds before acquiring the lock. 676280084ca8Sdrh */ 67637617e4a8Smistachkin static int SQLITE_TCLAPI win32_file_lock( 676480084ca8Sdrh void * clientData, 676580084ca8Sdrh Tcl_Interp *interp, 676680084ca8Sdrh int objc, 676780084ca8Sdrh Tcl_Obj *CONST objv[] 676880084ca8Sdrh ){ 6769176f1b47Smistachkin static struct win32FileLocker x = { "win32_file_lock", 0, 0, 0, 0, 0 }; 677080084ca8Sdrh const char *zFilename; 6771176f1b47Smistachkin char zBuf[200]; 677280084ca8Sdrh int retry = 0; 6773176f1b47Smistachkin HANDLE ev; 6774176f1b47Smistachkin DWORD wResult; 677580084ca8Sdrh 677680084ca8Sdrh if( objc!=4 && objc!=1 ){ 677780084ca8Sdrh Tcl_WrongNumArgs(interp, 1, objv, "FILENAME DELAY1 DELAY2"); 677880084ca8Sdrh return TCL_ERROR; 677980084ca8Sdrh } 678080084ca8Sdrh if( objc==1 ){ 678180084ca8Sdrh sqlite3_snprintf(sizeof(zBuf), zBuf, "%d %d %d %d %d", 678280084ca8Sdrh x.ok, x.err, x.delay1, x.delay2, x.h); 678380084ca8Sdrh Tcl_AppendResult(interp, zBuf, (char*)0); 678480084ca8Sdrh return TCL_OK; 678580084ca8Sdrh } 6786d0cdf012Sdrh while( x.h && retry<30 ){ 678780084ca8Sdrh retry++; 678880084ca8Sdrh Sleep(100); 678980084ca8Sdrh } 679080084ca8Sdrh if( x.h ){ 679180084ca8Sdrh Tcl_AppendResult(interp, "busy", (char*)0); 679280084ca8Sdrh return TCL_ERROR; 679380084ca8Sdrh } 679480084ca8Sdrh if( Tcl_GetIntFromObj(interp, objv[2], &x.delay1) ) return TCL_ERROR; 679580084ca8Sdrh if( Tcl_GetIntFromObj(interp, objv[3], &x.delay2) ) return TCL_ERROR; 679680084ca8Sdrh zFilename = Tcl_GetString(objv[1]); 679780084ca8Sdrh x.h = CreateFile(zFilename, GENERIC_READ|GENERIC_WRITE, 679880084ca8Sdrh FILE_SHARE_READ|FILE_SHARE_WRITE, 0, OPEN_ALWAYS, 679980084ca8Sdrh FILE_ATTRIBUTE_NORMAL, 0); 680080084ca8Sdrh if( !x.h ){ 680180084ca8Sdrh Tcl_AppendResult(interp, "cannot open file: ", zFilename, (char*)0); 680280084ca8Sdrh return TCL_ERROR; 680380084ca8Sdrh } 6804176f1b47Smistachkin ev = CreateEvent(NULL, TRUE, FALSE, x.evName); 6805176f1b47Smistachkin if ( !ev ){ 6806176f1b47Smistachkin Tcl_AppendResult(interp, "cannot create event: ", x.evName, (char*)0); 6807176f1b47Smistachkin return TCL_ERROR; 6808176f1b47Smistachkin } 680980084ca8Sdrh _beginthread(win32_file_locker, 0, (void*)&x); 681080084ca8Sdrh Sleep(0); 6811176f1b47Smistachkin if ( (wResult = WaitForSingleObject(ev, 10000))!=WAIT_OBJECT_0 ){ 6812176f1b47Smistachkin sqlite3_snprintf(sizeof(zBuf), zBuf, "0x%x", wResult); 6813176f1b47Smistachkin Tcl_AppendResult(interp, "wait failed: ", zBuf, (char*)0); 6814176f1b47Smistachkin CloseHandle(ev); 6815176f1b47Smistachkin return TCL_ERROR; 6816176f1b47Smistachkin } 6817176f1b47Smistachkin CloseHandle(ev); 681880084ca8Sdrh return TCL_OK; 681980084ca8Sdrh } 68203741827eSmistachkin 68213741827eSmistachkin /* 68223741827eSmistachkin ** exists_win32_path PATH 68233741827eSmistachkin ** 68243741827eSmistachkin ** Returns non-zero if the specified path exists, whose fully qualified name 68253259fe79Smistachkin ** may exceed 260 characters if it is prefixed with "\\?\". 68263741827eSmistachkin */ 68277617e4a8Smistachkin static int SQLITE_TCLAPI win32_exists_path( 68283741827eSmistachkin void *clientData, 68293741827eSmistachkin Tcl_Interp *interp, 68303741827eSmistachkin int objc, 68313741827eSmistachkin Tcl_Obj *CONST objv[] 68323741827eSmistachkin ){ 68333741827eSmistachkin if( objc!=2 ){ 68343741827eSmistachkin Tcl_WrongNumArgs(interp, 1, objv, "PATH"); 68353741827eSmistachkin return TCL_ERROR; 68363741827eSmistachkin } 68373741827eSmistachkin Tcl_SetObjResult(interp, Tcl_NewBooleanObj( 68383741827eSmistachkin GetFileAttributesW( Tcl_GetUnicode(objv[1]))!=INVALID_FILE_ATTRIBUTES )); 68393741827eSmistachkin return TCL_OK; 68403741827eSmistachkin } 68413741827eSmistachkin 68423741827eSmistachkin /* 68433741827eSmistachkin ** find_win32_file PATTERN 68443741827eSmistachkin ** 68453741827eSmistachkin ** Returns a list of entries in a directory that match the specified pattern, 68463741827eSmistachkin ** whose fully qualified name may exceed 248 characters if it is prefixed with 68473741827eSmistachkin ** "\\?\". 68483741827eSmistachkin */ 68497617e4a8Smistachkin static int SQLITE_TCLAPI win32_find_file( 68503741827eSmistachkin void *clientData, 68513741827eSmistachkin Tcl_Interp *interp, 68523741827eSmistachkin int objc, 68533741827eSmistachkin Tcl_Obj *CONST objv[] 68543741827eSmistachkin ){ 68553741827eSmistachkin HANDLE hFindFile = INVALID_HANDLE_VALUE; 68563741827eSmistachkin WIN32_FIND_DATAW findData; 68573741827eSmistachkin Tcl_Obj *listObj; 68583741827eSmistachkin DWORD lastErrno; 68593741827eSmistachkin if( objc!=2 ){ 68603741827eSmistachkin Tcl_WrongNumArgs(interp, 1, objv, "PATTERN"); 68613741827eSmistachkin return TCL_ERROR; 68623741827eSmistachkin } 68633741827eSmistachkin hFindFile = FindFirstFileW(Tcl_GetUnicode(objv[1]), &findData); 68643741827eSmistachkin if( hFindFile==INVALID_HANDLE_VALUE ){ 68653741827eSmistachkin Tcl_SetObjResult(interp, Tcl_NewWideIntObj(GetLastError())); 68663741827eSmistachkin return TCL_ERROR; 68673741827eSmistachkin } 68683741827eSmistachkin listObj = Tcl_NewObj(); 68693741827eSmistachkin Tcl_IncrRefCount(listObj); 68703741827eSmistachkin do { 68713741827eSmistachkin Tcl_ListObjAppendElement(interp, listObj, Tcl_NewUnicodeObj( 68723741827eSmistachkin findData.cFileName, -1)); 68733741827eSmistachkin Tcl_ListObjAppendElement(interp, listObj, Tcl_NewWideIntObj( 68743741827eSmistachkin findData.dwFileAttributes)); 68753741827eSmistachkin } while( FindNextFileW(hFindFile, &findData) ); 68763741827eSmistachkin lastErrno = GetLastError(); 68773741827eSmistachkin if( lastErrno!=NO_ERROR && lastErrno!=ERROR_NO_MORE_FILES ){ 68783741827eSmistachkin FindClose(hFindFile); 68793741827eSmistachkin Tcl_DecrRefCount(listObj); 68803741827eSmistachkin Tcl_SetObjResult(interp, Tcl_NewWideIntObj(GetLastError())); 68813741827eSmistachkin return TCL_ERROR; 68823741827eSmistachkin } 68833741827eSmistachkin FindClose(hFindFile); 68843741827eSmistachkin Tcl_SetObjResult(interp, listObj); 68853741827eSmistachkin return TCL_OK; 68863741827eSmistachkin } 68873741827eSmistachkin 68883741827eSmistachkin /* 68893741827eSmistachkin ** delete_win32_file FILENAME 68903741827eSmistachkin ** 68913259fe79Smistachkin ** Deletes the specified file, whose fully qualified name may exceed 260 68923741827eSmistachkin ** characters if it is prefixed with "\\?\". 68933741827eSmistachkin */ 68947617e4a8Smistachkin static int SQLITE_TCLAPI win32_delete_file( 68953741827eSmistachkin void *clientData, 68963741827eSmistachkin Tcl_Interp *interp, 68973741827eSmistachkin int objc, 68983741827eSmistachkin Tcl_Obj *CONST objv[] 68993741827eSmistachkin ){ 69003741827eSmistachkin if( objc!=2 ){ 69013741827eSmistachkin Tcl_WrongNumArgs(interp, 1, objv, "FILENAME"); 69023741827eSmistachkin return TCL_ERROR; 69033741827eSmistachkin } 69043741827eSmistachkin if( !DeleteFileW(Tcl_GetUnicode(objv[1])) ){ 69053741827eSmistachkin Tcl_SetObjResult(interp, Tcl_NewWideIntObj(GetLastError())); 69063741827eSmistachkin return TCL_ERROR; 69073741827eSmistachkin } 69083741827eSmistachkin Tcl_ResetResult(interp); 69093741827eSmistachkin return TCL_OK; 69103741827eSmistachkin } 69113741827eSmistachkin 69123741827eSmistachkin /* 69133741827eSmistachkin ** make_win32_dir DIRECTORY 69143741827eSmistachkin ** 69153741827eSmistachkin ** Creates the specified directory, whose fully qualified name may exceed 248 69163741827eSmistachkin ** characters if it is prefixed with "\\?\". 69173741827eSmistachkin */ 69187617e4a8Smistachkin static int SQLITE_TCLAPI win32_mkdir( 69193741827eSmistachkin void *clientData, 69203741827eSmistachkin Tcl_Interp *interp, 69213741827eSmistachkin int objc, 69223741827eSmistachkin Tcl_Obj *CONST objv[] 69233741827eSmistachkin ){ 69243741827eSmistachkin if( objc!=2 ){ 69253741827eSmistachkin Tcl_WrongNumArgs(interp, 1, objv, "DIRECTORY"); 69263741827eSmistachkin return TCL_ERROR; 69273741827eSmistachkin } 69283741827eSmistachkin if( !CreateDirectoryW(Tcl_GetUnicode(objv[1]), NULL) ){ 69293741827eSmistachkin Tcl_SetObjResult(interp, Tcl_NewWideIntObj(GetLastError())); 69303741827eSmistachkin return TCL_ERROR; 69313741827eSmistachkin } 69323741827eSmistachkin Tcl_ResetResult(interp); 69333741827eSmistachkin return TCL_OK; 69343741827eSmistachkin } 69353741827eSmistachkin 69363741827eSmistachkin /* 69373741827eSmistachkin ** remove_win32_dir DIRECTORY 69383741827eSmistachkin ** 69393741827eSmistachkin ** Removes the specified directory, whose fully qualified name may exceed 248 69403741827eSmistachkin ** characters if it is prefixed with "\\?\". 69413741827eSmistachkin */ 69427617e4a8Smistachkin static int SQLITE_TCLAPI win32_rmdir( 69433741827eSmistachkin void *clientData, 69443741827eSmistachkin Tcl_Interp *interp, 69453741827eSmistachkin int objc, 69463741827eSmistachkin Tcl_Obj *CONST objv[] 69473741827eSmistachkin ){ 69483741827eSmistachkin if( objc!=2 ){ 69493741827eSmistachkin Tcl_WrongNumArgs(interp, 1, objv, "DIRECTORY"); 69503741827eSmistachkin return TCL_ERROR; 69513741827eSmistachkin } 69523741827eSmistachkin if( !RemoveDirectoryW(Tcl_GetUnicode(objv[1])) ){ 69533741827eSmistachkin Tcl_SetObjResult(interp, Tcl_NewWideIntObj(GetLastError())); 69543741827eSmistachkin return TCL_ERROR; 69553741827eSmistachkin } 69563741827eSmistachkin Tcl_ResetResult(interp); 69573741827eSmistachkin return TCL_OK; 69583741827eSmistachkin } 695980084ca8Sdrh #endif 6960c17d696cSdan 6961d0cdf012Sdrh 6962c17d696cSdan /* 6963f58ee7f1Sdrh ** optimization_control DB OPT BOOLEAN 6964f58ee7f1Sdrh ** 6965f58ee7f1Sdrh ** Enable or disable query optimizations using the sqlite3_test_control() 6966f58ee7f1Sdrh ** interface. Disable if BOOLEAN is false and enable if BOOLEAN is true. 6967f58ee7f1Sdrh ** OPT is the name of the optimization to be disabled. 6968f58ee7f1Sdrh */ 69697617e4a8Smistachkin static int SQLITE_TCLAPI optimization_control( 6970f58ee7f1Sdrh void * clientData, 6971f58ee7f1Sdrh Tcl_Interp *interp, 6972f58ee7f1Sdrh int objc, 6973f58ee7f1Sdrh Tcl_Obj *CONST objv[] 6974f58ee7f1Sdrh ){ 6975f58ee7f1Sdrh int i; 6976f58ee7f1Sdrh sqlite3 *db; 6977f58ee7f1Sdrh const char *zOpt; 6978f58ee7f1Sdrh int onoff; 6979fc30b042Sdrh int mask = 0; 6980f58ee7f1Sdrh static const struct { 6981f58ee7f1Sdrh const char *zOptName; 6982f58ee7f1Sdrh int mask; 6983f58ee7f1Sdrh } aOpt[] = { 69847e5418e4Sdrh { "all", SQLITE_AllOpts }, 69859d5a579cSdrh { "none", 0 }, 6986f58ee7f1Sdrh { "query-flattener", SQLITE_QueryFlattener }, 6987f58ee7f1Sdrh { "groupby-order", SQLITE_GroupByOrder }, 6988f58ee7f1Sdrh { "factor-constants", SQLITE_FactorOutConst }, 6989f4af1089Sdrh { "distinct-opt", SQLITE_DistinctOpt }, 6990de9a7b8aSdrh { "cover-idx-scan", SQLITE_CoverIdxScan }, 69917e5418e4Sdrh { "order-by-idx-join", SQLITE_OrderByIdxJoin }, 69929d5a579cSdrh { "transitive", SQLITE_Transitive }, 69939d5a579cSdrh { "omit-noop-join", SQLITE_OmitNoopJoin }, 6994d7d71470Sdrh { "stat3", SQLITE_Stat34 }, 6995d7d71470Sdrh { "stat4", SQLITE_Stat34 }, 6996e8825519Sdan { "skip-scan", SQLITE_SkipScan }, 6997f58ee7f1Sdrh }; 6998f58ee7f1Sdrh 6999f58ee7f1Sdrh if( objc!=4 ){ 7000f58ee7f1Sdrh Tcl_WrongNumArgs(interp, 1, objv, "DB OPT BOOLEAN"); 7001f58ee7f1Sdrh return TCL_ERROR; 7002f58ee7f1Sdrh } 7003f58ee7f1Sdrh if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 7004f58ee7f1Sdrh if( Tcl_GetBooleanFromObj(interp, objv[3], &onoff) ) return TCL_ERROR; 7005f58ee7f1Sdrh zOpt = Tcl_GetString(objv[2]); 7006f58ee7f1Sdrh for(i=0; i<sizeof(aOpt)/sizeof(aOpt[0]); i++){ 7007f58ee7f1Sdrh if( strcmp(zOpt, aOpt[i].zOptName)==0 ){ 7008f58ee7f1Sdrh mask = aOpt[i].mask; 7009f58ee7f1Sdrh break; 7010f58ee7f1Sdrh } 7011f58ee7f1Sdrh } 7012f58ee7f1Sdrh if( onoff ) mask = ~mask; 7013f58ee7f1Sdrh if( i>=sizeof(aOpt)/sizeof(aOpt[0]) ){ 7014f58ee7f1Sdrh Tcl_AppendResult(interp, "unknown optimization - should be one of:", 7015f58ee7f1Sdrh (char*)0); 7016f58ee7f1Sdrh for(i=0; i<sizeof(aOpt)/sizeof(aOpt[0]); i++){ 70179d5a579cSdrh Tcl_AppendResult(interp, " ", aOpt[i].zOptName, (char*)0); 7018f58ee7f1Sdrh } 7019f58ee7f1Sdrh return TCL_ERROR; 7020f58ee7f1Sdrh } 7021f58ee7f1Sdrh sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS, db, mask); 7022f58ee7f1Sdrh return TCL_OK; 7023f58ee7f1Sdrh } 7024f58ee7f1Sdrh 7025248f2be9Sdrh /* 7026ea41dc44Sdrh ** load_static_extension DB NAME ... 7027248f2be9Sdrh ** 7028ea41dc44Sdrh ** Load one or more statically linked extensions. 7029248f2be9Sdrh */ 70307617e4a8Smistachkin static int SQLITE_TCLAPI tclLoadStaticExtensionCmd( 7031248f2be9Sdrh void * clientData, 7032248f2be9Sdrh Tcl_Interp *interp, 7033248f2be9Sdrh int objc, 7034248f2be9Sdrh Tcl_Obj *CONST objv[] 7035248f2be9Sdrh ){ 70368416fc7fSdrh extern int sqlite3_amatch_init(sqlite3*,char**,const sqlite3_api_routines*); 70372e3f87aeSdrh extern int sqlite3_carray_init(sqlite3*,char**,const sqlite3_api_routines*); 70388416fc7fSdrh extern int sqlite3_closure_init(sqlite3*,char**,const sqlite3_api_routines*); 703935db31b2Sdrh extern int sqlite3_csv_init(sqlite3*,char**,const sqlite3_api_routines*); 70401728bcb0Sdrh extern int sqlite3_eval_init(sqlite3*,char**,const sqlite3_api_routines*); 704151ed2983Sdrh extern int sqlite3_fileio_init(sqlite3*,char**,const sqlite3_api_routines*); 7042e50db1c5Sdrh extern int sqlite3_fuzzer_init(sqlite3*,char**,const sqlite3_api_routines*); 70438416fc7fSdrh extern int sqlite3_ieee_init(sqlite3*,char**,const sqlite3_api_routines*); 7044ea41dc44Sdrh extern int sqlite3_nextchar_init(sqlite3*,char**,const sqlite3_api_routines*); 7045def3367eSdrh extern int sqlite3_percentile_init(sqlite3*,char**,const sqlite3_api_routines*); 7046248f2be9Sdrh extern int sqlite3_regexp_init(sqlite3*,char**,const sqlite3_api_routines*); 70476bada272Sdrh extern int sqlite3_remember_init(sqlite3*,char**,const sqlite3_api_routines*); 7048398f872dSdrh extern int sqlite3_series_init(sqlite3*,char**,const sqlite3_api_routines*); 7049b7045ab2Sdrh extern int sqlite3_spellfix_init(sqlite3*,char**,const sqlite3_api_routines*); 70505f8cdac6Sdrh extern int sqlite3_totype_init(sqlite3*,char**,const sqlite3_api_routines*); 705124b6422dSdrh extern int sqlite3_wholenumber_init(sqlite3*,char**,const sqlite3_api_routines*); 7052d8ecefa5Sdan extern int sqlite3_unionvtab_init(sqlite3*,char**,const sqlite3_api_routines*); 705391f7211cSmistachkin #ifdef SQLITE_HAVE_ZLIB 7054373dc3bbSdan extern int sqlite3_zipfile_init(sqlite3*,char**,const sqlite3_api_routines*); 705591f7211cSmistachkin #endif 7056248f2be9Sdrh static const struct { 7057248f2be9Sdrh const char *zExtName; 7058248f2be9Sdrh int (*pInit)(sqlite3*,char**,const sqlite3_api_routines*); 7059248f2be9Sdrh } aExtension[] = { 70608416fc7fSdrh { "amatch", sqlite3_amatch_init }, 70612e3f87aeSdrh { "carray", sqlite3_carray_init }, 70628416fc7fSdrh { "closure", sqlite3_closure_init }, 706335db31b2Sdrh { "csv", sqlite3_csv_init }, 70641728bcb0Sdrh { "eval", sqlite3_eval_init }, 706551ed2983Sdrh { "fileio", sqlite3_fileio_init }, 7066e50db1c5Sdrh { "fuzzer", sqlite3_fuzzer_init }, 70678416fc7fSdrh { "ieee754", sqlite3_ieee_init }, 7068ea41dc44Sdrh { "nextchar", sqlite3_nextchar_init }, 7069def3367eSdrh { "percentile", sqlite3_percentile_init }, 7070248f2be9Sdrh { "regexp", sqlite3_regexp_init }, 70716bada272Sdrh { "remember", sqlite3_remember_init }, 7072398f872dSdrh { "series", sqlite3_series_init }, 7073b7045ab2Sdrh { "spellfix", sqlite3_spellfix_init }, 70745f8cdac6Sdrh { "totype", sqlite3_totype_init }, 7075d8ecefa5Sdan { "unionvtab", sqlite3_unionvtab_init }, 707624b6422dSdrh { "wholenumber", sqlite3_wholenumber_init }, 707791f7211cSmistachkin #ifdef SQLITE_HAVE_ZLIB 7078373dc3bbSdan { "zipfile", sqlite3_zipfile_init }, 707991f7211cSmistachkin #endif 7080248f2be9Sdrh }; 7081248f2be9Sdrh sqlite3 *db; 7082248f2be9Sdrh const char *zName; 7083ea41dc44Sdrh int i, j, rc; 7084248f2be9Sdrh char *zErrMsg = 0; 7085ea41dc44Sdrh if( objc<3 ){ 7086ea41dc44Sdrh Tcl_WrongNumArgs(interp, 1, objv, "DB NAME ..."); 7087248f2be9Sdrh return TCL_ERROR; 7088248f2be9Sdrh } 7089248f2be9Sdrh if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 7090ea41dc44Sdrh for(j=2; j<objc; j++){ 7091ea41dc44Sdrh zName = Tcl_GetString(objv[j]); 7092248f2be9Sdrh for(i=0; i<ArraySize(aExtension); i++){ 7093248f2be9Sdrh if( strcmp(zName, aExtension[i].zExtName)==0 ) break; 7094248f2be9Sdrh } 7095248f2be9Sdrh if( i>=ArraySize(aExtension) ){ 7096248f2be9Sdrh Tcl_AppendResult(interp, "no such extension: ", zName, (char*)0); 7097248f2be9Sdrh return TCL_ERROR; 7098248f2be9Sdrh } 7099c306e08aSdrh if( aExtension[i].pInit ){ 7100248f2be9Sdrh rc = aExtension[i].pInit(db, &zErrMsg, 0); 7101c306e08aSdrh }else{ 7102c306e08aSdrh rc = SQLITE_OK; 7103c306e08aSdrh } 7104248f2be9Sdrh if( rc!=SQLITE_OK || zErrMsg ){ 7105248f2be9Sdrh Tcl_AppendResult(interp, "initialization of ", zName, " failed: ", zErrMsg, 7106248f2be9Sdrh (char*)0); 7107248f2be9Sdrh sqlite3_free(zErrMsg); 7108248f2be9Sdrh return TCL_ERROR; 7109248f2be9Sdrh } 7110ea41dc44Sdrh } 7111248f2be9Sdrh return TCL_OK; 7112248f2be9Sdrh } 7113248f2be9Sdrh 71140d51def2Sdan /* 71150d51def2Sdan ** sorter_test_fakeheap BOOL 71160d51def2Sdan ** 71170d51def2Sdan */ 71187617e4a8Smistachkin static int SQLITE_TCLAPI sorter_test_fakeheap( 71190d51def2Sdan void * clientData, 71200d51def2Sdan Tcl_Interp *interp, 71210d51def2Sdan int objc, 71220d51def2Sdan Tcl_Obj *CONST objv[] 71230d51def2Sdan ){ 71240d51def2Sdan int bArg; 71250d51def2Sdan if( objc!=2 ){ 71260d51def2Sdan Tcl_WrongNumArgs(interp, 1, objv, "BOOL"); 71270d51def2Sdan return TCL_ERROR; 71280d51def2Sdan } 71290d51def2Sdan 71300d51def2Sdan if( Tcl_GetBooleanFromObj(interp, objv[1], &bArg) ){ 71310d51def2Sdan return TCL_ERROR; 71320d51def2Sdan } 71330d51def2Sdan 71340d51def2Sdan if( bArg ){ 71350d51def2Sdan if( sqlite3GlobalConfig.pHeap==0 ){ 71360d51def2Sdan sqlite3GlobalConfig.pHeap = SQLITE_INT_TO_PTR(-1); 71370d51def2Sdan } 71380d51def2Sdan }else{ 71390d51def2Sdan if( sqlite3GlobalConfig.pHeap==SQLITE_INT_TO_PTR(-1) ){ 71400d51def2Sdan sqlite3GlobalConfig.pHeap = 0; 71410d51def2Sdan } 71420d51def2Sdan } 71430d51def2Sdan 71440d51def2Sdan Tcl_ResetResult(interp); 71450d51def2Sdan return TCL_OK; 71460d51def2Sdan } 71470d51def2Sdan 7148dfea4533Sdan /* 7149dfea4533Sdan ** sorter_test_sort4_helper DB SQL1 NSTEP SQL2 7150dfea4533Sdan ** 7151dfea4533Sdan ** Compile SQL statement $SQL1 and step it $NSTEP times. For each row, 7152dfea4533Sdan ** check that the leftmost and rightmost columns returned are both integers, 7153dfea4533Sdan ** and that both contain the same value. 7154dfea4533Sdan ** 7155dfea4533Sdan ** Then execute statement $SQL2. Check that the statement returns the same 7156dfea4533Sdan ** set of integers in the same order as in the previous step (using $SQL1). 7157dfea4533Sdan */ 71587617e4a8Smistachkin static int SQLITE_TCLAPI sorter_test_sort4_helper( 7159dfea4533Sdan void * clientData, 7160dfea4533Sdan Tcl_Interp *interp, 7161dfea4533Sdan int objc, 7162dfea4533Sdan Tcl_Obj *CONST objv[] 7163dfea4533Sdan ){ 7164dfea4533Sdan const char *zSql1; 7165dfea4533Sdan const char *zSql2; 7166dfea4533Sdan int nStep; 7167dfea4533Sdan int iStep; 716848cd59a5Sdrh unsigned int iCksum1 = 0; 716948cd59a5Sdrh unsigned int iCksum2 = 0; 7170dfea4533Sdan int rc; 7171dfea4533Sdan int iB; 7172dfea4533Sdan sqlite3 *db; 7173dfea4533Sdan sqlite3_stmt *pStmt; 7174dfea4533Sdan 7175dfea4533Sdan if( objc!=5 ){ 7176dfea4533Sdan Tcl_WrongNumArgs(interp, 1, objv, "DB SQL1 NSTEP SQL2"); 7177dfea4533Sdan return TCL_ERROR; 7178dfea4533Sdan } 7179dfea4533Sdan 7180dfea4533Sdan if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 7181dfea4533Sdan zSql1 = Tcl_GetString(objv[2]); 7182dfea4533Sdan if( Tcl_GetIntFromObj(interp, objv[3], &nStep) ) return TCL_ERROR; 7183dfea4533Sdan zSql2 = Tcl_GetString(objv[4]); 7184dfea4533Sdan 7185dfea4533Sdan rc = sqlite3_prepare_v2(db, zSql1, -1, &pStmt, 0); 7186dfea4533Sdan if( rc!=SQLITE_OK ) goto sql_error; 7187dfea4533Sdan 7188dfea4533Sdan iB = sqlite3_column_count(pStmt)-1; 7189dfea4533Sdan for(iStep=0; iStep<nStep && SQLITE_ROW==sqlite3_step(pStmt); iStep++){ 7190dfea4533Sdan int a = sqlite3_column_int(pStmt, 0); 7191dfea4533Sdan if( a!=sqlite3_column_int(pStmt, iB) ){ 7192dfea4533Sdan Tcl_AppendResult(interp, "data error: (a!=b)", 0); 7193dfea4533Sdan return TCL_ERROR; 7194dfea4533Sdan } 7195dfea4533Sdan 719648cd59a5Sdrh iCksum1 += (iCksum1 << 3) + (unsigned int)a; 7197dfea4533Sdan } 7198dfea4533Sdan rc = sqlite3_finalize(pStmt); 7199dfea4533Sdan if( rc!=SQLITE_OK ) goto sql_error; 7200dfea4533Sdan 7201dfea4533Sdan rc = sqlite3_prepare_v2(db, zSql2, -1, &pStmt, 0); 7202dfea4533Sdan if( rc!=SQLITE_OK ) goto sql_error; 7203dfea4533Sdan for(iStep=0; SQLITE_ROW==sqlite3_step(pStmt); iStep++){ 7204dfea4533Sdan int a = sqlite3_column_int(pStmt, 0); 720548cd59a5Sdrh iCksum2 += (iCksum2 << 3) + (unsigned int)a; 7206dfea4533Sdan } 7207dfea4533Sdan rc = sqlite3_finalize(pStmt); 7208dfea4533Sdan if( rc!=SQLITE_OK ) goto sql_error; 7209dfea4533Sdan 7210dfea4533Sdan if( iCksum1!=iCksum2 ){ 7211dfea4533Sdan Tcl_AppendResult(interp, "checksum mismatch", 0); 7212dfea4533Sdan return TCL_ERROR; 7213dfea4533Sdan } 7214dfea4533Sdan 7215dfea4533Sdan return TCL_OK; 7216dfea4533Sdan sql_error: 7217dfea4533Sdan Tcl_AppendResult(interp, "sql error: ", sqlite3_errmsg(db), 0); 7218dfea4533Sdan return TCL_ERROR; 7219dfea4533Sdan } 7220dfea4533Sdan 7221248f2be9Sdrh 7222d39c40ffSdrh #ifdef SQLITE_USER_AUTHENTICATION 7223d39c40ffSdrh #include "sqlite3userauth.h" 7224d39c40ffSdrh /* 7225d39c40ffSdrh ** tclcmd: sqlite3_user_authenticate DB USERNAME PASSWORD 7226d39c40ffSdrh */ 72277617e4a8Smistachkin static int SQLITE_TCLAPI test_user_authenticate( 7228d39c40ffSdrh ClientData clientData, /* Unused */ 7229d39c40ffSdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 7230d39c40ffSdrh int objc, /* Number of arguments */ 7231d39c40ffSdrh Tcl_Obj *CONST objv[] /* Command arguments */ 7232d39c40ffSdrh ){ 7233d39c40ffSdrh char *zUser = 0; 7234d39c40ffSdrh char *zPasswd = 0; 7235d39c40ffSdrh int nPasswd = 0; 7236d39c40ffSdrh sqlite3 *db; 7237d39c40ffSdrh int rc; 7238d39c40ffSdrh 7239d39c40ffSdrh if( objc!=4 ){ 7240d39c40ffSdrh Tcl_WrongNumArgs(interp, 1, objv, "DB USERNAME PASSWORD"); 7241d39c40ffSdrh return TCL_ERROR; 7242d39c40ffSdrh } 7243d39c40ffSdrh if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){ 7244d39c40ffSdrh return TCL_ERROR; 7245d39c40ffSdrh } 7246d39c40ffSdrh zUser = Tcl_GetString(objv[2]); 7247d39c40ffSdrh zPasswd = Tcl_GetStringFromObj(objv[3], &nPasswd); 7248d39c40ffSdrh rc = sqlite3_user_authenticate(db, zUser, zPasswd, nPasswd); 7249d39c40ffSdrh Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC); 7250d39c40ffSdrh return TCL_OK; 7251d39c40ffSdrh } 7252d39c40ffSdrh #endif /* SQLITE_USER_AUTHENTICATION */ 7253d39c40ffSdrh 7254d39c40ffSdrh #ifdef SQLITE_USER_AUTHENTICATION 7255d39c40ffSdrh /* 7256d39c40ffSdrh ** tclcmd: sqlite3_user_add DB USERNAME PASSWORD ISADMIN 7257d39c40ffSdrh */ 72587617e4a8Smistachkin static int SQLITE_TCLAPI test_user_add( 7259d39c40ffSdrh ClientData clientData, /* Unused */ 7260d39c40ffSdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 7261d39c40ffSdrh int objc, /* Number of arguments */ 7262d39c40ffSdrh Tcl_Obj *CONST objv[] /* Command arguments */ 7263d39c40ffSdrh ){ 7264d39c40ffSdrh char *zUser = 0; 7265d39c40ffSdrh char *zPasswd = 0; 7266d39c40ffSdrh int nPasswd = 0; 7267d39c40ffSdrh int isAdmin = 0; 7268d39c40ffSdrh sqlite3 *db; 7269d39c40ffSdrh int rc; 7270d39c40ffSdrh 7271d39c40ffSdrh if( objc!=5 ){ 7272d39c40ffSdrh Tcl_WrongNumArgs(interp, 1, objv, "DB USERNAME PASSWORD ISADMIN"); 7273d39c40ffSdrh return TCL_ERROR; 7274d39c40ffSdrh } 7275d39c40ffSdrh if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){ 7276d39c40ffSdrh return TCL_ERROR; 7277d39c40ffSdrh } 7278d39c40ffSdrh zUser = Tcl_GetString(objv[2]); 7279d39c40ffSdrh zPasswd = Tcl_GetStringFromObj(objv[3], &nPasswd); 7280d39c40ffSdrh Tcl_GetBooleanFromObj(interp, objv[4], &isAdmin); 7281d39c40ffSdrh rc = sqlite3_user_add(db, zUser, zPasswd, nPasswd, isAdmin); 7282d39c40ffSdrh Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC); 7283d39c40ffSdrh return TCL_OK; 7284d39c40ffSdrh } 7285d39c40ffSdrh #endif /* SQLITE_USER_AUTHENTICATION */ 7286d39c40ffSdrh 7287d39c40ffSdrh #ifdef SQLITE_USER_AUTHENTICATION 7288d39c40ffSdrh /* 7289d39c40ffSdrh ** tclcmd: sqlite3_user_change DB USERNAME PASSWORD ISADMIN 7290d39c40ffSdrh */ 72917617e4a8Smistachkin static int SQLITE_TCLAPI test_user_change( 7292d39c40ffSdrh ClientData clientData, /* Unused */ 7293d39c40ffSdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 7294d39c40ffSdrh int objc, /* Number of arguments */ 7295d39c40ffSdrh Tcl_Obj *CONST objv[] /* Command arguments */ 7296d39c40ffSdrh ){ 7297d39c40ffSdrh char *zUser = 0; 7298d39c40ffSdrh char *zPasswd = 0; 7299d39c40ffSdrh int nPasswd = 0; 7300d39c40ffSdrh int isAdmin = 0; 7301d39c40ffSdrh sqlite3 *db; 7302d39c40ffSdrh int rc; 7303d39c40ffSdrh 7304d39c40ffSdrh if( objc!=5 ){ 7305d39c40ffSdrh Tcl_WrongNumArgs(interp, 1, objv, "DB USERNAME PASSWORD ISADMIN"); 7306d39c40ffSdrh return TCL_ERROR; 7307d39c40ffSdrh } 7308d39c40ffSdrh if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){ 7309d39c40ffSdrh return TCL_ERROR; 7310d39c40ffSdrh } 7311d39c40ffSdrh zUser = Tcl_GetString(objv[2]); 7312d39c40ffSdrh zPasswd = Tcl_GetStringFromObj(objv[3], &nPasswd); 7313d39c40ffSdrh Tcl_GetBooleanFromObj(interp, objv[4], &isAdmin); 7314d39c40ffSdrh rc = sqlite3_user_change(db, zUser, zPasswd, nPasswd, isAdmin); 7315d39c40ffSdrh Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC); 7316d39c40ffSdrh return TCL_OK; 7317d39c40ffSdrh } 7318d39c40ffSdrh #endif /* SQLITE_USER_AUTHENTICATION */ 7319d39c40ffSdrh 7320d39c40ffSdrh #ifdef SQLITE_USER_AUTHENTICATION 7321d39c40ffSdrh /* 7322d39c40ffSdrh ** tclcmd: sqlite3_user_delete DB USERNAME 7323d39c40ffSdrh */ 73247617e4a8Smistachkin static int SQLITE_TCLAPI test_user_delete( 7325d39c40ffSdrh ClientData clientData, /* Unused */ 7326d39c40ffSdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 7327d39c40ffSdrh int objc, /* Number of arguments */ 7328d39c40ffSdrh Tcl_Obj *CONST objv[] /* Command arguments */ 7329d39c40ffSdrh ){ 7330d39c40ffSdrh char *zUser = 0; 7331d39c40ffSdrh sqlite3 *db; 7332d39c40ffSdrh int rc; 7333d39c40ffSdrh 7334d39c40ffSdrh if( objc!=3 ){ 7335d39c40ffSdrh Tcl_WrongNumArgs(interp, 1, objv, "DB USERNAME"); 7336d39c40ffSdrh return TCL_ERROR; 7337d39c40ffSdrh } 7338d39c40ffSdrh if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){ 7339d39c40ffSdrh return TCL_ERROR; 7340d39c40ffSdrh } 7341d39c40ffSdrh zUser = Tcl_GetString(objv[2]); 7342d39c40ffSdrh rc = sqlite3_user_delete(db, zUser); 7343d39c40ffSdrh Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC); 7344d39c40ffSdrh return TCL_OK; 7345d39c40ffSdrh } 7346d39c40ffSdrh #endif /* SQLITE_USER_AUTHENTICATION */ 7347d39c40ffSdrh 7348f58ee7f1Sdrh /* 7349edb31cd1Sdrh ** tclcmd: bad_behavior TYPE 7350edb31cd1Sdrh ** 7351edb31cd1Sdrh ** Do some things that should trigger a valgrind or -fsanitize=undefined 7352edb31cd1Sdrh ** warning. This is used to verify that errors and warnings output by those 7353edb31cd1Sdrh ** tools are detected by the test scripts. 7354edb31cd1Sdrh ** 7355edb31cd1Sdrh ** TYPE BEHAVIOR 7356edb31cd1Sdrh ** 1 Overflow a signed integer 7357edb31cd1Sdrh ** 2 Jump based on an uninitialized variable 7358edb31cd1Sdrh ** 3 Read after free 7359db6bafaeSdrh ** 4 Panic 7360edb31cd1Sdrh */ 73617617e4a8Smistachkin static int SQLITE_TCLAPI test_bad_behavior( 7362edb31cd1Sdrh ClientData clientData, /* Pointer to an integer containing zero */ 7363edb31cd1Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 7364edb31cd1Sdrh int objc, /* Number of arguments */ 7365edb31cd1Sdrh Tcl_Obj *CONST objv[] /* Command arguments */ 7366edb31cd1Sdrh ){ 7367edb31cd1Sdrh int iType; 7368edb31cd1Sdrh int xyz; 7369edb31cd1Sdrh int i = *(int*)clientData; 7370edb31cd1Sdrh int j; 7371edb31cd1Sdrh int w[10]; 7372edb31cd1Sdrh int *a; 7373edb31cd1Sdrh if( objc!=2 ){ 7374edb31cd1Sdrh Tcl_WrongNumArgs(interp, 1, objv, "TYPE"); 7375edb31cd1Sdrh return TCL_ERROR; 7376edb31cd1Sdrh } 7377edb31cd1Sdrh if( Tcl_GetIntFromObj(interp, objv[1], &iType) ) return TCL_ERROR; 7378edb31cd1Sdrh switch( iType ){ 7379edb31cd1Sdrh case 1: { 7380edb31cd1Sdrh xyz = 0x7fffff00 - i; 7381edb31cd1Sdrh xyz += 0x100; 7382edb31cd1Sdrh Tcl_SetObjResult(interp, Tcl_NewIntObj(xyz)); 7383edb31cd1Sdrh break; 7384edb31cd1Sdrh } 7385edb31cd1Sdrh case 2: { 7386edb31cd1Sdrh w[1] = 5; 7387edb31cd1Sdrh if( w[i]>0 ) w[1]++; 7388edb31cd1Sdrh Tcl_SetObjResult(interp, Tcl_NewIntObj(w[1])); 7389edb31cd1Sdrh break; 7390edb31cd1Sdrh } 7391edb31cd1Sdrh case 3: { 7392edb31cd1Sdrh a = malloc( sizeof(int)*10 ); 7393edb31cd1Sdrh for(j=0; j<10; j++) a[j] = j; 7394edb31cd1Sdrh free(a); 7395edb31cd1Sdrh Tcl_SetObjResult(interp, Tcl_NewIntObj(a[i])); 7396edb31cd1Sdrh break; 7397edb31cd1Sdrh } 7398db6bafaeSdrh case 4: { 7399db6bafaeSdrh Tcl_Panic("Deliberate panic"); 7400db6bafaeSdrh break; 7401db6bafaeSdrh } 7402edb31cd1Sdrh } 7403edb31cd1Sdrh return TCL_OK; 7404edb31cd1Sdrh } 7405edb31cd1Sdrh 74063e0327d5Sdrh /* 74073e0327d5Sdrh ** tclcmd: register_dbstat_vtab DB 74083e0327d5Sdrh ** 74093e0327d5Sdrh ** Cause the dbstat virtual table to be available on the connection DB 74103e0327d5Sdrh */ 74117617e4a8Smistachkin static int SQLITE_TCLAPI test_register_dbstat_vtab( 74123e0327d5Sdrh void *clientData, 74133e0327d5Sdrh Tcl_Interp *interp, 74143e0327d5Sdrh int objc, 74153e0327d5Sdrh Tcl_Obj *CONST objv[] 74163e0327d5Sdrh ){ 74173e0327d5Sdrh #ifdef SQLITE_OMIT_VIRTUALTABLE 74183e0327d5Sdrh Tcl_AppendResult(interp, "dbstat not available because of " 74193e0327d5Sdrh "SQLITE_OMIT_VIRTUALTABLE", (void*)0); 74203e0327d5Sdrh return TCL_ERROR; 74213e0327d5Sdrh #else 74223e0327d5Sdrh struct SqliteDb { sqlite3 *db; }; 74233e0327d5Sdrh char *zDb; 74243e0327d5Sdrh Tcl_CmdInfo cmdInfo; 74253e0327d5Sdrh 74263e0327d5Sdrh if( objc!=2 ){ 74273e0327d5Sdrh Tcl_WrongNumArgs(interp, 1, objv, "DB"); 74283e0327d5Sdrh return TCL_ERROR; 74293e0327d5Sdrh } 74303e0327d5Sdrh 74313e0327d5Sdrh zDb = Tcl_GetString(objv[1]); 74323e0327d5Sdrh if( Tcl_GetCommandInfo(interp, zDb, &cmdInfo) ){ 74333e0327d5Sdrh sqlite3* db = ((struct SqliteDb*)cmdInfo.objClientData)->db; 74343e0327d5Sdrh sqlite3DbstatRegister(db); 74353e0327d5Sdrh } 74363e0327d5Sdrh return TCL_OK; 74373e0327d5Sdrh #endif /* SQLITE_OMIT_VIRTUALTABLE */ 74383e0327d5Sdrh } 7439edb31cd1Sdrh 7440edb31cd1Sdrh /* 7441d42908fbSdrh ** tclcmd: sqlite3_db_config DB SETTING VALUE 7442d42908fbSdrh ** 7443d42908fbSdrh ** Invoke sqlite3_db_config() for one of the setting values. 7444d42908fbSdrh */ 74457617e4a8Smistachkin static int SQLITE_TCLAPI test_sqlite3_db_config( 7446d42908fbSdrh void *clientData, 7447d42908fbSdrh Tcl_Interp *interp, 7448d42908fbSdrh int objc, 7449d42908fbSdrh Tcl_Obj *CONST objv[] 7450d42908fbSdrh ){ 7451d42908fbSdrh static const struct { 7452d42908fbSdrh const char *zName; 7453d42908fbSdrh int eVal; 7454d42908fbSdrh } aSetting[] = { 7455d42908fbSdrh { "FKEY", SQLITE_DBCONFIG_ENABLE_FKEY }, 7456d42908fbSdrh { "TRIGGER", SQLITE_DBCONFIG_ENABLE_TRIGGER }, 7457d42908fbSdrh { "FTS3_TOKENIZER", SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER }, 7458191dd061Sdrh { "LOAD_EXTENSION", SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION }, 7459298af023Sdan { "NO_CKPT_ON_CLOSE",SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE }, 7460169dd928Sdrh { "QPSG", SQLITE_DBCONFIG_ENABLE_QPSG }, 74617df01196Sdrh { "TRIGGER_EQP", SQLITE_DBCONFIG_TRIGGER_EQP }, 74627df01196Sdrh { "RESET_DB", SQLITE_DBCONFIG_RESET_DATABASE }, 7463d42908fbSdrh }; 7464d42908fbSdrh int i; 7465d42908fbSdrh int v; 7466d42908fbSdrh const char *zSetting; 7467d42908fbSdrh sqlite3 *db; 7468d42908fbSdrh 7469d42908fbSdrh if( objc!=4 ){ 7470d42908fbSdrh Tcl_WrongNumArgs(interp, 1, objv, "DB SETTING VALUE"); 7471d42908fbSdrh return TCL_ERROR; 7472d42908fbSdrh } 7473d42908fbSdrh if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 7474d42908fbSdrh zSetting = Tcl_GetString(objv[2]); 7475d42908fbSdrh if( sqlite3_strglob("SQLITE_*", zSetting)==0 ) zSetting += 7; 7476d42908fbSdrh if( sqlite3_strglob("DBCONFIG_*", zSetting)==0 ) zSetting += 9; 7477d42908fbSdrh if( sqlite3_strglob("ENABLE_*", zSetting)==0 ) zSetting += 7; 7478d42908fbSdrh for(i=0; i<ArraySize(aSetting); i++){ 7479d42908fbSdrh if( strcmp(zSetting, aSetting[i].zName)==0 ) break; 7480d42908fbSdrh } 7481d42908fbSdrh if( i>=ArraySize(aSetting) ){ 7482d42908fbSdrh Tcl_SetObjResult(interp, 7483d42908fbSdrh Tcl_NewStringObj("unknown sqlite3_db_config setting", -1)); 7484d42908fbSdrh return TCL_ERROR; 7485d42908fbSdrh } 7486d42908fbSdrh if( Tcl_GetIntFromObj(interp, objv[3], &v) ) return TCL_ERROR; 7487d42908fbSdrh sqlite3_db_config(db, aSetting[i].eVal, v, &v); 7488d42908fbSdrh Tcl_SetObjResult(interp, Tcl_NewIntObj(v)); 7489d42908fbSdrh return TCL_OK; 7490d42908fbSdrh } 7491d42908fbSdrh 7492d42908fbSdrh /* 7493da84dcaeSdrh ** Change the name of the main database schema from "main" to "icecube". 7494da84dcaeSdrh */ 7495da84dcaeSdrh static int SQLITE_TCLAPI test_dbconfig_maindbname_icecube( 7496da84dcaeSdrh void * clientData, 7497da84dcaeSdrh Tcl_Interp *interp, 7498da84dcaeSdrh int objc, 7499da84dcaeSdrh Tcl_Obj *CONST objv[] 7500da84dcaeSdrh ){ 7501da84dcaeSdrh int rc; 7502da84dcaeSdrh sqlite3 *db; 7503da84dcaeSdrh extern int getDbPointer(Tcl_Interp*, const char*, sqlite3**); 7504da84dcaeSdrh if( objc!=2 ){ 7505da84dcaeSdrh Tcl_WrongNumArgs(interp, 1, objv, "DB"); 7506da84dcaeSdrh return TCL_ERROR; 7507da84dcaeSdrh }else{ 7508da84dcaeSdrh if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 7509da84dcaeSdrh rc = sqlite3_db_config(db, SQLITE_DBCONFIG_MAINDBNAME, "icecube"); 7510da84dcaeSdrh Tcl_SetObjResult(interp, Tcl_NewIntObj(rc)); 7511da84dcaeSdrh return TCL_OK; 7512da84dcaeSdrh } 7513da84dcaeSdrh } 7514da84dcaeSdrh 7515da84dcaeSdrh /* 7516460f1fa5Sdan ** Usage: sqlite3_mmap_warm DB DBNAME 7517460f1fa5Sdan */ 7518460f1fa5Sdan static int SQLITE_TCLAPI test_mmap_warm( 7519460f1fa5Sdan void * clientData, 7520460f1fa5Sdan Tcl_Interp *interp, 7521460f1fa5Sdan int objc, 7522460f1fa5Sdan Tcl_Obj *CONST objv[] 7523460f1fa5Sdan ){ 7524460f1fa5Sdan extern int getDbPointer(Tcl_Interp*, const char*, sqlite3**); 7525460f1fa5Sdan extern int sqlite3_mmap_warm(sqlite3 *db, const char *); 7526460f1fa5Sdan 7527460f1fa5Sdan if( objc!=2 && objc!=3 ){ 7528460f1fa5Sdan Tcl_WrongNumArgs(interp, 1, objv, "DB ?DBNAME?"); 7529460f1fa5Sdan return TCL_ERROR; 7530460f1fa5Sdan }else{ 7531460f1fa5Sdan int rc; 7532460f1fa5Sdan sqlite3 *db; 7533460f1fa5Sdan const char *zDb = 0; 7534460f1fa5Sdan if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 7535460f1fa5Sdan if( objc==3 ){ 7536460f1fa5Sdan zDb = Tcl_GetString(objv[2]); 7537460f1fa5Sdan } 7538460f1fa5Sdan rc = sqlite3_mmap_warm(db, zDb); 7539460f1fa5Sdan Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1)); 7540460f1fa5Sdan return TCL_OK; 7541460f1fa5Sdan } 7542460f1fa5Sdan } 7543460f1fa5Sdan 7544460f1fa5Sdan /* 7545d1bf3512Sdrh ** Register commands with the TCL interpreter. 7546d1bf3512Sdrh */ 7547d1bf3512Sdrh int Sqlitetest1_Init(Tcl_Interp *interp){ 75486f8a503dSdanielk1977 extern int sqlite3_search_count; 75490ff297eaSdan extern int sqlite3_found_count; 75506f8a503dSdanielk1977 extern int sqlite3_interrupt_count; 75516f8a503dSdanielk1977 extern int sqlite3_open_file_count; 75526bf89570Sdrh extern int sqlite3_sort_count; 75536f8a503dSdanielk1977 extern int sqlite3_current_time; 755484a2bf67Sdrh #if SQLITE_OS_UNIX && defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE 7555aebf413dSaswift extern int sqlite3_hostid_num; 7556aabbed22Spweilbacher #endif 7557ae7e151aSdrh extern int sqlite3_max_blobsize; 75587617e4a8Smistachkin extern int SQLITE_TCLAPI sqlite3BtreeSharedCacheReport(void*, 755916a9b836Sdrh Tcl_Interp*,int,Tcl_Obj*CONST*); 7560edb31cd1Sdrh static int iZero = 0; 7561c2eef3b3Sdrh static struct { 7562c2eef3b3Sdrh char *zName; 7563c2eef3b3Sdrh Tcl_CmdProc *xProc; 7564c2eef3b3Sdrh } aCmd[] = { 756527641703Sdrh { "db_enter", (Tcl_CmdProc*)db_enter }, 756627641703Sdrh { "db_leave", (Tcl_CmdProc*)db_leave }, 75676f8a503dSdanielk1977 { "sqlite3_mprintf_int", (Tcl_CmdProc*)sqlite3_mprintf_int }, 7568e9707671Sdrh { "sqlite3_mprintf_int64", (Tcl_CmdProc*)sqlite3_mprintf_int64 }, 7569c5cad1e3Sdrh { "sqlite3_mprintf_long", (Tcl_CmdProc*)sqlite3_mprintf_long }, 75706f8a503dSdanielk1977 { "sqlite3_mprintf_str", (Tcl_CmdProc*)sqlite3_mprintf_str }, 7571b3738b6cSdrh { "sqlite3_snprintf_str", (Tcl_CmdProc*)sqlite3_snprintf_str }, 7572e29b1a05Sdrh { "sqlite3_mprintf_stronly", (Tcl_CmdProc*)sqlite3_mprintf_stronly}, 75736f8a503dSdanielk1977 { "sqlite3_mprintf_double", (Tcl_CmdProc*)sqlite3_mprintf_double }, 75746f8a503dSdanielk1977 { "sqlite3_mprintf_scaled", (Tcl_CmdProc*)sqlite3_mprintf_scaled }, 757563782855Sdrh { "sqlite3_mprintf_hexdouble", (Tcl_CmdProc*)sqlite3_mprintf_hexdouble}, 75766f8a503dSdanielk1977 { "sqlite3_mprintf_z_test", (Tcl_CmdProc*)test_mprintf_z }, 757705a82983Sdrh { "sqlite3_mprintf_n_test", (Tcl_CmdProc*)test_mprintf_n }, 757868853907Sdrh { "sqlite3_snprintf_int", (Tcl_CmdProc*)test_snprintf_int }, 75796f8a503dSdanielk1977 { "sqlite3_last_insert_rowid", (Tcl_CmdProc*)test_last_rowid }, 75806f8a503dSdanielk1977 { "sqlite3_exec_printf", (Tcl_CmdProc*)test_exec_printf }, 75815bd98aefSdrh { "sqlite3_exec_hex", (Tcl_CmdProc*)test_exec_hex }, 7582b62c335eSdrh { "sqlite3_exec", (Tcl_CmdProc*)test_exec }, 7583b62c335eSdrh { "sqlite3_exec_nr", (Tcl_CmdProc*)test_exec_nr }, 75848225f5acSshane #ifndef SQLITE_OMIT_GET_TABLE 75856f8a503dSdanielk1977 { "sqlite3_get_table_printf", (Tcl_CmdProc*)test_get_table_printf }, 75868225f5acSshane #endif 75876f8a503dSdanielk1977 { "sqlite3_close", (Tcl_CmdProc*)sqlite_test_close }, 7588617dc860Sdan { "sqlite3_close_v2", (Tcl_CmdProc*)sqlite_test_close_v2 }, 75896f8a503dSdanielk1977 { "sqlite3_create_function", (Tcl_CmdProc*)test_create_function }, 75906f8a503dSdanielk1977 { "sqlite3_create_aggregate", (Tcl_CmdProc*)test_create_aggregate }, 7591c2eef3b3Sdrh { "sqlite_register_test_function", (Tcl_CmdProc*)test_register_func }, 7592c2eef3b3Sdrh { "sqlite_abort", (Tcl_CmdProc*)sqlite_abort }, 759396fc5fe6Sdanielk1977 { "sqlite_bind", (Tcl_CmdProc*)test_bind }, 759499ee3600Sdrh { "breakpoint", (Tcl_CmdProc*)test_breakpoint }, 759525d6543dSdrh { "sqlite3_key", (Tcl_CmdProc*)test_key }, 759625d6543dSdrh { "sqlite3_rekey", (Tcl_CmdProc*)test_rekey }, 7597cacb208eSdrh { "sqlite_set_magic", (Tcl_CmdProc*)sqlite_set_magic }, 7598c5cdca61Sdrh { "sqlite3_interrupt", (Tcl_CmdProc*)test_interrupt }, 75999636c4e1Sdanielk1977 { "sqlite_delete_function", (Tcl_CmdProc*)delete_function }, 76003e1d8e63Sdrh { "sqlite_delete_collation", (Tcl_CmdProc*)delete_collation }, 76013e1d8e63Sdrh { "sqlite3_get_autocommit", (Tcl_CmdProc*)get_autocommit }, 76023086765bSdrh { "sqlite3_busy_timeout", (Tcl_CmdProc*)test_busy_timeout }, 76033c23a885Sdrh { "printf", (Tcl_CmdProc*)test_printf }, 76043a00f907Smlcreech { "sqlite3IoTrace", (Tcl_CmdProc*)test_io_trace }, 7605afcf9bd8Sdan { "clang_sanitize_address", (Tcl_CmdProc*)clang_sanitize_address }, 7606c2eef3b3Sdrh }; 760751e3d8e2Sdanielk1977 static struct { 760851e3d8e2Sdanielk1977 char *zName; 760951e3d8e2Sdanielk1977 Tcl_ObjCmdProc *xProc; 761004f2e68dSdanielk1977 void *clientData; 761151e3d8e2Sdanielk1977 } aObjCmd[] = { 7612d42908fbSdrh { "sqlite3_db_config", test_sqlite3_db_config, 0 }, 7613edb31cd1Sdrh { "bad_behavior", test_bad_behavior, (void*)&iZero }, 76143e0327d5Sdrh { "register_dbstat_vtab", test_register_dbstat_vtab }, 7615dddca286Sdrh { "sqlite3_connection_pointer", get_sqlite_pointer, 0 }, 76162e3f87aeSdrh { "intarray_addr", test_intarray_addr, 0 }, 76172e3f87aeSdrh { "int64array_addr", test_int64array_addr, 0 }, 76182e3f87aeSdrh { "doublearray_addr", test_doublearray_addr, 0 }, 76192e3f87aeSdrh { "textarray_addr", test_textarray_addr, 0 }, 7620241db313Sdrh { "sqlite3_bind_int", test_bind_int, 0 }, 7621b026e05eSdrh { "sqlite3_bind_zeroblob", test_bind_zeroblob, 0 }, 762280c03022Sdan { "sqlite3_bind_zeroblob64", test_bind_zeroblob64, 0 }, 762304f2e68dSdanielk1977 { "sqlite3_bind_int64", test_bind_int64, 0 }, 762404f2e68dSdanielk1977 { "sqlite3_bind_double", test_bind_double, 0 }, 762504f2e68dSdanielk1977 { "sqlite3_bind_null", test_bind_null ,0 }, 762604f2e68dSdanielk1977 { "sqlite3_bind_text", test_bind_text ,0 }, 762704f2e68dSdanielk1977 { "sqlite3_bind_text16", test_bind_text16 ,0 }, 762804f2e68dSdanielk1977 { "sqlite3_bind_blob", test_bind_blob ,0 }, 762975f6a032Sdrh { "sqlite3_bind_parameter_count", test_bind_parameter_count, 0}, 7630895d7472Sdrh { "sqlite3_bind_parameter_name", test_bind_parameter_name, 0}, 7631fa6bc000Sdrh { "sqlite3_bind_parameter_index", test_bind_parameter_index, 0}, 7632600dd0baSdanielk1977 { "sqlite3_clear_bindings", test_clear_bindings, 0}, 7633f9cb7f58Sdrh { "sqlite3_sleep", test_sleep, 0}, 763404f2e68dSdanielk1977 { "sqlite3_errcode", test_errcode ,0 }, 763599dfe5ebSdrh { "sqlite3_extended_errcode", test_ex_errcode ,0 }, 763604f2e68dSdanielk1977 { "sqlite3_errmsg", test_errmsg ,0 }, 763704f2e68dSdanielk1977 { "sqlite3_errmsg16", test_errmsg16 ,0 }, 763804f2e68dSdanielk1977 { "sqlite3_open", test_open ,0 }, 763904f2e68dSdanielk1977 { "sqlite3_open16", test_open16 ,0 }, 7640286ab7c2Sdan { "sqlite3_open_v2", test_open_v2 ,0 }, 7641bc6ada41Sdanielk1977 { "sqlite3_complete16", test_complete16 ,0 }, 764291694dbdSdrh { "sqlite3_normalize", test_normalize ,0 }, 764304f2e68dSdanielk1977 764404f2e68dSdanielk1977 { "sqlite3_prepare", test_prepare ,0 }, 764504f2e68dSdanielk1977 { "sqlite3_prepare16", test_prepare16 ,0 }, 7646b900aaf3Sdrh { "sqlite3_prepare_v2", test_prepare_v2 ,0 }, 76474837f531Sdrh { "sqlite3_prepare_tkt3134", test_prepare_tkt3134, 0}, 7648b900aaf3Sdrh { "sqlite3_prepare16_v2", test_prepare16_v2 ,0 }, 764904f2e68dSdanielk1977 { "sqlite3_finalize", test_finalize ,0 }, 7650d1d38488Sdrh { "sqlite3_stmt_status", test_stmt_status ,0 }, 765104f2e68dSdanielk1977 { "sqlite3_reset", test_reset ,0 }, 7652d89bd007Sdrh { "sqlite3_expired", test_expired ,0 }, 7653f8db1bc0Sdrh { "sqlite3_transfer_bindings", test_transfer_bind ,0 }, 7654fbcd585fSdanielk1977 { "sqlite3_changes", test_changes ,0 }, 765504f2e68dSdanielk1977 { "sqlite3_step", test_step ,0 }, 7656404ca075Sdanielk1977 { "sqlite3_sql", test_sql ,0 }, 7657fca760c8Sdrh { "sqlite3_expanded_sql", test_ex_sql ,0 }, 7658bb5a9c3eSdrh { "sqlite3_next_stmt", test_next_stmt ,0 }, 7659f03d9cccSdrh { "sqlite3_stmt_readonly", test_stmt_readonly ,0 }, 76602fb6693eSdrh { "sqlite3_stmt_busy", test_stmt_busy ,0 }, 7661d9495cd0Sdan { "uses_stmt_journal", uses_stmt_journal ,0 }, 766204f2e68dSdanielk1977 76636aafc29bSdrh { "sqlite3_release_memory", test_release_memory, 0}, 766409419b4bSdrh { "sqlite3_db_release_memory", test_db_release_memory, 0}, 76656fa255fdSdan { "sqlite3_db_cacheflush", test_db_cacheflush, 0}, 76660e80e509Sdrh { "sqlite3_system_errno", test_system_errno, 0}, 7667283829cbSdrh { "sqlite3_db_filename", test_db_filename, 0}, 7668421377e6Sdrh { "sqlite3_db_readonly", test_db_readonly, 0}, 76696aafc29bSdrh { "sqlite3_soft_heap_limit", test_soft_heap_limit, 0}, 7670b4bc7057Sdrh { "sqlite3_thread_cleanup", test_thread_cleanup, 0}, 7671c6ba55f4Sdrh { "sqlite3_pager_refcounts", test_pager_refcounts, 0}, 76726aafc29bSdrh 7673c2e87a3eSdrh { "sqlite3_load_extension", test_load_extension, 0}, 7674c2e87a3eSdrh { "sqlite3_enable_load_extension", test_enable_load, 0}, 76754ac285a1Sdrh { "sqlite3_extended_result_codes", test_extended_result_codes, 0}, 7676b1a6c3c1Sdrh { "sqlite3_limit", test_limit, 0}, 7677da84dcaeSdrh { "dbconfig_maindbname_icecube", test_dbconfig_maindbname_icecube }, 7678c2e87a3eSdrh 767993aed5a1Sdrh { "save_prng_state", save_prng_state, 0 }, 768093aed5a1Sdrh { "restore_prng_state", restore_prng_state, 0 }, 768193aed5a1Sdrh { "reset_prng_state", reset_prng_state, 0 }, 768209fe6143Sdrh { "database_never_corrupt", database_never_corrupt, 0}, 768309fe6143Sdrh { "database_may_be_corrupt", database_may_be_corrupt, 0}, 7684f58ee7f1Sdrh { "optimization_control", optimization_control,0}, 768580084ca8Sdrh #if SQLITE_OS_WIN 768680084ca8Sdrh { "lock_win32_file", win32_file_lock, 0 }, 76873741827eSmistachkin { "exists_win32_path", win32_exists_path, 0 }, 76883741827eSmistachkin { "find_win32_file", win32_find_file, 0 }, 76893741827eSmistachkin { "delete_win32_file", win32_delete_file, 0 }, 76903741827eSmistachkin { "make_win32_dir", win32_mkdir, 0 }, 76913741827eSmistachkin { "remove_win32_dir", win32_rmdir, 0 }, 769280084ca8Sdrh #endif 7693a2c8a95bSdrh { "tcl_objproc", runAsObjProc, 0 }, 769493aed5a1Sdrh 769504f2e68dSdanielk1977 /* sqlite3_column_*() API */ 769604f2e68dSdanielk1977 { "sqlite3_column_count", test_column_count ,0 }, 769704f2e68dSdanielk1977 { "sqlite3_data_count", test_data_count ,0 }, 769804f2e68dSdanielk1977 { "sqlite3_column_type", test_column_type ,0 }, 7699ea61b2c4Sdanielk1977 { "sqlite3_column_blob", test_column_blob ,0 }, 770004f2e68dSdanielk1977 { "sqlite3_column_double", test_column_double ,0 }, 770104f2e68dSdanielk1977 { "sqlite3_column_int64", test_column_int64 ,0 }, 770244a376f6Sdanielk1977 { "sqlite3_column_text", test_stmt_utf8, (void*)sqlite3_column_text }, 770344a376f6Sdanielk1977 { "sqlite3_column_name", test_stmt_utf8, (void*)sqlite3_column_name }, 770444a376f6Sdanielk1977 { "sqlite3_column_int", test_stmt_int, (void*)sqlite3_column_int }, 770544a376f6Sdanielk1977 { "sqlite3_column_bytes", test_stmt_int, (void*)sqlite3_column_bytes}, 77063f913576Sdrh #ifndef SQLITE_OMIT_DECLTYPE 770744a376f6Sdanielk1977 { "sqlite3_column_decltype",test_stmt_utf8,(void*)sqlite3_column_decltype}, 77083f913576Sdrh #endif 77094b1ae99dSdanielk1977 #ifdef SQLITE_ENABLE_COLUMN_METADATA 771044a376f6Sdanielk1977 { "sqlite3_column_database_name",test_stmt_utf8,(void*)sqlite3_column_database_name}, 771144a376f6Sdanielk1977 { "sqlite3_column_table_name",test_stmt_utf8,(void*)sqlite3_column_table_name}, 771244a376f6Sdanielk1977 { "sqlite3_column_origin_name",test_stmt_utf8,(void*)sqlite3_column_origin_name}, 77134b1ae99dSdanielk1977 #endif 7714955de52cSdanielk1977 77156c62608fSdrh #ifndef SQLITE_OMIT_UTF16 771644a376f6Sdanielk1977 { "sqlite3_column_bytes16", test_stmt_int, (void*)sqlite3_column_bytes16 }, 771744a376f6Sdanielk1977 { "sqlite3_column_text16", test_stmt_utf16, (void*)sqlite3_column_text16}, 771844a376f6Sdanielk1977 { "sqlite3_column_name16", test_stmt_utf16, (void*)sqlite3_column_name16}, 77197d9bd4e1Sdrh { "add_alignment_test_collations", add_alignment_test_collations, 0 }, 77203f913576Sdrh #ifndef SQLITE_OMIT_DECLTYPE 772144a376f6Sdanielk1977 { "sqlite3_column_decltype16",test_stmt_utf16,(void*)sqlite3_column_decltype16}, 77223f913576Sdrh #endif 77234b1ae99dSdanielk1977 #ifdef SQLITE_ENABLE_COLUMN_METADATA 7724955de52cSdanielk1977 {"sqlite3_column_database_name16", 77257da5fcb0Sdrh test_stmt_utf16, (void*)sqlite3_column_database_name16}, 772644a376f6Sdanielk1977 {"sqlite3_column_table_name16", test_stmt_utf16, (void*)sqlite3_column_table_name16}, 772744a376f6Sdanielk1977 {"sqlite3_column_origin_name16", test_stmt_utf16, (void*)sqlite3_column_origin_name16}, 77286c62608fSdrh #endif 77294b1ae99dSdanielk1977 #endif 7730a393c036Sdanielk1977 { "sqlite3_create_collation_v2", test_create_collation_v2, 0 }, 77316b456a2bSdanielk1977 { "sqlite3_global_recover", test_global_recover, 0 }, 773280788d8bSdrh { "working_64bit_int", working_64bit_int, 0 }, 77339bc5449fSdrh { "vfs_unlink_test", vfs_unlink_test, 0 }, 7734c8d75674Sdrh { "vfs_initfail_test", vfs_initfail_test, 0 }, 7735a2820970Sdrh { "vfs_unregister_all", vfs_unregister_all, 0 }, 7736a2820970Sdrh { "vfs_reregister_all", vfs_reregister_all, 0 }, 773755176259Sdrh { "file_control_test", file_control_test, 0 }, 7738aebf413dSaswift { "file_control_lasterrno_test", file_control_lasterrno_test, 0 }, 7739aebf413dSaswift { "file_control_lockproxy_test", file_control_lockproxy_test, 0 }, 77406e09d69cSdan { "file_control_chunksize_test", file_control_chunksize_test, 0 }, 7741661d71afSdan { "file_control_sizehint_test", file_control_sizehint_test, 0 }, 7742ea99a31cSdrh { "file_control_data_version", file_control_data_version, 0 }, 77436b98d67bSmistachkin #if SQLITE_OS_WIN 7744d0cdf012Sdrh { "file_control_win32_av_retry", file_control_win32_av_retry, 0 }, 77451b361ff3Smistachkin { "file_control_win32_get_handle", file_control_win32_get_handle, 0 }, 77466b98d67bSmistachkin { "file_control_win32_set_handle", file_control_win32_set_handle, 0 }, 77476b98d67bSmistachkin #endif 7748253cea5cSdrh { "file_control_persist_wal", file_control_persist_wal, 0 }, 7749cb15f35fSdrh { "file_control_powersafe_overwrite",file_control_powersafe_overwrite,0}, 7750de60fc2dSdrh { "file_control_vfsname", file_control_vfsname, 0 }, 7751696b33e6Sdrh { "file_control_tempfilename", file_control_tempfilename, 0 }, 7752e339d65aSdanielk1977 { "sqlite3_vfs_list", vfs_list, 0 }, 7753d2199f0fSdan { "sqlite3_create_function_v2", test_create_function_v2, 0 }, 775404f2e68dSdanielk1977 77559a1d0abeSdanielk1977 /* Functions from os.h */ 77565436dc2dSdrh #ifndef SQLITE_OMIT_UTF16 77574e6af134Sdanielk1977 { "add_test_collate", test_collate, 0 }, 7758312d6b36Sdanielk1977 { "add_test_collate_needed", test_collate_needed, 0 }, 7759c8e9a2dfSdanielk1977 { "add_test_function", test_function, 0 }, 776038fdead8Sdan { "add_test_utf16bin_collate", test_utf16bin_collate, 0 }, 77615436dc2dSdrh #endif 7762312d6b36Sdanielk1977 { "sqlite3_test_errstr", test_errstr, 0 }, 776392febd92Sdrh { "tcl_variable_type", tcl_variable_type, 0 }, 7764aef0bf64Sdanielk1977 #ifndef SQLITE_OMIT_SHARED_CACHE 77656f7adc8aSdrh { "sqlite3_enable_shared_cache", test_enable_shared, 0 }, 776616a9b836Sdrh { "sqlite3_shared_cache_report", sqlite3BtreeSharedCacheReport, 0}, 7767aef0bf64Sdanielk1977 #endif 7768161fb796Sdanielk1977 { "sqlite3_libversion_number", test_libversion_number, 0 }, 7769deb802cdSdanielk1977 { "sqlite3_table_column_metadata", test_table_column_metadata, 0 }, 7770dcbb5d3fSdanielk1977 #ifndef SQLITE_OMIT_INCRBLOB 77714e76cc36Sdan { "sqlite3_blob_reopen", test_blob_reopen, 0 }, 7772dcbb5d3fSdanielk1977 #endif 7773062d4cb0Sdanielk1977 { "pcache_stats", test_pcache_stats, 0 }, 7774404ca075Sdanielk1977 #ifdef SQLITE_ENABLE_UNLOCK_NOTIFY 7775404ca075Sdanielk1977 { "sqlite3_unlock_notify", test_unlock_notify, 0 }, 7776404ca075Sdanielk1977 #endif 777787c1fe1bSdan { "sqlite3_wal_checkpoint", test_wal_checkpoint, 0 }, 77789c5e3680Sdan { "sqlite3_wal_checkpoint_v2",test_wal_checkpoint_v2, 0 }, 77799af10620Sdan { "sqlite3_wal_autocheckpoint",test_wal_autocheckpoint, 0 }, 7780eb8763d7Sdan { "test_sqlite3_log", test_sqlite3_log, 0 }, 7781bb201344Sshaneh #ifndef SQLITE_OMIT_EXPLAIN 778291da6b83Sdan { "print_explain_query_plan", test_print_eqp, 0 }, 7783bb201344Sshaneh #endif 7784c17d696cSdan { "sqlite3_test_control", test_test_control }, 7785daf9a5a4Smistachkin #if SQLITE_OS_UNIX 7786a72014faSdan { "getrusage", test_getrusage }, 7787daf9a5a4Smistachkin #endif 7788248f2be9Sdrh { "load_static_extension", tclLoadStaticExtensionCmd }, 77890d51def2Sdan { "sorter_test_fakeheap", sorter_test_fakeheap }, 7790dfea4533Sdan { "sorter_test_sort4_helper", sorter_test_sort4_helper }, 7791d39c40ffSdrh #ifdef SQLITE_USER_AUTHENTICATION 7792d39c40ffSdrh { "sqlite3_user_authenticate", test_user_authenticate, 0 }, 7793d39c40ffSdrh { "sqlite3_user_add", test_user_add, 0 }, 7794d39c40ffSdrh { "sqlite3_user_change", test_user_change, 0 }, 7795d39c40ffSdrh { "sqlite3_user_delete", test_user_delete, 0 }, 7796d39c40ffSdrh #endif 779704489b6dSdan #ifdef SQLITE_ENABLE_STMT_SCANSTATUS 779804489b6dSdan { "sqlite3_stmt_scanstatus", test_stmt_scanstatus, 0 }, 779904489b6dSdan { "sqlite3_stmt_scanstatus_reset", test_stmt_scanstatus_reset, 0 }, 780004489b6dSdan #endif 7801d83f7ca1Sdan #ifdef SQLITE_ENABLE_SQLLOG 7802d83f7ca1Sdan { "sqlite3_config_sqllog", test_config_sqllog, 0 }, 7803d83f7ca1Sdan #endif 7804e4e416e8Sdan { "vfs_current_time_int64", vfsCurrentTimeInt64, 0 }, 7805fc1acf33Sdan #ifdef SQLITE_ENABLE_SNAPSHOT 7806fc1acf33Sdan { "sqlite3_snapshot_get", test_snapshot_get, 0 }, 7807fc1acf33Sdan { "sqlite3_snapshot_open", test_snapshot_open, 0 }, 7808fc1acf33Sdan { "sqlite3_snapshot_free", test_snapshot_free, 0 }, 7809ad2d5bafSdan { "sqlite3_snapshot_cmp", test_snapshot_cmp, 0 }, 78101158498dSdan { "sqlite3_snapshot_recover", test_snapshot_recover, 0 }, 781125accbcaSdan { "sqlite3_snapshot_get_blob", test_snapshot_get_blob, 0 }, 781225accbcaSdan { "sqlite3_snapshot_open_blob", test_snapshot_open_blob, 0 }, 781325accbcaSdan { "sqlite3_snapshot_cmp_blob", test_snapshot_cmp_blob, 0 }, 7814fc1acf33Sdan #endif 7815000f95b1Sdan { "sqlite3_delete_database", test_delete_database, 0 }, 78164da30f88Sdan { "atomic_batch_write", test_atomic_batch_write, 0 }, 7817460f1fa5Sdan { "sqlite3_mmap_warm", test_mmap_warm, 0 }, 78182e3a5a81Sdan { "sqlite3_config_sorterref", test_config_sorterref, 0 }, 781951e3d8e2Sdanielk1977 }; 78201398ad36Sdrh static int bitmask_size = sizeof(Bitmask)*8; 78212ab410aaSdrh static int longdouble_size = sizeof(LONGDOUBLE_TYPE); 7822c2eef3b3Sdrh int i; 7823b851b2c9Sdrh extern int sqlite3_sync_count, sqlite3_fullsync_count; 7824af6df11fSdrh extern int sqlite3_opentemp_count; 782555ef4d97Sdrh extern int sqlite3_like_count; 7826dd73521bSdrh extern int sqlite3_xferopt_count; 7827538f570cSdrh extern int sqlite3_pager_readdb_count; 7828538f570cSdrh extern int sqlite3_pager_writedb_count; 7829538f570cSdrh extern int sqlite3_pager_writej_count; 783029bafeabSdanielk1977 #if SQLITE_OS_WIN 7831202cb641Smistachkin extern LONG volatile sqlite3_os_type; 7832c0929987Sdrh #endif 78338b3d990bSdrh #ifdef SQLITE_DEBUG 78343a00f907Smlcreech extern int sqlite3WhereTrace; 78353a00f907Smlcreech extern int sqlite3OSTrace; 7836c74c3334Sdrh extern int sqlite3WalTrace; 7837549c8b68Sdrh #endif 7838549c8b68Sdrh #ifdef SQLITE_TEST 783933e89035Sdanielk1977 #ifdef SQLITE_ENABLE_FTS3 784033e89035Sdanielk1977 extern int sqlite3_fts3_enable_parentheses; 784133e89035Sdanielk1977 #endif 784248083ceeSdrh #endif 784386fb6e17Sdan #if defined(SQLITE_ENABLE_SELECTTRACE) 784486fb6e17Sdan extern int sqlite3SelectTrace; 784586fb6e17Sdan #endif 7846c2eef3b3Sdrh 7847c2eef3b3Sdrh for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){ 7848c2eef3b3Sdrh Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0); 7849c2eef3b3Sdrh } 785051e3d8e2Sdanielk1977 for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){ 7851c572ef7fSdanielk1977 Tcl_CreateObjCommand(interp, aObjCmd[i].zName, 7852c572ef7fSdanielk1977 aObjCmd[i].xProc, aObjCmd[i].clientData, 0); 785351e3d8e2Sdanielk1977 } 78546490bebdSdanielk1977 Tcl_LinkVar(interp, "sqlite_search_count", 78556f8a503dSdanielk1977 (char*)&sqlite3_search_count, TCL_LINK_INT); 78560ff297eaSdan Tcl_LinkVar(interp, "sqlite_found_count", 78570ff297eaSdan (char*)&sqlite3_found_count, TCL_LINK_INT); 78586bf89570Sdrh Tcl_LinkVar(interp, "sqlite_sort_count", 78596bf89570Sdrh (char*)&sqlite3_sort_count, TCL_LINK_INT); 7860ae7e151aSdrh Tcl_LinkVar(interp, "sqlite3_max_blobsize", 7861ae7e151aSdrh (char*)&sqlite3_max_blobsize, TCL_LINK_INT); 786255ef4d97Sdrh Tcl_LinkVar(interp, "sqlite_like_count", 786355ef4d97Sdrh (char*)&sqlite3_like_count, TCL_LINK_INT); 78646490bebdSdanielk1977 Tcl_LinkVar(interp, "sqlite_interrupt_count", 78656f8a503dSdanielk1977 (char*)&sqlite3_interrupt_count, TCL_LINK_INT); 78666490bebdSdanielk1977 Tcl_LinkVar(interp, "sqlite_open_file_count", 78676f8a503dSdanielk1977 (char*)&sqlite3_open_file_count, TCL_LINK_INT); 78686490bebdSdanielk1977 Tcl_LinkVar(interp, "sqlite_current_time", 78696f8a503dSdanielk1977 (char*)&sqlite3_current_time, TCL_LINK_INT); 787084a2bf67Sdrh #if SQLITE_OS_UNIX && defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE 7871aebf413dSaswift Tcl_LinkVar(interp, "sqlite_hostid_num", 7872aebf413dSaswift (char*)&sqlite3_hostid_num, TCL_LINK_INT); 7873aabbed22Spweilbacher #endif 7874dd73521bSdrh Tcl_LinkVar(interp, "sqlite3_xferopt_count", 7875dd73521bSdrh (char*)&sqlite3_xferopt_count, TCL_LINK_INT); 7876538f570cSdrh Tcl_LinkVar(interp, "sqlite3_pager_readdb_count", 7877538f570cSdrh (char*)&sqlite3_pager_readdb_count, TCL_LINK_INT); 7878538f570cSdrh Tcl_LinkVar(interp, "sqlite3_pager_writedb_count", 7879538f570cSdrh (char*)&sqlite3_pager_writedb_count, TCL_LINK_INT); 7880538f570cSdrh Tcl_LinkVar(interp, "sqlite3_pager_writej_count", 7881538f570cSdrh (char*)&sqlite3_pager_writej_count, TCL_LINK_INT); 78824b2688abSdanielk1977 #ifndef SQLITE_OMIT_UTF16 78837d9bd4e1Sdrh Tcl_LinkVar(interp, "unaligned_string_counter", 78847d9bd4e1Sdrh (char*)&unaligned_string_counter, TCL_LINK_INT); 78854b2688abSdanielk1977 #endif 7886268803a9Sdrh #ifndef SQLITE_OMIT_UTF16 7887268803a9Sdrh Tcl_LinkVar(interp, "sqlite_last_needed_collation", 7888268803a9Sdrh (char*)&pzNeededCollation, TCL_LINK_STRING|TCL_LINK_READ_ONLY); 7889268803a9Sdrh #endif 789029bafeabSdanielk1977 #if SQLITE_OS_WIN 7891c0929987Sdrh Tcl_LinkVar(interp, "sqlite_os_type", 7892202cb641Smistachkin (char*)&sqlite3_os_type, TCL_LINK_LONG); 7893c0929987Sdrh #endif 7894549c8b68Sdrh #ifdef SQLITE_TEST 78956fa978daSdrh { 78966fa978daSdrh static const char *query_plan = "*** OBSOLETE VARIABLE ***"; 7897549c8b68Sdrh Tcl_LinkVar(interp, "sqlite_query_plan", 7898549c8b68Sdrh (char*)&query_plan, TCL_LINK_STRING|TCL_LINK_READ_ONLY); 78996fa978daSdrh } 7900549c8b68Sdrh #endif 79018b3d990bSdrh #ifdef SQLITE_DEBUG 790248083ceeSdrh Tcl_LinkVar(interp, "sqlite_where_trace", 79033a00f907Smlcreech (char*)&sqlite3WhereTrace, TCL_LINK_INT); 790473be5013Sdrh Tcl_LinkVar(interp, "sqlite_os_trace", 79053a00f907Smlcreech (char*)&sqlite3OSTrace, TCL_LINK_INT); 790638e1a279Sdan #ifndef SQLITE_OMIT_WAL 7907c74c3334Sdrh Tcl_LinkVar(interp, "sqlite_wal_trace", 7908c74c3334Sdrh (char*)&sqlite3WalTrace, TCL_LINK_INT); 79098b3d990bSdrh #endif 791038e1a279Sdan #endif 7911cbe21be3Sdanielk1977 #ifndef SQLITE_OMIT_DISKIO 7912af6df11fSdrh Tcl_LinkVar(interp, "sqlite_opentemp_count", 7913af6df11fSdrh (char*)&sqlite3_opentemp_count, TCL_LINK_INT); 7914cbe21be3Sdanielk1977 #endif 79157c972decSdrh Tcl_LinkVar(interp, "sqlite_static_bind_value", 79167c972decSdrh (char*)&sqlite_static_bind_value, TCL_LINK_STRING); 7917f0313813Sdrh Tcl_LinkVar(interp, "sqlite_static_bind_nbyte", 7918f0313813Sdrh (char*)&sqlite_static_bind_nbyte, TCL_LINK_INT); 7919ab3f9feaSdrh Tcl_LinkVar(interp, "sqlite_temp_directory", 7920effd02bcSdrh (char*)&sqlite3_temp_directory, TCL_LINK_STRING); 7921a112d140Smistachkin Tcl_LinkVar(interp, "sqlite_data_directory", 7922a112d140Smistachkin (char*)&sqlite3_data_directory, TCL_LINK_STRING); 79231398ad36Sdrh Tcl_LinkVar(interp, "bitmask_size", 79241398ad36Sdrh (char*)&bitmask_size, TCL_LINK_INT|TCL_LINK_READ_ONLY); 79252ab410aaSdrh Tcl_LinkVar(interp, "longdouble_size", 79262ab410aaSdrh (char*)&longdouble_size, TCL_LINK_INT|TCL_LINK_READ_ONLY); 7927b851b2c9Sdrh Tcl_LinkVar(interp, "sqlite_sync_count", 7928b851b2c9Sdrh (char*)&sqlite3_sync_count, TCL_LINK_INT); 7929b851b2c9Sdrh Tcl_LinkVar(interp, "sqlite_fullsync_count", 7930b851b2c9Sdrh (char*)&sqlite3_fullsync_count, TCL_LINK_INT); 793186fb6e17Sdan #if defined(SQLITE_ENABLE_SELECTTRACE) 793286fb6e17Sdan Tcl_LinkVar(interp, "sqlite3SelectTrace", 793386fb6e17Sdan (char*)&sqlite3SelectTrace, TCL_LINK_INT); 793486fb6e17Sdan #endif 7935d1fa7bcaSdrh #if defined(SQLITE_ENABLE_FTS3) && defined(SQLITE_TEST) 793633e89035Sdanielk1977 Tcl_LinkVar(interp, "sqlite_fts3_enable_parentheses", 793733e89035Sdanielk1977 (char*)&sqlite3_fts3_enable_parentheses, TCL_LINK_INT); 793833e89035Sdanielk1977 #endif 7939d1bf3512Sdrh return TCL_OK; 7940d1bf3512Sdrh } 7941