| Index: third_party/sqlite/src/src/test1.c
|
| diff --git a/third_party/sqlite/src/src/test1.c b/third_party/sqlite/src/src/test1.c
|
| index 8a0d09a7164752018c497f0e957345118593260a..85a16488ba850f82143dfd67f54a2eb673ac8db2 100644
|
| --- a/third_party/sqlite/src/src/test1.c
|
| +++ b/third_party/sqlite/src/src/test1.c
|
| @@ -14,6 +14,11 @@
|
| ** testing of the SQLite library.
|
| */
|
| #include "sqliteInt.h"
|
| +#if SQLITE_OS_WIN
|
| +# include "os_win.h"
|
| +#endif
|
| +
|
| +#include "vdbeInt.h"
|
| #include "tcl.h"
|
| #include <stdlib.h>
|
| #include <string.h>
|
| @@ -112,61 +117,18 @@ int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb){
|
| return TCL_OK;
|
| }
|
|
|
| +#if SQLITE_OS_WIN
|
| +/*
|
| +** Decode a Win32 HANDLE object.
|
| +*/
|
| +int getWin32Handle(Tcl_Interp *interp, const char *zA, LPHANDLE phFile){
|
| + *phFile = (HANDLE)sqlite3TestTextToPtr(zA);
|
| + return TCL_OK;
|
| +}
|
| +#endif
|
|
|
| -const char *sqlite3TestErrorName(int rc){
|
| - const char *zName = 0;
|
| - switch( rc ){
|
| - case SQLITE_OK: zName = "SQLITE_OK"; break;
|
| - case SQLITE_ERROR: zName = "SQLITE_ERROR"; break;
|
| - case SQLITE_INTERNAL: zName = "SQLITE_INTERNAL"; break;
|
| - case SQLITE_PERM: zName = "SQLITE_PERM"; break;
|
| - case SQLITE_ABORT: zName = "SQLITE_ABORT"; break;
|
| - case SQLITE_BUSY: zName = "SQLITE_BUSY"; break;
|
| - case SQLITE_LOCKED: zName = "SQLITE_LOCKED"; break;
|
| - case SQLITE_LOCKED_SHAREDCACHE: zName = "SQLITE_LOCKED_SHAREDCACHE";break;
|
| - case SQLITE_NOMEM: zName = "SQLITE_NOMEM"; break;
|
| - case SQLITE_READONLY: zName = "SQLITE_READONLY"; break;
|
| - case SQLITE_INTERRUPT: zName = "SQLITE_INTERRUPT"; break;
|
| - case SQLITE_IOERR: zName = "SQLITE_IOERR"; break;
|
| - case SQLITE_CORRUPT: zName = "SQLITE_CORRUPT"; break;
|
| - case SQLITE_NOTFOUND: zName = "SQLITE_NOTFOUND"; break;
|
| - case SQLITE_FULL: zName = "SQLITE_FULL"; break;
|
| - case SQLITE_CANTOPEN: zName = "SQLITE_CANTOPEN"; break;
|
| - case SQLITE_PROTOCOL: zName = "SQLITE_PROTOCOL"; break;
|
| - case SQLITE_EMPTY: zName = "SQLITE_EMPTY"; break;
|
| - case SQLITE_SCHEMA: zName = "SQLITE_SCHEMA"; break;
|
| - case SQLITE_TOOBIG: zName = "SQLITE_TOOBIG"; break;
|
| - case SQLITE_CONSTRAINT: zName = "SQLITE_CONSTRAINT"; break;
|
| - case SQLITE_MISMATCH: zName = "SQLITE_MISMATCH"; break;
|
| - case SQLITE_MISUSE: zName = "SQLITE_MISUSE"; break;
|
| - case SQLITE_NOLFS: zName = "SQLITE_NOLFS"; break;
|
| - case SQLITE_AUTH: zName = "SQLITE_AUTH"; break;
|
| - case SQLITE_FORMAT: zName = "SQLITE_FORMAT"; break;
|
| - case SQLITE_RANGE: zName = "SQLITE_RANGE"; break;
|
| - case SQLITE_NOTADB: zName = "SQLITE_NOTADB"; break;
|
| - case SQLITE_ROW: zName = "SQLITE_ROW"; break;
|
| - case SQLITE_DONE: zName = "SQLITE_DONE"; break;
|
| - case SQLITE_IOERR_READ: zName = "SQLITE_IOERR_READ"; break;
|
| - case SQLITE_IOERR_SHORT_READ: zName = "SQLITE_IOERR_SHORT_READ"; break;
|
| - case SQLITE_IOERR_WRITE: zName = "SQLITE_IOERR_WRITE"; break;
|
| - case SQLITE_IOERR_FSYNC: zName = "SQLITE_IOERR_FSYNC"; break;
|
| - case SQLITE_IOERR_DIR_FSYNC: zName = "SQLITE_IOERR_DIR_FSYNC"; break;
|
| - case SQLITE_IOERR_TRUNCATE: zName = "SQLITE_IOERR_TRUNCATE"; break;
|
| - case SQLITE_IOERR_FSTAT: zName = "SQLITE_IOERR_FSTAT"; break;
|
| - case SQLITE_IOERR_UNLOCK: zName = "SQLITE_IOERR_UNLOCK"; break;
|
| - case SQLITE_IOERR_RDLOCK: zName = "SQLITE_IOERR_RDLOCK"; break;
|
| - case SQLITE_IOERR_DELETE: zName = "SQLITE_IOERR_DELETE"; break;
|
| - case SQLITE_IOERR_BLOCKED: zName = "SQLITE_IOERR_BLOCKED"; break;
|
| - case SQLITE_IOERR_NOMEM: zName = "SQLITE_IOERR_NOMEM"; break;
|
| - case SQLITE_IOERR_ACCESS: zName = "SQLITE_IOERR_ACCESS"; break;
|
| - case SQLITE_IOERR_CHECKRESERVEDLOCK:
|
| - zName = "SQLITE_IOERR_CHECKRESERVEDLOCK"; break;
|
| - case SQLITE_IOERR_LOCK: zName = "SQLITE_IOERR_LOCK"; break;
|
| - default: zName = "SQLITE_Unknown"; break;
|
| - }
|
| - return zName;
|
| -}
|
| -#define t1ErrorName sqlite3TestErrorName
|
| +extern const char *sqlite3ErrName(int);
|
| +#define t1ErrorName sqlite3ErrName
|
|
|
| /*
|
| ** Convert an sqlite3_stmt* into an sqlite3*. This depends on the
|
| @@ -294,7 +256,28 @@ static int test_io_trace(
|
| return TCL_OK;
|
| }
|
|
|
| -
|
| +/*
|
| +** Usage: clang_sanitize_address
|
| +**
|
| +** Returns true if the program was compiled using clang with the
|
| +** -fsanitize=address switch on the command line. False otherwise.
|
| +*/
|
| +static int clang_sanitize_address(
|
| + void *NotUsed,
|
| + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
|
| + int argc, /* Number of arguments */
|
| + char **argv /* Text of each argument */
|
| +){
|
| + int res = 0;
|
| +#if defined(__has_feature)
|
| +# if __has_feature(address_sanitizer)
|
| + res = 1;
|
| +# endif
|
| +#endif
|
| + Tcl_SetObjResult(interp, Tcl_NewIntObj(res));
|
| + return TCL_OK;
|
| +}
|
| +
|
| /*
|
| ** Usage: sqlite3_exec_printf DB FORMAT STRING
|
| **
|
| @@ -664,6 +647,7 @@ static int test_key(
|
| int argc, /* Number of arguments */
|
| char **argv /* Text of each argument */
|
| ){
|
| +#ifdef SQLITE_HAS_CODEC
|
| sqlite3 *db;
|
| const char *zKey;
|
| int nKey;
|
| @@ -675,7 +659,6 @@ static int test_key(
|
| if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
|
| zKey = argv[2];
|
| nKey = strlen(zKey);
|
| -#ifdef SQLITE_HAS_CODEC
|
| sqlite3_key(db, zKey, nKey);
|
| #endif
|
| return TCL_OK;
|
| @@ -692,6 +675,7 @@ static int test_rekey(
|
| int argc, /* Number of arguments */
|
| char **argv /* Text of each argument */
|
| ){
|
| +#ifdef SQLITE_HAS_CODEC
|
| sqlite3 *db;
|
| const char *zKey;
|
| int nKey;
|
| @@ -703,7 +687,6 @@ static int test_rekey(
|
| if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
|
| zKey = argv[2];
|
| nKey = strlen(zKey);
|
| -#ifdef SQLITE_HAS_CODEC
|
| sqlite3_rekey(db, zKey, nKey);
|
| #endif
|
| return TCL_OK;
|
| @@ -734,6 +717,30 @@ static int sqlite_test_close(
|
| }
|
|
|
| /*
|
| +** Usage: sqlite3_close_v2 DB
|
| +**
|
| +** Closes the database opened by sqlite3_open.
|
| +*/
|
| +static int sqlite_test_close_v2(
|
| + void *NotUsed,
|
| + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
|
| + int argc, /* Number of arguments */
|
| + char **argv /* Text of each argument */
|
| +){
|
| + sqlite3 *db;
|
| + int rc;
|
| + if( argc!=2 ){
|
| + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
|
| + " FILENAME\"", 0);
|
| + return TCL_ERROR;
|
| + }
|
| + if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
|
| + rc = sqlite3_close_v2(db);
|
| + Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
|
| + return TCL_OK;
|
| +}
|
| +
|
| +/*
|
| ** Implementation of the x_coalesce() function.
|
| ** Return the first argument non-NULL argument.
|
| */
|
| @@ -796,7 +803,7 @@ struct dstr {
|
| ** Append text to a dstr
|
| */
|
| static void dstrAppend(struct dstr *p, const char *z, int divider){
|
| - int n = strlen(z);
|
| + int n = (int)strlen(z);
|
| if( p->nUsed + n + 2 > p->nAlloc ){
|
| char *zNew;
|
| p->nAlloc = p->nAlloc*2 + n + 200;
|
| @@ -970,9 +977,21 @@ static void ptrChngFunction(
|
| sqlite3_result_int(context, p1!=p2);
|
| }
|
|
|
| +/*
|
| +** This SQL function returns a different answer each time it is called, even if
|
| +** the arguments are the same.
|
| +*/
|
| +static void nondeterministicFunction(
|
| + sqlite3_context *context,
|
| + int argc,
|
| + sqlite3_value **argv
|
| +){
|
| + static int cnt = 0;
|
| + sqlite3_result_int(context, cnt++);
|
| +}
|
|
|
| /*
|
| -** Usage: sqlite_test_create_function DB
|
| +** Usage: sqlite3_create_function DB
|
| **
|
| ** Call the sqlite3_create_function API on the given database in order
|
| ** to create a function named "x_coalesce". This function does the same thing
|
| @@ -1001,16 +1020,16 @@ static int test_create_function(
|
| return TCL_ERROR;
|
| }
|
| if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
|
| - rc = sqlite3_create_function(db, "x_coalesce", -1, SQLITE_ANY, 0,
|
| + rc = sqlite3_create_function(db, "x_coalesce", -1, SQLITE_UTF8, 0,
|
| t1_ifnullFunc, 0, 0);
|
| if( rc==SQLITE_OK ){
|
| - rc = sqlite3_create_function(db, "hex8", 1, SQLITE_ANY, 0,
|
| - hex8Func, 0, 0);
|
| + rc = sqlite3_create_function(db, "hex8", 1, SQLITE_UTF8 | SQLITE_DETERMINISTIC,
|
| + 0, hex8Func, 0, 0);
|
| }
|
| #ifndef SQLITE_OMIT_UTF16
|
| if( rc==SQLITE_OK ){
|
| - rc = sqlite3_create_function(db, "hex16", 1, SQLITE_ANY, 0,
|
| - hex16Func, 0, 0);
|
| + rc = sqlite3_create_function(db, "hex16", 1, SQLITE_UTF16 | SQLITE_DETERMINISTIC,
|
| + 0, hex16Func, 0, 0);
|
| }
|
| #endif
|
| if( rc==SQLITE_OK ){
|
| @@ -1022,6 +1041,19 @@ static int test_create_function(
|
| ptrChngFunction, 0, 0);
|
| }
|
|
|
| + /* Functions counter1() and counter2() have the same implementation - they
|
| + ** both return an ascending integer with each call. But counter1() is marked
|
| + ** as non-deterministic and counter2() is marked as deterministic.
|
| + */
|
| + if( rc==SQLITE_OK ){
|
| + rc = sqlite3_create_function(db, "counter1", -1, SQLITE_UTF8,
|
| + 0, nondeterministicFunction, 0, 0);
|
| + }
|
| + if( rc==SQLITE_OK ){
|
| + rc = sqlite3_create_function(db, "counter2", -1, SQLITE_UTF8|SQLITE_DETERMINISTIC,
|
| + 0, nondeterministicFunction, 0, 0);
|
| + }
|
| +
|
| #ifndef SQLITE_OMIT_UTF16
|
| /* Use the sqlite3_create_function16() API here. Mainly for fun, but also
|
| ** because it is not tested anywhere else. */
|
| @@ -1711,7 +1743,7 @@ static int test_blob_read(
|
| if( rc==SQLITE_OK ){
|
| Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(zBuf, nByte));
|
| }else{
|
| - Tcl_SetResult(interp, (char *)sqlite3TestErrorName(rc), TCL_VOLATILE);
|
| + Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);
|
| }
|
| Tcl_Free((char *)zBuf);
|
|
|
| @@ -1761,7 +1793,7 @@ static int test_blob_write(
|
| }
|
| rc = sqlite3_blob_write(pBlob, zBuf, nBuf, iOffset);
|
| if( rc!=SQLITE_OK ){
|
| - Tcl_SetResult(interp, (char *)sqlite3TestErrorName(rc), TCL_VOLATILE);
|
| + Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);
|
| }
|
|
|
| return (rc==SQLITE_OK ? TCL_OK : TCL_ERROR);
|
| @@ -1787,7 +1819,7 @@ static int test_blob_reopen(
|
|
|
| rc = sqlite3_blob_reopen(pBlob, iRowid);
|
| if( rc!=SQLITE_OK ){
|
| - Tcl_SetResult(interp, (char *)sqlite3TestErrorName(rc), TCL_VOLATILE);
|
| + Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);
|
| }
|
|
|
| return (rc==SQLITE_OK ? TCL_OK : TCL_ERROR);
|
| @@ -1997,7 +2029,7 @@ static int test_create_function_v2(
|
| );
|
| if( rc!=SQLITE_OK ){
|
| Tcl_ResetResult(interp);
|
| - Tcl_AppendResult(interp, sqlite3TestErrorName(rc), 0);
|
| + Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
|
| return TCL_ERROR;
|
| }
|
| return TCL_OK;
|
| @@ -2246,6 +2278,7 @@ static int test_stmt_status(
|
| { "SQLITE_STMTSTATUS_FULLSCAN_STEP", SQLITE_STMTSTATUS_FULLSCAN_STEP },
|
| { "SQLITE_STMTSTATUS_SORT", SQLITE_STMTSTATUS_SORT },
|
| { "SQLITE_STMTSTATUS_AUTOINDEX", SQLITE_STMTSTATUS_AUTOINDEX },
|
| + { "SQLITE_STMTSTATUS_VM_STEP", SQLITE_STMTSTATUS_VM_STEP },
|
| };
|
| if( objc!=4 ){
|
| Tcl_WrongNumArgs(interp, 1, objv, "STMT PARAMETER RESETFLAG");
|
| @@ -2326,6 +2359,58 @@ static int test_stmt_readonly(
|
| return TCL_OK;
|
| }
|
|
|
| +/*
|
| +** Usage: sqlite3_stmt_busy STMT
|
| +**
|
| +** Return true if STMT is a non-NULL pointer to a statement
|
| +** that has been stepped but not to completion.
|
| +*/
|
| +static int test_stmt_busy(
|
| + void * clientData,
|
| + Tcl_Interp *interp,
|
| + int objc,
|
| + Tcl_Obj *CONST objv[]
|
| +){
|
| + sqlite3_stmt *pStmt;
|
| + int rc;
|
| +
|
| + if( objc!=2 ){
|
| + Tcl_AppendResult(interp, "wrong # args: should be \"",
|
| + Tcl_GetStringFromObj(objv[0], 0), " STMT", 0);
|
| + return TCL_ERROR;
|
| + }
|
| +
|
| + if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
|
| + rc = sqlite3_stmt_busy(pStmt);
|
| + Tcl_SetObjResult(interp, Tcl_NewBooleanObj(rc));
|
| + return TCL_OK;
|
| +}
|
| +
|
| +/*
|
| +** Usage: uses_stmt_journal STMT
|
| +**
|
| +** Return true if STMT uses a statement journal.
|
| +*/
|
| +static int uses_stmt_journal(
|
| + void * clientData,
|
| + Tcl_Interp *interp,
|
| + int objc,
|
| + Tcl_Obj *CONST objv[]
|
| +){
|
| + sqlite3_stmt *pStmt;
|
| +
|
| + if( objc!=2 ){
|
| + Tcl_AppendResult(interp, "wrong # args: should be \"",
|
| + Tcl_GetStringFromObj(objv[0], 0), " STMT", 0);
|
| + return TCL_ERROR;
|
| + }
|
| +
|
| + if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
|
| + sqlite3_stmt_readonly(pStmt);
|
| + Tcl_SetObjResult(interp, Tcl_NewBooleanObj(((Vdbe *)pStmt)->usesStmtJournal));
|
| + return TCL_OK;
|
| +}
|
| +
|
|
|
| /*
|
| ** Usage: sqlite3_reset STMT
|
| @@ -2445,7 +2530,7 @@ static int sqlite_static_bind_nbyte = 0;
|
| /*
|
| ** Usage: sqlite3_bind VM IDX VALUE FLAGS
|
| **
|
| -** Sets the value of the IDX-th occurance of "?" in the original SQL
|
| +** Sets the value of the IDX-th occurrence of "?" in the original SQL
|
| ** string. VALUE is the new value. If FLAGS=="null" then VALUE is
|
| ** ignored and the value is set to NULL. If FLAGS=="static" then
|
| ** the value is set to the value of a static variable named
|
| @@ -2520,7 +2605,7 @@ static int test_bind(
|
| ** SQLite selected to call. The TCL test script implements the
|
| ** "test_collate" proc.
|
| **
|
| -** Note that this will only work with one intepreter at a time, as the
|
| +** Note that this will only work with one interpreter at a time, as the
|
| ** interp pointer to use when evaluating the TCL script is stored in
|
| ** pTestCollateInterp.
|
| */
|
| @@ -2621,7 +2706,7 @@ static int test_collate(
|
| if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
|
|
|
| if( rc!=SQLITE_OK ){
|
| - Tcl_AppendResult(interp, sqlite3TestErrorName(rc), 0);
|
| + Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
|
| return TCL_ERROR;
|
| }
|
| return TCL_OK;
|
| @@ -2633,6 +2718,46 @@ bad_args:
|
| }
|
|
|
| /*
|
| +** Usage: add_test_utf16bin_collate <db ptr>
|
| +**
|
| +** Add a utf-16 collation sequence named "utf16bin" to the database
|
| +** handle. This collation sequence compares arguments in the same way as the
|
| +** built-in collation "binary".
|
| +*/
|
| +static int test_utf16bin_collate_func(
|
| + void *pCtx,
|
| + int nA, const void *zA,
|
| + int nB, const void *zB
|
| +){
|
| + int nCmp = (nA>nB ? nB : nA);
|
| + int res = memcmp(zA, zB, nCmp);
|
| + if( res==0 ) res = nA - nB;
|
| + return res;
|
| +}
|
| +static int test_utf16bin_collate(
|
| + void * clientData,
|
| + Tcl_Interp *interp,
|
| + int objc,
|
| + Tcl_Obj *CONST objv[]
|
| +){
|
| + sqlite3 *db;
|
| + int rc;
|
| +
|
| + if( objc!=2 ) goto bad_args;
|
| + if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
|
| +
|
| + rc = sqlite3_create_collation(db, "utf16bin", SQLITE_UTF16, 0,
|
| + test_utf16bin_collate_func
|
| + );
|
| + if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
|
| + return TCL_OK;
|
| +
|
| +bad_args:
|
| + Tcl_WrongNumArgs(interp, 1, objv, "DB");
|
| + 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
|
| @@ -3011,7 +3136,7 @@ static int test_bind_int64(
|
| ){
|
| sqlite3_stmt *pStmt;
|
| int idx;
|
| - i64 value;
|
| + Tcl_WideInt value;
|
| int rc;
|
|
|
| if( objc!=4 ){
|
| @@ -3179,7 +3304,7 @@ static int test_bind_text(
|
| rc = sqlite3_bind_text(pStmt, idx, value, bytes, SQLITE_TRANSIENT);
|
| if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
|
| if( rc!=SQLITE_OK ){
|
| - Tcl_AppendResult(interp, sqlite3TestErrorName(rc), 0);
|
| + Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
|
| return TCL_ERROR;
|
| }
|
|
|
| @@ -3207,7 +3332,7 @@ static int test_bind_text16(
|
| char *value;
|
| int rc;
|
|
|
| - void (*xDel)() = (objc==6?SQLITE_STATIC:SQLITE_TRANSIENT);
|
| + void (*xDel)(void*) = (objc==6?SQLITE_STATIC:SQLITE_TRANSIENT);
|
| Tcl_Obj *oStmt = objv[objc-4];
|
| Tcl_Obj *oN = objv[objc-3];
|
| Tcl_Obj *oString = objv[objc-2];
|
| @@ -3227,7 +3352,7 @@ static int test_bind_text16(
|
| rc = sqlite3_bind_text16(pStmt, idx, (void *)value, bytes, xDel);
|
| if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
|
| if( rc!=SQLITE_OK ){
|
| - Tcl_AppendResult(interp, sqlite3TestErrorName(rc), 0);
|
| + Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
|
| return TCL_ERROR;
|
| }
|
|
|
| @@ -3553,10 +3678,10 @@ static int test_prepare(
|
| if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
|
| if( zTail && objc>=5 ){
|
| if( bytes>=0 ){
|
| - bytes = bytes - (zTail-zSql);
|
| + bytes = bytes - (int)(zTail-zSql);
|
| }
|
| - if( strlen(zTail)<bytes ){
|
| - bytes = strlen(zTail);
|
| + if( (int)strlen(zTail)<bytes ){
|
| + bytes = (int)strlen(zTail);
|
| }
|
| Tcl_ObjSetVar2(interp, objv[4], 0, Tcl_NewStringObj(zTail, bytes), 0);
|
| }
|
| @@ -3611,7 +3736,7 @@ static int test_prepare_v2(
|
| if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
|
| if( zTail && objc>=5 ){
|
| if( bytes>=0 ){
|
| - bytes = bytes - (zTail-zSql);
|
| + bytes = bytes - (int)(zTail-zSql);
|
| }
|
| Tcl_ObjSetVar2(interp, objv[4], 0, Tcl_NewStringObj(zTail, bytes), 0);
|
| }
|
| @@ -3633,7 +3758,7 @@ static int test_prepare_v2(
|
| ** Usage: sqlite3_prepare_tkt3134 DB
|
| **
|
| ** Generate a prepared statement for a zero-byte string as a test
|
| -** for ticket #3134. The string should be preceeded by a zero byte.
|
| +** for ticket #3134. The string should be preceded by a zero byte.
|
| */
|
| static int test_prepare_tkt3134(
|
| void * clientData,
|
| @@ -3712,7 +3837,7 @@ static int test_prepare16(
|
|
|
| if( objc>=5 ){
|
| if( zTail ){
|
| - objlen = objlen - ((u8 *)zTail-(u8 *)zSql);
|
| + objlen = objlen - (int)((u8 *)zTail-(u8 *)zSql);
|
| }else{
|
| objlen = 0;
|
| }
|
| @@ -3772,7 +3897,7 @@ static int test_prepare16_v2(
|
|
|
| if( objc>=5 ){
|
| if( zTail ){
|
| - objlen = objlen - ((u8 *)zTail-(u8 *)zSql);
|
| + objlen = objlen - (int)((u8 *)zTail-(u8 *)zSql);
|
| }else{
|
| objlen = 0;
|
| }
|
| @@ -3801,7 +3926,6 @@ static int test_open(
|
| ){
|
| const char *zFilename;
|
| sqlite3 *db;
|
| - int rc;
|
| char zBuf[100];
|
|
|
| if( objc!=3 && objc!=2 && objc!=1 ){
|
| @@ -3811,7 +3935,7 @@ static int test_open(
|
| }
|
|
|
| zFilename = objc>1 ? Tcl_GetString(objv[1]) : 0;
|
| - rc = sqlite3_open(zFilename, &db);
|
| + sqlite3_open(zFilename, &db);
|
|
|
| if( sqlite3TestMakePointerStr(interp, zBuf, db) ) return TCL_ERROR;
|
| Tcl_AppendResult(interp, zBuf, 0);
|
| @@ -3819,6 +3943,76 @@ static int test_open(
|
| }
|
|
|
| /*
|
| +** Usage: sqlite3_open_v2 FILENAME FLAGS VFS
|
| +*/
|
| +static int test_open_v2(
|
| + void * clientData,
|
| + Tcl_Interp *interp,
|
| + int objc,
|
| + Tcl_Obj *CONST objv[]
|
| +){
|
| + const char *zFilename;
|
| + const char *zVfs;
|
| + int flags = 0;
|
| + sqlite3 *db;
|
| + int rc;
|
| + char zBuf[100];
|
| +
|
| + int nFlag;
|
| + Tcl_Obj **apFlag;
|
| + int i;
|
| +
|
| + if( objc!=4 ){
|
| + Tcl_WrongNumArgs(interp, 1, objv, "FILENAME FLAGS VFS");
|
| + return TCL_ERROR;
|
| + }
|
| + zFilename = Tcl_GetString(objv[1]);
|
| + zVfs = Tcl_GetString(objv[3]);
|
| + if( zVfs[0]==0x00 ) zVfs = 0;
|
| +
|
| + rc = Tcl_ListObjGetElements(interp, objv[2], &nFlag, &apFlag);
|
| + if( rc!=TCL_OK ) return rc;
|
| + for(i=0; i<nFlag; i++){
|
| + int iFlag;
|
| + struct OpenFlag {
|
| + const char *zFlag;
|
| + int flag;
|
| + } aFlag[] = {
|
| + { "SQLITE_OPEN_READONLY", SQLITE_OPEN_READONLY },
|
| + { "SQLITE_OPEN_READWRITE", SQLITE_OPEN_READWRITE },
|
| + { "SQLITE_OPEN_CREATE", SQLITE_OPEN_CREATE },
|
| + { "SQLITE_OPEN_DELETEONCLOSE", SQLITE_OPEN_DELETEONCLOSE },
|
| + { "SQLITE_OPEN_EXCLUSIVE", SQLITE_OPEN_EXCLUSIVE },
|
| + { "SQLITE_OPEN_AUTOPROXY", SQLITE_OPEN_AUTOPROXY },
|
| + { "SQLITE_OPEN_MAIN_DB", SQLITE_OPEN_MAIN_DB },
|
| + { "SQLITE_OPEN_TEMP_DB", SQLITE_OPEN_TEMP_DB },
|
| + { "SQLITE_OPEN_TRANSIENT_DB", SQLITE_OPEN_TRANSIENT_DB },
|
| + { "SQLITE_OPEN_MAIN_JOURNAL", SQLITE_OPEN_MAIN_JOURNAL },
|
| + { "SQLITE_OPEN_TEMP_JOURNAL", SQLITE_OPEN_TEMP_JOURNAL },
|
| + { "SQLITE_OPEN_SUBJOURNAL", SQLITE_OPEN_SUBJOURNAL },
|
| + { "SQLITE_OPEN_MASTER_JOURNAL", SQLITE_OPEN_MASTER_JOURNAL },
|
| + { "SQLITE_OPEN_NOMUTEX", SQLITE_OPEN_NOMUTEX },
|
| + { "SQLITE_OPEN_FULLMUTEX", SQLITE_OPEN_FULLMUTEX },
|
| + { "SQLITE_OPEN_SHAREDCACHE", SQLITE_OPEN_SHAREDCACHE },
|
| + { "SQLITE_OPEN_PRIVATECACHE", SQLITE_OPEN_PRIVATECACHE },
|
| + { "SQLITE_OPEN_WAL", SQLITE_OPEN_WAL },
|
| + { "SQLITE_OPEN_URI", SQLITE_OPEN_URI },
|
| + { 0, 0 }
|
| + };
|
| + rc = Tcl_GetIndexFromObjStruct(interp, apFlag[i], aFlag, sizeof(aFlag[0]),
|
| + "flag", 0, &iFlag
|
| + );
|
| + if( rc!=TCL_OK ) return rc;
|
| + flags |= aFlag[iFlag].flag;
|
| + }
|
| +
|
| + rc = sqlite3_open_v2(zFilename, &db, flags, zVfs);
|
| + if( sqlite3TestMakePointerStr(interp, zBuf, db) ) return TCL_ERROR;
|
| + Tcl_AppendResult(interp, zBuf, 0);
|
| + return TCL_OK;
|
| +}
|
| +
|
| +/*
|
| ** Usage: sqlite3_open16 filename options
|
| */
|
| static int test_open16(
|
| @@ -3830,7 +4024,6 @@ static int test_open16(
|
| #ifndef SQLITE_OMIT_UTF16
|
| const void *zFilename;
|
| sqlite3 *db;
|
| - int rc;
|
| char zBuf[100];
|
|
|
| if( objc!=3 ){
|
| @@ -3840,7 +4033,7 @@ static int test_open16(
|
| }
|
|
|
| zFilename = Tcl_GetByteArrayFromObj(objv[1], 0);
|
| - rc = sqlite3_open16(zFilename, &db);
|
| + sqlite3_open16(zFilename, &db);
|
|
|
| if( sqlite3TestMakePointerStr(interp, zBuf, db) ) return TCL_ERROR;
|
| Tcl_AppendResult(interp, zBuf, 0);
|
| @@ -4295,7 +4488,7 @@ static u8 *sqlite3_stack_baseline = 0;
|
| static void prepStack(void){
|
| int i;
|
| u32 bigBuf[65536];
|
| - for(i=0; i<sizeof(bigBuf); i++) bigBuf[i] = 0xdeadbeef;
|
| + for(i=0; i<sizeof(bigBuf)/sizeof(bigBuf[0]); i++) bigBuf[i] = 0xdeadbeef;
|
| sqlite3_stack_baseline = (u8*)&bigBuf[65536];
|
| }
|
|
|
| @@ -4433,7 +4626,7 @@ static int test_busy_timeout(
|
| 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);
|
| + Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
|
| return TCL_OK;
|
| }
|
|
|
| @@ -4493,6 +4686,78 @@ static int test_release_memory(
|
| return TCL_OK;
|
| }
|
|
|
| +
|
| +/*
|
| +** Usage: sqlite3_db_release_memory DB
|
| +**
|
| +** Attempt to release memory currently held by database DB. Return the
|
| +** result code (which in the current implementation is always zero).
|
| +*/
|
| +static int test_db_release_memory(
|
| + void * clientData,
|
| + Tcl_Interp *interp,
|
| + int objc,
|
| + Tcl_Obj *CONST objv[]
|
| +){
|
| + sqlite3 *db;
|
| + int rc;
|
| + if( objc!=2 ){
|
| + Tcl_WrongNumArgs(interp, 1, objv, "DB");
|
| + return TCL_ERROR;
|
| + }
|
| + if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
|
| + rc = sqlite3_db_release_memory(db);
|
| + Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
|
| + return TCL_OK;
|
| +}
|
| +
|
| +/*
|
| +** Usage: sqlite3_db_filename DB DBNAME
|
| +**
|
| +** Return the name of a file associated with a database.
|
| +*/
|
| +static int test_db_filename(
|
| + void * clientData,
|
| + Tcl_Interp *interp,
|
| + int objc,
|
| + Tcl_Obj *CONST objv[]
|
| +){
|
| + sqlite3 *db;
|
| + const char *zDbName;
|
| + if( objc!=3 ){
|
| + Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME");
|
| + return TCL_ERROR;
|
| + }
|
| + if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
|
| + zDbName = Tcl_GetString(objv[2]);
|
| + Tcl_AppendResult(interp, sqlite3_db_filename(db, zDbName), (void*)0);
|
| + return TCL_OK;
|
| +}
|
| +
|
| +/*
|
| +** Usage: sqlite3_db_readonly DB DBNAME
|
| +**
|
| +** Return 1 or 0 if DBNAME is readonly or not. Return -1 if DBNAME does
|
| +** not exist.
|
| +*/
|
| +static int test_db_readonly(
|
| + void * clientData,
|
| + Tcl_Interp *interp,
|
| + int objc,
|
| + Tcl_Obj *CONST objv[]
|
| +){
|
| + sqlite3 *db;
|
| + const char *zDbName;
|
| + if( objc!=3 ){
|
| + Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME");
|
| + return TCL_ERROR;
|
| + }
|
| + if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
|
| + zDbName = Tcl_GetString(objv[2]);
|
| + Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_db_readonly(db, zDbName)));
|
| + return TCL_OK;
|
| +}
|
| +
|
| /*
|
| ** Usage: sqlite3_soft_heap_limit ?N?
|
| **
|
| @@ -4507,7 +4772,7 @@ static int test_soft_heap_limit(
|
| Tcl_Obj *CONST objv[]
|
| ){
|
| sqlite3_int64 amt;
|
| - sqlite3_int64 N = -1;
|
| + Tcl_WideInt N = -1;
|
| if( objc!=1 && objc!=2 ){
|
| Tcl_WrongNumArgs(interp, 1, objv, "?N?");
|
| return TCL_ERROR;
|
| @@ -4882,7 +5147,7 @@ static int file_control_chunksize_test(
|
|
|
| rc = sqlite3_file_control(db, zDb, SQLITE_FCNTL_CHUNK_SIZE, (void *)&nSize);
|
| if( rc ){
|
| - Tcl_SetResult(interp, (char *)sqlite3TestErrorName(rc), TCL_STATIC);
|
| + Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_STATIC);
|
| return TCL_ERROR;
|
| }
|
| return TCL_OK;
|
| @@ -4891,9 +5156,8 @@ static int file_control_chunksize_test(
|
| /*
|
| ** tclcmd: file_control_sizehint_test DB DBNAME SIZE
|
| **
|
| -** This TCL command runs the sqlite3_file_control interface and
|
| -** verifies correct operation of the SQLITE_GET_LOCKPROXYFILE and
|
| -** SQLITE_SET_LOCKPROXYFILE verbs.
|
| +** This TCL command runs the sqlite3_file_control interface
|
| +** with SQLITE_FCNTL_SIZE_HINT
|
| */
|
| static int file_control_sizehint_test(
|
| ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
|
| @@ -4901,7 +5165,7 @@ static int file_control_sizehint_test(
|
| int objc, /* Number of arguments */
|
| Tcl_Obj *CONST objv[] /* Command arguments */
|
| ){
|
| - sqlite3_int64 nSize; /* Hinted size */
|
| + Tcl_WideInt nSize; /* Hinted size */
|
| char *zDb; /* Db name ("main", "temp" etc.) */
|
| sqlite3 *db; /* Database handle */
|
| int rc; /* file_control() return code */
|
| @@ -4920,7 +5184,7 @@ static int file_control_sizehint_test(
|
|
|
| rc = sqlite3_file_control(db, zDb, SQLITE_FCNTL_SIZE_HINT, (void *)&nSize);
|
| if( rc ){
|
| - Tcl_SetResult(interp, (char *)sqlite3TestErrorName(rc), TCL_STATIC);
|
| + Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_STATIC);
|
| return TCL_ERROR;
|
| }
|
| return TCL_OK;
|
| @@ -4940,8 +5204,6 @@ static int file_control_lockproxy_test(
|
| Tcl_Obj *CONST objv[] /* Command arguments */
|
| ){
|
| sqlite3 *db;
|
| - const char *zPwd;
|
| - int nPwd;
|
|
|
| if( objc!=3 ){
|
| Tcl_AppendResult(interp, "wrong # args: should be \"",
|
| @@ -4951,7 +5213,6 @@ static int file_control_lockproxy_test(
|
| if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
|
| return TCL_ERROR;
|
| }
|
| - zPwd = Tcl_GetStringFromObj(objv[2], &nPwd);
|
|
|
| #if !defined(SQLITE_ENABLE_LOCKING_STYLE)
|
| # if defined(__APPLE__)
|
| @@ -4964,8 +5225,11 @@ static int file_control_lockproxy_test(
|
| {
|
| char *testPath;
|
| int rc;
|
| + int nPwd;
|
| + const char *zPwd;
|
| char proxyPath[400];
|
|
|
| + zPwd = Tcl_GetStringFromObj(objv[2], &nPwd);
|
| if( sizeof(proxyPath)<nPwd+20 ){
|
| Tcl_AppendResult(interp, "PWD too big", (void*)0);
|
| return TCL_ERROR;
|
| @@ -4996,38 +5260,47 @@ static int file_control_lockproxy_test(
|
| return TCL_OK;
|
| }
|
|
|
| -
|
| +#if SQLITE_OS_WIN
|
| /*
|
| -** tclcmd: sqlite3_vfs_list
|
| +** tclcmd: file_control_win32_av_retry DB NRETRY DELAY
|
| **
|
| -** Return a tcl list containing the names of all registered vfs's.
|
| +** This TCL command runs the sqlite3_file_control interface with
|
| +** the SQLITE_FCNTL_WIN32_AV_RETRY opcode.
|
| */
|
| -static int vfs_list(
|
| +static int file_control_win32_av_retry(
|
| 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_vfs *pVfs;
|
| - Tcl_Obj *pRet = Tcl_NewObj();
|
| - if( objc!=1 ){
|
| - Tcl_WrongNumArgs(interp, 1, objv, "");
|
| + sqlite3 *db;
|
| + int rc;
|
| + int a[2];
|
| + char z[100];
|
| +
|
| + if( objc!=4 ){
|
| + Tcl_AppendResult(interp, "wrong # args: should be \"",
|
| + Tcl_GetStringFromObj(objv[0], 0), " DB NRETRY DELAY", 0);
|
| return TCL_ERROR;
|
| }
|
| - for(pVfs=sqlite3_vfs_find(0); pVfs; pVfs=pVfs->pNext){
|
| - Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj(pVfs->zName, -1));
|
| + if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
|
| + return TCL_ERROR;
|
| }
|
| - Tcl_SetObjResult(interp, pRet);
|
| + if( Tcl_GetIntFromObj(interp, objv[2], &a[0]) ) return TCL_ERROR;
|
| + if( Tcl_GetIntFromObj(interp, objv[3], &a[1]) ) return TCL_ERROR;
|
| + rc = sqlite3_file_control(db, NULL, SQLITE_FCNTL_WIN32_AV_RETRY, (void*)a);
|
| + sqlite3_snprintf(sizeof(z), z, "%d %d %d", rc, a[0], a[1]);
|
| + Tcl_AppendResult(interp, z, (char*)0);
|
| return TCL_OK;
|
| }
|
|
|
| /*
|
| -** tclcmd: sqlite3_limit DB ID VALUE
|
| +** tclcmd: file_control_win32_set_handle DB HANDLE
|
| **
|
| -** This TCL command runs the sqlite3_limit interface and
|
| -** verifies correct operation of the same.
|
| +** This TCL command runs the sqlite3_file_control interface with
|
| +** the SQLITE_FCNTL_WIN32_SET_HANDLE opcode.
|
| */
|
| -static int test_limit(
|
| +static int file_control_win32_set_handle(
|
| ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
|
| Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
|
| int objc, /* Number of arguments */
|
| @@ -5035,29 +5308,220 @@ static int test_limit(
|
| ){
|
| sqlite3 *db;
|
| int rc;
|
| - static const struct {
|
| - char *zName;
|
| - int id;
|
| - } aId[] = {
|
| - { "SQLITE_LIMIT_LENGTH", SQLITE_LIMIT_LENGTH },
|
| - { "SQLITE_LIMIT_SQL_LENGTH", SQLITE_LIMIT_SQL_LENGTH },
|
| - { "SQLITE_LIMIT_COLUMN", SQLITE_LIMIT_COLUMN },
|
| - { "SQLITE_LIMIT_EXPR_DEPTH", SQLITE_LIMIT_EXPR_DEPTH },
|
| - { "SQLITE_LIMIT_COMPOUND_SELECT", SQLITE_LIMIT_COMPOUND_SELECT },
|
| - { "SQLITE_LIMIT_VDBE_OP", SQLITE_LIMIT_VDBE_OP },
|
| - { "SQLITE_LIMIT_FUNCTION_ARG", SQLITE_LIMIT_FUNCTION_ARG },
|
| - { "SQLITE_LIMIT_ATTACHED", SQLITE_LIMIT_ATTACHED },
|
| - { "SQLITE_LIMIT_LIKE_PATTERN_LENGTH", SQLITE_LIMIT_LIKE_PATTERN_LENGTH },
|
| - { "SQLITE_LIMIT_VARIABLE_NUMBER", SQLITE_LIMIT_VARIABLE_NUMBER },
|
| - { "SQLITE_LIMIT_TRIGGER_DEPTH", SQLITE_LIMIT_TRIGGER_DEPTH },
|
| -
|
| - /* Out of range test cases */
|
| - { "SQLITE_LIMIT_TOOSMALL", -1, },
|
| - { "SQLITE_LIMIT_TOOBIG", SQLITE_LIMIT_TRIGGER_DEPTH+1 },
|
| - };
|
| - int i, id;
|
| - int val;
|
| - const char *zId;
|
| + HANDLE hFile = NULL;
|
| + char z[100];
|
| +
|
| + if( objc!=3 ){
|
| + Tcl_AppendResult(interp, "wrong # args: should be \"",
|
| + Tcl_GetStringFromObj(objv[0], 0), " DB HANDLE", 0);
|
| + return TCL_ERROR;
|
| + }
|
| + if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
|
| + return TCL_ERROR;
|
| + }
|
| + if( getWin32Handle(interp, Tcl_GetString(objv[2]), &hFile) ){
|
| + return TCL_ERROR;
|
| + }
|
| + rc = sqlite3_file_control(db, NULL, SQLITE_FCNTL_WIN32_SET_HANDLE,
|
| + (void*)&hFile);
|
| + sqlite3_snprintf(sizeof(z), z, "%d %p", rc, (void*)hFile);
|
| + Tcl_AppendResult(interp, z, (char*)0);
|
| + return TCL_OK;
|
| +}
|
| +#endif
|
| +
|
| +/*
|
| +** tclcmd: file_control_persist_wal DB PERSIST-FLAG
|
| +**
|
| +** This TCL command runs the sqlite3_file_control interface with
|
| +** the SQLITE_FCNTL_PERSIST_WAL opcode.
|
| +*/
|
| +static int file_control_persist_wal(
|
| + 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;
|
| + int rc;
|
| + int bPersist;
|
| + char z[100];
|
| +
|
| + if( objc!=3 ){
|
| + Tcl_AppendResult(interp, "wrong # args: should be \"",
|
| + Tcl_GetStringFromObj(objv[0], 0), " DB FLAG", 0);
|
| + return TCL_ERROR;
|
| + }
|
| + if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
|
| + return TCL_ERROR;
|
| + }
|
| + if( Tcl_GetIntFromObj(interp, objv[2], &bPersist) ) return TCL_ERROR;
|
| + rc = sqlite3_file_control(db, NULL, SQLITE_FCNTL_PERSIST_WAL, (void*)&bPersist);
|
| + sqlite3_snprintf(sizeof(z), z, "%d %d", rc, bPersist);
|
| + Tcl_AppendResult(interp, z, (char*)0);
|
| + return TCL_OK;
|
| +}
|
| +
|
| +/*
|
| +** tclcmd: file_control_powersafe_overwrite DB PSOW-FLAG
|
| +**
|
| +** This TCL command runs the sqlite3_file_control interface with
|
| +** the SQLITE_FCNTL_POWERSAFE_OVERWRITE opcode.
|
| +*/
|
| +static int file_control_powersafe_overwrite(
|
| + 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;
|
| + int rc;
|
| + int b;
|
| + char z[100];
|
| +
|
| + if( objc!=3 ){
|
| + Tcl_AppendResult(interp, "wrong # args: should be \"",
|
| + Tcl_GetStringFromObj(objv[0], 0), " DB FLAG", 0);
|
| + return TCL_ERROR;
|
| + }
|
| + if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
|
| + return TCL_ERROR;
|
| + }
|
| + if( Tcl_GetIntFromObj(interp, objv[2], &b) ) return TCL_ERROR;
|
| + rc = sqlite3_file_control(db,NULL,SQLITE_FCNTL_POWERSAFE_OVERWRITE,(void*)&b);
|
| + sqlite3_snprintf(sizeof(z), z, "%d %d", rc, b);
|
| + Tcl_AppendResult(interp, z, (char*)0);
|
| + return TCL_OK;
|
| +}
|
| +
|
| +
|
| +/*
|
| +** tclcmd: file_control_vfsname DB ?AUXDB?
|
| +**
|
| +** Return a string that describes the stack of VFSes.
|
| +*/
|
| +static int file_control_vfsname(
|
| + 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 *zDbName = "main";
|
| + char *zVfsName = 0;
|
| +
|
| + if( objc!=2 && objc!=3 ){
|
| + Tcl_AppendResult(interp, "wrong # args: should be \"",
|
| + Tcl_GetStringFromObj(objv[0], 0), " DB ?AUXDB?", 0);
|
| + return TCL_ERROR;
|
| + }
|
| + if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
|
| + return TCL_ERROR;
|
| + }
|
| + if( objc==3 ){
|
| + zDbName = Tcl_GetString(objv[2]);
|
| + }
|
| + sqlite3_file_control(db, zDbName, SQLITE_FCNTL_VFSNAME,(void*)&zVfsName);
|
| + Tcl_AppendResult(interp, zVfsName, (char*)0);
|
| + sqlite3_free(zVfsName);
|
| + return TCL_OK;
|
| +}
|
| +
|
| +/*
|
| +** tclcmd: file_control_tempfilename DB ?AUXDB?
|
| +**
|
| +** Return a string that is a temporary filename
|
| +*/
|
| +static int file_control_tempfilename(
|
| + 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 *zDbName = "main";
|
| + char *zTName = 0;
|
| +
|
| + if( objc!=2 && objc!=3 ){
|
| + Tcl_AppendResult(interp, "wrong # args: should be \"",
|
| + Tcl_GetStringFromObj(objv[0], 0), " DB ?AUXDB?", 0);
|
| + return TCL_ERROR;
|
| + }
|
| + if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
|
| + return TCL_ERROR;
|
| + }
|
| + if( objc==3 ){
|
| + zDbName = Tcl_GetString(objv[2]);
|
| + }
|
| + sqlite3_file_control(db, zDbName, SQLITE_FCNTL_TEMPFILENAME, (void*)&zTName);
|
| + Tcl_AppendResult(interp, zTName, (char*)0);
|
| + sqlite3_free(zTName);
|
| + return TCL_OK;
|
| +}
|
| +
|
| +
|
| +/*
|
| +** tclcmd: sqlite3_vfs_list
|
| +**
|
| +** Return a tcl list containing the names of all registered vfs's.
|
| +*/
|
| +static int vfs_list(
|
| + 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_vfs *pVfs;
|
| + Tcl_Obj *pRet = Tcl_NewObj();
|
| + if( objc!=1 ){
|
| + Tcl_WrongNumArgs(interp, 1, objv, "");
|
| + return TCL_ERROR;
|
| + }
|
| + for(pVfs=sqlite3_vfs_find(0); pVfs; pVfs=pVfs->pNext){
|
| + Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj(pVfs->zName, -1));
|
| + }
|
| + Tcl_SetObjResult(interp, pRet);
|
| + return TCL_OK;
|
| +}
|
| +
|
| +/*
|
| +** tclcmd: sqlite3_limit DB ID VALUE
|
| +**
|
| +** This TCL command runs the sqlite3_limit interface and
|
| +** verifies correct operation of the same.
|
| +*/
|
| +static int test_limit(
|
| + 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;
|
| + int rc;
|
| + static const struct {
|
| + char *zName;
|
| + int id;
|
| + } aId[] = {
|
| + { "SQLITE_LIMIT_LENGTH", SQLITE_LIMIT_LENGTH },
|
| + { "SQLITE_LIMIT_SQL_LENGTH", SQLITE_LIMIT_SQL_LENGTH },
|
| + { "SQLITE_LIMIT_COLUMN", SQLITE_LIMIT_COLUMN },
|
| + { "SQLITE_LIMIT_EXPR_DEPTH", SQLITE_LIMIT_EXPR_DEPTH },
|
| + { "SQLITE_LIMIT_COMPOUND_SELECT", SQLITE_LIMIT_COMPOUND_SELECT },
|
| + { "SQLITE_LIMIT_VDBE_OP", SQLITE_LIMIT_VDBE_OP },
|
| + { "SQLITE_LIMIT_FUNCTION_ARG", SQLITE_LIMIT_FUNCTION_ARG },
|
| + { "SQLITE_LIMIT_ATTACHED", SQLITE_LIMIT_ATTACHED },
|
| + { "SQLITE_LIMIT_LIKE_PATTERN_LENGTH", SQLITE_LIMIT_LIKE_PATTERN_LENGTH },
|
| + { "SQLITE_LIMIT_VARIABLE_NUMBER", SQLITE_LIMIT_VARIABLE_NUMBER },
|
| + { "SQLITE_LIMIT_TRIGGER_DEPTH", SQLITE_LIMIT_TRIGGER_DEPTH },
|
| + { "SQLITE_LIMIT_WORKER_THREADS", SQLITE_LIMIT_WORKER_THREADS },
|
| +
|
| + /* Out of range test cases */
|
| + { "SQLITE_LIMIT_TOOSMALL", -1, },
|
| + { "SQLITE_LIMIT_TOOBIG", SQLITE_LIMIT_WORKER_THREADS+1 },
|
| + };
|
| + int i, id;
|
| + int val;
|
| + const char *zId;
|
|
|
| if( objc!=4 ){
|
| Tcl_AppendResult(interp, "wrong # args: should be \"",
|
| @@ -5128,6 +5592,37 @@ static int reset_prng_state(
|
| }
|
|
|
| /*
|
| +** tclcmd: database_may_be_corrupt
|
| +**
|
| +** Indicate that database files might be corrupt. In other words, set the normal
|
| +** state of operation.
|
| +*/
|
| +static int database_may_be_corrupt(
|
| + 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_test_control(SQLITE_TESTCTRL_NEVER_CORRUPT, 0);
|
| + return TCL_OK;
|
| +}
|
| +/*
|
| +** tclcmd: database_never_corrupt
|
| +**
|
| +** Indicate that database files are always well-formed. This enables extra assert()
|
| +** statements that test conditions that are always true for well-formed databases.
|
| +*/
|
| +static int database_never_corrupt(
|
| + 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_test_control(SQLITE_TESTCTRL_NEVER_CORRUPT, 1);
|
| + return TCL_OK;
|
| +}
|
| +
|
| +/*
|
| ** tclcmd: pcache_stats
|
| */
|
| static int test_pcache_stats(
|
| @@ -5238,7 +5733,7 @@ static int test_wal_checkpoint(
|
| **
|
| ** Otherwise, this command returns a list of three integers. The first integer
|
| ** is 1 if SQLITE_BUSY was returned, or 0 otherwise. The following two integers
|
| -** are the values returned via the output paramaters by wal_checkpoint_v2() -
|
| +** are the values returned via the output parameters by wal_checkpoint_v2() -
|
| ** the number of frames in the log and the number of frames in the log
|
| ** that have been checkpointed.
|
| */
|
| @@ -5302,7 +5797,7 @@ static void xLogcallback(void *unused, int err, char *zMsg){
|
| Tcl_Obj *pNew = Tcl_DuplicateObj(logcallback.pObj);
|
| Tcl_IncrRefCount(pNew);
|
| Tcl_ListObjAppendElement(
|
| - 0, pNew, Tcl_NewStringObj(sqlite3TestErrorName(err), -1)
|
| + 0, pNew, Tcl_NewStringObj(sqlite3ErrName(err), -1)
|
| );
|
| Tcl_ListObjAppendElement(0, pNew, Tcl_NewStringObj(zMsg, -1));
|
| Tcl_EvalObjEx(logcallback.pInterp, pNew, TCL_EVAL_GLOBAL|TCL_EVAL_DIRECT);
|
| @@ -5417,91 +5912,740 @@ static int test_print_eqp(
|
| }
|
| if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
|
| rc = printExplainQueryPlan(pStmt);
|
| + /* This is needed on Windows so that a test case using this
|
| + ** function can open a read pipe and get the output of
|
| + ** printExplainQueryPlan() immediately.
|
| + */
|
| + fflush(stdout);
|
| Tcl_SetResult(interp, (char *)t1ErrorName(rc), 0);
|
| return TCL_OK;
|
| }
|
| #endif /* SQLITE_OMIT_EXPLAIN */
|
|
|
| /*
|
| -** optimization_control DB OPT BOOLEAN
|
| -**
|
| -** Enable or disable query optimizations using the sqlite3_test_control()
|
| -** interface. Disable if BOOLEAN is false and enable if BOOLEAN is true.
|
| -** OPT is the name of the optimization to be disabled.
|
| +** sqlite3_test_control VERB ARGS...
|
| */
|
| -static int optimization_control(
|
| +static int test_test_control(
|
| void * clientData,
|
| Tcl_Interp *interp,
|
| int objc,
|
| Tcl_Obj *CONST objv[]
|
| ){
|
| - int i;
|
| - sqlite3 *db;
|
| - const char *zOpt;
|
| - int onoff;
|
| - int mask;
|
| - static const struct {
|
| - const char *zOptName;
|
| - int mask;
|
| - } aOpt[] = {
|
| - { "all", SQLITE_OptMask },
|
| - { "query-flattener", SQLITE_QueryFlattener },
|
| - { "column-cache", SQLITE_ColumnCache },
|
| - { "index-sort", SQLITE_IndexSort },
|
| - { "index-search", SQLITE_IndexSearch },
|
| - { "index-cover", SQLITE_IndexCover },
|
| - { "groupby-order", SQLITE_GroupByOrder },
|
| - { "factor-constants", SQLITE_FactorOutConst },
|
| + struct Verb {
|
| + const char *zName;
|
| + int i;
|
| + } aVerb[] = {
|
| + { "SQLITE_TESTCTRL_LOCALTIME_FAULT", SQLITE_TESTCTRL_LOCALTIME_FAULT },
|
| + { "SQLITE_TESTCTRL_SORTER_MMAP", SQLITE_TESTCTRL_SORTER_MMAP },
|
| };
|
| + int iVerb;
|
| + int iFlag;
|
| + int rc;
|
|
|
| - if( objc!=4 ){
|
| - Tcl_WrongNumArgs(interp, 1, objv, "DB OPT BOOLEAN");
|
| + if( objc<2 ){
|
| + Tcl_WrongNumArgs(interp, 1, objv, "VERB ARGS...");
|
| return TCL_ERROR;
|
| }
|
| - if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
|
| - if( Tcl_GetBooleanFromObj(interp, objv[3], &onoff) ) return TCL_ERROR;
|
| - zOpt = Tcl_GetString(objv[2]);
|
| - for(i=0; i<sizeof(aOpt)/sizeof(aOpt[0]); i++){
|
| - if( strcmp(zOpt, aOpt[i].zOptName)==0 ){
|
| - mask = aOpt[i].mask;
|
| +
|
| + rc = Tcl_GetIndexFromObjStruct(
|
| + interp, objv[1], aVerb, sizeof(aVerb[0]), "VERB", 0, &iVerb
|
| + );
|
| + if( rc!=TCL_OK ) return rc;
|
| +
|
| + iFlag = aVerb[iVerb].i;
|
| + switch( iFlag ){
|
| + case SQLITE_TESTCTRL_LOCALTIME_FAULT: {
|
| + int val;
|
| + if( objc!=3 ){
|
| + Tcl_WrongNumArgs(interp, 2, objv, "ONOFF");
|
| + return TCL_ERROR;
|
| + }
|
| + if( Tcl_GetBooleanFromObj(interp, objv[2], &val) ) return TCL_ERROR;
|
| + sqlite3_test_control(SQLITE_TESTCTRL_LOCALTIME_FAULT, val);
|
| break;
|
| }
|
| - }
|
| - if( onoff ) mask = ~mask;
|
| - if( i>=sizeof(aOpt)/sizeof(aOpt[0]) ){
|
| - Tcl_AppendResult(interp, "unknown optimization - should be one of:",
|
| - (char*)0);
|
| - for(i=0; i<sizeof(aOpt)/sizeof(aOpt[0]); i++){
|
| - Tcl_AppendResult(interp, " ", aOpt[i].zOptName);
|
| +
|
| + case SQLITE_TESTCTRL_SORTER_MMAP: {
|
| + int val;
|
| + sqlite3 *db;
|
| + if( objc!=4 ){
|
| + Tcl_WrongNumArgs(interp, 2, objv, "DB LIMIT");
|
| + return TCL_ERROR;
|
| + }
|
| + if( getDbPointer(interp, Tcl_GetString(objv[2]), &db) ) return TCL_ERROR;
|
| + if( Tcl_GetIntFromObj(interp, objv[3], &val) ) return TCL_ERROR;
|
| + sqlite3_test_control(SQLITE_TESTCTRL_SORTER_MMAP, db, val);
|
| + break;
|
| }
|
| - return TCL_ERROR;
|
| }
|
| - sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS, db, mask);
|
| +
|
| + Tcl_ResetResult(interp);
|
| + return TCL_OK;
|
| +}
|
| +
|
| +#if SQLITE_OS_UNIX
|
| +#include <sys/time.h>
|
| +#include <sys/resource.h>
|
| +
|
| +static int test_getrusage(
|
| + void * clientData,
|
| + Tcl_Interp *interp,
|
| + int objc,
|
| + Tcl_Obj *CONST objv[]
|
| +){
|
| + char buf[1024];
|
| + struct rusage r;
|
| + memset(&r, 0, sizeof(r));
|
| + getrusage(RUSAGE_SELF, &r);
|
| +
|
| + sprintf(buf, "ru_utime=%d.%06d ru_stime=%d.%06d ru_minflt=%d ru_majflt=%d",
|
| + (int)r.ru_utime.tv_sec, (int)r.ru_utime.tv_usec,
|
| + (int)r.ru_stime.tv_sec, (int)r.ru_stime.tv_usec,
|
| + (int)r.ru_minflt, (int)r.ru_majflt
|
| + );
|
| + Tcl_SetObjResult(interp, Tcl_NewStringObj(buf, -1));
|
| return TCL_OK;
|
| }
|
| +#endif
|
|
|
| +#if SQLITE_OS_WIN
|
| /*
|
| -** Register commands with the TCL interpreter.
|
| +** Information passed from the main thread into the windows file locker
|
| +** background thread.
|
| */
|
| -int Sqlitetest1_Init(Tcl_Interp *interp){
|
| - extern int sqlite3_search_count;
|
| - extern int sqlite3_found_count;
|
| - extern int sqlite3_interrupt_count;
|
| - extern int sqlite3_open_file_count;
|
| - extern int sqlite3_sort_count;
|
| - extern int sqlite3_current_time;
|
| -#if SQLITE_OS_UNIX && defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
|
| - extern int sqlite3_hostid_num;
|
| +struct win32FileLocker {
|
| + char *evName; /* Name of event to signal thread startup */
|
| + HANDLE h; /* Handle of the file to be locked */
|
| + int delay1; /* Delay before locking */
|
| + int delay2; /* Delay before unlocking */
|
| + int ok; /* Finished ok */
|
| + int err; /* True if an error occurs */
|
| +};
|
| #endif
|
| - extern int sqlite3_max_blobsize;
|
| - extern int sqlite3BtreeSharedCacheReport(void*,
|
| - Tcl_Interp*,int,Tcl_Obj*CONST*);
|
| - static struct {
|
| - char *zName;
|
| - Tcl_CmdProc *xProc;
|
| - } aCmd[] = {
|
| - { "db_enter", (Tcl_CmdProc*)db_enter },
|
| - { "db_leave", (Tcl_CmdProc*)db_leave },
|
| +
|
| +
|
| +#if SQLITE_OS_WIN
|
| +#include <process.h>
|
| +/*
|
| +** The background thread that does file locking.
|
| +*/
|
| +static void win32_file_locker(void *pAppData){
|
| + struct win32FileLocker *p = (struct win32FileLocker*)pAppData;
|
| + if( p->evName ){
|
| + HANDLE ev = OpenEvent(EVENT_MODIFY_STATE, FALSE, p->evName);
|
| + if ( ev ){
|
| + SetEvent(ev);
|
| + CloseHandle(ev);
|
| + }
|
| + }
|
| + if( p->delay1 ) Sleep(p->delay1);
|
| + if( LockFile(p->h, 0, 0, 100000000, 0) ){
|
| + Sleep(p->delay2);
|
| + UnlockFile(p->h, 0, 0, 100000000, 0);
|
| + p->ok = 1;
|
| + }else{
|
| + p->err = 1;
|
| + }
|
| + CloseHandle(p->h);
|
| + p->h = 0;
|
| + p->delay1 = 0;
|
| + p->delay2 = 0;
|
| +}
|
| +#endif
|
| +
|
| +#if SQLITE_OS_WIN
|
| +/*
|
| +** lock_win32_file FILENAME DELAY1 DELAY2
|
| +**
|
| +** Get an exclusive manditory lock on file for DELAY2 milliseconds.
|
| +** Wait DELAY1 milliseconds before acquiring the lock.
|
| +*/
|
| +static int win32_file_lock(
|
| + void * clientData,
|
| + Tcl_Interp *interp,
|
| + int objc,
|
| + Tcl_Obj *CONST objv[]
|
| +){
|
| + static struct win32FileLocker x = { "win32_file_lock", 0, 0, 0, 0, 0 };
|
| + const char *zFilename;
|
| + char zBuf[200];
|
| + int retry = 0;
|
| + HANDLE ev;
|
| + DWORD wResult;
|
| +
|
| + if( objc!=4 && objc!=1 ){
|
| + Tcl_WrongNumArgs(interp, 1, objv, "FILENAME DELAY1 DELAY2");
|
| + return TCL_ERROR;
|
| + }
|
| + if( objc==1 ){
|
| + sqlite3_snprintf(sizeof(zBuf), zBuf, "%d %d %d %d %d",
|
| + x.ok, x.err, x.delay1, x.delay2, x.h);
|
| + Tcl_AppendResult(interp, zBuf, (char*)0);
|
| + return TCL_OK;
|
| + }
|
| + while( x.h && retry<30 ){
|
| + retry++;
|
| + Sleep(100);
|
| + }
|
| + if( x.h ){
|
| + Tcl_AppendResult(interp, "busy", (char*)0);
|
| + return TCL_ERROR;
|
| + }
|
| + if( Tcl_GetIntFromObj(interp, objv[2], &x.delay1) ) return TCL_ERROR;
|
| + if( Tcl_GetIntFromObj(interp, objv[3], &x.delay2) ) return TCL_ERROR;
|
| + zFilename = Tcl_GetString(objv[1]);
|
| + x.h = CreateFile(zFilename, GENERIC_READ|GENERIC_WRITE,
|
| + FILE_SHARE_READ|FILE_SHARE_WRITE, 0, OPEN_ALWAYS,
|
| + FILE_ATTRIBUTE_NORMAL, 0);
|
| + if( !x.h ){
|
| + Tcl_AppendResult(interp, "cannot open file: ", zFilename, (char*)0);
|
| + return TCL_ERROR;
|
| + }
|
| + ev = CreateEvent(NULL, TRUE, FALSE, x.evName);
|
| + if ( !ev ){
|
| + Tcl_AppendResult(interp, "cannot create event: ", x.evName, (char*)0);
|
| + return TCL_ERROR;
|
| + }
|
| + _beginthread(win32_file_locker, 0, (void*)&x);
|
| + Sleep(0);
|
| + if ( (wResult = WaitForSingleObject(ev, 10000))!=WAIT_OBJECT_0 ){
|
| + sqlite3_snprintf(sizeof(zBuf), zBuf, "0x%x", wResult);
|
| + Tcl_AppendResult(interp, "wait failed: ", zBuf, (char*)0);
|
| + CloseHandle(ev);
|
| + return TCL_ERROR;
|
| + }
|
| + CloseHandle(ev);
|
| + return TCL_OK;
|
| +}
|
| +
|
| +/*
|
| +** exists_win32_path PATH
|
| +**
|
| +** Returns non-zero if the specified path exists, whose fully qualified name
|
| +** may exceed 260 characters if it is prefixed with "\\?\".
|
| +*/
|
| +static int win32_exists_path(
|
| + void *clientData,
|
| + Tcl_Interp *interp,
|
| + int objc,
|
| + Tcl_Obj *CONST objv[]
|
| +){
|
| + if( objc!=2 ){
|
| + Tcl_WrongNumArgs(interp, 1, objv, "PATH");
|
| + return TCL_ERROR;
|
| + }
|
| + Tcl_SetObjResult(interp, Tcl_NewBooleanObj(
|
| + GetFileAttributesW( Tcl_GetUnicode(objv[1]))!=INVALID_FILE_ATTRIBUTES ));
|
| + return TCL_OK;
|
| +}
|
| +
|
| +/*
|
| +** find_win32_file PATTERN
|
| +**
|
| +** Returns a list of entries in a directory that match the specified pattern,
|
| +** whose fully qualified name may exceed 248 characters if it is prefixed with
|
| +** "\\?\".
|
| +*/
|
| +static int win32_find_file(
|
| + void *clientData,
|
| + Tcl_Interp *interp,
|
| + int objc,
|
| + Tcl_Obj *CONST objv[]
|
| +){
|
| + HANDLE hFindFile = INVALID_HANDLE_VALUE;
|
| + WIN32_FIND_DATAW findData;
|
| + Tcl_Obj *listObj;
|
| + DWORD lastErrno;
|
| + if( objc!=2 ){
|
| + Tcl_WrongNumArgs(interp, 1, objv, "PATTERN");
|
| + return TCL_ERROR;
|
| + }
|
| + hFindFile = FindFirstFileW(Tcl_GetUnicode(objv[1]), &findData);
|
| + if( hFindFile==INVALID_HANDLE_VALUE ){
|
| + Tcl_SetObjResult(interp, Tcl_NewWideIntObj(GetLastError()));
|
| + return TCL_ERROR;
|
| + }
|
| + listObj = Tcl_NewObj();
|
| + Tcl_IncrRefCount(listObj);
|
| + do {
|
| + Tcl_ListObjAppendElement(interp, listObj, Tcl_NewUnicodeObj(
|
| + findData.cFileName, -1));
|
| + Tcl_ListObjAppendElement(interp, listObj, Tcl_NewWideIntObj(
|
| + findData.dwFileAttributes));
|
| + } while( FindNextFileW(hFindFile, &findData) );
|
| + lastErrno = GetLastError();
|
| + if( lastErrno!=NO_ERROR && lastErrno!=ERROR_NO_MORE_FILES ){
|
| + FindClose(hFindFile);
|
| + Tcl_DecrRefCount(listObj);
|
| + Tcl_SetObjResult(interp, Tcl_NewWideIntObj(GetLastError()));
|
| + return TCL_ERROR;
|
| + }
|
| + FindClose(hFindFile);
|
| + Tcl_SetObjResult(interp, listObj);
|
| + return TCL_OK;
|
| +}
|
| +
|
| +/*
|
| +** delete_win32_file FILENAME
|
| +**
|
| +** Deletes the specified file, whose fully qualified name may exceed 260
|
| +** characters if it is prefixed with "\\?\".
|
| +*/
|
| +static int win32_delete_file(
|
| + void *clientData,
|
| + Tcl_Interp *interp,
|
| + int objc,
|
| + Tcl_Obj *CONST objv[]
|
| +){
|
| + if( objc!=2 ){
|
| + Tcl_WrongNumArgs(interp, 1, objv, "FILENAME");
|
| + return TCL_ERROR;
|
| + }
|
| + if( !DeleteFileW(Tcl_GetUnicode(objv[1])) ){
|
| + Tcl_SetObjResult(interp, Tcl_NewWideIntObj(GetLastError()));
|
| + return TCL_ERROR;
|
| + }
|
| + Tcl_ResetResult(interp);
|
| + return TCL_OK;
|
| +}
|
| +
|
| +/*
|
| +** make_win32_dir DIRECTORY
|
| +**
|
| +** Creates the specified directory, whose fully qualified name may exceed 248
|
| +** characters if it is prefixed with "\\?\".
|
| +*/
|
| +static int win32_mkdir(
|
| + void *clientData,
|
| + Tcl_Interp *interp,
|
| + int objc,
|
| + Tcl_Obj *CONST objv[]
|
| +){
|
| + if( objc!=2 ){
|
| + Tcl_WrongNumArgs(interp, 1, objv, "DIRECTORY");
|
| + return TCL_ERROR;
|
| + }
|
| + if( !CreateDirectoryW(Tcl_GetUnicode(objv[1]), NULL) ){
|
| + Tcl_SetObjResult(interp, Tcl_NewWideIntObj(GetLastError()));
|
| + return TCL_ERROR;
|
| + }
|
| + Tcl_ResetResult(interp);
|
| + return TCL_OK;
|
| +}
|
| +
|
| +/*
|
| +** remove_win32_dir DIRECTORY
|
| +**
|
| +** Removes the specified directory, whose fully qualified name may exceed 248
|
| +** characters if it is prefixed with "\\?\".
|
| +*/
|
| +static int win32_rmdir(
|
| + void *clientData,
|
| + Tcl_Interp *interp,
|
| + int objc,
|
| + Tcl_Obj *CONST objv[]
|
| +){
|
| + if( objc!=2 ){
|
| + Tcl_WrongNumArgs(interp, 1, objv, "DIRECTORY");
|
| + return TCL_ERROR;
|
| + }
|
| + if( !RemoveDirectoryW(Tcl_GetUnicode(objv[1])) ){
|
| + Tcl_SetObjResult(interp, Tcl_NewWideIntObj(GetLastError()));
|
| + return TCL_ERROR;
|
| + }
|
| + Tcl_ResetResult(interp);
|
| + return TCL_OK;
|
| +}
|
| +#endif
|
| +
|
| +
|
| +/*
|
| +** optimization_control DB OPT BOOLEAN
|
| +**
|
| +** Enable or disable query optimizations using the sqlite3_test_control()
|
| +** interface. Disable if BOOLEAN is false and enable if BOOLEAN is true.
|
| +** OPT is the name of the optimization to be disabled.
|
| +*/
|
| +static int optimization_control(
|
| + void * clientData,
|
| + Tcl_Interp *interp,
|
| + int objc,
|
| + Tcl_Obj *CONST objv[]
|
| +){
|
| + int i;
|
| + sqlite3 *db;
|
| + const char *zOpt;
|
| + int onoff;
|
| + int mask = 0;
|
| + static const struct {
|
| + const char *zOptName;
|
| + int mask;
|
| + } aOpt[] = {
|
| + { "all", SQLITE_AllOpts },
|
| + { "none", 0 },
|
| + { "query-flattener", SQLITE_QueryFlattener },
|
| + { "column-cache", SQLITE_ColumnCache },
|
| + { "groupby-order", SQLITE_GroupByOrder },
|
| + { "factor-constants", SQLITE_FactorOutConst },
|
| + { "distinct-opt", SQLITE_DistinctOpt },
|
| + { "cover-idx-scan", SQLITE_CoverIdxScan },
|
| + { "order-by-idx-join", SQLITE_OrderByIdxJoin },
|
| + { "transitive", SQLITE_Transitive },
|
| + { "subquery-coroutine", SQLITE_SubqCoroutine },
|
| + { "omit-noop-join", SQLITE_OmitNoopJoin },
|
| + { "stat3", SQLITE_Stat3 },
|
| + };
|
| +
|
| + if( objc!=4 ){
|
| + Tcl_WrongNumArgs(interp, 1, objv, "DB OPT BOOLEAN");
|
| + return TCL_ERROR;
|
| + }
|
| + if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
|
| + if( Tcl_GetBooleanFromObj(interp, objv[3], &onoff) ) return TCL_ERROR;
|
| + zOpt = Tcl_GetString(objv[2]);
|
| + for(i=0; i<sizeof(aOpt)/sizeof(aOpt[0]); i++){
|
| + if( strcmp(zOpt, aOpt[i].zOptName)==0 ){
|
| + mask = aOpt[i].mask;
|
| + break;
|
| + }
|
| + }
|
| + if( onoff ) mask = ~mask;
|
| + if( i>=sizeof(aOpt)/sizeof(aOpt[0]) ){
|
| + Tcl_AppendResult(interp, "unknown optimization - should be one of:",
|
| + (char*)0);
|
| + for(i=0; i<sizeof(aOpt)/sizeof(aOpt[0]); i++){
|
| + Tcl_AppendResult(interp, " ", aOpt[i].zOptName, (char*)0);
|
| + }
|
| + return TCL_ERROR;
|
| + }
|
| + sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS, db, mask);
|
| + return TCL_OK;
|
| +}
|
| +
|
| +typedef struct sqlite3_api_routines sqlite3_api_routines;
|
| +/*
|
| +** load_static_extension DB NAME ...
|
| +**
|
| +** Load one or more statically linked extensions.
|
| +*/
|
| +static int tclLoadStaticExtensionCmd(
|
| + void * clientData,
|
| + Tcl_Interp *interp,
|
| + int objc,
|
| + Tcl_Obj *CONST objv[]
|
| +){
|
| + extern int sqlite3_amatch_init(sqlite3*,char**,const sqlite3_api_routines*);
|
| + extern int sqlite3_closure_init(sqlite3*,char**,const sqlite3_api_routines*);
|
| + extern int sqlite3_fileio_init(sqlite3*,char**,const sqlite3_api_routines*);
|
| + extern int sqlite3_fuzzer_init(sqlite3*,char**,const sqlite3_api_routines*);
|
| + extern int sqlite3_ieee_init(sqlite3*,char**,const sqlite3_api_routines*);
|
| + extern int sqlite3_nextchar_init(sqlite3*,char**,const sqlite3_api_routines*);
|
| + extern int sqlite3_percentile_init(sqlite3*,char**,const sqlite3_api_routines*);
|
| + extern int sqlite3_regexp_init(sqlite3*,char**,const sqlite3_api_routines*);
|
| + extern int sqlite3_spellfix_init(sqlite3*,char**,const sqlite3_api_routines*);
|
| + extern int sqlite3_totype_init(sqlite3*,char**,const sqlite3_api_routines*);
|
| + extern int sqlite3_wholenumber_init(sqlite3*,char**,const sqlite3_api_routines*);
|
| + static const struct {
|
| + const char *zExtName;
|
| + int (*pInit)(sqlite3*,char**,const sqlite3_api_routines*);
|
| + } aExtension[] = {
|
| + { "amatch", sqlite3_amatch_init },
|
| + { "closure", sqlite3_closure_init },
|
| + { "fileio", sqlite3_fileio_init },
|
| + { "fuzzer", sqlite3_fuzzer_init },
|
| + { "ieee754", sqlite3_ieee_init },
|
| + { "nextchar", sqlite3_nextchar_init },
|
| + { "percentile", sqlite3_percentile_init },
|
| + { "regexp", sqlite3_regexp_init },
|
| + { "spellfix", sqlite3_spellfix_init },
|
| + { "totype", sqlite3_totype_init },
|
| + { "wholenumber", sqlite3_wholenumber_init },
|
| + };
|
| + sqlite3 *db;
|
| + const char *zName;
|
| + int i, j, rc;
|
| + char *zErrMsg = 0;
|
| + if( objc<3 ){
|
| + Tcl_WrongNumArgs(interp, 1, objv, "DB NAME ...");
|
| + return TCL_ERROR;
|
| + }
|
| + if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
|
| + for(j=2; j<objc; j++){
|
| + zName = Tcl_GetString(objv[j]);
|
| + for(i=0; i<ArraySize(aExtension); i++){
|
| + if( strcmp(zName, aExtension[i].zExtName)==0 ) break;
|
| + }
|
| + if( i>=ArraySize(aExtension) ){
|
| + Tcl_AppendResult(interp, "no such extension: ", zName, (char*)0);
|
| + return TCL_ERROR;
|
| + }
|
| + rc = aExtension[i].pInit(db, &zErrMsg, 0);
|
| + if( rc!=SQLITE_OK || zErrMsg ){
|
| + Tcl_AppendResult(interp, "initialization of ", zName, " failed: ", zErrMsg,
|
| + (char*)0);
|
| + sqlite3_free(zErrMsg);
|
| + return TCL_ERROR;
|
| + }
|
| + }
|
| + return TCL_OK;
|
| +}
|
| +
|
| +/*
|
| +** sorter_test_fakeheap BOOL
|
| +**
|
| +*/
|
| +static int sorter_test_fakeheap(
|
| + void * clientData,
|
| + Tcl_Interp *interp,
|
| + int objc,
|
| + Tcl_Obj *CONST objv[]
|
| +){
|
| + int bArg;
|
| + if( objc!=2 ){
|
| + Tcl_WrongNumArgs(interp, 1, objv, "BOOL");
|
| + return TCL_ERROR;
|
| + }
|
| +
|
| + if( Tcl_GetBooleanFromObj(interp, objv[1], &bArg) ){
|
| + return TCL_ERROR;
|
| + }
|
| +
|
| + if( bArg ){
|
| + if( sqlite3GlobalConfig.pHeap==0 ){
|
| + sqlite3GlobalConfig.pHeap = SQLITE_INT_TO_PTR(-1);
|
| + }
|
| + }else{
|
| + if( sqlite3GlobalConfig.pHeap==SQLITE_INT_TO_PTR(-1) ){
|
| + sqlite3GlobalConfig.pHeap = 0;
|
| + }
|
| + }
|
| +
|
| + Tcl_ResetResult(interp);
|
| + return TCL_OK;
|
| +}
|
| +
|
| +/*
|
| +** sorter_test_sort4_helper DB SQL1 NSTEP SQL2
|
| +**
|
| +** Compile SQL statement $SQL1 and step it $NSTEP times. For each row,
|
| +** check that the leftmost and rightmost columns returned are both integers,
|
| +** and that both contain the same value.
|
| +**
|
| +** Then execute statement $SQL2. Check that the statement returns the same
|
| +** set of integers in the same order as in the previous step (using $SQL1).
|
| +*/
|
| +static int sorter_test_sort4_helper(
|
| + void * clientData,
|
| + Tcl_Interp *interp,
|
| + int objc,
|
| + Tcl_Obj *CONST objv[]
|
| +){
|
| + const char *zSql1;
|
| + const char *zSql2;
|
| + int nStep;
|
| + int iStep;
|
| + int iCksum1 = 0;
|
| + int iCksum2 = 0;
|
| + int rc;
|
| + int iB;
|
| + sqlite3 *db;
|
| + sqlite3_stmt *pStmt;
|
| +
|
| + if( objc!=5 ){
|
| + Tcl_WrongNumArgs(interp, 1, objv, "DB SQL1 NSTEP SQL2");
|
| + return TCL_ERROR;
|
| + }
|
| +
|
| + if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
|
| + zSql1 = Tcl_GetString(objv[2]);
|
| + if( Tcl_GetIntFromObj(interp, objv[3], &nStep) ) return TCL_ERROR;
|
| + zSql2 = Tcl_GetString(objv[4]);
|
| +
|
| + rc = sqlite3_prepare_v2(db, zSql1, -1, &pStmt, 0);
|
| + if( rc!=SQLITE_OK ) goto sql_error;
|
| +
|
| + iB = sqlite3_column_count(pStmt)-1;
|
| + for(iStep=0; iStep<nStep && SQLITE_ROW==sqlite3_step(pStmt); iStep++){
|
| + int a = sqlite3_column_int(pStmt, 0);
|
| + if( a!=sqlite3_column_int(pStmt, iB) ){
|
| + Tcl_AppendResult(interp, "data error: (a!=b)", 0);
|
| + return TCL_ERROR;
|
| + }
|
| +
|
| + iCksum1 += (iCksum1 << 3) + a;
|
| + }
|
| + rc = sqlite3_finalize(pStmt);
|
| + if( rc!=SQLITE_OK ) goto sql_error;
|
| +
|
| + rc = sqlite3_prepare_v2(db, zSql2, -1, &pStmt, 0);
|
| + if( rc!=SQLITE_OK ) goto sql_error;
|
| + for(iStep=0; SQLITE_ROW==sqlite3_step(pStmt); iStep++){
|
| + int a = sqlite3_column_int(pStmt, 0);
|
| + iCksum2 += (iCksum2 << 3) + a;
|
| + }
|
| + rc = sqlite3_finalize(pStmt);
|
| + if( rc!=SQLITE_OK ) goto sql_error;
|
| +
|
| + if( iCksum1!=iCksum2 ){
|
| + Tcl_AppendResult(interp, "checksum mismatch", 0);
|
| + return TCL_ERROR;
|
| + }
|
| +
|
| + return TCL_OK;
|
| + sql_error:
|
| + Tcl_AppendResult(interp, "sql error: ", sqlite3_errmsg(db), 0);
|
| + return TCL_ERROR;
|
| +}
|
| +
|
| +
|
| +#ifdef SQLITE_USER_AUTHENTICATION
|
| +#include "sqlite3userauth.h"
|
| +/*
|
| +** tclcmd: sqlite3_user_authenticate DB USERNAME PASSWORD
|
| +*/
|
| +static int test_user_authenticate(
|
| + ClientData clientData, /* Unused */
|
| + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
|
| + int objc, /* Number of arguments */
|
| + Tcl_Obj *CONST objv[] /* Command arguments */
|
| +){
|
| + char *zUser = 0;
|
| + char *zPasswd = 0;
|
| + int nPasswd = 0;
|
| + sqlite3 *db;
|
| + int rc;
|
| +
|
| + if( objc!=4 ){
|
| + Tcl_WrongNumArgs(interp, 1, objv, "DB USERNAME PASSWORD");
|
| + return TCL_ERROR;
|
| + }
|
| + if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
|
| + return TCL_ERROR;
|
| + }
|
| + zUser = Tcl_GetString(objv[2]);
|
| + zPasswd = Tcl_GetStringFromObj(objv[3], &nPasswd);
|
| + rc = sqlite3_user_authenticate(db, zUser, zPasswd, nPasswd);
|
| + Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
|
| + return TCL_OK;
|
| +}
|
| +#endif /* SQLITE_USER_AUTHENTICATION */
|
| +
|
| +#ifdef SQLITE_USER_AUTHENTICATION
|
| +/*
|
| +** tclcmd: sqlite3_user_add DB USERNAME PASSWORD ISADMIN
|
| +*/
|
| +static int test_user_add(
|
| + ClientData clientData, /* Unused */
|
| + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
|
| + int objc, /* Number of arguments */
|
| + Tcl_Obj *CONST objv[] /* Command arguments */
|
| +){
|
| + char *zUser = 0;
|
| + char *zPasswd = 0;
|
| + int nPasswd = 0;
|
| + int isAdmin = 0;
|
| + sqlite3 *db;
|
| + int rc;
|
| +
|
| + if( objc!=5 ){
|
| + Tcl_WrongNumArgs(interp, 1, objv, "DB USERNAME PASSWORD ISADMIN");
|
| + return TCL_ERROR;
|
| + }
|
| + if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
|
| + return TCL_ERROR;
|
| + }
|
| + zUser = Tcl_GetString(objv[2]);
|
| + zPasswd = Tcl_GetStringFromObj(objv[3], &nPasswd);
|
| + Tcl_GetBooleanFromObj(interp, objv[4], &isAdmin);
|
| + rc = sqlite3_user_add(db, zUser, zPasswd, nPasswd, isAdmin);
|
| + Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
|
| + return TCL_OK;
|
| +}
|
| +#endif /* SQLITE_USER_AUTHENTICATION */
|
| +
|
| +#ifdef SQLITE_USER_AUTHENTICATION
|
| +/*
|
| +** tclcmd: sqlite3_user_change DB USERNAME PASSWORD ISADMIN
|
| +*/
|
| +static int test_user_change(
|
| + ClientData clientData, /* Unused */
|
| + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
|
| + int objc, /* Number of arguments */
|
| + Tcl_Obj *CONST objv[] /* Command arguments */
|
| +){
|
| + char *zUser = 0;
|
| + char *zPasswd = 0;
|
| + int nPasswd = 0;
|
| + int isAdmin = 0;
|
| + sqlite3 *db;
|
| + int rc;
|
| +
|
| + if( objc!=5 ){
|
| + Tcl_WrongNumArgs(interp, 1, objv, "DB USERNAME PASSWORD ISADMIN");
|
| + return TCL_ERROR;
|
| + }
|
| + if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
|
| + return TCL_ERROR;
|
| + }
|
| + zUser = Tcl_GetString(objv[2]);
|
| + zPasswd = Tcl_GetStringFromObj(objv[3], &nPasswd);
|
| + Tcl_GetBooleanFromObj(interp, objv[4], &isAdmin);
|
| + rc = sqlite3_user_change(db, zUser, zPasswd, nPasswd, isAdmin);
|
| + Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
|
| + return TCL_OK;
|
| +}
|
| +#endif /* SQLITE_USER_AUTHENTICATION */
|
| +
|
| +#ifdef SQLITE_USER_AUTHENTICATION
|
| +/*
|
| +** tclcmd: sqlite3_user_delete DB USERNAME
|
| +*/
|
| +static int test_user_delete(
|
| + ClientData clientData, /* Unused */
|
| + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
|
| + int objc, /* Number of arguments */
|
| + Tcl_Obj *CONST objv[] /* Command arguments */
|
| +){
|
| + char *zUser = 0;
|
| + sqlite3 *db;
|
| + int rc;
|
| +
|
| + if( objc!=3 ){
|
| + Tcl_WrongNumArgs(interp, 1, objv, "DB USERNAME");
|
| + return TCL_ERROR;
|
| + }
|
| + if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
|
| + return TCL_ERROR;
|
| + }
|
| + zUser = Tcl_GetString(objv[2]);
|
| + rc = sqlite3_user_delete(db, zUser);
|
| + Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
|
| + return TCL_OK;
|
| +}
|
| +#endif /* SQLITE_USER_AUTHENTICATION */
|
| +
|
| +/*
|
| +** Register commands with the TCL interpreter.
|
| +*/
|
| +int Sqlitetest1_Init(Tcl_Interp *interp){
|
| + extern int sqlite3_search_count;
|
| + extern int sqlite3_found_count;
|
| + extern int sqlite3_interrupt_count;
|
| + extern int sqlite3_open_file_count;
|
| + extern int sqlite3_sort_count;
|
| + extern int sqlite3_current_time;
|
| +#if SQLITE_OS_UNIX && defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
|
| + extern int sqlite3_hostid_num;
|
| +#endif
|
| + extern int sqlite3_max_blobsize;
|
| + extern int sqlite3BtreeSharedCacheReport(void*,
|
| + Tcl_Interp*,int,Tcl_Obj*CONST*);
|
| + static struct {
|
| + char *zName;
|
| + Tcl_CmdProc *xProc;
|
| + } aCmd[] = {
|
| + { "db_enter", (Tcl_CmdProc*)db_enter },
|
| + { "db_leave", (Tcl_CmdProc*)db_leave },
|
| { "sqlite3_mprintf_int", (Tcl_CmdProc*)sqlite3_mprintf_int },
|
| { "sqlite3_mprintf_int64", (Tcl_CmdProc*)sqlite3_mprintf_int64 },
|
| { "sqlite3_mprintf_long", (Tcl_CmdProc*)sqlite3_mprintf_long },
|
| @@ -5523,6 +6667,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
|
| { "sqlite3_get_table_printf", (Tcl_CmdProc*)test_get_table_printf },
|
| #endif
|
| { "sqlite3_close", (Tcl_CmdProc*)sqlite_test_close },
|
| + { "sqlite3_close_v2", (Tcl_CmdProc*)sqlite_test_close_v2 },
|
| { "sqlite3_create_function", (Tcl_CmdProc*)test_create_function },
|
| { "sqlite3_create_aggregate", (Tcl_CmdProc*)test_create_aggregate },
|
| { "sqlite_register_test_function", (Tcl_CmdProc*)test_register_func },
|
| @@ -5540,6 +6685,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
|
| { "sqlite3_busy_timeout", (Tcl_CmdProc*)test_busy_timeout },
|
| { "printf", (Tcl_CmdProc*)test_printf },
|
| { "sqlite3IoTrace", (Tcl_CmdProc*)test_io_trace },
|
| + { "clang_sanitize_address", (Tcl_CmdProc*)clang_sanitize_address },
|
| };
|
| static struct {
|
| char *zName;
|
| @@ -5566,6 +6712,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
|
| { "sqlite3_errmsg16", test_errmsg16 ,0 },
|
| { "sqlite3_open", test_open ,0 },
|
| { "sqlite3_open16", test_open16 ,0 },
|
| + { "sqlite3_open_v2", test_open_v2 ,0 },
|
| { "sqlite3_complete16", test_complete16 ,0 },
|
|
|
| { "sqlite3_prepare", test_prepare ,0 },
|
| @@ -5583,8 +6730,13 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
|
| { "sqlite3_sql", test_sql ,0 },
|
| { "sqlite3_next_stmt", test_next_stmt ,0 },
|
| { "sqlite3_stmt_readonly", test_stmt_readonly ,0 },
|
| + { "sqlite3_stmt_busy", test_stmt_busy ,0 },
|
| + { "uses_stmt_journal", uses_stmt_journal ,0 },
|
|
|
| { "sqlite3_release_memory", test_release_memory, 0},
|
| + { "sqlite3_db_release_memory", test_db_release_memory, 0},
|
| + { "sqlite3_db_filename", test_db_filename, 0},
|
| + { "sqlite3_db_readonly", test_db_readonly, 0},
|
| { "sqlite3_soft_heap_limit", test_soft_heap_limit, 0},
|
| { "sqlite3_thread_cleanup", test_thread_cleanup, 0},
|
| { "sqlite3_pager_refcounts", test_pager_refcounts, 0},
|
| @@ -5597,7 +6749,17 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
|
| { "save_prng_state", save_prng_state, 0 },
|
| { "restore_prng_state", restore_prng_state, 0 },
|
| { "reset_prng_state", reset_prng_state, 0 },
|
| + { "database_never_corrupt", database_never_corrupt, 0},
|
| + { "database_may_be_corrupt", database_may_be_corrupt, 0},
|
| { "optimization_control", optimization_control,0},
|
| +#if SQLITE_OS_WIN
|
| + { "lock_win32_file", win32_file_lock, 0 },
|
| + { "exists_win32_path", win32_exists_path, 0 },
|
| + { "find_win32_file", win32_find_file, 0 },
|
| + { "delete_win32_file", win32_delete_file, 0 },
|
| + { "make_win32_dir", win32_mkdir, 0 },
|
| + { "remove_win32_dir", win32_rmdir, 0 },
|
| +#endif
|
| { "tcl_objproc", runAsObjProc, 0 },
|
|
|
| /* sqlite3_column_*() API */
|
| @@ -5630,7 +6792,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
|
| #endif
|
| #ifdef SQLITE_ENABLE_COLUMN_METADATA
|
| {"sqlite3_column_database_name16",
|
| - test_stmt_utf16, sqlite3_column_database_name16},
|
| + test_stmt_utf16, (void*)sqlite3_column_database_name16},
|
| {"sqlite3_column_table_name16", test_stmt_utf16, (void*)sqlite3_column_table_name16},
|
| {"sqlite3_column_origin_name16", test_stmt_utf16, (void*)sqlite3_column_origin_name16},
|
| #endif
|
| @@ -5646,7 +6808,15 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
|
| { "file_control_lasterrno_test", file_control_lasterrno_test, 0 },
|
| { "file_control_lockproxy_test", file_control_lockproxy_test, 0 },
|
| { "file_control_chunksize_test", file_control_chunksize_test, 0 },
|
| - { "file_control_sizehint_test", file_control_sizehint_test, 0 },
|
| + { "file_control_sizehint_test", file_control_sizehint_test, 0 },
|
| +#if SQLITE_OS_WIN
|
| + { "file_control_win32_av_retry", file_control_win32_av_retry, 0 },
|
| + { "file_control_win32_set_handle", file_control_win32_set_handle, 0 },
|
| +#endif
|
| + { "file_control_persist_wal", file_control_persist_wal, 0 },
|
| + { "file_control_powersafe_overwrite",file_control_powersafe_overwrite,0},
|
| + { "file_control_vfsname", file_control_vfsname, 0 },
|
| + { "file_control_tempfilename", file_control_tempfilename, 0 },
|
| { "sqlite3_vfs_list", vfs_list, 0 },
|
| { "sqlite3_create_function_v2", test_create_function_v2, 0 },
|
|
|
| @@ -5655,6 +6825,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
|
| { "add_test_collate", test_collate, 0 },
|
| { "add_test_collate_needed", test_collate_needed, 0 },
|
| { "add_test_function", test_function, 0 },
|
| + { "add_test_utf16bin_collate", test_utf16bin_collate, 0 },
|
| #endif
|
| { "sqlite3_test_errstr", test_errstr, 0 },
|
| { "tcl_variable_type", tcl_variable_type, 0 },
|
| @@ -5683,6 +6854,20 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
|
| #ifndef SQLITE_OMIT_EXPLAIN
|
| { "print_explain_query_plan", test_print_eqp, 0 },
|
| #endif
|
| + { "sqlite3_test_control", test_test_control },
|
| +#if SQLITE_OS_UNIX
|
| + { "getrusage", test_getrusage },
|
| +#endif
|
| + { "load_static_extension", tclLoadStaticExtensionCmd },
|
| + { "sorter_test_fakeheap", sorter_test_fakeheap },
|
| + { "sorter_test_sort4_helper", sorter_test_sort4_helper },
|
| +#ifdef SQLITE_USER_AUTHENTICATION
|
| + { "sqlite3_user_authenticate", test_user_authenticate, 0 },
|
| + { "sqlite3_user_add", test_user_add, 0 },
|
| + { "sqlite3_user_change", test_user_change, 0 },
|
| + { "sqlite3_user_delete", test_user_delete, 0 },
|
| +#endif
|
| +
|
| };
|
| static int bitmask_size = sizeof(Bitmask)*8;
|
| int i;
|
| @@ -5694,17 +6879,14 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
|
| extern int sqlite3_pager_writedb_count;
|
| extern int sqlite3_pager_writej_count;
|
| #if SQLITE_OS_WIN
|
| - extern int sqlite3_os_type;
|
| + extern LONG volatile sqlite3_os_type;
|
| #endif
|
| #ifdef SQLITE_DEBUG
|
| extern int sqlite3WhereTrace;
|
| extern int sqlite3OSTrace;
|
| - extern int sqlite3VdbeAddopTrace;
|
| extern int sqlite3WalTrace;
|
| #endif
|
| #ifdef SQLITE_TEST
|
| - extern char sqlite3_query_plan[];
|
| - static char *query_plan = sqlite3_query_plan;
|
| #ifdef SQLITE_ENABLE_FTS3
|
| extern int sqlite3_fts3_enable_parentheses;
|
| #endif
|
| @@ -5755,15 +6937,16 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
|
| #endif
|
| #if SQLITE_OS_WIN
|
| Tcl_LinkVar(interp, "sqlite_os_type",
|
| - (char*)&sqlite3_os_type, TCL_LINK_INT);
|
| + (char*)&sqlite3_os_type, TCL_LINK_LONG);
|
| #endif
|
| #ifdef SQLITE_TEST
|
| - Tcl_LinkVar(interp, "sqlite_query_plan",
|
| - (char*)&query_plan, TCL_LINK_STRING|TCL_LINK_READ_ONLY);
|
| + {
|
| + static const char *query_plan = "*** OBSOLETE VARIABLE ***";
|
| + Tcl_LinkVar(interp, "sqlite_query_plan",
|
| + (char*)&query_plan, TCL_LINK_STRING|TCL_LINK_READ_ONLY);
|
| + }
|
| #endif
|
| #ifdef SQLITE_DEBUG
|
| - Tcl_LinkVar(interp, "sqlite_addop_trace",
|
| - (char*)&sqlite3VdbeAddopTrace, TCL_LINK_INT);
|
| Tcl_LinkVar(interp, "sqlite_where_trace",
|
| (char*)&sqlite3WhereTrace, TCL_LINK_INT);
|
| Tcl_LinkVar(interp, "sqlite_os_trace",
|
| @@ -5783,6 +6966,8 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
|
| (char*)&sqlite_static_bind_nbyte, TCL_LINK_INT);
|
| Tcl_LinkVar(interp, "sqlite_temp_directory",
|
| (char*)&sqlite3_temp_directory, TCL_LINK_STRING);
|
| + Tcl_LinkVar(interp, "sqlite_data_directory",
|
| + (char*)&sqlite3_data_directory, TCL_LINK_STRING);
|
| Tcl_LinkVar(interp, "bitmask_size",
|
| (char*)&bitmask_size, TCL_LINK_INT|TCL_LINK_READ_ONLY);
|
| Tcl_LinkVar(interp, "sqlite_sync_count",
|
|
|