diff options
Diffstat (limited to 'ext/pdo_sqlite/sqlite/src/test1.c')
-rw-r--r-- | ext/pdo_sqlite/sqlite/src/test1.c | 880 |
1 files changed, 794 insertions, 86 deletions
diff --git a/ext/pdo_sqlite/sqlite/src/test1.c b/ext/pdo_sqlite/sqlite/src/test1.c index ceac5cd6d..fd474b276 100644 --- a/ext/pdo_sqlite/sqlite/src/test1.c +++ b/ext/pdo_sqlite/sqlite/src/test1.c @@ -9,7 +9,7 @@ ** May you share freely, never taking more than you give. ** ************************************************************************* -** Code for testing the printf() interface to SQLite. This code +** Code for testing all sorts of SQLite interfaces. This code ** is not included in the SQLite library. It is used for automated ** testing of the SQLite library. ** @@ -21,6 +21,48 @@ #include <stdlib.h> #include <string.h> +/* +** This is a copy of the first part of the SqliteDb structure in +** tclsqlite.c. We need it here so that the get_sqlite_pointer routine +** can extract the sqlite3* pointer from an existing Tcl SQLite +** connection. +*/ +struct SqliteDb { + sqlite3 *db; +}; + +/* +** A TCL command that returns the address of the sqlite* pointer +** for an sqlite connection instance. Bad things happen if the +** input is not an sqlite connection. +*/ +static int get_sqlite_pointer( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + struct SqliteDb *p; + Tcl_CmdInfo cmdInfo; + char zBuf[100]; + if( objc!=2 ){ + Tcl_WrongNumArgs(interp, 1, objv, "SQLITE-CONNECTION"); + return TCL_ERROR; + } + if( !Tcl_GetCommandInfo(interp, Tcl_GetString(objv[1]), &cmdInfo) ){ + Tcl_AppendResult(interp, "command not found: ", + Tcl_GetString(objv[1]), (char*)0); + return TCL_ERROR; + } + p = (struct SqliteDb*)cmdInfo.objClientData; + sprintf(zBuf, "%p", p->db); + if( strncmp(zBuf,"0x",2) ){ + sprintf(zBuf, "0x%p", p->db); + } + Tcl_AppendResult(interp, zBuf, 0); + return TCL_OK; +} + const char *sqlite3TestErrorName(int rc){ const char *zName = 0; switch( rc ){ @@ -124,7 +166,7 @@ static int getFilePointer( ** understood by scanf, and if not, try prepending an "0x" to see if ** that helps. If nothing works, a fatal error is generated. */ -static int makePointerStr(Tcl_Interp *interp, char *zPtr, void *p){ +int sqlite3TestMakePointerStr(Tcl_Interp *interp, char *zPtr, void *p){ sqlite3_snprintf(100, zPtr, "%p", p); return TCL_OK; } @@ -180,7 +222,7 @@ static int test_exec_printf( Tcl_AppendElement(interp, zBuf); Tcl_AppendElement(interp, rc==SQLITE_OK ? Tcl_DStringValue(&str) : zErr); Tcl_DStringFree(&str); - if( zErr ) free(zErr); + if( zErr ) sqlite3_free(zErr); if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; return TCL_OK; } @@ -188,7 +230,7 @@ static int test_exec_printf( /* ** Usage: sqlite3_mprintf_z_test SEPARATOR ARG0 ARG1 ... ** -** Test the %z format of mprintf(). Use multiple mprintf() calls to +** Test the %z format of sqliteMPrintf(). Use multiple mprintf() calls to ** concatenate arg0 through argn using separator as the separator. ** Return the result. */ @@ -210,6 +252,26 @@ static int test_mprintf_z( } /* +** Usage: sqlite3_mprintf_n_test STRING +** +** Test the %n format of sqliteMPrintf(). Return the length of the +** input string. +*/ +static int test_mprintf_n( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + char **argv /* Text of each argument */ +){ + char *zStr; + int n = 0; + zStr = sqlite3MPrintf("%s%n", argv[1], &n); + sqliteFree(zStr); + Tcl_SetObjResult(interp, Tcl_NewIntObj(n)); + return TCL_OK; +} + +/* ** Usage: sqlite3_get_table_printf DB FORMAT STRING ** ** Invoke the sqlite3_get_table_printf() interface using the open database @@ -255,7 +317,7 @@ static int test_get_table_printf( Tcl_AppendElement(interp, zErr); } sqlite3_free_table(aResult); - if( zErr ) free(zErr); + if( zErr ) sqlite3_free(zErr); if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; return TCL_OK; } @@ -373,8 +435,8 @@ static void ifnullFunc(sqlite3_context *context, int argc, sqlite3_value **argv) int i; for(i=0; i<argc; i++){ if( SQLITE_NULL!=sqlite3_value_type(argv[i]) ){ - sqlite3_result_text(context, sqlite3_value_text(argv[i]), -1, - SQLITE_TRANSIENT); + sqlite3_result_text(context, (char*)sqlite3_value_text(argv[i]), + sqlite3_value_bytes(argv[i]), SQLITE_TRANSIENT); break; } } @@ -446,8 +508,8 @@ static void sqlite3ExecFunc( ){ struct dstr x; memset(&x, 0, sizeof(x)); - sqlite3_exec((sqlite3*)sqlite3_user_data(context), - sqlite3_value_text(argv[0]), + (void)sqlite3_exec((sqlite3*)sqlite3_user_data(context), + (char*)sqlite3_value_text(argv[0]), execFuncCallback, &x, 0); sqlite3_result_text(context, x.z, x.nUsed, SQLITE_TRANSIENT); sqliteFree(x.z); @@ -492,6 +554,11 @@ static int test_create_function( ** because it is not tested anywhere else. */ if( rc==SQLITE_OK ){ sqlite3_value *pVal; +#ifdef SQLITE_MEMDEBUG + if( sqlite3_iMallocFail>0 ){ + sqlite3_iMallocFail++; + } +#endif pVal = sqlite3ValueNew(); sqlite3ValueSetStr(pVal, -1, "x_sqlite_exec", SQLITE_UTF8, SQLITE_STATIC); rc = sqlite3_create_function16(db, @@ -508,6 +575,14 @@ static int test_create_function( /* ** Routines to implement the x_count() aggregate function. +** +** x_count() counts the number of non-null arguments. But there are +** some twists for testing purposes. +** +** If the argument to x_count() is 40 then a UTF-8 error is reported +** on the step function. If x_count(41) is seen, then a UTF-16 error +** is reported on the step function. If the total count is 42, then +** a UTF-8 error is reported on the finalize function. */ typedef struct CountCtx CountCtx; struct CountCtx { @@ -519,11 +594,28 @@ static void countStep(sqlite3_context *context, int argc, sqlite3_value **argv){ if( (argc==0 || SQLITE_NULL!=sqlite3_value_type(argv[0]) ) && p ){ p->n++; } + if( argc>0 ){ + int v = sqlite3_value_int(argv[0]); + if( v==40 ){ + sqlite3_result_error(context, "value of 40 handed to x_count", -1); +#ifndef SQLITE_OMIT_UTF16 + }else if( v==41 ){ + const char zUtf16ErrMsg[] = { 0, 0x61, 0, 0x62, 0, 0x63, 0, 0, 0}; + sqlite3_result_error16(context, &zUtf16ErrMsg[1-SQLITE_BIGENDIAN], -1); +#endif + } + } } static void countFinalize(sqlite3_context *context){ CountCtx *p; p = sqlite3_aggregate_context(context, sizeof(*p)); - sqlite3_result_int(context, p ? p->n : 0); + if( p ){ + if( p->n==42 ){ + sqlite3_result_error(context, "x_count totals to 42", -1); + }else{ + sqlite3_result_int(context, p ? p->n : 0); + } + } } /* @@ -535,7 +627,10 @@ static void countFinalize(sqlite3_context *context){ ** ** The original motivation for this routine was to be able to call the ** sqlite3_create_aggregate function while a query is in progress in order -** to test the SQLITE_MISUSE detection logic. +** to test the SQLITE_MISUSE detection logic. See misuse.test. +** +** This routine was later extended to test the use of sqlite3_result_error() +** within aggregate functions. */ static int test_create_aggregate( void *NotUsed, @@ -787,7 +882,8 @@ static int sqlite3_mprintf_hexdouble( ** first failure will continue to fail on every call. If REPEAT-INTERVAL is ** 2 then every other malloc will fail. And so forth. ** -** Turn off this mechanism and reset the sqlite3_malloc_failed variable is N==0. +** Turn off this mechanism and reset the sqlite3ThreadData()->mallocFailed +** variable if N==0. */ #ifdef SQLITE_MEMDEBUG static int sqlite_malloc_fail( @@ -810,7 +906,6 @@ static int sqlite_malloc_fail( } sqlite3_iMallocFail = n; sqlite3_iMallocReset = rep; - sqlite3_malloc_failed = 0; return TCL_OK; } #endif @@ -828,13 +923,277 @@ static int sqlite_malloc_stat( char **argv /* Text of each argument */ ){ char zBuf[200]; - sprintf(zBuf, "%d %d %d", sqlite3_nMalloc, sqlite3_nFree, sqlite3_iMallocFail); + sprintf(zBuf, "%d %d %d", sqlite3_nMalloc,sqlite3_nFree,sqlite3_iMallocFail); Tcl_AppendResult(interp, zBuf, 0); return TCL_OK; } + +/* +** This function implements a Tcl command that may be invoked using any of +** the four forms enumerated below. +** +** sqlite_malloc_outstanding +** Return a summary of all unfreed blocks of memory allocated by the +** current thread. See comments above function sqlite3OutstandingMallocs() +** in util.c for a description of the returned value. +** +** sqlite_malloc_outstanding -bytes +** Return the total amount of unfreed memory (in bytes) allocated by +** this thread. +** +** sqlite_malloc_outstanding -maxbytes +** Return the maximum amount of dynamic memory in use at one time +** by this thread. +** +** sqlite_malloc_outstanding -clearmaxbytes +** Set the value returned by [sqlite_malloc_outstanding -maxbytes] +** to the current value of [sqlite_malloc_outstanding -bytes]. +*/ +static int sqlite_malloc_outstanding( + ClientData clientData, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int objc, /* Number of arguments */ + Tcl_Obj *CONST objv[] /* Command arguments */ +){ + extern int sqlite3OutstandingMallocs(Tcl_Interp *interp); + +#if defined(SQLITE_DEBUG) && defined(SQLITE_MEMDEBUG) && SQLITE_MEMDEBUG>1 + if( objc==2 ){ + const char *zArg = Tcl_GetString(objv[1]); +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT + ThreadData const *pTd = sqlite3ThreadDataReadOnly(); + if( 0==strcmp(zArg, "-bytes") ){ + Tcl_SetObjResult(interp, Tcl_NewIntObj(pTd->nAlloc)); + }else if( 0==strcmp(zArg, "-clearmaxbytes") ){ + sqlite3_nMaxAlloc = pTd->nAlloc; + }else +#endif + if( 0==strcmp(zArg, "-maxbytes") ){ + Tcl_SetObjResult(interp, Tcl_NewWideIntObj(sqlite3_nMaxAlloc)); + }else{ + Tcl_AppendResult(interp, "bad option \"", zArg, + "\": must be -bytes, -maxbytes or -clearmaxbytes", 0 + ); + return TCL_ERROR; + } + + return TCL_OK; + } + + if( objc!=1 ){ + Tcl_WrongNumArgs(interp, 1, objv, "?-bytes?"); + return TCL_ERROR; + } + + return sqlite3OutstandingMallocs(interp); +#else + return TCL_OK; +#endif +} #endif /* +** Usage: sqlite3_enable_shared_cache BOOLEAN +** +*/ +#if !defined(SQLITE_OMIT_SHARED_CACHE) +static int test_enable_shared( + ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int objc, /* Number of arguments */ + Tcl_Obj *CONST objv[] /* Command arguments */ +){ + int rc; + int enable; + int ret = 0; + + if( objc!=2 ){ + Tcl_WrongNumArgs(interp, 1, objv, "BOOLEAN"); + return TCL_ERROR; + } + if( Tcl_GetBooleanFromObj(interp, objv[1], &enable) ){ + return TCL_ERROR; + } + ret = sqlite3ThreadDataReadOnly()->useSharedData; + rc = sqlite3_enable_shared_cache(enable); + if( rc!=SQLITE_OK ){ + Tcl_SetResult(interp, (char *)sqlite3ErrStr(rc), TCL_STATIC); + return TCL_ERROR; + } + Tcl_SetObjResult(interp, Tcl_NewBooleanObj(ret)); + return TCL_OK; +} +#endif + +/* +** Usage: sqlite3_libversion_number +** +*/ +static int test_libversion_number( + ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int objc, /* Number of arguments */ + Tcl_Obj *CONST objv[] /* Command arguments */ +){ + Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_libversion_number())); + return TCL_OK; +} + +/* +** Usage: sqlite3_table_column_metadata DB dbname tblname colname +** +*/ +#ifdef SQLITE_ENABLE_COLUMN_METADATA +static int test_table_column_metadata( + ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int objc, /* Number of arguments */ + Tcl_Obj *CONST objv[] /* Command arguments */ +){ + sqlite3 *db; + const char *zDb; + const char *zTbl; + const char *zCol; + int rc; + Tcl_Obj *pRet; + + const char *zDatatype; + const char *zCollseq; + int notnull; + int primarykey; + int autoincrement; + + if( objc!=5 ){ + Tcl_WrongNumArgs(interp, 1, objv, "DB dbname tblname colname"); + return TCL_ERROR; + } + if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; + zDb = Tcl_GetString(objv[2]); + zTbl = Tcl_GetString(objv[3]); + zCol = Tcl_GetString(objv[4]); + + if( strlen(zDb)==0 ) zDb = 0; + + rc = sqlite3_table_column_metadata(db, zDb, zTbl, zCol, + &zDatatype, &zCollseq, ¬null, &primarykey, &autoincrement); + + if( rc!=SQLITE_OK ){ + Tcl_AppendResult(interp, sqlite3_errmsg(db), 0); + return TCL_ERROR; + } + + pRet = Tcl_NewObj(); + Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zDatatype, -1)); + Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zCollseq, -1)); + Tcl_ListObjAppendElement(0, pRet, Tcl_NewIntObj(notnull)); + Tcl_ListObjAppendElement(0, pRet, Tcl_NewIntObj(primarykey)); + Tcl_ListObjAppendElement(0, pRet, Tcl_NewIntObj(autoincrement)); + Tcl_SetObjResult(interp, pRet); + + return TCL_OK; +} +#endif + + +/* +** Usage: sqlite3_load_extension DB-HANDLE FILE ?PROC? +*/ +static int test_load_extension( + ClientData clientData, /* Not used */ + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int objc, /* Number of arguments */ + Tcl_Obj *CONST objv[] /* Command arguments */ +){ + Tcl_CmdInfo cmdInfo; + sqlite3 *db; + int rc; + char *zDb; + char *zFile; + char *zProc = 0; + char *zErr = 0; + + if( objc!=4 && objc!=3 ){ + Tcl_WrongNumArgs(interp, 1, objv, "DB-HANDLE FILE ?PROC?"); + return TCL_ERROR; + } + zDb = Tcl_GetString(objv[1]); + zFile = Tcl_GetString(objv[2]); + if( objc==4 ){ + zProc = Tcl_GetString(objv[3]); + } + + /* Extract the C database handle from the Tcl command name */ + if( !Tcl_GetCommandInfo(interp, zDb, &cmdInfo) ){ + Tcl_AppendResult(interp, "command not found: ", zDb, (char*)0); + return TCL_ERROR; + } + db = ((struct SqliteDb*)cmdInfo.objClientData)->db; + assert(db); + + /* Call the underlying C function. If an error occurs, set rc to + ** TCL_ERROR and load any error string into the interpreter. If no + ** error occurs, set rc to TCL_OK. + */ +#ifdef SQLITE_OMIT_LOAD_EXTENSION + rc = SQLITE_ERROR; + zErr = sqlite3_mprintf("this build omits sqlite3_load_extension()"); +#else + rc = sqlite3_load_extension(db, zFile, zProc, &zErr); +#endif + if( rc!=SQLITE_OK ){ + Tcl_SetResult(interp, zErr ? zErr : "", TCL_VOLATILE); + rc = TCL_ERROR; + }else{ + rc = TCL_OK; + } + sqlite3_free(zErr); + + return rc; +} + +/* +** Usage: sqlite3_enable_load_extension DB-HANDLE ONOFF +*/ +static int test_enable_load( + ClientData clientData, /* Not used */ + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int objc, /* Number of arguments */ + Tcl_Obj *CONST objv[] /* Command arguments */ +){ + Tcl_CmdInfo cmdInfo; + sqlite3 *db; + char *zDb; + int onoff; + + if( objc!=3 ){ + Tcl_WrongNumArgs(interp, 1, objv, "DB-HANDLE ONOFF"); + return TCL_ERROR; + } + zDb = Tcl_GetString(objv[1]); + + /* Extract the C database handle from the Tcl command name */ + if( !Tcl_GetCommandInfo(interp, zDb, &cmdInfo) ){ + Tcl_AppendResult(interp, "command not found: ", zDb, (char*)0); + return TCL_ERROR; + } + db = ((struct SqliteDb*)cmdInfo.objClientData)->db; + assert(db); + + /* Get the onoff parameter */ + if( Tcl_GetBooleanFromObj(interp, objv[2], &onoff) ){ + return TCL_ERROR; + } + +#ifdef SQLITE_OMIT_LOAD_EXTENSION + Tcl_AppendResult(interp, "this build omits sqlite3_load_extension()"); + return TCL_ERROR; +#else + sqlite3_enable_load_extension(db, onoff); + return TCL_OK; +#endif +} + +/* ** Usage: sqlite_abort ** ** Shutdown the process immediately. This is not a clean shutdown. @@ -857,14 +1216,14 @@ static int sqlite_abort( */ static void testFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ while( argc>=2 ){ - const char *zArg0 = sqlite3_value_text(argv[0]); + const char *zArg0 = (char*)sqlite3_value_text(argv[0]); if( zArg0 ){ if( 0==sqlite3StrICmp(zArg0, "int") ){ sqlite3_result_int(context, sqlite3_value_int(argv[1])); }else if( sqlite3StrICmp(zArg0,"int64")==0 ){ sqlite3_result_int64(context, sqlite3_value_int64(argv[1])); }else if( sqlite3StrICmp(zArg0,"string")==0 ){ - sqlite3_result_text(context, sqlite3_value_text(argv[1]), -1, + sqlite3_result_text(context, (char*)sqlite3_value_text(argv[1]), -1, SQLITE_TRANSIENT); }else if( sqlite3StrICmp(zArg0,"double")==0 ){ sqlite3_result_double(context, sqlite3_value_double(argv[1])); @@ -952,7 +1311,7 @@ static int test_finalize( /* ** Usage: sqlite3_reset STMT ** -** Finalize a statement handle. +** Reset a statement handle. */ static int test_reset( void * clientData, @@ -972,12 +1331,15 @@ static int test_reset( if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; rc = sqlite3_reset(pStmt); - if( pStmt && - sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR; + if( pStmt && sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ){ + return TCL_ERROR; + } Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC); +/* if( rc ){ return TCL_ERROR; } +*/ return TCL_OK; } @@ -1064,7 +1426,8 @@ static char *sqlite_static_bind_value = 0; ** ignored and the value is set to NULL. If FLAGS=="static" then ** the value is set to the value of a static variable named ** "sqlite_static_bind_value". If FLAGS=="normal" then a copy -** of the VALUE is made. +** of the VALUE is made. If FLAGS=="blob10" then a VALUE is ignored +** an a 10-byte blob "abc\000xyz\000pq" is inserted. */ static int test_bind( void *NotUsed, @@ -1088,6 +1451,8 @@ static int test_bind( rc = sqlite3_bind_text(pStmt, idx, sqlite_static_bind_value, -1, 0); }else if( strcmp(argv[4],"normal")==0 ){ rc = sqlite3_bind_text(pStmt, idx, argv[3], -1, SQLITE_TRANSIENT); + }else if( strcmp(argv[4],"blob10")==0 ){ + rc = sqlite3_bind_text(pStmt, idx, "abc\000xyz\000pq", 10, SQLITE_STATIC); }else{ Tcl_AppendResult(interp, "4th argument should be " "\"null\" or \"static\" or \"normal\"", 0); @@ -1166,10 +1531,12 @@ static int test_collate_func( pVal = sqlite3ValueNew(); sqlite3ValueSetStr(pVal, nA, zA, encin, SQLITE_STATIC); n = sqlite3_value_bytes(pVal); - Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj(sqlite3_value_text(pVal),n)); + Tcl_ListObjAppendElement(i,pX, + Tcl_NewStringObj((char*)sqlite3_value_text(pVal),n)); sqlite3ValueSetStr(pVal, nB, zB, encin, SQLITE_STATIC); n = sqlite3_value_bytes(pVal); - Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj(sqlite3_value_text(pVal),n)); + Tcl_ListObjAppendElement(i,pX, + Tcl_NewStringObj((char*)sqlite3_value_text(pVal),n)); sqlite3ValueFree(pVal); Tcl_EvalObjEx(i, pX, 0); @@ -1201,13 +1568,24 @@ static int test_collate( (void *)SQLITE_UTF16LE, val?test_collate_func:0); if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[4], &val) ) return TCL_ERROR; +#ifdef SQLITE_MEMDEBUG + if( sqlite3_iMallocFail>0 ){ + sqlite3_iMallocFail++; + } +#endif pVal = sqlite3ValueNew(); sqlite3ValueSetStr(pVal, -1, "test_collate", SQLITE_UTF8, SQLITE_STATIC); - sqlite3_create_collation16(db, sqlite3ValueText(pVal, SQLITE_UTF16NATIVE), - SQLITE_UTF16BE, (void *)SQLITE_UTF16BE, val?test_collate_func:0); + rc = sqlite3_create_collation16(db, + sqlite3ValueText(pVal, SQLITE_UTF16NATIVE), SQLITE_UTF16BE, + (void *)SQLITE_UTF16BE, val?test_collate_func:0); sqlite3ValueFree(pVal); } if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; + + if( rc!=SQLITE_OK ){ + Tcl_AppendResult(interp, sqlite3TestErrorName(rc), 0); + return TCL_ERROR; + } return TCL_OK; bad_args: @@ -1216,15 +1594,35 @@ bad_args: return TCL_ERROR; } +/* +** When the collation needed callback is invoked, record the name of +** the requested collating function here. The recorded name is linked +** to a TCL variable and used to make sure that the requested collation +** name is correct. +*/ +static char zNeededCollation[200]; +static char *pzNeededCollation = zNeededCollation; + + +/* +** Called when a collating sequence is needed. Registered using +** sqlite3_collation_needed16(). +*/ static void test_collate_needed_cb( void *pCtx, sqlite3 *db, int eTextRep, - const void *notUsed + const void *pName ){ - int enc = db->enc; + int enc = ENC(db); + int i; + char *z; + for(z = (char*)pName, i=0; *z || z[1]; z++){ + if( *z ) zNeededCollation[i++] = *z; + } + zNeededCollation[i] = 0; sqlite3_create_collation( - db, "test_collate", db->enc, (void *)enc, test_collate_func); + db, "test_collate", ENC(db), (void *)enc, test_collate_func); } /* @@ -1242,6 +1640,7 @@ static int test_collate_needed( if( objc!=2 ) goto bad_args; if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; rc = sqlite3_collation_needed16(db, 0, test_collate_needed_cb); + zNeededCollation[0] = 0; if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; return TCL_OK; @@ -1249,7 +1648,56 @@ bad_args: Tcl_WrongNumArgs(interp, 1, objv, "DB"); return TCL_ERROR; } -#endif /* SQLITE_OMIT_UTF16 */ + +/* +** tclcmd: add_alignment_test_collations DB +** +** Add two new collating sequences to the database DB +** +** utf16_aligned +** utf16_unaligned +** +** Both collating sequences use the same sort order as BINARY. +** The only difference is that the utf16_aligned collating +** sequence is declared with the SQLITE_UTF16_ALIGNED flag. +** Both collating functions increment the unaligned utf16 counter +** whenever they see a string that begins on an odd byte boundary. +*/ +static int unaligned_string_counter = 0; +static int alignmentCollFunc( + void *NotUsed, + int nKey1, const void *pKey1, + int nKey2, const void *pKey2 +){ + int rc, n; + n = nKey1<nKey2 ? nKey1 : nKey2; + if( nKey1>0 && 1==(1&(int)pKey1) ) unaligned_string_counter++; + if( nKey2>0 && 1==(1&(int)pKey2) ) unaligned_string_counter++; + rc = memcmp(pKey1, pKey2, n); + if( rc==0 ){ + rc = nKey1 - nKey2; + } + return rc; +} +static int add_alignment_test_collations( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + sqlite3 *db; + if( objc>=2 ){ + if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; + sqlite3_create_collation(db, "utf16_unaligned", + SQLITE_UTF16, + 0, alignmentCollFunc); + sqlite3_create_collation(db, "utf16_aligned", + SQLITE_UTF16 | SQLITE_UTF16_ALIGNED, + 0, alignmentCollFunc); + } + return SQLITE_OK; +} +#endif /* !defined(SQLITE_OMIT_UTF16) */ /* ** Usage: add_test_function <db ptr> <utf8> <utf16le> <utf16be> @@ -1290,7 +1738,7 @@ static void test_function_utf8( Tcl_IncrRefCount(pX); Tcl_ListObjAppendElement(interp, pX, Tcl_NewStringObj("UTF-8", -1)); Tcl_ListObjAppendElement(interp, pX, - Tcl_NewStringObj(sqlite3_value_text(argv[0]), -1)); + Tcl_NewStringObj((char*)sqlite3_value_text(argv[0]), -1)); Tcl_EvalObjEx(interp, pX, 0); Tcl_DecrRefCount(pX); sqlite3_result_text(pCtx, Tcl_GetStringResult(interp), -1, SQLITE_TRANSIENT); @@ -1314,13 +1762,13 @@ static void test_function_utf16le( Tcl_IncrRefCount(pX); Tcl_ListObjAppendElement(interp, pX, Tcl_NewStringObj("UTF-16LE", -1)); Tcl_ListObjAppendElement(interp, pX, - Tcl_NewStringObj(sqlite3_value_text(argv[0]), -1)); + Tcl_NewStringObj((char*)sqlite3_value_text(argv[0]), -1)); Tcl_EvalObjEx(interp, pX, 0); Tcl_DecrRefCount(pX); pVal = sqlite3ValueNew(); sqlite3ValueSetStr(pVal, -1, Tcl_GetStringResult(interp), SQLITE_UTF8, SQLITE_STATIC); - sqlite3_result_text(pCtx,sqlite3_value_text(pVal),-1,SQLITE_TRANSIENT); + sqlite3_result_text(pCtx,(char*)sqlite3_value_text(pVal),-1,SQLITE_TRANSIENT); sqlite3ValueFree(pVal); } static void test_function_utf16be( @@ -1336,7 +1784,7 @@ static void test_function_utf16be( Tcl_IncrRefCount(pX); Tcl_ListObjAppendElement(interp, pX, Tcl_NewStringObj("UTF-16BE", -1)); Tcl_ListObjAppendElement(interp, pX, - Tcl_NewStringObj(sqlite3_value_text(argv[0]), -1)); + Tcl_NewStringObj((char*)sqlite3_value_text(argv[0]), -1)); Tcl_EvalObjEx(interp, pX, 0); Tcl_DecrRefCount(pX); pVal = sqlite3ValueNew(); @@ -1412,29 +1860,6 @@ static int test_errstr( return TCL_OK; } -static int sqlite3_crashparams( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ -#ifdef OS_TEST - int delay; - if( objc!=3 ) goto bad_args; - if( Tcl_GetIntFromObj(interp, objv[1], &delay) ) return TCL_ERROR; - sqlite3SetCrashParams(delay, Tcl_GetString(objv[2])); -#endif - return TCL_OK; - -#ifdef OS_TEST -bad_args: - Tcl_AppendResult(interp, "wrong # args: should be \"", - Tcl_GetStringFromObj(objv[0], 0), "<delay> <filename>", 0); - return TCL_ERROR; -#endif -} - - /* ** Usage: breakpoint ** @@ -1647,7 +2072,7 @@ static int test_bind_text( } /* -** Usage: sqlite3_bind_text16 STMT N STRING BYTES +** Usage: sqlite3_bind_text16 ?-static? STMT N STRING BYTES ** ** Test the sqlite3_bind_text16 interface. STMT is a prepared statement. ** N is the index of a wildcard in the prepared statement. This command @@ -1667,18 +2092,24 @@ static int test_bind_text16( char *value; int rc; - if( objc!=5 ){ + void (*xDel)() = (objc==6?SQLITE_STATIC:SQLITE_TRANSIENT); + Tcl_Obj *oStmt = objv[objc-4]; + Tcl_Obj *oN = objv[objc-3]; + Tcl_Obj *oString = objv[objc-2]; + Tcl_Obj *oBytes = objv[objc-1]; + + if( objc!=5 && objc!=6){ Tcl_AppendResult(interp, "wrong # args: should be \"", Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE BYTES", 0); return TCL_ERROR; } - if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; - if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; - value = Tcl_GetByteArrayFromObj(objv[3], 0); - if( Tcl_GetIntFromObj(interp, objv[4], &bytes) ) return TCL_ERROR; + if( getStmtPointer(interp, Tcl_GetString(oStmt), &pStmt) ) return TCL_ERROR; + if( Tcl_GetIntFromObj(interp, oN, &idx) ) return TCL_ERROR; + value = (char*)Tcl_GetByteArrayFromObj(oString, 0); + if( Tcl_GetIntFromObj(interp, oBytes, &bytes) ) return TCL_ERROR; - rc = sqlite3_bind_text16(pStmt, idx, (void *)value, bytes, SQLITE_TRANSIENT); + rc = sqlite3_bind_text16(pStmt, idx, (void *)value, bytes, xDel); if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR; if( rc!=SQLITE_OK ){ return TCL_ERROR; @@ -1808,7 +2239,6 @@ static int test_bind_parameter_index( ** Usage: sqlite3_clear_bindings STMT ** */ -#if 0 static int test_clear_bindings( void * clientData, Tcl_Interp *interp, @@ -1825,7 +2255,28 @@ static int test_clear_bindings( Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_clear_bindings(pStmt))); return TCL_OK; } -#endif + +/* +** Usage: sqlite3_sleep MILLISECONDS +*/ +static int test_sleep( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + int ms; + + if( objc!=2 ){ + Tcl_WrongNumArgs(interp, 1, objv, "MILLISECONDS"); + return TCL_ERROR; + } + if( Tcl_GetIntFromObj(interp, objv[1], &ms) ){ + return TCL_ERROR; + } + Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_sleep(ms))); + return TCL_OK; +} /* ** Usage: sqlite3_errcode DB @@ -1895,7 +2346,7 @@ static int test_errmsg16( #ifndef SQLITE_OMIT_UTF16 sqlite3 *db; const void *zErr; - int bytes; + int bytes = 0; if( objc!=2 ){ Tcl_AppendResult(interp, "wrong # args: should be \"", @@ -1905,7 +2356,9 @@ static int test_errmsg16( if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; zErr = sqlite3_errmsg16(db); - bytes = sqlite3utf16ByteLen(zErr, -1); + if( zErr ){ + bytes = sqlite3utf16ByteLen(zErr, -1); + } Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(zErr, bytes)); #endif /* SQLITE_OMIT_UTF16 */ return TCL_OK; @@ -1958,7 +2411,7 @@ static int test_prepare( } if( pStmt ){ - if( makePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR; + if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR; Tcl_AppendResult(interp, zBuf, 0); } return TCL_OK; @@ -2015,7 +2468,7 @@ static int test_prepare16( Tcl_DecrRefCount(pTail); if( pStmt ){ - if( makePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR; + if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR; } Tcl_AppendResult(interp, zBuf, 0); #endif /* SQLITE_OMIT_UTF16 */ @@ -2045,7 +2498,7 @@ static int test_open( zFilename = Tcl_GetString(objv[1]); rc = sqlite3_open(zFilename, &db); - if( makePointerStr(interp, zBuf, db) ) return TCL_ERROR; + if( sqlite3TestMakePointerStr(interp, zBuf, db) ) return TCL_ERROR; Tcl_AppendResult(interp, zBuf, 0); return TCL_OK; } @@ -2074,7 +2527,7 @@ static int test_open16( zFilename = Tcl_GetByteArrayFromObj(objv[1], 0); rc = sqlite3_open16(zFilename, &db); - if( makePointerStr(interp, zBuf, db) ) return TCL_ERROR; + if( sqlite3TestMakePointerStr(interp, zBuf, db) ) return TCL_ERROR; Tcl_AppendResult(interp, zBuf, 0); #endif /* SQLITE_OMIT_UTF16 */ return TCL_OK; @@ -2100,7 +2553,7 @@ static int test_complete16( return TCL_ERROR; } - zBuf = Tcl_GetByteArrayFromObj(objv[1], 0); + zBuf = (char*)Tcl_GetByteArrayFromObj(objv[1], 0); Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_complete16(zBuf))); #endif /* SQLITE_OMIT_COMPLETE && SQLITE_OMIT_UTF16 */ return TCL_OK; @@ -2452,7 +2905,7 @@ static int test_sqlite3OsOpenReadWrite( int objc, Tcl_Obj *CONST objv[] ){ - OsFile * pFile; + OsFile *pFile; int rc; int dummy; char zBuf[100]; @@ -2463,14 +2916,12 @@ static int test_sqlite3OsOpenReadWrite( return TCL_ERROR; } - pFile = sqliteMalloc(sizeof(OsFile)); - rc = sqlite3OsOpenReadWrite(Tcl_GetString(objv[1]), pFile, &dummy); + rc = sqlite3OsOpenReadWrite(Tcl_GetString(objv[1]), &pFile, &dummy); if( rc!=SQLITE_OK ){ - sqliteFree(pFile); Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC); return TCL_ERROR; } - makePointerStr(interp, zBuf, pFile); + sqlite3TestMakePointerStr(interp, zBuf, pFile); Tcl_SetResult(interp, zBuf, 0); return TCL_ERROR; } @@ -2484,7 +2935,7 @@ static int test_sqlite3OsClose( int objc, Tcl_Obj *CONST objv[] ){ - OsFile * pFile; + OsFile *pFile; int rc; if( objc!=2 ){ @@ -2496,12 +2947,11 @@ static int test_sqlite3OsClose( if( getFilePointer(interp, Tcl_GetString(objv[1]), &pFile) ){ return TCL_ERROR; } - rc = sqlite3OsClose(pFile); + rc = sqlite3OsClose(&pFile); if( rc!=SQLITE_OK ){ Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC); return TCL_ERROR; } - sqliteFree(pFile); return TCL_OK; } @@ -2697,7 +3147,7 @@ static int test_stack_used( } if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; prepStack(); - sqlite3_exec(db, argv[2], 0, 0, 0); + (void)sqlite3_exec(db, argv[2], 0, 0, 0); for(i=65535; i>=0 && ((u32*)sqlite3_stack_baseline)[-i]==0xdeadbeef; i--){} Tcl_SetObjResult(interp, Tcl_NewIntObj(i*4)); return TCL_OK; @@ -2781,6 +3231,33 @@ static int get_autocommit( } /* +** Usage: sqlite3_busy_timeout DB MS +** +** Set the busy timeout. This is more easily done using the timeout +** method of the TCL interface. But we need a way to test the case +** where it returns SQLITE_MISUSE. +*/ +static int test_busy_timeout( + void * clientData, + Tcl_Interp *interp, + int argc, + char **argv +){ + int rc, ms; + sqlite3 *db; + if( argc!=3 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " DB", 0); + return TCL_ERROR; + } + if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; + if( Tcl_GetInt(interp, argv[2], &ms) ) return TCL_ERROR; + rc = sqlite3_busy_timeout(db, ms); + Tcl_AppendResult(interp, sqlite3TestErrorName(rc), 0); + return TCL_OK; +} + +/* ** Usage: tcl_variable_type VARIABLENAME ** ** Return the name of the internal representation for the @@ -2806,6 +3283,115 @@ static int tcl_variable_type( } /* +** Usage: sqlite3_release_memory ?N? +** +** Attempt to release memory currently held but not actually required. +** The integer N is the number of bytes we are trying to release. The +** return value is the amount of memory actually released. +*/ +static int test_release_memory( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ +#if defined(SQLITE_ENABLE_MEMORY_MANAGEMENT) && !defined(SQLITE_OMIT_DISKIO) + int N; + int amt; + if( objc!=1 && objc!=2 ){ + Tcl_WrongNumArgs(interp, 1, objv, "?N?"); + return TCL_ERROR; + } + if( objc==2 ){ + if( Tcl_GetIntFromObj(interp, objv[1], &N) ) return TCL_ERROR; + }else{ + N = -1; + } + amt = sqlite3_release_memory(N); + Tcl_SetObjResult(interp, Tcl_NewIntObj(amt)); +#endif + return TCL_OK; +} + +/* +** Usage: sqlite3_soft_heap_limit ?N? +** +** Query or set the soft heap limit for the current thread. The +** limit is only changed if the N is present. The previous limit +** is returned. +*/ +static int test_soft_heap_limit( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ +#if defined(SQLITE_ENABLE_MEMORY_MANAGEMENT) && !defined(SQLITE_OMIT_DISKIO) + int amt; + if( objc!=1 && objc!=2 ){ + Tcl_WrongNumArgs(interp, 1, objv, "?N?"); + return TCL_ERROR; + } + amt = sqlite3ThreadDataReadOnly()->nSoftHeapLimit; + if( objc==2 ){ + int N; + if( Tcl_GetIntFromObj(interp, objv[1], &N) ) return TCL_ERROR; + sqlite3_soft_heap_limit(N); + } + Tcl_SetObjResult(interp, Tcl_NewIntObj(amt)); +#endif + return TCL_OK; +} + +/* +** Usage: sqlite3_clear_tsd_memdebug +** +** Clear all of the MEMDEBUG information out of thread-specific data. +** This will allow it to be deallocated. +*/ +static int test_clear_tsd_memdebug( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + return TCL_OK; +} + +/* +** Usage: sqlite3_tsd_release +** +** Call sqlite3ReleaseThreadData. +*/ +static int test_tsd_release( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ +#if defined(SQLITE_MEMDEBUG) + sqlite3ReleaseThreadData(); +#endif + return TCL_OK; +} + +/* +** Usage: sqlite3_thread_cleanup +** +** Call the sqlite3_thread_cleanup API. +*/ +static int test_thread_cleanup( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + sqlite3_thread_cleanup(); + return TCL_OK; +} + + +/* ** This routine sets entries in the global ::sqlite_options() array variable ** according to the compile-time configuration of the database. Test ** procedures use this to determine when tests should be omitted. @@ -2823,6 +3409,18 @@ static void set_options(Tcl_Interp *interp){ Tcl_SetVar2(interp, "sqlite_options","casesensitivelike","0",TCL_GLOBAL_ONLY); #endif +#ifdef SQLITE_DISABLE_DIRSYNC + Tcl_SetVar2(interp, "sqlite_options", "dirsync", "0", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "dirsync", "1", TCL_GLOBAL_ONLY); +#endif + +#ifdef SQLITE_DISABLE_LFS + Tcl_SetVar2(interp, "sqlite_options", "lfs", "0", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "lfs", "1", TCL_GLOBAL_ONLY); +#endif + #ifdef SQLITE_OMIT_ALTERTABLE Tcl_SetVar2(interp, "sqlite_options", "altertable", "0", TCL_GLOBAL_ONLY); #else @@ -2876,6 +3474,18 @@ static void set_options(Tcl_Interp *interp){ Tcl_SetVar2(interp, "sqlite_options", "cast", "1", TCL_GLOBAL_ONLY); #endif +#ifdef SQLITE_OMIT_CHECK + Tcl_SetVar2(interp, "sqlite_options", "check", "0", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "check", "1", TCL_GLOBAL_ONLY); +#endif + +#ifdef SQLITE_ENABLE_COLUMN_METADATA + Tcl_SetVar2(interp, "sqlite_options", "columnmetadata", "1", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "columnmetadata", "0", TCL_GLOBAL_ONLY); +#endif + #ifdef SQLITE_OMIT_COMPLETE Tcl_SetVar2(interp, "sqlite_options", "complete", "0", TCL_GLOBAL_ONLY); #else @@ -2894,6 +3504,12 @@ static void set_options(Tcl_Interp *interp){ Tcl_SetVar2(interp, "sqlite_options", "conflict", "1", TCL_GLOBAL_ONLY); #endif +#if OS_UNIX + Tcl_SetVar2(interp, "sqlite_options", "crashtest", "1", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "crashtest", "0", TCL_GLOBAL_ONLY); +#endif + #ifdef SQLITE_OMIT_DATETIME_FUNCS Tcl_SetVar2(interp, "sqlite_options", "datetime", "0", TCL_GLOBAL_ONLY); #else @@ -2936,6 +3552,12 @@ static void set_options(Tcl_Interp *interp){ Tcl_SetVar2(interp, "sqlite_options", "integrityck", "1", TCL_GLOBAL_ONLY); #endif +#if defined(SQLITE_DEFAULT_FILE_FORMAT) && SQLITE_DEFAULT_FILE_FORMAT==1 + Tcl_SetVar2(interp, "sqlite_options", "legacyformat", "1", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "legacyformat", "0", TCL_GLOBAL_ONLY); +#endif + #ifdef SQLITE_OMIT_LIKE_OPTIMIZATION Tcl_SetVar2(interp, "sqlite_options", "like_opt", "0", TCL_GLOBAL_ONLY); #else @@ -2948,6 +3570,12 @@ static void set_options(Tcl_Interp *interp){ Tcl_SetVar2(interp, "sqlite_options", "memorydb", "1", TCL_GLOBAL_ONLY); #endif +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT + Tcl_SetVar2(interp, "sqlite_options", "memorymanage", "1", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "memorymanage", "0", TCL_GLOBAL_ONLY); +#endif + #ifdef SQLITE_OMIT_OR_OPTIMIZATION Tcl_SetVar2(interp, "sqlite_options", "or_opt", "0", TCL_GLOBAL_ONLY); #else @@ -2979,6 +3607,12 @@ static void set_options(Tcl_Interp *interp){ Tcl_SetVar2(interp, "sqlite_options", "progress", "1", TCL_GLOBAL_ONLY); #endif +#ifdef SQLITE_ENABLE_REDEF_IO + Tcl_SetVar2(interp, "sqlite_options", "redefio", "1", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "redefio", "0", TCL_GLOBAL_ONLY); +#endif + #ifdef SQLITE_OMIT_REINDEX Tcl_SetVar2(interp, "sqlite_options", "reindex", "0", TCL_GLOBAL_ONLY); #else @@ -2997,6 +3631,12 @@ static void set_options(Tcl_Interp *interp){ Tcl_SetVar2(interp, "sqlite_options", "schema_version", "1", TCL_GLOBAL_ONLY); #endif +#ifdef SQLITE_OMIT_SHARED_CACHE + Tcl_SetVar2(interp, "sqlite_options", "shared_cache", "0", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "shared_cache", "1", TCL_GLOBAL_ONLY); +#endif + #ifdef SQLITE_OMIT_SUBQUERY Tcl_SetVar2(interp, "sqlite_options", "subquery", "0", TCL_GLOBAL_ONLY); #else @@ -3050,6 +3690,12 @@ static void set_options(Tcl_Interp *interp){ #else Tcl_SetVar2(interp, "sqlite_options", "view", "1", TCL_GLOBAL_ONLY); #endif + +#ifdef SQLITE_OMIT_VIRTUALTABLE + Tcl_SetVar2(interp, "sqlite_options", "vtab", "0", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "vtab", "1", TCL_GLOBAL_ONLY); +#endif } /* @@ -3073,6 +3719,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){ { "sqlite3_mprintf_scaled", (Tcl_CmdProc*)sqlite3_mprintf_scaled }, { "sqlite3_mprintf_hexdouble", (Tcl_CmdProc*)sqlite3_mprintf_hexdouble}, { "sqlite3_mprintf_z_test", (Tcl_CmdProc*)test_mprintf_z }, + { "sqlite3_mprintf_n_test", (Tcl_CmdProc*)test_mprintf_n }, { "sqlite3_last_insert_rowid", (Tcl_CmdProc*)test_last_rowid }, { "sqlite3_exec_printf", (Tcl_CmdProc*)test_exec_printf }, { "sqlite3_get_table_printf", (Tcl_CmdProc*)test_get_table_printf }, @@ -3091,19 +3738,18 @@ int Sqlitetest1_Init(Tcl_Interp *interp){ { "sqlite3_rekey", (Tcl_CmdProc*)test_rekey }, { "sqlite_set_magic", (Tcl_CmdProc*)sqlite_set_magic }, { "sqlite3_interrupt", (Tcl_CmdProc*)test_interrupt }, -#if 0 - { "sqlite3_sleep", (Tcl_CmdProc*)test_sleep }, -#endif { "sqlite_delete_function", (Tcl_CmdProc*)delete_function }, { "sqlite_delete_collation", (Tcl_CmdProc*)delete_collation }, { "sqlite3_get_autocommit", (Tcl_CmdProc*)get_autocommit }, { "sqlite3_stack_used", (Tcl_CmdProc*)test_stack_used }, + { "sqlite3_busy_timeout", (Tcl_CmdProc*)test_busy_timeout }, }; static struct { char *zName; Tcl_ObjCmdProc *xProc; void *clientData; } aObjCmd[] = { + { "sqlite3_connection_pointer", get_sqlite_pointer, 0 }, { "sqlite3_bind_int", test_bind_int, 0 }, { "sqlite3_bind_int64", test_bind_int64, 0 }, { "sqlite3_bind_double", test_bind_double, 0 }, @@ -3114,9 +3760,8 @@ int Sqlitetest1_Init(Tcl_Interp *interp){ { "sqlite3_bind_parameter_count", test_bind_parameter_count, 0}, { "sqlite3_bind_parameter_name", test_bind_parameter_name, 0}, { "sqlite3_bind_parameter_index", test_bind_parameter_index, 0}, -#if 0 { "sqlite3_clear_bindings", test_clear_bindings, 0}, -#endif + { "sqlite3_sleep", test_sleep, 0}, { "sqlite3_errcode", test_errcode ,0 }, { "sqlite3_errmsg", test_errmsg ,0 }, { "sqlite3_errmsg16", test_errmsg16 ,0 }, @@ -3133,6 +3778,15 @@ int Sqlitetest1_Init(Tcl_Interp *interp){ { "sqlite3_changes", test_changes ,0 }, { "sqlite3_step", test_step ,0 }, + { "sqlite3_release_memory", test_release_memory, 0}, + { "sqlite3_soft_heap_limit", test_soft_heap_limit, 0}, + { "sqlite3_clear_tsd_memdebug", test_clear_tsd_memdebug, 0}, + { "sqlite3_tsd_release", test_tsd_release, 0}, + { "sqlite3_thread_cleanup", test_thread_cleanup, 0}, + + { "sqlite3_load_extension", test_load_extension, 0}, + { "sqlite3_enable_load_extension", test_enable_load, 0}, + /* sqlite3_column_*() API */ { "sqlite3_column_count", test_column_count ,0 }, { "sqlite3_data_count", test_data_count ,0 }, @@ -3145,11 +3799,24 @@ int Sqlitetest1_Init(Tcl_Interp *interp){ { "sqlite3_column_name", test_stmt_utf8, sqlite3_column_name }, { "sqlite3_column_int", test_stmt_int, sqlite3_column_int }, { "sqlite3_column_bytes", test_stmt_int, sqlite3_column_bytes }, +#ifdef SQLITE_ENABLE_COLUMN_METADATA +{ "sqlite3_column_database_name", test_stmt_utf8, sqlite3_column_database_name}, +{ "sqlite3_column_table_name", test_stmt_utf8, sqlite3_column_table_name}, +{ "sqlite3_column_origin_name", test_stmt_utf8, sqlite3_column_origin_name}, +#endif + #ifndef SQLITE_OMIT_UTF16 { "sqlite3_column_bytes16", test_stmt_int, sqlite3_column_bytes16 }, { "sqlite3_column_text16", test_stmt_utf16, sqlite3_column_text16 }, { "sqlite3_column_decltype16", test_stmt_utf16, sqlite3_column_decltype16}, { "sqlite3_column_name16", test_stmt_utf16, sqlite3_column_name16 }, + { "add_alignment_test_collations", add_alignment_test_collations, 0 }, +#ifdef SQLITE_ENABLE_COLUMN_METADATA +{"sqlite3_column_database_name16", + test_stmt_utf16, sqlite3_column_database_name16}, +{"sqlite3_column_table_name16", test_stmt_utf16, sqlite3_column_table_name16}, +{"sqlite3_column_origin_name16", test_stmt_utf16, sqlite3_column_origin_name16}, +#endif #endif { "sqlite3_global_recover", test_global_recover, 0 }, @@ -3168,9 +3835,18 @@ int Sqlitetest1_Init(Tcl_Interp *interp){ { "add_test_collate_needed", test_collate_needed, 0 }, { "add_test_function", test_function, 0 }, #endif - { "sqlite3_crashparams", sqlite3_crashparams, 0 }, +#ifdef SQLITE_MEMDEBUG + { "sqlite_malloc_outstanding", sqlite_malloc_outstanding, 0}, +#endif { "sqlite3_test_errstr", test_errstr, 0 }, { "tcl_variable_type", tcl_variable_type, 0 }, +#ifndef SQLITE_OMIT_SHARED_CACHE + { "sqlite3_enable_shared_cache", test_enable_shared, 0 }, +#endif + { "sqlite3_libversion_number", test_libversion_number, 0 }, +#ifdef SQLITE_ENABLE_COLUMN_METADATA + { "sqlite3_table_column_metadata", test_table_column_metadata, 0 }, +#endif }; static int bitmask_size = sizeof(Bitmask)*8; int i; @@ -3179,8 +3855,13 @@ int Sqlitetest1_Init(Tcl_Interp *interp){ extern int sqlite3_sync_count, sqlite3_fullsync_count; extern int sqlite3_opentemp_count; extern int sqlite3_memUsed; + extern int sqlite3_malloc_id; extern int sqlite3_memMax; extern int sqlite3_like_count; + extern int sqlite3_tsd_count; +#if OS_UNIX && defined(SQLITE_TEST) && defined(THREADSAFE) && THREADSAFE + extern int threadsOverrideEachOthersLocks; +#endif #if OS_WIN extern int sqlite3_os_type; #endif @@ -3213,6 +3894,24 @@ int Sqlitetest1_Init(Tcl_Interp *interp){ (char*)&sqlite3_current_time, TCL_LINK_INT); Tcl_LinkVar(interp, "sqlite_os_trace", (char*)&sqlite3_os_trace, TCL_LINK_INT); + Tcl_LinkVar(interp, "sqlite3_tsd_count", + (char*)&sqlite3_tsd_count, TCL_LINK_INT); +#ifndef SQLITE_OMIT_UTF16 + Tcl_LinkVar(interp, "unaligned_string_counter", + (char*)&unaligned_string_counter, TCL_LINK_INT); +#endif +#if OS_UNIX && defined(SQLITE_TEST) && defined(THREADSAFE) && THREADSAFE + Tcl_LinkVar(interp, "threadsOverrideEachOthersLocks", + (char*)&threadsOverrideEachOthersLocks, TCL_LINK_INT); +#endif +#ifndef SQLITE_OMIT_UTF16 + Tcl_LinkVar(interp, "sqlite_last_needed_collation", + (char*)&pzNeededCollation, TCL_LINK_STRING|TCL_LINK_READ_ONLY); +#endif +#ifdef SQLITE_MEMDEBUG + Tcl_LinkVar(interp, "sqlite_malloc_id", + (char*)&sqlite3_malloc_id, TCL_LINK_STRING); +#endif #if OS_WIN Tcl_LinkVar(interp, "sqlite_os_type", (char*)&sqlite3_os_type, TCL_LINK_INT); @@ -3250,5 +3949,14 @@ int Sqlitetest1_Init(Tcl_Interp *interp){ (char*)&sqlite3_fullsync_count, TCL_LINK_INT); #endif /* OS_UNIX */ set_options(interp); + + { +#ifdef SQLITE_DEBUG + extern int sqlite3_shared_cache_report(void *, Tcl_Interp *, + int, Tcl_Obj *CONST[]); + Tcl_CreateObjCommand(interp, "sqlite_shared_cache_report", + sqlite3_shared_cache_report, 0, 0); +#endif + } return TCL_OK; } |