diff options
Diffstat (limited to 'components/external/SQLite-3.8.1/SQLiteLib/test')
46 files changed, 0 insertions, 32916 deletions
diff --git a/components/external/SQLite-3.8.1/SQLiteLib/test/test1.c b/components/external/SQLite-3.8.1/SQLiteLib/test/test1.c deleted file mode 100644 index d8a9e52d21..0000000000 --- a/components/external/SQLite-3.8.1/SQLiteLib/test/test1.c +++ /dev/null @@ -1,6549 +0,0 @@ -/* -** 2001 September 15 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** 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. -*/ -#include "sqliteInt.h" -#include "vdbeInt.h" -#include "tcl.h" -#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; -}; - -/* -** Convert text generated by the "%p" conversion format back into -** a pointer. -*/ -static int testHexToInt(int h){ - if( h>='0' && h<='9' ){ - return h - '0'; - }else if( h>='a' && h<='f' ){ - return h - 'a' + 10; - }else{ - assert( h>='A' && h<='F' ); - return h - 'A' + 10; - } -} -void *sqlite3TestTextToPtr(const char *z){ - void *p; - u64 v; - u32 v2; - if( z[0]=='0' && z[1]=='x' ){ - z += 2; - } - v = 0; - while( *z ){ - v = (v<<4) + testHexToInt(*z); - z++; - } - if( sizeof(p)==sizeof(v) ){ - memcpy(&p, &v, sizeof(p)); - }else{ - assert( sizeof(p)==sizeof(v2) ); - v2 = (u32)v; - memcpy(&p, &v2, sizeof(p)); - } - return p; -} - - -/* -** 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; -} - -/* -** Decode a pointer to an sqlite3 object. -*/ -int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb){ - struct SqliteDb *p; - Tcl_CmdInfo cmdInfo; - if( Tcl_GetCommandInfo(interp, zA, &cmdInfo) ){ - p = (struct SqliteDb*)cmdInfo.objClientData; - *ppDb = p->db; - }else{ - *ppDb = (sqlite3*)sqlite3TestTextToPtr(zA); - } - return TCL_OK; -} - -extern const char *sqlite3ErrName(int); -#define t1ErrorName sqlite3ErrName - -/* -** Convert an sqlite3_stmt* into an sqlite3*. This depends on the -** fact that the sqlite3* is the first field in the Vdbe structure. -*/ -#define StmtToDb(X) sqlite3_db_handle(X) - -/* -** Check a return value to make sure it agrees with the results -** from sqlite3_errcode. -*/ -int sqlite3TestErrCode(Tcl_Interp *interp, sqlite3 *db, int rc){ - if( sqlite3_threadsafe()==0 && rc!=SQLITE_MISUSE && rc!=SQLITE_OK - && sqlite3_errcode(db)!=rc ){ - char zBuf[200]; - int r2 = sqlite3_errcode(db); - sprintf(zBuf, "error code %s (%d) does not match sqlite3_errcode %s (%d)", - t1ErrorName(rc), rc, t1ErrorName(r2), r2); - Tcl_ResetResult(interp); - Tcl_AppendResult(interp, zBuf, 0); - return 1; - } - return 0; -} - -/* -** Decode a pointer to an sqlite3_stmt object. -*/ -static int getStmtPointer( - Tcl_Interp *interp, - const char *zArg, - sqlite3_stmt **ppStmt -){ - *ppStmt = (sqlite3_stmt*)sqlite3TestTextToPtr(zArg); - return TCL_OK; -} - -/* -** Generate a text representation of a pointer that can be understood -** by the getDbPointer and getVmPointer routines above. -** -** The problem is, on some machines (Solaris) if you do a printf with -** "%p" you cannot turn around and do a scanf with the same "%p" and -** get your pointer back. You have to prepend a "0x" before it will -** work. Or at least that is what is reported to me (drh). But this -** behavior varies from machine to machine. The solution used her is -** to test the string right after it is generated to see if it can be -** understood by scanf, and if not, try prepending an "0x" to see if -** that helps. If nothing works, a fatal error is generated. -*/ -int sqlite3TestMakePointerStr(Tcl_Interp *interp, char *zPtr, void *p){ - sqlite3_snprintf(100, zPtr, "%p", p); - return TCL_OK; -} - -/* -** The callback routine for sqlite3_exec_printf(). -*/ -static int exec_printf_cb(void *pArg, int argc, char **argv, char **name){ - Tcl_DString *str = (Tcl_DString*)pArg; - int i; - - if( Tcl_DStringLength(str)==0 ){ - for(i=0; i<argc; i++){ - Tcl_DStringAppendElement(str, name[i] ? name[i] : "NULL"); - } - } - for(i=0; i<argc; i++){ - Tcl_DStringAppendElement(str, argv[i] ? argv[i] : "NULL"); - } - return 0; -} - -/* -** The I/O tracing callback. -*/ -#if !defined(SQLITE_OMIT_TRACE) && defined(SQLITE_ENABLE_IOTRACE) -static FILE *iotrace_file = 0; -static void io_trace_callback(const char *zFormat, ...){ - va_list ap; - va_start(ap, zFormat); - vfprintf(iotrace_file, zFormat, ap); - va_end(ap); - fflush(iotrace_file); -} -#endif - -/* -** Usage: io_trace FILENAME -** -** Turn I/O tracing on or off. If FILENAME is not an empty string, -** I/O tracing begins going into FILENAME. If FILENAME is an empty -** string, I/O tracing is turned off. -*/ -static int test_io_trace( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - char **argv /* Text of each argument */ -){ -#if !defined(SQLITE_OMIT_TRACE) && defined(SQLITE_ENABLE_IOTRACE) - if( argc!=2 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " FILENAME\"", 0); - return TCL_ERROR; - } - if( iotrace_file ){ - if( iotrace_file!=stdout && iotrace_file!=stderr ){ - fclose(iotrace_file); - } - iotrace_file = 0; - sqlite3IoTrace = 0; - } - if( argv[1][0] ){ - if( strcmp(argv[1],"stdout")==0 ){ - iotrace_file = stdout; - }else if( strcmp(argv[1],"stderr")==0 ){ - iotrace_file = stderr; - }else{ - iotrace_file = fopen(argv[1], "w"); - } - sqlite3IoTrace = io_trace_callback; - } -#endif - return TCL_OK; -} - - -/* -** Usage: sqlite3_exec_printf DB FORMAT STRING -** -** Invoke the sqlite3_exec_printf() interface using the open database -** DB. The SQL is the string FORMAT. The format string should contain -** one %s or %q. STRING is the value inserted into %s or %q. -*/ -static int test_exec_printf( - 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; - Tcl_DString str; - int rc; - char *zErr = 0; - char *zSql; - char zBuf[30]; - if( argc!=4 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " DB FORMAT STRING", 0); - return TCL_ERROR; - } - if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; - Tcl_DStringInit(&str); - zSql = sqlite3_mprintf(argv[2], argv[3]); - rc = sqlite3_exec(db, zSql, exec_printf_cb, &str, &zErr); - sqlite3_free(zSql); - sprintf(zBuf, "%d", rc); - Tcl_AppendElement(interp, zBuf); - Tcl_AppendElement(interp, rc==SQLITE_OK ? Tcl_DStringValue(&str) : zErr); - Tcl_DStringFree(&str); - if( zErr ) sqlite3_free(zErr); - if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; - return TCL_OK; -} - -/* -** Usage: sqlite3_exec_hex DB HEX -** -** Invoke the sqlite3_exec() on a string that is obtained by translating -** HEX into ASCII. Most characters are translated as is. %HH becomes -** a hex character. -*/ -static int test_exec_hex( - 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; - Tcl_DString str; - int rc, i, j; - char *zErr = 0; - char *zHex; - char zSql[500]; - char zBuf[30]; - if( argc!=3 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " DB HEX", 0); - return TCL_ERROR; - } - if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; - zHex = argv[2]; - for(i=j=0; i<sizeof(zSql) && zHex[j]; i++, j++){ - if( zHex[j]=='%' && zHex[j+2] && zHex[j+2] ){ - zSql[i] = (testHexToInt(zHex[j+1])<<4) + testHexToInt(zHex[j+2]); - j += 2; - }else{ - zSql[i] = zHex[j]; - } - } - zSql[i] = 0; - Tcl_DStringInit(&str); - rc = sqlite3_exec(db, zSql, exec_printf_cb, &str, &zErr); - sprintf(zBuf, "%d", rc); - Tcl_AppendElement(interp, zBuf); - Tcl_AppendElement(interp, rc==SQLITE_OK ? Tcl_DStringValue(&str) : zErr); - Tcl_DStringFree(&str); - if( zErr ) sqlite3_free(zErr); - if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; - return TCL_OK; -} - -/* -** Usage: db_enter DB -** db_leave DB -** -** Enter or leave the mutex on a database connection. -*/ -static int db_enter( - 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; - if( argc!=2 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " DB", 0); - return TCL_ERROR; - } - if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; - sqlite3_mutex_enter(db->mutex); - return TCL_OK; -} -static int db_leave( - 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; - if( argc!=2 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " DB", 0); - return TCL_ERROR; - } - if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; - sqlite3_mutex_leave(db->mutex); - return TCL_OK; -} - -/* -** Usage: sqlite3_exec DB SQL -** -** Invoke the sqlite3_exec interface using the open database DB -*/ -static int test_exec( - 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; - Tcl_DString str; - int rc; - char *zErr = 0; - char *zSql; - int i, j; - char zBuf[30]; - if( argc!=3 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " DB SQL", 0); - return TCL_ERROR; - } - if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; - Tcl_DStringInit(&str); - zSql = sqlite3_mprintf("%s", argv[2]); - for(i=j=0; zSql[i];){ - if( zSql[i]=='%' ){ - zSql[j++] = (testHexToInt(zSql[i+1])<<4) + testHexToInt(zSql[i+2]); - i += 3; - }else{ - zSql[j++] = zSql[i++]; - } - } - zSql[j] = 0; - rc = sqlite3_exec(db, zSql, exec_printf_cb, &str, &zErr); - sqlite3_free(zSql); - sprintf(zBuf, "%d", rc); - Tcl_AppendElement(interp, zBuf); - Tcl_AppendElement(interp, rc==SQLITE_OK ? Tcl_DStringValue(&str) : zErr); - Tcl_DStringFree(&str); - if( zErr ) sqlite3_free(zErr); - if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; - return TCL_OK; -} - -/* -** Usage: sqlite3_exec_nr DB SQL -** -** Invoke the sqlite3_exec interface using the open database DB. Discard -** all results -*/ -static int test_exec_nr( - 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; - char *zErr = 0; - if( argc!=3 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " DB SQL", 0); - return TCL_ERROR; - } - if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; - rc = sqlite3_exec(db, argv[2], 0, 0, &zErr); - if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; - return TCL_OK; -} - -/* -** Usage: sqlite3_mprintf_z_test SEPARATOR ARG0 ARG1 ... -** -** Test the %z format of sqlite_mprintf(). Use multiple mprintf() calls to -** concatenate arg0 through argn using separator as the separator. -** Return the result. -*/ -static int test_mprintf_z( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - char **argv /* Text of each argument */ -){ - char *zResult = 0; - int i; - - for(i=2; i<argc && (i==2 || zResult); i++){ - zResult = sqlite3_mprintf("%z%s%s", zResult, argv[1], argv[i]); - } - Tcl_AppendResult(interp, zResult, 0); - sqlite3_free(zResult); - return TCL_OK; -} - -/* -** Usage: sqlite3_mprintf_n_test STRING -** -** Test the %n format of sqlite_mprintf(). 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 = sqlite3_mprintf("%s%n", argv[1], &n); - sqlite3_free(zStr); - Tcl_SetObjResult(interp, Tcl_NewIntObj(n)); - return TCL_OK; -} - -/* -** Usage: sqlite3_snprintf_int SIZE FORMAT INT -** -** Test the of sqlite3_snprintf() routine. SIZE is the size of the -** output buffer in bytes. The maximum size is 100. FORMAT is the -** format string. INT is a single integer argument. The FORMAT -** string must require no more than this one integer argument. If -** You pass in a format string that requires more than one argument, -** bad things will happen. -*/ -static int test_snprintf_int( - 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[100]; - int n = atoi(argv[1]); - const char *zFormat = argv[2]; - int a1 = atoi(argv[3]); - if( n>sizeof(zStr) ) n = sizeof(zStr); - sqlite3_snprintf(sizeof(zStr), zStr, "abcdefghijklmnopqrstuvwxyz"); - sqlite3_snprintf(n, zStr, zFormat, a1); - Tcl_AppendResult(interp, zStr, 0); - return TCL_OK; -} - -#ifndef SQLITE_OMIT_GET_TABLE - -/* -** Usage: sqlite3_get_table_printf DB FORMAT STRING ?--no-counts? -** -** Invoke the sqlite3_get_table_printf() interface using the open database -** DB. The SQL is the string FORMAT. The format string should contain -** one %s or %q. STRING is the value inserted into %s or %q. -*/ -static int test_get_table_printf( - 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; - Tcl_DString str; - int rc; - char *zErr = 0; - int nRow, nCol; - char **aResult; - int i; - char zBuf[30]; - char *zSql; - int resCount = -1; - if( argc==5 ){ - if( Tcl_GetInt(interp, argv[4], &resCount) ) return TCL_ERROR; - } - if( argc!=4 && argc!=5 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " DB FORMAT STRING ?COUNT?", 0); - return TCL_ERROR; - } - if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; - Tcl_DStringInit(&str); - zSql = sqlite3_mprintf(argv[2],argv[3]); - if( argc==5 ){ - rc = sqlite3_get_table(db, zSql, &aResult, 0, 0, &zErr); - }else{ - rc = sqlite3_get_table(db, zSql, &aResult, &nRow, &nCol, &zErr); - resCount = (nRow+1)*nCol; - } - sqlite3_free(zSql); - sprintf(zBuf, "%d", rc); - Tcl_AppendElement(interp, zBuf); - if( rc==SQLITE_OK ){ - if( argc==4 ){ - sprintf(zBuf, "%d", nRow); - Tcl_AppendElement(interp, zBuf); - sprintf(zBuf, "%d", nCol); - Tcl_AppendElement(interp, zBuf); - } - for(i=0; i<resCount; i++){ - Tcl_AppendElement(interp, aResult[i] ? aResult[i] : "NULL"); - } - }else{ - Tcl_AppendElement(interp, zErr); - } - sqlite3_free_table(aResult); - if( zErr ) sqlite3_free(zErr); - if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; - return TCL_OK; -} - -#endif /* SQLITE_OMIT_GET_TABLE */ - - -/* -** Usage: sqlite3_last_insert_rowid DB -** -** Returns the integer ROWID of the most recent insert. -*/ -static int test_last_rowid( - 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; - char zBuf[30]; - - if( argc!=2 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " DB\"", 0); - return TCL_ERROR; - } - if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; - sprintf(zBuf, "%lld", sqlite3_last_insert_rowid(db)); - Tcl_AppendResult(interp, zBuf, 0); - return SQLITE_OK; -} - -/* -** Usage: sqlite3_key DB KEY -** -** Set the codec key. -*/ -static int test_key( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - char **argv /* Text of each argument */ -){ -#ifdef SQLITE_HAS_CODEC - sqlite3 *db; - const char *zKey; - int nKey; - if( argc!=3 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " FILENAME\"", 0); - return TCL_ERROR; - } - if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; - zKey = argv[2]; - nKey = strlen(zKey); - sqlite3_key(db, zKey, nKey); -#endif - return TCL_OK; -} - -/* -** Usage: sqlite3_rekey DB KEY -** -** Change the codec key. -*/ -static int test_rekey( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - char **argv /* Text of each argument */ -){ -#ifdef SQLITE_HAS_CODEC - sqlite3 *db; - const char *zKey; - int nKey; - if( argc!=3 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " FILENAME\"", 0); - return TCL_ERROR; - } - if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; - zKey = argv[2]; - nKey = strlen(zKey); - sqlite3_rekey(db, zKey, nKey); -#endif - return TCL_OK; -} - -/* -** Usage: sqlite3_close DB -** -** Closes the database opened by sqlite3_open. -*/ -static int sqlite_test_close( - 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(db); - Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC); - return TCL_OK; -} - -/* -** 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. -*/ -static void t1_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]) ){ - int n = sqlite3_value_bytes(argv[i]); - sqlite3_result_text(context, (char*)sqlite3_value_text(argv[i]), - n, SQLITE_TRANSIENT); - break; - } - } -} - -/* -** These are test functions. hex8() interprets its argument as -** UTF8 and returns a hex encoding. hex16le() interprets its argument -** as UTF16le and returns a hex encoding. -*/ -static void hex8Func(sqlite3_context *p, int argc, sqlite3_value **argv){ - const unsigned char *z; - int i; - char zBuf[200]; - z = sqlite3_value_text(argv[0]); - for(i=0; i<sizeof(zBuf)/2 - 2 && z[i]; i++){ - sprintf(&zBuf[i*2], "%02x", z[i]&0xff); - } - zBuf[i*2] = 0; - sqlite3_result_text(p, (char*)zBuf, -1, SQLITE_TRANSIENT); -} -#ifndef SQLITE_OMIT_UTF16 -static void hex16Func(sqlite3_context *p, int argc, sqlite3_value **argv){ - const unsigned short int *z; - int i; - char zBuf[400]; - z = sqlite3_value_text16(argv[0]); - for(i=0; i<sizeof(zBuf)/4 - 4 && z[i]; i++){ - sprintf(&zBuf[i*4], "%04x", z[i]&0xff); - } - zBuf[i*4] = 0; - sqlite3_result_text(p, (char*)zBuf, -1, SQLITE_TRANSIENT); -} -#endif - -/* -** A structure into which to accumulate text. -*/ -struct dstr { - int nAlloc; /* Space allocated */ - int nUsed; /* Space used */ - char *z; /* The space */ -}; - -/* -** Append text to a dstr -*/ -static void dstrAppend(struct dstr *p, const char *z, int divider){ - int n = (int)strlen(z); - if( p->nUsed + n + 2 > p->nAlloc ){ - char *zNew; - p->nAlloc = p->nAlloc*2 + n + 200; - zNew = sqlite3_realloc(p->z, p->nAlloc); - if( zNew==0 ){ - sqlite3_free(p->z); - memset(p, 0, sizeof(*p)); - return; - } - p->z = zNew; - } - if( divider && p->nUsed>0 ){ - p->z[p->nUsed++] = divider; - } - memcpy(&p->z[p->nUsed], z, n+1); - p->nUsed += n; -} - -/* -** Invoked for each callback from sqlite3ExecFunc -*/ -static int execFuncCallback(void *pData, int argc, char **argv, char **NotUsed){ - struct dstr *p = (struct dstr*)pData; - int i; - for(i=0; i<argc; i++){ - if( argv[i]==0 ){ - dstrAppend(p, "NULL", ' '); - }else{ - dstrAppend(p, argv[i], ' '); - } - } - return 0; -} - -/* -** Implementation of the x_sqlite_exec() function. This function takes -** a single argument and attempts to execute that argument as SQL code. -** This is illegal and should set the SQLITE_MISUSE flag on the database. -** -** 2004-Jan-07: We have changed this to make it legal to call sqlite3_exec() -** from within a function call. -** -** This routine simulates the effect of having two threads attempt to -** use the same database at the same time. -*/ -static void sqlite3ExecFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - struct dstr x; - memset(&x, 0, sizeof(x)); - (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); - sqlite3_free(x.z); -} - -/* -** Implementation of tkt2213func(), a scalar function that takes exactly -** one argument. It has two interesting features: -** -** * It calls sqlite3_value_text() 3 times on the argument sqlite3_value*. -** If the three pointers returned are not the same an SQL error is raised. -** -** * Otherwise it returns a copy of the text representation of its -** argument in such a way as the VDBE representation is a Mem* cell -** with the MEM_Term flag clear. -** -** Ticket #2213 can therefore be tested by evaluating the following -** SQL expression: -** -** tkt2213func(tkt2213func('a string')); -*/ -static void tkt2213Function( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - int nText; - unsigned char const *zText1; - unsigned char const *zText2; - unsigned char const *zText3; - - nText = sqlite3_value_bytes(argv[0]); - zText1 = sqlite3_value_text(argv[0]); - zText2 = sqlite3_value_text(argv[0]); - zText3 = sqlite3_value_text(argv[0]); - - if( zText1!=zText2 || zText2!=zText3 ){ - sqlite3_result_error(context, "tkt2213 is not fixed", -1); - }else{ - char *zCopy = (char *)sqlite3_malloc(nText); - memcpy(zCopy, zText1, nText); - sqlite3_result_text(context, zCopy, nText, sqlite3_free); - } -} - -/* -** The following SQL function takes 4 arguments. The 2nd and -** 4th argument must be one of these strings: 'text', 'text16', -** or 'blob' corresponding to API functions -** -** sqlite3_value_text() -** sqlite3_value_text16() -** sqlite3_value_blob() -** -** The third argument is a string, either 'bytes' or 'bytes16' or 'noop', -** corresponding to APIs: -** -** sqlite3_value_bytes() -** sqlite3_value_bytes16() -** noop -** -** The APIs designated by the 2nd through 4th arguments are applied -** to the first argument in order. If the pointers returned by the -** second and fourth are different, this routine returns 1. Otherwise, -** this routine returns 0. -** -** This function is used to test to see when returned pointers from -** the _text(), _text16() and _blob() APIs become invalidated. -*/ -static void ptrChngFunction( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - const void *p1, *p2; - const char *zCmd; - if( argc!=4 ) return; - zCmd = (const char*)sqlite3_value_text(argv[1]); - if( zCmd==0 ) return; - if( strcmp(zCmd,"text")==0 ){ - p1 = (const void*)sqlite3_value_text(argv[0]); -#ifndef SQLITE_OMIT_UTF16 - }else if( strcmp(zCmd, "text16")==0 ){ - p1 = (const void*)sqlite3_value_text16(argv[0]); -#endif - }else if( strcmp(zCmd, "blob")==0 ){ - p1 = (const void*)sqlite3_value_blob(argv[0]); - }else{ - return; - } - zCmd = (const char*)sqlite3_value_text(argv[2]); - if( zCmd==0 ) return; - if( strcmp(zCmd,"bytes")==0 ){ - sqlite3_value_bytes(argv[0]); -#ifndef SQLITE_OMIT_UTF16 - }else if( strcmp(zCmd, "bytes16")==0 ){ - sqlite3_value_bytes16(argv[0]); -#endif - }else if( strcmp(zCmd, "noop")==0 ){ - /* do nothing */ - }else{ - return; - } - zCmd = (const char*)sqlite3_value_text(argv[3]); - if( zCmd==0 ) return; - if( strcmp(zCmd,"text")==0 ){ - p2 = (const void*)sqlite3_value_text(argv[0]); -#ifndef SQLITE_OMIT_UTF16 - }else if( strcmp(zCmd, "text16")==0 ){ - p2 = (const void*)sqlite3_value_text16(argv[0]); -#endif - }else if( strcmp(zCmd, "blob")==0 ){ - p2 = (const void*)sqlite3_value_blob(argv[0]); - }else{ - return; - } - sqlite3_result_int(context, p1!=p2); -} - - -/* -** Usage: sqlite_test_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 -** as the "coalesce" function. This function also registers an SQL function -** named "x_sqlite_exec" that invokes sqlite3_exec(). Invoking sqlite3_exec() -** in this way is illegal recursion and should raise an SQLITE_MISUSE error. -** The effect is similar to trying to use the same database connection from -** two threads at the same time. -** -** The original motivation for this routine was to be able to call the -** sqlite3_create_function function while a query is in progress in order -** to test the SQLITE_MISUSE detection logic. -*/ -static int test_create_function( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - char **argv /* Text of each argument */ -){ - int rc; - sqlite3 *db; - - if( argc!=2 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " DB\"", 0); - return TCL_ERROR; - } - if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; - rc = sqlite3_create_function(db, "x_coalesce", -1, SQLITE_ANY, 0, - t1_ifnullFunc, 0, 0); - if( rc==SQLITE_OK ){ - rc = sqlite3_create_function(db, "hex8", 1, SQLITE_ANY, 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); - } -#endif - if( rc==SQLITE_OK ){ - rc = sqlite3_create_function(db, "tkt2213func", 1, SQLITE_ANY, 0, - tkt2213Function, 0, 0); - } - if( rc==SQLITE_OK ){ - rc = sqlite3_create_function(db, "pointer_change", 4, SQLITE_ANY, 0, - ptrChngFunction, 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. */ - if( rc==SQLITE_OK ){ - const void *zUtf16; - sqlite3_value *pVal; - sqlite3_mutex_enter(db->mutex); - pVal = sqlite3ValueNew(db); - sqlite3ValueSetStr(pVal, -1, "x_sqlite_exec", SQLITE_UTF8, SQLITE_STATIC); - zUtf16 = sqlite3ValueText(pVal, SQLITE_UTF16NATIVE); - if( db->mallocFailed ){ - rc = SQLITE_NOMEM; - }else{ - rc = sqlite3_create_function16(db, zUtf16, - 1, SQLITE_UTF16, db, sqlite3ExecFunc, 0, 0); - } - sqlite3ValueFree(pVal); - sqlite3_mutex_leave(db->mutex); - } -#endif - - if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; - Tcl_SetResult(interp, (char *)t1ErrorName(rc), 0); - return TCL_OK; -} - -/* -** 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 t1CountCtx t1CountCtx; -struct t1CountCtx { - int n; -}; -static void t1CountStep( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - t1CountCtx *p; - p = sqlite3_aggregate_context(context, sizeof(*p)); - 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 t1CountFinalize(sqlite3_context *context){ - t1CountCtx *p; - p = sqlite3_aggregate_context(context, sizeof(*p)); - 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); - } - } -} - -#ifndef SQLITE_OMIT_DEPRECATED -static void legacyCountStep( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - /* no-op */ -} - -static void legacyCountFinalize(sqlite3_context *context){ - sqlite3_result_int(context, sqlite3_aggregate_count(context)); -} -#endif - -/* -** Usage: sqlite3_create_aggregate DB -** -** Call the sqlite3_create_function API on the given database in order -** to create a function named "x_count". This function is similar -** to the built-in count() function, with a few special quirks -** for testing the sqlite3_result_error() APIs. -** -** 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. See misuse.test. -** -** This routine was later extended to test the use of sqlite3_result_error() -** within aggregate functions. -** -** Later: It is now also extended to register the aggregate function -** "legacy_count()" with the supplied database handle. This is used -** to test the deprecated sqlite3_aggregate_count() API. -*/ -static int test_create_aggregate( - 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_create_function(db, "x_count", 0, SQLITE_UTF8, 0, 0, - t1CountStep,t1CountFinalize); - if( rc==SQLITE_OK ){ - rc = sqlite3_create_function(db, "x_count", 1, SQLITE_UTF8, 0, 0, - t1CountStep,t1CountFinalize); - } -#ifndef SQLITE_OMIT_DEPRECATED - if( rc==SQLITE_OK ){ - rc = sqlite3_create_function(db, "legacy_count", 0, SQLITE_ANY, 0, 0, - legacyCountStep, legacyCountFinalize - ); - } -#endif - if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; - Tcl_SetResult(interp, (char *)t1ErrorName(rc), 0); - return TCL_OK; -} - - -/* -** Usage: printf TEXT -** -** Send output to printf. Use this rather than puts to merge the output -** in the correct sequence with debugging printfs inserted into C code. -** Puts uses a separate buffer and debugging statements will be out of -** sequence if it is used. -*/ -static int test_printf( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - char **argv /* Text of each argument */ -){ - if( argc!=2 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " TEXT\"", 0); - return TCL_ERROR; - } - printf("%s\n", argv[1]); - return TCL_OK; -} - - - -/* -** Usage: sqlite3_mprintf_int FORMAT INTEGER INTEGER INTEGER -** -** Call mprintf with three integer arguments -*/ -static int sqlite3_mprintf_int( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - char **argv /* Text of each argument */ -){ - int a[3], i; - char *z; - if( argc!=5 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " FORMAT INT INT INT\"", 0); - return TCL_ERROR; - } - for(i=2; i<5; i++){ - if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR; - } - z = sqlite3_mprintf(argv[1], a[0], a[1], a[2]); - Tcl_AppendResult(interp, z, 0); - sqlite3_free(z); - return TCL_OK; -} - -/* -** Usage: sqlite3_mprintf_int64 FORMAT INTEGER INTEGER INTEGER -** -** Call mprintf with three 64-bit integer arguments -*/ -static int sqlite3_mprintf_int64( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - char **argv /* Text of each argument */ -){ - int i; - sqlite_int64 a[3]; - char *z; - if( argc!=5 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " FORMAT INT INT INT\"", 0); - return TCL_ERROR; - } - for(i=2; i<5; i++){ - if( sqlite3Atoi64(argv[i], &a[i-2], 1000000, SQLITE_UTF8) ){ - Tcl_AppendResult(interp, "argument is not a valid 64-bit integer", 0); - return TCL_ERROR; - } - } - z = sqlite3_mprintf(argv[1], a[0], a[1], a[2]); - Tcl_AppendResult(interp, z, 0); - sqlite3_free(z); - return TCL_OK; -} - -/* -** Usage: sqlite3_mprintf_long FORMAT INTEGER INTEGER INTEGER -** -** Call mprintf with three long integer arguments. This might be the -** same as sqlite3_mprintf_int or sqlite3_mprintf_int64, depending on -** platform. -*/ -static int sqlite3_mprintf_long( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - char **argv /* Text of each argument */ -){ - int i; - long int a[3]; - int b[3]; - char *z; - if( argc!=5 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " FORMAT INT INT INT\"", 0); - return TCL_ERROR; - } - for(i=2; i<5; i++){ - if( Tcl_GetInt(interp, argv[i], &b[i-2]) ) return TCL_ERROR; - a[i-2] = (long int)b[i-2]; - a[i-2] &= (((u64)1)<<(sizeof(int)*8))-1; - } - z = sqlite3_mprintf(argv[1], a[0], a[1], a[2]); - Tcl_AppendResult(interp, z, 0); - sqlite3_free(z); - return TCL_OK; -} - -/* -** Usage: sqlite3_mprintf_str FORMAT INTEGER INTEGER STRING -** -** Call mprintf with two integer arguments and one string argument -*/ -static int sqlite3_mprintf_str( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - char **argv /* Text of each argument */ -){ - int a[3], i; - char *z; - if( argc<4 || argc>5 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " FORMAT INT INT ?STRING?\"", 0); - return TCL_ERROR; - } - for(i=2; i<4; i++){ - if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR; - } - z = sqlite3_mprintf(argv[1], a[0], a[1], argc>4 ? argv[4] : NULL); - Tcl_AppendResult(interp, z, 0); - sqlite3_free(z); - return TCL_OK; -} - -/* -** Usage: sqlite3_snprintf_str INTEGER FORMAT INTEGER INTEGER STRING -** -** Call mprintf with two integer arguments and one string argument -*/ -static int sqlite3_snprintf_str( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - char **argv /* Text of each argument */ -){ - int a[3], i; - int n; - char *z; - if( argc<5 || argc>6 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " INT FORMAT INT INT ?STRING?\"", 0); - return TCL_ERROR; - } - if( Tcl_GetInt(interp, argv[1], &n) ) return TCL_ERROR; - if( n<0 ){ - Tcl_AppendResult(interp, "N must be non-negative", 0); - return TCL_ERROR; - } - for(i=3; i<5; i++){ - if( Tcl_GetInt(interp, argv[i], &a[i-3]) ) return TCL_ERROR; - } - z = sqlite3_malloc( n+1 ); - sqlite3_snprintf(n, z, argv[2], a[0], a[1], argc>4 ? argv[5] : NULL); - Tcl_AppendResult(interp, z, 0); - sqlite3_free(z); - return TCL_OK; -} - -/* -** Usage: sqlite3_mprintf_double FORMAT INTEGER INTEGER DOUBLE -** -** Call mprintf with two integer arguments and one double argument -*/ -static int sqlite3_mprintf_double( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - char **argv /* Text of each argument */ -){ - int a[3], i; - double r; - char *z; - if( argc!=5 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " FORMAT INT INT DOUBLE\"", 0); - return TCL_ERROR; - } - for(i=2; i<4; i++){ - if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR; - } - if( Tcl_GetDouble(interp, argv[4], &r) ) return TCL_ERROR; - z = sqlite3_mprintf(argv[1], a[0], a[1], r); - Tcl_AppendResult(interp, z, 0); - sqlite3_free(z); - return TCL_OK; -} - -/* -** Usage: sqlite3_mprintf_scaled FORMAT DOUBLE DOUBLE -** -** Call mprintf with a single double argument which is the product of the -** two arguments given above. This is used to generate overflow and underflow -** doubles to test that they are converted properly. -*/ -static int sqlite3_mprintf_scaled( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - char **argv /* Text of each argument */ -){ - int i; - double r[2]; - char *z; - if( argc!=4 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " FORMAT DOUBLE DOUBLE\"", 0); - return TCL_ERROR; - } - for(i=2; i<4; i++){ - if( Tcl_GetDouble(interp, argv[i], &r[i-2]) ) return TCL_ERROR; - } - z = sqlite3_mprintf(argv[1], r[0]*r[1]); - Tcl_AppendResult(interp, z, 0); - sqlite3_free(z); - return TCL_OK; -} - -/* -** Usage: sqlite3_mprintf_stronly FORMAT STRING -** -** Call mprintf with a single double argument which is the product of the -** two arguments given above. This is used to generate overflow and underflow -** doubles to test that they are converted properly. -*/ -static int sqlite3_mprintf_stronly( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - char **argv /* Text of each argument */ -){ - char *z; - if( argc!=3 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " FORMAT STRING\"", 0); - return TCL_ERROR; - } - z = sqlite3_mprintf(argv[1], argv[2]); - Tcl_AppendResult(interp, z, 0); - sqlite3_free(z); - return TCL_OK; -} - -/* -** Usage: sqlite3_mprintf_hexdouble FORMAT HEX -** -** Call mprintf with a single double argument which is derived from the -** hexadecimal encoding of an IEEE double. -*/ -static int sqlite3_mprintf_hexdouble( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - char **argv /* Text of each argument */ -){ - char *z; - double r; - unsigned int x1, x2; - sqlite_uint64 d; - if( argc!=3 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " FORMAT STRING\"", 0); - return TCL_ERROR; - } - if( sscanf(argv[2], "%08x%08x", &x2, &x1)!=2 ){ - Tcl_AppendResult(interp, "2nd argument should be 16-characters of hex", 0); - return TCL_ERROR; - } - d = x2; - d = (d<<32) + x1; - memcpy(&r, &d, sizeof(r)); - z = sqlite3_mprintf(argv[1], r); - Tcl_AppendResult(interp, z, 0); - sqlite3_free(z); - return TCL_OK; -} - -/* -** 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 && objc!=1 ){ - Tcl_WrongNumArgs(interp, 1, objv, "?BOOLEAN?"); - return TCL_ERROR; - } - ret = sqlite3GlobalConfig.sharedCacheEnabled; - - if( objc==2 ){ - if( Tcl_GetBooleanFromObj(interp, objv[1], &enable) ){ - return TCL_ERROR; - } - 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_extended_result_codes DB BOOLEAN -** -*/ -static int test_extended_result_codes( - 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 enable; - sqlite3 *db; - - if( objc!=3 ){ - Tcl_WrongNumArgs(interp, 1, objv, "DB BOOLEAN"); - return TCL_ERROR; - } - if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; - if( Tcl_GetBooleanFromObj(interp, objv[2], &enable) ) return TCL_ERROR; - sqlite3_extended_result_codes(db, enable); - return TCL_OK; -} - -/* -** 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 - -#ifndef SQLITE_OMIT_INCRBLOB - -static int blobHandleFromObj( - Tcl_Interp *interp, - Tcl_Obj *pObj, - sqlite3_blob **ppBlob -){ - char *z; - int n; - - z = Tcl_GetStringFromObj(pObj, &n); - if( n==0 ){ - *ppBlob = 0; - }else{ - int notUsed; - Tcl_Channel channel; - ClientData instanceData; - - channel = Tcl_GetChannel(interp, z, ¬Used); - if( !channel ) return TCL_ERROR; - - Tcl_Flush(channel); - Tcl_Seek(channel, 0, SEEK_SET); - - instanceData = Tcl_GetChannelInstanceData(channel); - *ppBlob = *((sqlite3_blob **)instanceData); - } - - return TCL_OK; -} - -/* -** sqlite3_blob_bytes CHANNEL -*/ -static int test_blob_bytes( - 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 */ -){ - sqlite3_blob *pBlob; - int nByte; - - if( objc!=2 ){ - Tcl_WrongNumArgs(interp, 1, objv, "CHANNEL"); - return TCL_ERROR; - } - - if( blobHandleFromObj(interp, objv[1], &pBlob) ) return TCL_ERROR; - nByte = sqlite3_blob_bytes(pBlob); - Tcl_SetObjResult(interp, Tcl_NewIntObj(nByte)); - - return TCL_OK; -} - -/* -** sqlite3_blob_close CHANNEL -*/ -static int test_blob_close( - 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 */ -){ - sqlite3_blob *pBlob; - - if( objc!=2 ){ - Tcl_WrongNumArgs(interp, 1, objv, "CHANNEL"); - return TCL_ERROR; - } - - if( blobHandleFromObj(interp, objv[1], &pBlob) ) return TCL_ERROR; - sqlite3_blob_close(pBlob); - - return TCL_OK; -} - -/* -** sqlite3_blob_read CHANNEL OFFSET N -** -** This command is used to test the sqlite3_blob_read() in ways that -** the Tcl channel interface does not. The first argument should -** be the name of a valid channel created by the [incrblob] method -** of a database handle. This function calls sqlite3_blob_read() -** to read N bytes from offset OFFSET from the underlying SQLite -** blob handle. -** -** On success, a byte-array object containing the read data is -** returned. On failure, the interpreter result is set to the -** text representation of the returned error code (i.e. "SQLITE_NOMEM") -** and a Tcl exception is thrown. -*/ -static int test_blob_read( - 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 */ -){ - sqlite3_blob *pBlob; - int nByte; - int iOffset; - unsigned char *zBuf = 0; - int rc; - - if( objc!=4 ){ - Tcl_WrongNumArgs(interp, 1, objv, "CHANNEL OFFSET N"); - return TCL_ERROR; - } - - if( blobHandleFromObj(interp, objv[1], &pBlob) ) return TCL_ERROR; - if( TCL_OK!=Tcl_GetIntFromObj(interp, objv[2], &iOffset) - || TCL_OK!=Tcl_GetIntFromObj(interp, objv[3], &nByte) - ){ - return TCL_ERROR; - } - - if( nByte>0 ){ - zBuf = (unsigned char *)Tcl_Alloc(nByte); - } - rc = sqlite3_blob_read(pBlob, zBuf, nByte, iOffset); - if( rc==SQLITE_OK ){ - Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(zBuf, nByte)); - }else{ - Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE); - } - Tcl_Free((char *)zBuf); - - return (rc==SQLITE_OK ? TCL_OK : TCL_ERROR); -} - -/* -** sqlite3_blob_write CHANNEL OFFSET DATA ?NDATA? -** -** This command is used to test the sqlite3_blob_write() in ways that -** the Tcl channel interface does not. The first argument should -** be the name of a valid channel created by the [incrblob] method -** of a database handle. This function calls sqlite3_blob_write() -** to write the DATA byte-array to the underlying SQLite blob handle. -** at offset OFFSET. -** -** On success, an empty string is returned. On failure, the interpreter -** result is set to the text representation of the returned error code -** (i.e. "SQLITE_NOMEM") and a Tcl exception is thrown. -*/ -static int test_blob_write( - 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 */ -){ - sqlite3_blob *pBlob; - int iOffset; - int rc; - - unsigned char *zBuf; - int nBuf; - - if( objc!=4 && objc!=5 ){ - Tcl_WrongNumArgs(interp, 1, objv, "CHANNEL OFFSET DATA ?NDATA?"); - return TCL_ERROR; - } - - if( blobHandleFromObj(interp, objv[1], &pBlob) ) return TCL_ERROR; - if( TCL_OK!=Tcl_GetIntFromObj(interp, objv[2], &iOffset) ){ - return TCL_ERROR; - } - - zBuf = Tcl_GetByteArrayFromObj(objv[3], &nBuf); - if( objc==5 && Tcl_GetIntFromObj(interp, objv[4], &nBuf) ){ - return TCL_ERROR; - } - rc = sqlite3_blob_write(pBlob, zBuf, nBuf, iOffset); - if( rc!=SQLITE_OK ){ - Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE); - } - - return (rc==SQLITE_OK ? TCL_OK : TCL_ERROR); -} - -static int test_blob_reopen( - 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_WideInt iRowid; - sqlite3_blob *pBlob; - int rc; - - if( objc!=3 ){ - Tcl_WrongNumArgs(interp, 1, objv, "CHANNEL ROWID"); - return TCL_ERROR; - } - - if( blobHandleFromObj(interp, objv[1], &pBlob) ) return TCL_ERROR; - if( Tcl_GetWideIntFromObj(interp, objv[2], &iRowid) ) return TCL_ERROR; - - rc = sqlite3_blob_reopen(pBlob, iRowid); - if( rc!=SQLITE_OK ){ - Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE); - } - - return (rc==SQLITE_OK ? TCL_OK : TCL_ERROR); -} - -#endif - -/* -** Usage: sqlite3_create_collation_v2 DB-HANDLE NAME CMP-PROC DEL-PROC -** -** This Tcl proc is used for testing the experimental -** sqlite3_create_collation_v2() interface. -*/ -struct TestCollationX { - Tcl_Interp *interp; - Tcl_Obj *pCmp; - Tcl_Obj *pDel; -}; -typedef struct TestCollationX TestCollationX; -static void testCreateCollationDel(void *pCtx){ - TestCollationX *p = (TestCollationX *)pCtx; - - int rc = Tcl_EvalObjEx(p->interp, p->pDel, TCL_EVAL_DIRECT|TCL_EVAL_GLOBAL); - if( rc!=TCL_OK ){ - Tcl_BackgroundError(p->interp); - } - - Tcl_DecrRefCount(p->pCmp); - Tcl_DecrRefCount(p->pDel); - sqlite3_free((void *)p); -} -static int testCreateCollationCmp( - void *pCtx, - int nLeft, - const void *zLeft, - int nRight, - const void *zRight -){ - TestCollationX *p = (TestCollationX *)pCtx; - Tcl_Obj *pScript = Tcl_DuplicateObj(p->pCmp); - int iRes = 0; - - Tcl_IncrRefCount(pScript); - Tcl_ListObjAppendElement(0, pScript, Tcl_NewStringObj((char *)zLeft, nLeft)); - Tcl_ListObjAppendElement(0, pScript, Tcl_NewStringObj((char *)zRight,nRight)); - - if( TCL_OK!=Tcl_EvalObjEx(p->interp, pScript, TCL_EVAL_DIRECT|TCL_EVAL_GLOBAL) - || TCL_OK!=Tcl_GetIntFromObj(p->interp, Tcl_GetObjResult(p->interp), &iRes) - ){ - Tcl_BackgroundError(p->interp); - } - Tcl_DecrRefCount(pScript); - - return iRes; -} -static int test_create_collation_v2( - 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 */ -){ - TestCollationX *p; - sqlite3 *db; - int rc; - - if( objc!=5 ){ - Tcl_WrongNumArgs(interp, 1, objv, "DB-HANDLE NAME CMP-PROC DEL-PROC"); - return TCL_ERROR; - } - if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; - - p = (TestCollationX *)sqlite3_malloc(sizeof(TestCollationX)); - p->pCmp = objv[3]; - p->pDel = objv[4]; - p->interp = interp; - Tcl_IncrRefCount(p->pCmp); - Tcl_IncrRefCount(p->pDel); - - rc = sqlite3_create_collation_v2(db, Tcl_GetString(objv[2]), 16, - (void *)p, testCreateCollationCmp, testCreateCollationDel - ); - if( rc!=SQLITE_MISUSE ){ - Tcl_AppendResult(interp, "sqlite3_create_collate_v2() failed to detect " - "an invalid encoding", (char*)0); - return TCL_ERROR; - } - rc = sqlite3_create_collation_v2(db, Tcl_GetString(objv[2]), SQLITE_UTF8, - (void *)p, testCreateCollationCmp, testCreateCollationDel - ); - return TCL_OK; -} - -/* -** USAGE: sqlite3_create_function_v2 DB NAME NARG ENC ?SWITCHES? -** -** Available switches are: -** -** -func SCRIPT -** -step SCRIPT -** -final SCRIPT -** -destroy SCRIPT -*/ -typedef struct CreateFunctionV2 CreateFunctionV2; -struct CreateFunctionV2 { - Tcl_Interp *interp; - Tcl_Obj *pFunc; /* Script for function invocation */ - Tcl_Obj *pStep; /* Script for agg. step invocation */ - Tcl_Obj *pFinal; /* Script for agg. finalization invocation */ - Tcl_Obj *pDestroy; /* Destructor script */ -}; -static void cf2Func(sqlite3_context *ctx, int nArg, sqlite3_value **aArg){ -} -static void cf2Step(sqlite3_context *ctx, int nArg, sqlite3_value **aArg){ -} -static void cf2Final(sqlite3_context *ctx){ -} -static void cf2Destroy(void *pUser){ - CreateFunctionV2 *p = (CreateFunctionV2 *)pUser; - - if( p->interp && p->pDestroy ){ - int rc = Tcl_EvalObjEx(p->interp, p->pDestroy, 0); - if( rc!=TCL_OK ) Tcl_BackgroundError(p->interp); - } - - if( p->pFunc ) Tcl_DecrRefCount(p->pFunc); - if( p->pStep ) Tcl_DecrRefCount(p->pStep); - if( p->pFinal ) Tcl_DecrRefCount(p->pFinal); - if( p->pDestroy ) Tcl_DecrRefCount(p->pDestroy); - sqlite3_free(p); -} -static int test_create_function_v2( - ClientData clientData, /* Not used */ - Tcl_Interp *interp, /* The invoking TCL interpreter */ - int objc, /* Number of arguments */ - Tcl_Obj *CONST objv[] /* Command arguments */ -){ - sqlite3 *db; - const char *zFunc; - int nArg; - int enc; - CreateFunctionV2 *p; - int i; - int rc; - - struct EncTable { - const char *zEnc; - int enc; - } aEnc[] = { - {"utf8", SQLITE_UTF8 }, - {"utf16", SQLITE_UTF16 }, - {"utf16le", SQLITE_UTF16LE }, - {"utf16be", SQLITE_UTF16BE }, - {"any", SQLITE_ANY }, - {"0", 0 } - }; - - if( objc<5 || (objc%2)==0 ){ - Tcl_WrongNumArgs(interp, 1, objv, "DB NAME NARG ENC SWITCHES..."); - return TCL_ERROR; - } - - if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; - zFunc = Tcl_GetString(objv[2]); - if( Tcl_GetIntFromObj(interp, objv[3], &nArg) ) return TCL_ERROR; - if( Tcl_GetIndexFromObjStruct(interp, objv[4], aEnc, sizeof(aEnc[0]), - "encoding", 0, &enc) - ){ - return TCL_ERROR; - } - enc = aEnc[enc].enc; - - p = sqlite3_malloc(sizeof(CreateFunctionV2)); - assert( p ); - memset(p, 0, sizeof(CreateFunctionV2)); - p->interp = interp; - - for(i=5; i<objc; i+=2){ - int iSwitch; - const char *azSwitch[] = {"-func", "-step", "-final", "-destroy", 0}; - if( Tcl_GetIndexFromObj(interp, objv[i], azSwitch, "switch", 0, &iSwitch) ){ - sqlite3_free(p); - return TCL_ERROR; - } - - switch( iSwitch ){ - case 0: p->pFunc = objv[i+1]; break; - case 1: p->pStep = objv[i+1]; break; - case 2: p->pFinal = objv[i+1]; break; - case 3: p->pDestroy = objv[i+1]; break; - } - } - if( p->pFunc ) p->pFunc = Tcl_DuplicateObj(p->pFunc); - if( p->pStep ) p->pStep = Tcl_DuplicateObj(p->pStep); - if( p->pFinal ) p->pFinal = Tcl_DuplicateObj(p->pFinal); - if( p->pDestroy ) p->pDestroy = Tcl_DuplicateObj(p->pDestroy); - - if( p->pFunc ) Tcl_IncrRefCount(p->pFunc); - if( p->pStep ) Tcl_IncrRefCount(p->pStep); - if( p->pFinal ) Tcl_IncrRefCount(p->pFinal); - if( p->pDestroy ) Tcl_IncrRefCount(p->pDestroy); - - rc = sqlite3_create_function_v2(db, zFunc, nArg, enc, (void *)p, - (p->pFunc ? cf2Func : 0), - (p->pStep ? cf2Step : 0), - (p->pFinal ? cf2Final : 0), - cf2Destroy - ); - if( rc!=SQLITE_OK ){ - Tcl_ResetResult(interp); - Tcl_AppendResult(interp, sqlite3ErrName(rc), 0); - return TCL_ERROR; - } - return TCL_OK; -} - -/* -** 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. -** This command is used to test the recoverability of a database in -** the event of a program crash. -*/ -static int sqlite_abort( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - char **argv /* Text of each argument */ -){ -#if defined(_MSC_VER) - /* We do this, otherwise the test will halt with a popup message - * that we have to click away before the test will continue. - */ - _set_abort_behavior( 0, _CALL_REPORTFAULT ); -#endif - exit(255); - assert( interp==0 ); /* This will always fail */ - return TCL_OK; -} - -/* -** The following routine is a user-defined SQL function whose purpose -** is to test the sqlite_set_result() API. -*/ -static void testFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ - while( argc>=2 ){ - 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, (char*)sqlite3_value_text(argv[1]), -1, - SQLITE_TRANSIENT); - }else if( sqlite3StrICmp(zArg0,"double")==0 ){ - sqlite3_result_double(context, sqlite3_value_double(argv[1])); - }else if( sqlite3StrICmp(zArg0,"null")==0 ){ - sqlite3_result_null(context); - }else if( sqlite3StrICmp(zArg0,"value")==0 ){ - sqlite3_result_value(context, argv[sqlite3_value_int(argv[1])]); - }else{ - goto error_out; - } - }else{ - goto error_out; - } - argc -= 2; - argv += 2; - } - return; - -error_out: - sqlite3_result_error(context,"first argument should be one of: " - "int int64 string double null value", -1); -} - -/* -** Usage: sqlite_register_test_function DB NAME -** -** Register the test SQL function on the database DB under the name NAME. -*/ -static int test_register_func( - 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!=3 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " DB FUNCTION-NAME", 0); - return TCL_ERROR; - } - if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; - rc = sqlite3_create_function(db, argv[2], -1, SQLITE_UTF8, 0, - testFunc, 0, 0); - if( rc!=0 ){ - Tcl_AppendResult(interp, sqlite3ErrStr(rc), 0); - return TCL_ERROR; - } - if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; - return TCL_OK; -} - -/* -** Usage: sqlite3_finalize STMT -** -** Finalize a statement handle. -*/ -static int test_finalize( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - sqlite3_stmt *pStmt; - int rc; - sqlite3 *db = 0; - - 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; - - if( pStmt ){ - db = StmtToDb(pStmt); - } - rc = sqlite3_finalize(pStmt); - Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC); - if( db && sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; - return TCL_OK; -} - -/* -** Usage: sqlite3_stmt_status STMT CODE RESETFLAG -** -** Get the value of a status counter from a statement. -*/ -static int test_stmt_status( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - int iValue; - int i, op, resetFlag; - const char *zOpName; - sqlite3_stmt *pStmt; - - static const struct { - const char *zName; - int op; - } aOp[] = { - { "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"); - return TCL_ERROR; - } - if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; - zOpName = Tcl_GetString(objv[2]); - for(i=0; i<ArraySize(aOp); i++){ - if( strcmp(aOp[i].zName, zOpName)==0 ){ - op = aOp[i].op; - break; - } - } - if( i>=ArraySize(aOp) ){ - if( Tcl_GetIntFromObj(interp, objv[2], &op) ) return TCL_ERROR; - } - if( Tcl_GetBooleanFromObj(interp, objv[3], &resetFlag) ) return TCL_ERROR; - iValue = sqlite3_stmt_status(pStmt, op, resetFlag); - Tcl_SetObjResult(interp, Tcl_NewIntObj(iValue)); - return TCL_OK; -} - -/* -** Usage: sqlite3_next_stmt DB STMT -** -** Return the next statment in sequence after STMT. -*/ -static int test_next_stmt( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - sqlite3_stmt *pStmt; - sqlite3 *db = 0; - char zBuf[50]; - - if( objc!=3 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", - Tcl_GetStringFromObj(objv[0], 0), " DB STMT", 0); - return TCL_ERROR; - } - - if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; - if( getStmtPointer(interp, Tcl_GetString(objv[2]), &pStmt) ) return TCL_ERROR; - pStmt = sqlite3_next_stmt(db, pStmt); - if( pStmt ){ - if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR; - Tcl_AppendResult(interp, zBuf, 0); - } - return TCL_OK; -} - -/* -** Usage: sqlite3_stmt_readonly STMT -** -** Return true if STMT is a NULL pointer or a pointer to a statement -** that is guaranteed to leave the database unmodified. -*/ -static int test_stmt_readonly( - 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_readonly(pStmt); - Tcl_SetObjResult(interp, Tcl_NewBooleanObj(rc)); - 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 -** -** Reset a statement handle. -*/ -static int test_reset( - 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_reset(pStmt); - if( pStmt && sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ){ - return TCL_ERROR; - } - Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC); -/* - if( rc ){ - return TCL_ERROR; - } -*/ - return TCL_OK; -} - -/* -** Usage: sqlite3_expired STMT -** -** Return TRUE if a recompilation of the statement is recommended. -*/ -static int test_expired( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ -#ifndef SQLITE_OMIT_DEPRECATED - 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; - Tcl_SetObjResult(interp, Tcl_NewBooleanObj(sqlite3_expired(pStmt))); -#endif - return TCL_OK; -} - -/* -** Usage: sqlite3_transfer_bindings FROMSTMT TOSTMT -** -** Transfer all bindings from FROMSTMT over to TOSTMT -*/ -static int test_transfer_bind( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ -#ifndef SQLITE_OMIT_DEPRECATED - sqlite3_stmt *pStmt1, *pStmt2; - if( objc!=3 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", - Tcl_GetStringFromObj(objv[0], 0), " FROM-STMT TO-STMT", 0); - return TCL_ERROR; - } - if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt1)) return TCL_ERROR; - if( getStmtPointer(interp, Tcl_GetString(objv[2]), &pStmt2)) return TCL_ERROR; - Tcl_SetObjResult(interp, - Tcl_NewIntObj(sqlite3_transfer_bindings(pStmt1,pStmt2))); -#endif - return TCL_OK; -} - -/* -** Usage: sqlite3_changes DB -** -** Return the number of changes made to the database by the last SQL -** execution. -*/ -static int test_changes( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - sqlite3 *db; - if( objc!=2 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", - Tcl_GetString(objv[0]), " DB", 0); - return TCL_ERROR; - } - if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; - Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_changes(db))); - return TCL_OK; -} - -/* -** This is the "static_bind_value" that variables are bound to when -** the FLAG option of sqlite3_bind is "static" -*/ -static char *sqlite_static_bind_value = 0; -static int sqlite_static_bind_nbyte = 0; - -/* -** Usage: sqlite3_bind VM IDX VALUE FLAGS -** -** 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 -** "sqlite_static_bind_value". If FLAGS=="normal" then a copy -** 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, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - char **argv /* Text of each argument */ -){ - sqlite3_stmt *pStmt; - int rc; - int idx; - if( argc!=5 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " VM IDX VALUE (null|static|normal)\"", 0); - return TCL_ERROR; - } - if( getStmtPointer(interp, argv[1], &pStmt) ) return TCL_ERROR; - if( Tcl_GetInt(interp, argv[2], &idx) ) return TCL_ERROR; - if( strcmp(argv[4],"null")==0 ){ - rc = sqlite3_bind_null(pStmt, idx); - }else if( strcmp(argv[4],"static")==0 ){ - rc = sqlite3_bind_text(pStmt, idx, sqlite_static_bind_value, -1, 0); - }else if( strcmp(argv[4],"static-nbytes")==0 ){ - rc = sqlite3_bind_text(pStmt, idx, sqlite_static_bind_value, - sqlite_static_bind_nbyte, 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); - return TCL_ERROR; - } - if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR; - if( rc ){ - char zBuf[50]; - sprintf(zBuf, "(%d) ", rc); - Tcl_AppendResult(interp, zBuf, sqlite3ErrStr(rc), 0); - return TCL_ERROR; - } - return TCL_OK; -} - -#ifndef SQLITE_OMIT_UTF16 -/* -** Usage: add_test_collate <db ptr> <utf8> <utf16le> <utf16be> -** -** This function is used to test that SQLite selects the correct collation -** sequence callback when multiple versions (for different text encodings) -** are available. -** -** Calling this routine registers the collation sequence "test_collate" -** with database handle <db>. The second argument must be a list of three -** boolean values. If the first is true, then a version of test_collate is -** registered for UTF-8, if the second is true, a version is registered for -** UTF-16le, if the third is true, a UTF-16be version is available. -** Previous versions of test_collate are deleted. -** -** The collation sequence test_collate is implemented by calling the -** following TCL script: -** -** "test_collate <enc> <lhs> <rhs>" -** -** The <lhs> and <rhs> are the two values being compared, encoded in UTF-8. -** The <enc> parameter is the encoding of the collation function that -** 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 -** interp pointer to use when evaluating the TCL script is stored in -** pTestCollateInterp. -*/ -static Tcl_Interp* pTestCollateInterp; -static int test_collate_func( - void *pCtx, - int nA, const void *zA, - int nB, const void *zB -){ - Tcl_Interp *i = pTestCollateInterp; - int encin = SQLITE_PTR_TO_INT(pCtx); - int res; - int n; - - sqlite3_value *pVal; - Tcl_Obj *pX; - - pX = Tcl_NewStringObj("test_collate", -1); - Tcl_IncrRefCount(pX); - - switch( encin ){ - case SQLITE_UTF8: - Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-8",-1)); - break; - case SQLITE_UTF16LE: - Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-16LE",-1)); - break; - case SQLITE_UTF16BE: - Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-16BE",-1)); - break; - default: - assert(0); - } - - sqlite3BeginBenignMalloc(); - pVal = sqlite3ValueNew(0); - if( pVal ){ - sqlite3ValueSetStr(pVal, nA, zA, encin, SQLITE_STATIC); - n = sqlite3_value_bytes(pVal); - 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((char*)sqlite3_value_text(pVal),n)); - sqlite3ValueFree(pVal); - } - sqlite3EndBenignMalloc(); - - Tcl_EvalObjEx(i, pX, 0); - Tcl_DecrRefCount(pX); - Tcl_GetIntFromObj(i, Tcl_GetObjResult(i), &res); - return res; -} -static int test_collate( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - sqlite3 *db; - int val; - sqlite3_value *pVal; - int rc; - - if( objc!=5 ) goto bad_args; - pTestCollateInterp = interp; - if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; - - if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[2], &val) ) return TCL_ERROR; - rc = sqlite3_create_collation(db, "test_collate", SQLITE_UTF8, - (void *)SQLITE_UTF8, val?test_collate_func:0); - if( rc==SQLITE_OK ){ - const void *zUtf16; - if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[3], &val) ) return TCL_ERROR; - rc = sqlite3_create_collation(db, "test_collate", SQLITE_UTF16LE, - (void *)SQLITE_UTF16LE, val?test_collate_func:0); - if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[4], &val) ) return TCL_ERROR; - -#if 0 - if( sqlite3_iMallocFail>0 ){ - sqlite3_iMallocFail++; - } -#endif - sqlite3_mutex_enter(db->mutex); - pVal = sqlite3ValueNew(db); - sqlite3ValueSetStr(pVal, -1, "test_collate", SQLITE_UTF8, SQLITE_STATIC); - zUtf16 = sqlite3ValueText(pVal, SQLITE_UTF16NATIVE); - if( db->mallocFailed ){ - rc = SQLITE_NOMEM; - }else{ - rc = sqlite3_create_collation16(db, zUtf16, SQLITE_UTF16BE, - (void *)SQLITE_UTF16BE, val?test_collate_func:0); - } - sqlite3ValueFree(pVal); - sqlite3_mutex_leave(db->mutex); - } - if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; - - if( rc!=SQLITE_OK ){ - Tcl_AppendResult(interp, sqlite3ErrName(rc), 0); - return TCL_ERROR; - } - return TCL_OK; - -bad_args: - Tcl_AppendResult(interp, "wrong # args: should be \"", - Tcl_GetStringFromObj(objv[0], 0), " <DB> <utf8> <utf16le> <utf16be>", 0); - 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 *pName -){ - 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", ENC(db), SQLITE_INT_TO_PTR(enc), test_collate_func); -} - -/* -** Usage: add_test_collate_needed DB -*/ -static int test_collate_needed( - 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_collation_needed16(db, 0, test_collate_needed_cb); - zNeededCollation[0] = 0; - if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; - return TCL_OK; - -bad_args: - Tcl_WrongNumArgs(interp, 1, objv, "DB"); - return TCL_ERROR; -} - -/* -** 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&(SQLITE_PTR_TO_INT(pKey1))) ) unaligned_string_counter++; - if( nKey2>0 && 1==(1&(SQLITE_PTR_TO_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_ALIGNED, - 0, alignmentCollFunc); - } - return SQLITE_OK; -} -#endif /* !defined(SQLITE_OMIT_UTF16) */ - -/* -** Usage: add_test_function <db ptr> <utf8> <utf16le> <utf16be> -** -** This function is used to test that SQLite selects the correct user -** function callback when multiple versions (for different text encodings) -** are available. -** -** Calling this routine registers up to three versions of the user function -** "test_function" with database handle <db>. If the second argument is -** true, then a version of test_function is registered for UTF-8, if the -** third is true, a version is registered for UTF-16le, if the fourth is -** true, a UTF-16be version is available. Previous versions of -** test_function are deleted. -** -** The user function is implemented by calling the following TCL script: -** -** "test_function <enc> <arg>" -** -** Where <enc> is one of UTF-8, UTF-16LE or UTF16BE, and <arg> is the -** single argument passed to the SQL function. The value returned by -** the TCL script is used as the return value of the SQL function. It -** is passed to SQLite using UTF-16BE for a UTF-8 test_function(), UTF-8 -** for a UTF-16LE test_function(), and UTF-16LE for an implementation that -** prefers UTF-16BE. -*/ -#ifndef SQLITE_OMIT_UTF16 -static void test_function_utf8( - sqlite3_context *pCtx, - int nArg, - sqlite3_value **argv -){ - Tcl_Interp *interp; - Tcl_Obj *pX; - sqlite3_value *pVal; - interp = (Tcl_Interp *)sqlite3_user_data(pCtx); - pX = Tcl_NewStringObj("test_function", -1); - Tcl_IncrRefCount(pX); - Tcl_ListObjAppendElement(interp, pX, Tcl_NewStringObj("UTF-8", -1)); - Tcl_ListObjAppendElement(interp, pX, - 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); - pVal = sqlite3ValueNew(0); - sqlite3ValueSetStr(pVal, -1, Tcl_GetStringResult(interp), - SQLITE_UTF8, SQLITE_STATIC); - sqlite3_result_text16be(pCtx, sqlite3_value_text16be(pVal), - -1, SQLITE_TRANSIENT); - sqlite3ValueFree(pVal); -} -static void test_function_utf16le( - sqlite3_context *pCtx, - int nArg, - sqlite3_value **argv -){ - Tcl_Interp *interp; - Tcl_Obj *pX; - sqlite3_value *pVal; - interp = (Tcl_Interp *)sqlite3_user_data(pCtx); - pX = Tcl_NewStringObj("test_function", -1); - Tcl_IncrRefCount(pX); - Tcl_ListObjAppendElement(interp, pX, Tcl_NewStringObj("UTF-16LE", -1)); - Tcl_ListObjAppendElement(interp, pX, - Tcl_NewStringObj((char*)sqlite3_value_text(argv[0]), -1)); - Tcl_EvalObjEx(interp, pX, 0); - Tcl_DecrRefCount(pX); - pVal = sqlite3ValueNew(0); - sqlite3ValueSetStr(pVal, -1, Tcl_GetStringResult(interp), - SQLITE_UTF8, SQLITE_STATIC); - sqlite3_result_text(pCtx,(char*)sqlite3_value_text(pVal),-1,SQLITE_TRANSIENT); - sqlite3ValueFree(pVal); -} -static void test_function_utf16be( - sqlite3_context *pCtx, - int nArg, - sqlite3_value **argv -){ - Tcl_Interp *interp; - Tcl_Obj *pX; - sqlite3_value *pVal; - interp = (Tcl_Interp *)sqlite3_user_data(pCtx); - pX = Tcl_NewStringObj("test_function", -1); - Tcl_IncrRefCount(pX); - Tcl_ListObjAppendElement(interp, pX, Tcl_NewStringObj("UTF-16BE", -1)); - Tcl_ListObjAppendElement(interp, pX, - Tcl_NewStringObj((char*)sqlite3_value_text(argv[0]), -1)); - Tcl_EvalObjEx(interp, pX, 0); - Tcl_DecrRefCount(pX); - pVal = sqlite3ValueNew(0); - sqlite3ValueSetStr(pVal, -1, Tcl_GetStringResult(interp), - SQLITE_UTF8, SQLITE_STATIC); - sqlite3_result_text16(pCtx, sqlite3_value_text16le(pVal), - -1, SQLITE_TRANSIENT); - sqlite3_result_text16be(pCtx, sqlite3_value_text16le(pVal), - -1, SQLITE_TRANSIENT); - sqlite3_result_text16le(pCtx, sqlite3_value_text16le(pVal), - -1, SQLITE_TRANSIENT); - sqlite3ValueFree(pVal); -} -#endif /* SQLITE_OMIT_UTF16 */ -static int test_function( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ -#ifndef SQLITE_OMIT_UTF16 - sqlite3 *db; - int val; - - if( objc!=5 ) goto bad_args; - if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; - - if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[2], &val) ) return TCL_ERROR; - if( val ){ - sqlite3_create_function(db, "test_function", 1, SQLITE_UTF8, - interp, test_function_utf8, 0, 0); - } - if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[3], &val) ) return TCL_ERROR; - if( val ){ - sqlite3_create_function(db, "test_function", 1, SQLITE_UTF16LE, - interp, test_function_utf16le, 0, 0); - } - if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[4], &val) ) return TCL_ERROR; - if( val ){ - sqlite3_create_function(db, "test_function", 1, SQLITE_UTF16BE, - interp, test_function_utf16be, 0, 0); - } - - return TCL_OK; -bad_args: - Tcl_AppendResult(interp, "wrong # args: should be \"", - Tcl_GetStringFromObj(objv[0], 0), " <DB> <utf8> <utf16le> <utf16be>", 0); -#endif /* SQLITE_OMIT_UTF16 */ - return TCL_ERROR; -} - -/* -** Usage: sqlite3_test_errstr <err code> -** -** Test that the english language string equivalents for sqlite error codes -** are sane. The parameter is an integer representing an sqlite error code. -** The result is a list of two elements, the string representation of the -** error code and the english language explanation. -*/ -static int test_errstr( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - char *zCode; - int i; - if( objc!=1 ){ - Tcl_WrongNumArgs(interp, 1, objv, "<error code>"); - } - - zCode = Tcl_GetString(objv[1]); - for(i=0; i<200; i++){ - if( 0==strcmp(t1ErrorName(i), zCode) ) break; - } - Tcl_SetResult(interp, (char *)sqlite3ErrStr(i), 0); - return TCL_OK; -} - -/* -** Usage: breakpoint -** -** This routine exists for one purpose - to provide a place to put a -** breakpoint with GDB that can be triggered using TCL code. The use -** for this is when a particular test fails on (say) the 1485th iteration. -** In the TCL test script, we can add code like this: -** -** if {$i==1485} breakpoint -** -** Then run testfixture in the debugger and wait for the breakpoint to -** fire. Then additional breakpoints can be set to trace down the bug. -*/ -static int test_breakpoint( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - char **argv /* Text of each argument */ -){ - return TCL_OK; /* Do nothing */ -} - -/* -** Usage: sqlite3_bind_zeroblob STMT IDX N -** -** Test the sqlite3_bind_zeroblob interface. STMT is a prepared statement. -** IDX is the index of a wildcard in the prepared statement. This command -** binds a N-byte zero-filled BLOB to the wildcard. -*/ -static int test_bind_zeroblob( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - sqlite3_stmt *pStmt; - int idx; - int n; - int rc; - - if( objc!=4 ){ - Tcl_WrongNumArgs(interp, 1, objv, "STMT IDX N"); - return TCL_ERROR; - } - - if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; - if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; - if( Tcl_GetIntFromObj(interp, objv[3], &n) ) return TCL_ERROR; - - rc = sqlite3_bind_zeroblob(pStmt, idx, n); - if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR; - if( rc!=SQLITE_OK ){ - return TCL_ERROR; - } - - return TCL_OK; -} - -/* -** Usage: sqlite3_bind_int STMT N VALUE -** -** Test the sqlite3_bind_int interface. STMT is a prepared statement. -** N is the index of a wildcard in the prepared statement. This command -** binds a 32-bit integer VALUE to that wildcard. -*/ -static int test_bind_int( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - sqlite3_stmt *pStmt; - int idx; - int value; - int rc; - - if( objc!=4 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", - Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE", 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; - if( Tcl_GetIntFromObj(interp, objv[3], &value) ) return TCL_ERROR; - - rc = sqlite3_bind_int(pStmt, idx, value); - if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR; - if( rc!=SQLITE_OK ){ - return TCL_ERROR; - } - - return TCL_OK; -} - - -/* -** Usage: sqlite3_bind_int64 STMT N VALUE -** -** Test the sqlite3_bind_int64 interface. STMT is a prepared statement. -** N is the index of a wildcard in the prepared statement. This command -** binds a 64-bit integer VALUE to that wildcard. -*/ -static int test_bind_int64( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - sqlite3_stmt *pStmt; - int idx; - Tcl_WideInt value; - int rc; - - if( objc!=4 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", - Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE", 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; - if( Tcl_GetWideIntFromObj(interp, objv[3], &value) ) return TCL_ERROR; - - rc = sqlite3_bind_int64(pStmt, idx, value); - if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR; - if( rc!=SQLITE_OK ){ - return TCL_ERROR; - } - - return TCL_OK; -} - - -/* -** Usage: sqlite3_bind_double STMT N VALUE -** -** Test the sqlite3_bind_double interface. STMT is a prepared statement. -** N is the index of a wildcard in the prepared statement. This command -** binds a 64-bit integer VALUE to that wildcard. -*/ -static int test_bind_double( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - sqlite3_stmt *pStmt; - int idx; - double value; - int rc; - const char *zVal; - int i; - static const struct { - const char *zName; /* Name of the special floating point value */ - unsigned int iUpper; /* Upper 32 bits */ - unsigned int iLower; /* Lower 32 bits */ - } aSpecialFp[] = { - { "NaN", 0x7fffffff, 0xffffffff }, - { "SNaN", 0x7ff7ffff, 0xffffffff }, - { "-NaN", 0xffffffff, 0xffffffff }, - { "-SNaN", 0xfff7ffff, 0xffffffff }, - { "+Inf", 0x7ff00000, 0x00000000 }, - { "-Inf", 0xfff00000, 0x00000000 }, - { "Epsilon", 0x00000000, 0x00000001 }, - { "-Epsilon", 0x80000000, 0x00000001 }, - { "NaN0", 0x7ff80000, 0x00000000 }, - { "-NaN0", 0xfff80000, 0x00000000 }, - }; - - if( objc!=4 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", - Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE", 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; - - /* Intercept the string "NaN" and generate a NaN value for it. - ** All other strings are passed through to Tcl_GetDoubleFromObj(). - ** Tcl_GetDoubleFromObj() should understand "NaN" but some versions - ** contain a bug. - */ - zVal = Tcl_GetString(objv[3]); - for(i=0; i<sizeof(aSpecialFp)/sizeof(aSpecialFp[0]); i++){ - if( strcmp(aSpecialFp[i].zName, zVal)==0 ){ - sqlite3_uint64 x; - x = aSpecialFp[i].iUpper; - x <<= 32; - x |= aSpecialFp[i].iLower; - assert( sizeof(value)==8 ); - assert( sizeof(x)==8 ); - memcpy(&value, &x, 8); - break; - } - } - if( i>=sizeof(aSpecialFp)/sizeof(aSpecialFp[0]) && - Tcl_GetDoubleFromObj(interp, objv[3], &value) ){ - return TCL_ERROR; - } - rc = sqlite3_bind_double(pStmt, idx, value); - if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR; - if( rc!=SQLITE_OK ){ - return TCL_ERROR; - } - - return TCL_OK; -} - -/* -** Usage: sqlite3_bind_null STMT N -** -** Test the sqlite3_bind_null interface. STMT is a prepared statement. -** N is the index of a wildcard in the prepared statement. This command -** binds a NULL to the wildcard. -*/ -static int test_bind_null( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - sqlite3_stmt *pStmt; - int idx; - int rc; - - if( objc!=3 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", - Tcl_GetStringFromObj(objv[0], 0), " STMT N", 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; - - rc = sqlite3_bind_null(pStmt, idx); - if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR; - if( rc!=SQLITE_OK ){ - return TCL_ERROR; - } - - return TCL_OK; -} - -/* -** Usage: sqlite3_bind_text STMT N STRING BYTES -** -** Test the sqlite3_bind_text interface. STMT is a prepared statement. -** N is the index of a wildcard in the prepared statement. This command -** binds a UTF-8 string STRING to the wildcard. The string is BYTES bytes -** long. -*/ -static int test_bind_text( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - sqlite3_stmt *pStmt; - int idx; - int bytes; - char *value; - int rc; - - if( objc!=5 ){ - 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 = (char*)Tcl_GetByteArrayFromObj(objv[3], &bytes); - if( Tcl_GetIntFromObj(interp, objv[4], &bytes) ) return TCL_ERROR; - - 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, sqlite3ErrName(rc), 0); - return TCL_ERROR; - } - - return TCL_OK; -} - -/* -** 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 -** binds a UTF-16 string STRING to the wildcard. The string is BYTES bytes -** long. -*/ -static int test_bind_text16( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ -#ifndef SQLITE_OMIT_UTF16 - sqlite3_stmt *pStmt; - int idx; - int bytes; - char *value; - int rc; - - 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]; - 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(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, xDel); - if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR; - if( rc!=SQLITE_OK ){ - Tcl_AppendResult(interp, sqlite3ErrName(rc), 0); - return TCL_ERROR; - } - -#endif /* SQLITE_OMIT_UTF16 */ - return TCL_OK; -} - -/* -** Usage: sqlite3_bind_blob ?-static? STMT N DATA BYTES -** -** Test the sqlite3_bind_blob interface. STMT is a prepared statement. -** N is the index of a wildcard in the prepared statement. This command -** binds a BLOB to the wildcard. The BLOB is BYTES bytes in size. -*/ -static int test_bind_blob( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - sqlite3_stmt *pStmt; - int idx; - int bytes; - char *value; - int rc; - sqlite3_destructor_type xDestructor = SQLITE_TRANSIENT; - - if( objc!=5 && objc!=6 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", - Tcl_GetStringFromObj(objv[0], 0), " STMT N DATA BYTES", 0); - return TCL_ERROR; - } - - if( objc==6 ){ - xDestructor = SQLITE_STATIC; - objv++; - } - - if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; - if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; - value = Tcl_GetString(objv[3]); - if( Tcl_GetIntFromObj(interp, objv[4], &bytes) ) return TCL_ERROR; - - rc = sqlite3_bind_blob(pStmt, idx, value, bytes, xDestructor); - if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR; - if( rc!=SQLITE_OK ){ - return TCL_ERROR; - } - - return TCL_OK; -} - -/* -** Usage: sqlite3_bind_parameter_count STMT -** -** Return the number of wildcards in the given statement. -*/ -static int test_bind_parameter_count( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - sqlite3_stmt *pStmt; - - if( objc!=2 ){ - Tcl_WrongNumArgs(interp, 1, objv, "STMT"); - return TCL_ERROR; - } - if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; - Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_bind_parameter_count(pStmt))); - return TCL_OK; -} - -/* -** Usage: sqlite3_bind_parameter_name STMT N -** -** Return the name of the Nth wildcard. The first wildcard is 1. -** An empty string is returned if N is out of range or if the wildcard -** is nameless. -*/ -static int test_bind_parameter_name( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - sqlite3_stmt *pStmt; - int i; - - if( objc!=3 ){ - Tcl_WrongNumArgs(interp, 1, objv, "STMT N"); - return TCL_ERROR; - } - if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; - if( Tcl_GetIntFromObj(interp, objv[2], &i) ) return TCL_ERROR; - Tcl_SetObjResult(interp, - Tcl_NewStringObj(sqlite3_bind_parameter_name(pStmt,i),-1) - ); - return TCL_OK; -} - -/* -** Usage: sqlite3_bind_parameter_index STMT NAME -** -** Return the index of the wildcard called NAME. Return 0 if there is -** no such wildcard. -*/ -static int test_bind_parameter_index( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - sqlite3_stmt *pStmt; - - if( objc!=3 ){ - Tcl_WrongNumArgs(interp, 1, objv, "STMT NAME"); - return TCL_ERROR; - } - if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; - Tcl_SetObjResult(interp, - Tcl_NewIntObj( - sqlite3_bind_parameter_index(pStmt,Tcl_GetString(objv[2])) - ) - ); - return TCL_OK; -} - -/* -** Usage: sqlite3_clear_bindings STMT -** -*/ -static int test_clear_bindings( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - sqlite3_stmt *pStmt; - - if( objc!=2 ){ - Tcl_WrongNumArgs(interp, 1, objv, "STMT"); - return TCL_ERROR; - } - if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; - Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_clear_bindings(pStmt))); - return TCL_OK; -} - -/* -** 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_extended_errcode DB -** -** Return the string representation of the most recent sqlite3_* API -** error code. e.g. "SQLITE_ERROR". -*/ -static int test_ex_errcode( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - sqlite3 *db; - int rc; - - if( objc!=2 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", - Tcl_GetString(objv[0]), " DB", 0); - return TCL_ERROR; - } - if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; - rc = sqlite3_extended_errcode(db); - Tcl_AppendResult(interp, (char *)t1ErrorName(rc), 0); - return TCL_OK; -} - - -/* -** Usage: sqlite3_errcode DB -** -** Return the string representation of the most recent sqlite3_* API -** error code. e.g. "SQLITE_ERROR". -*/ -static int test_errcode( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - sqlite3 *db; - int rc; - - if( objc!=2 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", - Tcl_GetString(objv[0]), " DB", 0); - return TCL_ERROR; - } - if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; - rc = sqlite3_errcode(db); - Tcl_AppendResult(interp, (char *)t1ErrorName(rc), 0); - return TCL_OK; -} - -/* -** Usage: sqlite3_errmsg DB -** -** Returns the UTF-8 representation of the error message string for the -** most recent sqlite3_* API call. -*/ -static int test_errmsg( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - sqlite3 *db; - const char *zErr; - - if( objc!=2 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", - Tcl_GetString(objv[0]), " DB", 0); - return TCL_ERROR; - } - if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; - - zErr = sqlite3_errmsg(db); - Tcl_SetObjResult(interp, Tcl_NewStringObj(zErr, -1)); - return TCL_OK; -} - -/* -** Usage: test_errmsg16 DB -** -** Returns the UTF-16 representation of the error message string for the -** most recent sqlite3_* API call. This is a byte array object at the TCL -** level, and it includes the 0x00 0x00 terminator bytes at the end of the -** UTF-16 string. -*/ -static int test_errmsg16( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ -#ifndef SQLITE_OMIT_UTF16 - sqlite3 *db; - const void *zErr; - const char *z; - int bytes = 0; - - if( objc!=2 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", - Tcl_GetString(objv[0]), " DB", 0); - return TCL_ERROR; - } - if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; - - zErr = sqlite3_errmsg16(db); - if( zErr ){ - z = zErr; - for(bytes=0; z[bytes] || z[bytes+1]; bytes+=2){} - } - Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(zErr, bytes)); -#endif /* SQLITE_OMIT_UTF16 */ - return TCL_OK; -} - -/* -** Usage: sqlite3_prepare DB sql bytes ?tailvar? -** -** Compile up to <bytes> bytes of the supplied SQL string <sql> using -** database handle <DB>. The parameter <tailval> is the name of a global -** variable that is set to the unused portion of <sql> (if any). A -** STMT handle is returned. -*/ -static int test_prepare( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - sqlite3 *db; - const char *zSql; - int bytes; - const char *zTail = 0; - sqlite3_stmt *pStmt = 0; - char zBuf[50]; - int rc; - - if( objc!=5 && objc!=4 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", - Tcl_GetString(objv[0]), " DB sql bytes ?tailvar?", 0); - return TCL_ERROR; - } - if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; - zSql = Tcl_GetString(objv[2]); - if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR; - - rc = sqlite3_prepare(db, zSql, bytes, &pStmt, objc>=5 ? &zTail : 0); - Tcl_ResetResult(interp); - if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; - if( zTail && objc>=5 ){ - if( bytes>=0 ){ - bytes = bytes - (int)(zTail-zSql); - } - if( (int)strlen(zTail)<bytes ){ - bytes = (int)strlen(zTail); - } - Tcl_ObjSetVar2(interp, objv[4], 0, Tcl_NewStringObj(zTail, bytes), 0); - } - if( rc!=SQLITE_OK ){ - assert( pStmt==0 ); - sprintf(zBuf, "(%d) ", rc); - Tcl_AppendResult(interp, zBuf, sqlite3_errmsg(db), 0); - return TCL_ERROR; - } - - if( pStmt ){ - if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR; - Tcl_AppendResult(interp, zBuf, 0); - } - return TCL_OK; -} - -/* -** Usage: sqlite3_prepare_v2 DB sql bytes ?tailvar? -** -** Compile up to <bytes> bytes of the supplied SQL string <sql> using -** database handle <DB>. The parameter <tailval> is the name of a global -** variable that is set to the unused portion of <sql> (if any). A -** STMT handle is returned. -*/ -static int test_prepare_v2( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - sqlite3 *db; - const char *zSql; - int bytes; - const char *zTail = 0; - sqlite3_stmt *pStmt = 0; - char zBuf[50]; - int rc; - - if( objc!=5 && objc!=4 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", - Tcl_GetString(objv[0]), " DB sql bytes tailvar", 0); - return TCL_ERROR; - } - if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; - zSql = Tcl_GetString(objv[2]); - if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR; - - rc = sqlite3_prepare_v2(db, zSql, bytes, &pStmt, objc>=5 ? &zTail : 0); - assert(rc==SQLITE_OK || pStmt==0); - Tcl_ResetResult(interp); - if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; - if( zTail && objc>=5 ){ - if( bytes>=0 ){ - bytes = bytes - (int)(zTail-zSql); - } - Tcl_ObjSetVar2(interp, objv[4], 0, Tcl_NewStringObj(zTail, bytes), 0); - } - if( rc!=SQLITE_OK ){ - assert( pStmt==0 ); - sprintf(zBuf, "(%d) ", rc); - Tcl_AppendResult(interp, zBuf, sqlite3_errmsg(db), 0); - return TCL_ERROR; - } - - if( pStmt ){ - if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR; - Tcl_AppendResult(interp, zBuf, 0); - } - return TCL_OK; -} - -/* -** 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. -*/ -static int test_prepare_tkt3134( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - sqlite3 *db; - static const char zSql[] = "\000SELECT 1"; - sqlite3_stmt *pStmt = 0; - char zBuf[50]; - int rc; - - if( objc!=2 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", - Tcl_GetString(objv[0]), " DB sql bytes tailvar", 0); - return TCL_ERROR; - } - if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; - rc = sqlite3_prepare_v2(db, &zSql[1], 0, &pStmt, 0); - assert(rc==SQLITE_OK || pStmt==0); - if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; - if( rc!=SQLITE_OK ){ - assert( pStmt==0 ); - sprintf(zBuf, "(%d) ", rc); - Tcl_AppendResult(interp, zBuf, sqlite3_errmsg(db), 0); - return TCL_ERROR; - } - - if( pStmt ){ - if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR; - Tcl_AppendResult(interp, zBuf, 0); - } - return TCL_OK; -} - -/* -** Usage: sqlite3_prepare16 DB sql bytes tailvar -** -** Compile up to <bytes> bytes of the supplied SQL string <sql> using -** database handle <DB>. The parameter <tailval> is the name of a global -** variable that is set to the unused portion of <sql> (if any). A -** STMT handle is returned. -*/ -static int test_prepare16( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ -#ifndef SQLITE_OMIT_UTF16 - sqlite3 *db; - const void *zSql; - const void *zTail = 0; - Tcl_Obj *pTail = 0; - sqlite3_stmt *pStmt = 0; - char zBuf[50]; - int rc; - int bytes; /* The integer specified as arg 3 */ - int objlen; /* The byte-array length of arg 2 */ - - if( objc!=5 && objc!=4 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", - Tcl_GetString(objv[0]), " DB sql bytes ?tailvar?", 0); - return TCL_ERROR; - } - if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; - zSql = Tcl_GetByteArrayFromObj(objv[2], &objlen); - if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR; - - rc = sqlite3_prepare16(db, zSql, bytes, &pStmt, objc>=5 ? &zTail : 0); - if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; - if( rc ){ - return TCL_ERROR; - } - - if( objc>=5 ){ - if( zTail ){ - objlen = objlen - (int)((u8 *)zTail-(u8 *)zSql); - }else{ - objlen = 0; - } - pTail = Tcl_NewByteArrayObj((u8 *)zTail, objlen); - Tcl_IncrRefCount(pTail); - Tcl_ObjSetVar2(interp, objv[4], 0, pTail, 0); - Tcl_DecrRefCount(pTail); - } - - if( pStmt ){ - if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR; - } - Tcl_AppendResult(interp, zBuf, 0); -#endif /* SQLITE_OMIT_UTF16 */ - return TCL_OK; -} - -/* -** Usage: sqlite3_prepare16_v2 DB sql bytes ?tailvar? -** -** Compile up to <bytes> bytes of the supplied SQL string <sql> using -** database handle <DB>. The parameter <tailval> is the name of a global -** variable that is set to the unused portion of <sql> (if any). A -** STMT handle is returned. -*/ -static int test_prepare16_v2( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ -#ifndef SQLITE_OMIT_UTF16 - sqlite3 *db; - const void *zSql; - const void *zTail = 0; - Tcl_Obj *pTail = 0; - sqlite3_stmt *pStmt = 0; - char zBuf[50]; - int rc; - int bytes; /* The integer specified as arg 3 */ - int objlen; /* The byte-array length of arg 2 */ - - if( objc!=5 && objc!=4 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", - Tcl_GetString(objv[0]), " DB sql bytes ?tailvar?", 0); - return TCL_ERROR; - } - if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; - zSql = Tcl_GetByteArrayFromObj(objv[2], &objlen); - if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR; - - rc = sqlite3_prepare16_v2(db, zSql, bytes, &pStmt, objc>=5 ? &zTail : 0); - if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; - if( rc ){ - return TCL_ERROR; - } - - if( objc>=5 ){ - if( zTail ){ - objlen = objlen - (int)((u8 *)zTail-(u8 *)zSql); - }else{ - objlen = 0; - } - pTail = Tcl_NewByteArrayObj((u8 *)zTail, objlen); - Tcl_IncrRefCount(pTail); - Tcl_ObjSetVar2(interp, objv[4], 0, pTail, 0); - Tcl_DecrRefCount(pTail); - } - - if( pStmt ){ - if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR; - } - Tcl_AppendResult(interp, zBuf, 0); -#endif /* SQLITE_OMIT_UTF16 */ - return TCL_OK; -} - -/* -** Usage: sqlite3_open filename ?options-list? -*/ -static int test_open( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - const char *zFilename; - sqlite3 *db; - char zBuf[100]; - - if( objc!=3 && objc!=2 && objc!=1 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", - Tcl_GetString(objv[0]), " filename options-list", 0); - return TCL_ERROR; - } - - zFilename = objc>1 ? Tcl_GetString(objv[1]) : 0; - sqlite3_open(zFilename, &db); - - if( sqlite3TestMakePointerStr(interp, zBuf, db) ) return TCL_ERROR; - Tcl_AppendResult(interp, zBuf, 0); - return TCL_OK; -} - -/* -** 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( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ -#ifndef SQLITE_OMIT_UTF16 - const void *zFilename; - sqlite3 *db; - char zBuf[100]; - - if( objc!=3 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", - Tcl_GetString(objv[0]), " filename options-list", 0); - return TCL_ERROR; - } - - zFilename = Tcl_GetByteArrayFromObj(objv[1], 0); - sqlite3_open16(zFilename, &db); - - if( sqlite3TestMakePointerStr(interp, zBuf, db) ) return TCL_ERROR; - Tcl_AppendResult(interp, zBuf, 0); -#endif /* SQLITE_OMIT_UTF16 */ - return TCL_OK; -} - -/* -** Usage: sqlite3_complete16 <UTF-16 string> -** -** Return 1 if the supplied argument is a complete SQL statement, or zero -** otherwise. -*/ -static int test_complete16( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ -#if !defined(SQLITE_OMIT_COMPLETE) && !defined(SQLITE_OMIT_UTF16) - char *zBuf; - - if( objc!=2 ){ - Tcl_WrongNumArgs(interp, 1, objv, "<utf-16 sql>"); - return TCL_ERROR; - } - - 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; -} - -/* -** Usage: sqlite3_step STMT -** -** Advance the statement to the next row. -*/ -static int test_step( - 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_GetString(objv[0]), " STMT", 0); - return TCL_ERROR; - } - - if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; - rc = sqlite3_step(pStmt); - - /* if( rc!=SQLITE_DONE && rc!=SQLITE_ROW ) return TCL_ERROR; */ - Tcl_SetResult(interp, (char *)t1ErrorName(rc), 0); - return TCL_OK; -} - -static int test_sql( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - sqlite3_stmt *pStmt; - - if( objc!=2 ){ - Tcl_WrongNumArgs(interp, 1, objv, "STMT"); - return TCL_ERROR; - } - - if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; - Tcl_SetResult(interp, (char *)sqlite3_sql(pStmt), TCL_VOLATILE); - return TCL_OK; -} - -/* -** Usage: sqlite3_column_count STMT -** -** Return the number of columns returned by the sql statement STMT. -*/ -static int test_column_count( - 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_GetString(objv[0]), " STMT column", 0); - return TCL_ERROR; - } - - if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; - - Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_column_count(pStmt))); - return TCL_OK; -} - -/* -** Usage: sqlite3_column_type STMT column -** -** Return the type of the data in column 'column' of the current row. -*/ -static int test_column_type( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - sqlite3_stmt *pStmt; - int col; - int tp; - - if( objc!=3 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", - Tcl_GetString(objv[0]), " STMT column", 0); - return TCL_ERROR; - } - - if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; - if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; - - tp = sqlite3_column_type(pStmt, col); - switch( tp ){ - case SQLITE_INTEGER: - Tcl_SetResult(interp, "INTEGER", TCL_STATIC); - break; - case SQLITE_NULL: - Tcl_SetResult(interp, "NULL", TCL_STATIC); - break; - case SQLITE_FLOAT: - Tcl_SetResult(interp, "FLOAT", TCL_STATIC); - break; - case SQLITE_TEXT: - Tcl_SetResult(interp, "TEXT", TCL_STATIC); - break; - case SQLITE_BLOB: - Tcl_SetResult(interp, "BLOB", TCL_STATIC); - break; - default: - assert(0); - } - - return TCL_OK; -} - -/* -** Usage: sqlite3_column_int64 STMT column -** -** Return the data in column 'column' of the current row cast as an -** wide (64-bit) integer. -*/ -static int test_column_int64( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - sqlite3_stmt *pStmt; - int col; - i64 iVal; - - if( objc!=3 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", - Tcl_GetString(objv[0]), " STMT column", 0); - return TCL_ERROR; - } - - if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; - if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; - - iVal = sqlite3_column_int64(pStmt, col); - Tcl_SetObjResult(interp, Tcl_NewWideIntObj(iVal)); - return TCL_OK; -} - -/* -** Usage: sqlite3_column_blob STMT column -*/ -static int test_column_blob( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - sqlite3_stmt *pStmt; - int col; - - int len; - const void *pBlob; - - if( objc!=3 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", - Tcl_GetString(objv[0]), " STMT column", 0); - return TCL_ERROR; - } - - if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; - if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; - - len = sqlite3_column_bytes(pStmt, col); - pBlob = sqlite3_column_blob(pStmt, col); - Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(pBlob, len)); - return TCL_OK; -} - -/* -** Usage: sqlite3_column_double STMT column -** -** Return the data in column 'column' of the current row cast as a double. -*/ -static int test_column_double( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - sqlite3_stmt *pStmt; - int col; - double rVal; - - if( objc!=3 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", - Tcl_GetString(objv[0]), " STMT column", 0); - return TCL_ERROR; - } - - if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; - if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; - - rVal = sqlite3_column_double(pStmt, col); - Tcl_SetObjResult(interp, Tcl_NewDoubleObj(rVal)); - return TCL_OK; -} - -/* -** Usage: sqlite3_data_count STMT -** -** Return the number of columns returned by the sql statement STMT. -*/ -static int test_data_count( - 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_GetString(objv[0]), " STMT column", 0); - return TCL_ERROR; - } - - if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; - - Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_data_count(pStmt))); - return TCL_OK; -} - -/* -** Usage: sqlite3_column_text STMT column -** -** Usage: sqlite3_column_decltype STMT column -** -** Usage: sqlite3_column_name STMT column -*/ -static int test_stmt_utf8( - void * clientData, /* Pointer to SQLite API function to be invoke */ - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - sqlite3_stmt *pStmt; - int col; - const char *(*xFunc)(sqlite3_stmt*, int); - const char *zRet; - - xFunc = (const char *(*)(sqlite3_stmt*, int))clientData; - if( objc!=3 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", - Tcl_GetString(objv[0]), " STMT column", 0); - return TCL_ERROR; - } - - if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; - if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; - zRet = xFunc(pStmt, col); - if( zRet ){ - Tcl_SetResult(interp, (char *)zRet, 0); - } - return TCL_OK; -} - -static int test_global_recover( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ -#ifndef SQLITE_OMIT_DEPRECATED - int rc; - if( objc!=1 ){ - Tcl_WrongNumArgs(interp, 1, objv, ""); - return TCL_ERROR; - } - rc = sqlite3_global_recover(); - Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC); -#endif - return TCL_OK; -} - -/* -** Usage: sqlite3_column_text STMT column -** -** Usage: sqlite3_column_decltype STMT column -** -** Usage: sqlite3_column_name STMT column -*/ -static int test_stmt_utf16( - void * clientData, /* Pointer to SQLite API function to be invoked */ - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ -#ifndef SQLITE_OMIT_UTF16 - sqlite3_stmt *pStmt; - int col; - Tcl_Obj *pRet; - const void *zName16; - const void *(*xFunc)(sqlite3_stmt*, int); - - xFunc = (const void *(*)(sqlite3_stmt*, int))clientData; - if( objc!=3 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", - Tcl_GetString(objv[0]), " STMT column", 0); - return TCL_ERROR; - } - - if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; - if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; - - zName16 = xFunc(pStmt, col); - if( zName16 ){ - int n; - const char *z = zName16; - for(n=0; z[n] || z[n+1]; n+=2){} - pRet = Tcl_NewByteArrayObj(zName16, n+2); - Tcl_SetObjResult(interp, pRet); - } -#endif /* SQLITE_OMIT_UTF16 */ - - return TCL_OK; -} - -/* -** Usage: sqlite3_column_int STMT column -** -** Usage: sqlite3_column_bytes STMT column -** -** Usage: sqlite3_column_bytes16 STMT column -** -*/ -static int test_stmt_int( - void * clientData, /* Pointer to SQLite API function to be invoked */ - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - sqlite3_stmt *pStmt; - int col; - int (*xFunc)(sqlite3_stmt*, int); - - xFunc = (int (*)(sqlite3_stmt*, int))clientData; - if( objc!=3 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", - Tcl_GetString(objv[0]), " STMT column", 0); - return TCL_ERROR; - } - - if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; - if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; - - Tcl_SetObjResult(interp, Tcl_NewIntObj(xFunc(pStmt, col))); - return TCL_OK; -} - -/* -** Usage: sqlite_set_magic DB MAGIC-NUMBER -** -** Set the db->magic value. This is used to test error recovery logic. -*/ -static int sqlite_set_magic( - void * clientData, - Tcl_Interp *interp, - int argc, - char **argv -){ - sqlite3 *db; - if( argc!=3 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " DB MAGIC", 0); - return TCL_ERROR; - } - if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; - if( strcmp(argv[2], "SQLITE_MAGIC_OPEN")==0 ){ - db->magic = SQLITE_MAGIC_OPEN; - }else if( strcmp(argv[2], "SQLITE_MAGIC_CLOSED")==0 ){ - db->magic = SQLITE_MAGIC_CLOSED; - }else if( strcmp(argv[2], "SQLITE_MAGIC_BUSY")==0 ){ - db->magic = SQLITE_MAGIC_BUSY; - }else if( strcmp(argv[2], "SQLITE_MAGIC_ERROR")==0 ){ - db->magic = SQLITE_MAGIC_ERROR; - }else if( Tcl_GetInt(interp, argv[2], (int*)&db->magic) ){ - return TCL_ERROR; - } - return TCL_OK; -} - -/* -** Usage: sqlite3_interrupt DB -** -** Trigger an interrupt on DB -*/ -static int test_interrupt( - void * clientData, - Tcl_Interp *interp, - int argc, - char **argv -){ - sqlite3 *db; - if( argc!=2 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " DB", 0); - return TCL_ERROR; - } - if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; - sqlite3_interrupt(db); - return TCL_OK; -} - -static u8 *sqlite3_stack_baseline = 0; - -/* -** Fill the stack with a known bitpattern. -*/ -static void prepStack(void){ - int i; - u32 bigBuf[65536]; - for(i=0; i<sizeof(bigBuf)/sizeof(bigBuf[0]); i++) bigBuf[i] = 0xdeadbeef; - sqlite3_stack_baseline = (u8*)&bigBuf[65536]; -} - -/* -** Get the current stack depth. Used for debugging only. -*/ -u64 sqlite3StackDepth(void){ - u8 x; - return (u64)(sqlite3_stack_baseline - &x); -} - -/* -** Usage: sqlite3_stack_used DB SQL -** -** Try to measure the amount of stack space used by a call to sqlite3_exec -*/ -static int test_stack_used( - void * clientData, - Tcl_Interp *interp, - int argc, - char **argv -){ - sqlite3 *db; - int i; - if( argc!=3 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " DB SQL", 0); - return TCL_ERROR; - } - if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; - prepStack(); - (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; -} - -/* -** Usage: sqlite_delete_function DB function-name -** -** Delete the user function 'function-name' from database handle DB. It -** is assumed that the user function was created as UTF8, any number of -** arguments (the way the TCL interface does it). -*/ -static int delete_function( - void * clientData, - Tcl_Interp *interp, - int argc, - char **argv -){ - int rc; - sqlite3 *db; - if( argc!=3 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " DB function-name", 0); - return TCL_ERROR; - } - if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; - rc = sqlite3_create_function(db, argv[2], -1, SQLITE_UTF8, 0, 0, 0, 0); - Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC); - return TCL_OK; -} - -/* -** Usage: sqlite_delete_collation DB collation-name -** -** Delete the collation sequence 'collation-name' from database handle -** DB. It is assumed that the collation sequence was created as UTF8 (the -** way the TCL interface does it). -*/ -static int delete_collation( - void * clientData, - Tcl_Interp *interp, - int argc, - char **argv -){ - int rc; - sqlite3 *db; - if( argc!=3 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " DB function-name", 0); - return TCL_ERROR; - } - if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; - rc = sqlite3_create_collation(db, argv[2], SQLITE_UTF8, 0, 0); - Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC); - return TCL_OK; -} - -/* -** Usage: sqlite3_get_autocommit DB -** -** Return true if the database DB is currently in auto-commit mode. -** Return false if not. -*/ -static int get_autocommit( - void * clientData, - Tcl_Interp *interp, - int argc, - char **argv -){ - char zBuf[30]; - sqlite3 *db; - if( argc!=2 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " DB", 0); - return TCL_ERROR; - } - if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; - sprintf(zBuf, "%d", sqlite3_get_autocommit(db)); - Tcl_AppendResult(interp, zBuf, 0); - return TCL_OK; -} - -/* -** 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, sqlite3ErrName(rc), 0); - return TCL_OK; -} - -/* -** Usage: tcl_variable_type VARIABLENAME -** -** Return the name of the internal representation for the -** value of the given variable. -*/ -static int tcl_variable_type( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - Tcl_Obj *pVar; - if( objc!=2 ){ - Tcl_WrongNumArgs(interp, 1, objv, "VARIABLE"); - return TCL_ERROR; - } - pVar = Tcl_GetVar2Ex(interp, Tcl_GetString(objv[1]), 0, TCL_LEAVE_ERR_MSG); - if( pVar==0 ) return TCL_ERROR; - if( pVar->typePtr ){ - Tcl_SetObjResult(interp, Tcl_NewStringObj(pVar->typePtr->name, -1)); - } - return TCL_OK; -} - -/* -** 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_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? -** -** 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[] -){ - sqlite3_int64 amt; - Tcl_WideInt N = -1; - if( objc!=1 && objc!=2 ){ - Tcl_WrongNumArgs(interp, 1, objv, "?N?"); - return TCL_ERROR; - } - if( objc==2 ){ - if( Tcl_GetWideIntFromObj(interp, objv[1], &N) ) return TCL_ERROR; - } - amt = sqlite3_soft_heap_limit64(N); - Tcl_SetObjResult(interp, Tcl_NewWideIntObj(amt)); - 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[] -){ -#ifndef SQLITE_OMIT_DEPRECATED - sqlite3_thread_cleanup(); -#endif - return TCL_OK; -} - -/* -** Usage: sqlite3_pager_refcounts DB -** -** Return a list of numbers which are the PagerRefcount for all -** pagers on each database connection. -*/ -static int test_pager_refcounts( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - sqlite3 *db; - int i; - int v, *a; - Tcl_Obj *pResult; - - if( objc!=2 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", - Tcl_GetStringFromObj(objv[0], 0), " DB", 0); - return TCL_ERROR; - } - if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; - pResult = Tcl_NewObj(); - for(i=0; i<db->nDb; i++){ - if( db->aDb[i].pBt==0 ){ - v = -1; - }else{ - sqlite3_mutex_enter(db->mutex); - a = sqlite3PagerStats(sqlite3BtreePager(db->aDb[i].pBt)); - v = a[0]; - sqlite3_mutex_leave(db->mutex); - } - Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(v)); - } - Tcl_SetObjResult(interp, pResult); - return TCL_OK; -} - - -/* -** tclcmd: working_64bit_int -** -** Some TCL builds (ex: cygwin) do not support 64-bit integers. This -** leads to a number of test failures. The present command checks the -** TCL build to see whether or not it supports 64-bit integers. It -** returns TRUE if it does and FALSE if not. -** -** This command is used to warn users that their TCL build is defective -** and that the errors they are seeing in the test scripts might be -** a result of their defective TCL rather than problems in SQLite. -*/ -static int working_64bit_int( - 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_Obj *pTestObj; - int working = 0; - - pTestObj = Tcl_NewWideIntObj(1000000*(i64)1234567890); - working = strcmp(Tcl_GetString(pTestObj), "1234567890000000")==0; - Tcl_DecrRefCount(pTestObj); - Tcl_SetObjResult(interp, Tcl_NewBooleanObj(working)); - return TCL_OK; -} - - -/* -** tclcmd: vfs_unlink_test -** -** This TCL command unregisters the primary VFS and then registers -** it back again. This is used to test the ability to register a -** VFS when none are previously registered, and the ability to -** unregister the only available VFS. Ticket #2738 -*/ -static int vfs_unlink_test( - 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 i; - sqlite3_vfs *pMain; - sqlite3_vfs *apVfs[20]; - sqlite3_vfs one, two; - - sqlite3_vfs_unregister(0); /* Unregister of NULL is harmless */ - one.zName = "__one"; - two.zName = "__two"; - - /* Calling sqlite3_vfs_register with 2nd argument of 0 does not - ** change the default VFS - */ - pMain = sqlite3_vfs_find(0); - sqlite3_vfs_register(&one, 0); - assert( pMain==0 || pMain==sqlite3_vfs_find(0) ); - sqlite3_vfs_register(&two, 0); - assert( pMain==0 || pMain==sqlite3_vfs_find(0) ); - - /* We can find a VFS by its name */ - assert( sqlite3_vfs_find("__one")==&one ); - assert( sqlite3_vfs_find("__two")==&two ); - - /* Calling sqlite_vfs_register with non-zero second parameter changes the - ** default VFS, even if the 1st parameter is an existig VFS that is - ** previously registered as the non-default. - */ - sqlite3_vfs_register(&one, 1); - assert( sqlite3_vfs_find("__one")==&one ); - assert( sqlite3_vfs_find("__two")==&two ); - assert( sqlite3_vfs_find(0)==&one ); - sqlite3_vfs_register(&two, 1); - assert( sqlite3_vfs_find("__one")==&one ); - assert( sqlite3_vfs_find("__two")==&two ); - assert( sqlite3_vfs_find(0)==&two ); - if( pMain ){ - sqlite3_vfs_register(pMain, 1); - assert( sqlite3_vfs_find("__one")==&one ); - assert( sqlite3_vfs_find("__two")==&two ); - assert( sqlite3_vfs_find(0)==pMain ); - } - - /* Unlink the default VFS. Repeat until there are no more VFSes - ** registered. - */ - for(i=0; i<sizeof(apVfs)/sizeof(apVfs[0]); i++){ - apVfs[i] = sqlite3_vfs_find(0); - if( apVfs[i] ){ - assert( apVfs[i]==sqlite3_vfs_find(apVfs[i]->zName) ); - sqlite3_vfs_unregister(apVfs[i]); - assert( 0==sqlite3_vfs_find(apVfs[i]->zName) ); - } - } - assert( 0==sqlite3_vfs_find(0) ); - - /* Register the main VFS as non-default (will be made default, since - ** it'll be the only one in existence). - */ - sqlite3_vfs_register(pMain, 0); - assert( sqlite3_vfs_find(0)==pMain ); - - /* Un-register the main VFS again to restore an empty VFS list */ - sqlite3_vfs_unregister(pMain); - assert( 0==sqlite3_vfs_find(0) ); - - /* Relink all VFSes in reverse order. */ - for(i=sizeof(apVfs)/sizeof(apVfs[0])-1; i>=0; i--){ - if( apVfs[i] ){ - sqlite3_vfs_register(apVfs[i], 1); - assert( apVfs[i]==sqlite3_vfs_find(0) ); - assert( apVfs[i]==sqlite3_vfs_find(apVfs[i]->zName) ); - } - } - - /* Unregister out sample VFSes. */ - sqlite3_vfs_unregister(&one); - sqlite3_vfs_unregister(&two); - - /* Unregistering a VFS that is not currently registered is harmless */ - sqlite3_vfs_unregister(&one); - sqlite3_vfs_unregister(&two); - assert( sqlite3_vfs_find("__one")==0 ); - assert( sqlite3_vfs_find("__two")==0 ); - - /* We should be left with the original default VFS back as the - ** original */ - assert( sqlite3_vfs_find(0)==pMain ); - - return TCL_OK; -} - -/* -** tclcmd: vfs_initfail_test -** -** This TCL command attempts to vfs_find and vfs_register when the -** sqlite3_initialize() interface is failing. All calls should fail. -*/ -static int vfs_initfail_test( - 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 one; - one.zName = "__one"; - - if( sqlite3_vfs_find(0) ) return TCL_ERROR; - sqlite3_vfs_register(&one, 0); - if( sqlite3_vfs_find(0) ) return TCL_ERROR; - sqlite3_vfs_register(&one, 1); - if( sqlite3_vfs_find(0) ) return TCL_ERROR; - return TCL_OK; -} - -/* -** Saved VFSes -*/ -static sqlite3_vfs *apVfs[20]; -static int nVfs = 0; - -/* -** tclcmd: vfs_unregister_all -** -** Unregister all VFSes. -*/ -static int vfs_unregister_all( - 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 i; - for(i=0; i<ArraySize(apVfs); i++){ - apVfs[i] = sqlite3_vfs_find(0); - if( apVfs[i]==0 ) break; - sqlite3_vfs_unregister(apVfs[i]); - } - nVfs = i; - return TCL_OK; -} -/* -** tclcmd: vfs_reregister_all -** -** Restore all VFSes that were removed using vfs_unregister_all -*/ -static int vfs_reregister_all( - 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 i; - for(i=0; i<nVfs; i++){ - sqlite3_vfs_register(apVfs[i], i==0); - } - return TCL_OK; -} - - -/* -** tclcmd: file_control_test DB -** -** This TCL command runs the sqlite3_file_control interface and -** verifies correct operation of the same. -*/ -static int file_control_test( - 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 iArg = 0; - sqlite3 *db; - int rc; - - if( objc!=2 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", - Tcl_GetStringFromObj(objv[0], 0), " DB", 0); - return TCL_ERROR; - } - if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; - rc = sqlite3_file_control(db, 0, 0, &iArg); - assert( rc==SQLITE_NOTFOUND ); - rc = sqlite3_file_control(db, "notadatabase", SQLITE_FCNTL_LOCKSTATE, &iArg); - assert( rc==SQLITE_ERROR ); - rc = sqlite3_file_control(db, "main", -1, &iArg); - assert( rc==SQLITE_NOTFOUND ); - rc = sqlite3_file_control(db, "temp", -1, &iArg); - assert( rc==SQLITE_NOTFOUND || rc==SQLITE_ERROR ); - - return TCL_OK; -} - - -/* -** tclcmd: file_control_lasterrno_test DB -** -** This TCL command runs the sqlite3_file_control interface and -** verifies correct operation of the SQLITE_LAST_ERRNO verb. -*/ -static int file_control_lasterrno_test( - 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 iArg = 0; - sqlite3 *db; - int rc; - - if( objc!=2 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", - Tcl_GetStringFromObj(objv[0], 0), " DB", 0); - return TCL_ERROR; - } - if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){ - return TCL_ERROR; - } - rc = sqlite3_file_control(db, NULL, SQLITE_LAST_ERRNO, &iArg); - if( rc ){ - Tcl_SetObjResult(interp, Tcl_NewIntObj(rc)); - return TCL_ERROR; - } - if( iArg!=0 ) { - Tcl_AppendResult(interp, "Unexpected non-zero errno: ", - Tcl_GetStringFromObj(Tcl_NewIntObj(iArg), 0), " ", 0); - return TCL_ERROR; - } - return TCL_OK; -} - -/* -** tclcmd: file_control_chunksize_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. -*/ -static int file_control_chunksize_test( - 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 nSize; /* New chunk size */ - char *zDb; /* Db name ("main", "temp" etc.) */ - sqlite3 *db; /* Database handle */ - int rc; /* file_control() return code */ - - if( objc!=4 ){ - Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME SIZE"); - return TCL_ERROR; - } - if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) - || Tcl_GetIntFromObj(interp, objv[3], &nSize) - ){ - return TCL_ERROR; - } - zDb = Tcl_GetString(objv[2]); - if( zDb[0]=='\0' ) zDb = NULL; - - rc = sqlite3_file_control(db, zDb, SQLITE_FCNTL_CHUNK_SIZE, (void *)&nSize); - if( rc ){ - Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_STATIC); - return TCL_ERROR; - } - return TCL_OK; -} - -/* -** tclcmd: file_control_sizehint_test DB DBNAME SIZE -** -** 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 */ - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int objc, /* Number of arguments */ - Tcl_Obj *CONST objv[] /* Command arguments */ -){ - Tcl_WideInt nSize; /* Hinted size */ - char *zDb; /* Db name ("main", "temp" etc.) */ - sqlite3 *db; /* Database handle */ - int rc; /* file_control() return code */ - - if( objc!=4 ){ - Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME SIZE"); - return TCL_ERROR; - } - if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) - || Tcl_GetWideIntFromObj(interp, objv[3], &nSize) - ){ - return TCL_ERROR; - } - zDb = Tcl_GetString(objv[2]); - if( zDb[0]=='\0' ) zDb = NULL; - - rc = sqlite3_file_control(db, zDb, SQLITE_FCNTL_SIZE_HINT, (void *)&nSize); - if( rc ){ - Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_STATIC); - return TCL_ERROR; - } - return TCL_OK; -} - -/* -** tclcmd: file_control_lockproxy_test DB PWD -** -** This TCL command runs the sqlite3_file_control interface and -** verifies correct operation of the SQLITE_GET_LOCKPROXYFILE and -** SQLITE_SET_LOCKPROXYFILE verbs. -*/ -static int file_control_lockproxy_test( - 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; - - if( objc!=3 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", - Tcl_GetStringFromObj(objv[0], 0), " DB PWD", 0); - return TCL_ERROR; - } - if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){ - return TCL_ERROR; - } - -#if !defined(SQLITE_ENABLE_LOCKING_STYLE) -# if defined(__APPLE__) -# define SQLITE_ENABLE_LOCKING_STYLE 1 -# else -# define SQLITE_ENABLE_LOCKING_STYLE 0 -# endif -#endif -#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) - { - 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; - } - sprintf(proxyPath, "%s/test.proxy", zPwd); - rc = sqlite3_file_control(db, NULL, SQLITE_SET_LOCKPROXYFILE, proxyPath); - if( rc ){ - Tcl_SetObjResult(interp, Tcl_NewIntObj(rc)); - return TCL_ERROR; - } - rc = sqlite3_file_control(db, NULL, SQLITE_GET_LOCKPROXYFILE, &testPath); - if( strncmp(proxyPath,testPath,11) ){ - Tcl_AppendResult(interp, "Lock proxy file did not match the " - "previously assigned value", 0); - return TCL_ERROR; - } - if( rc ){ - Tcl_SetObjResult(interp, Tcl_NewIntObj(rc)); - return TCL_ERROR; - } - rc = sqlite3_file_control(db, NULL, SQLITE_SET_LOCKPROXYFILE, proxyPath); - if( rc ){ - Tcl_SetObjResult(interp, Tcl_NewIntObj(rc)); - return TCL_ERROR; - } - } -#endif - return TCL_OK; -} - -/* -** tclcmd: file_control_win32_av_retry DB NRETRY DELAY -** -** This TCL command runs the sqlite3_file_control interface with -** the SQLITE_FCNTL_WIN32_AV_RETRY opcode. -*/ -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 *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; - } - if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){ - return TCL_ERROR; - } - 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: 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 }, - - /* 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; - - if( objc!=4 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", - Tcl_GetStringFromObj(objv[0], 0), " DB ID VALUE", 0); - return TCL_ERROR; - } - if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; - zId = Tcl_GetString(objv[2]); - for(i=0; i<sizeof(aId)/sizeof(aId[0]); i++){ - if( strcmp(zId, aId[i].zName)==0 ){ - id = aId[i].id; - break; - } - } - if( i>=sizeof(aId)/sizeof(aId[0]) ){ - Tcl_AppendResult(interp, "unknown limit type: ", zId, (char*)0); - return TCL_ERROR; - } - if( Tcl_GetIntFromObj(interp, objv[3], &val) ) return TCL_ERROR; - rc = sqlite3_limit(db, id, val); - Tcl_SetObjResult(interp, Tcl_NewIntObj(rc)); - return TCL_OK; -} - -/* -** tclcmd: save_prng_state -** -** Save the state of the pseudo-random number generator. -** At the same time, verify that sqlite3_test_control works even when -** called with an out-of-range opcode. -*/ -static int save_prng_state( - 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 = sqlite3_test_control(9999); - assert( rc==0 ); - rc = sqlite3_test_control(-1); - assert( rc==0 ); - sqlite3_test_control(SQLITE_TESTCTRL_PRNG_SAVE); - return TCL_OK; -} -/* -** tclcmd: restore_prng_state -*/ -static int restore_prng_state( - 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_PRNG_RESTORE); - return TCL_OK; -} -/* -** tclcmd: reset_prng_state -*/ -static int reset_prng_state( - 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_PRNG_RESET); - return TCL_OK; -} - -/* -** tclcmd: pcache_stats -*/ -static int test_pcache_stats( - 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 nMin; - int nMax; - int nCurrent; - int nRecyclable; - Tcl_Obj *pRet; - - sqlite3PcacheStats(&nCurrent, &nMax, &nMin, &nRecyclable); - - pRet = Tcl_NewObj(); - Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj("current", -1)); - Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(nCurrent)); - Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj("max", -1)); - Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(nMax)); - Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj("min", -1)); - Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(nMin)); - Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj("recyclable", -1)); - Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(nRecyclable)); - - Tcl_SetObjResult(interp, pRet); - - return TCL_OK; -} - -#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY -static void test_unlock_notify_cb(void **aArg, int nArg){ - int ii; - for(ii=0; ii<nArg; ii++){ - Tcl_EvalEx((Tcl_Interp *)aArg[ii], "unlock_notify", -1, TCL_EVAL_GLOBAL); - } -} -#endif /* SQLITE_ENABLE_UNLOCK_NOTIFY */ - -/* -** tclcmd: sqlite3_unlock_notify db -*/ -#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY -static int test_unlock_notify( - ClientData clientData, /* Unused */ - 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; - - 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_unlock_notify(db, test_unlock_notify_cb, (void *)interp); - Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC); - return TCL_OK; -} -#endif - -/* -** tclcmd: sqlite3_wal_checkpoint db ?NAME? -*/ -static int test_wal_checkpoint( - 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 *zDb = 0; - sqlite3 *db; - int rc; - - if( objc!=3 && objc!=2 ){ - Tcl_WrongNumArgs(interp, 1, objv, "DB ?NAME?"); - return TCL_ERROR; - } - - if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){ - return TCL_ERROR; - } - if( objc==3 ){ - zDb = Tcl_GetString(objv[2]); - } - rc = sqlite3_wal_checkpoint(db, zDb); - Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC); - return TCL_OK; -} - -/* -** tclcmd: sqlite3_wal_checkpoint_v2 db MODE ?NAME? -** -** This command calls the wal_checkpoint_v2() function with the specified -** mode argument (passive, full or restart). If present, the database name -** NAME is passed as the second argument to wal_checkpoint_v2(). If it the -** NAME argument is not present, a NULL pointer is passed instead. -** -** If wal_checkpoint_v2() returns any value other than SQLITE_BUSY or -** SQLITE_OK, then this command returns TCL_ERROR. The Tcl result is set -** to the error message obtained from sqlite3_errmsg(). -** -** 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 parameters by wal_checkpoint_v2() - -** the number of frames in the log and the number of frames in the log -** that have been checkpointed. -*/ -static int test_wal_checkpoint_v2( - 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 *zDb = 0; - sqlite3 *db; - int rc; - - int eMode; - int nLog = -555; - int nCkpt = -555; - Tcl_Obj *pRet; - - const char * aMode[] = { "passive", "full", "restart", 0 }; - assert( SQLITE_CHECKPOINT_PASSIVE==0 ); - assert( SQLITE_CHECKPOINT_FULL==1 ); - assert( SQLITE_CHECKPOINT_RESTART==2 ); - - if( objc!=3 && objc!=4 ){ - Tcl_WrongNumArgs(interp, 1, objv, "DB MODE ?NAME?"); - return TCL_ERROR; - } - - if( objc==4 ){ - zDb = Tcl_GetString(objv[3]); - } - if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) - || Tcl_GetIndexFromObj(interp, objv[2], aMode, "mode", 0, &eMode) - ){ - return TCL_ERROR; - } - - rc = sqlite3_wal_checkpoint_v2(db, zDb, eMode, &nLog, &nCkpt); - if( rc!=SQLITE_OK && rc!=SQLITE_BUSY ){ - Tcl_SetResult(interp, (char *)sqlite3_errmsg(db), TCL_VOLATILE); - return TCL_ERROR; - } - - pRet = Tcl_NewObj(); - Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(rc==SQLITE_BUSY?1:0)); - Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(nLog)); - Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(nCkpt)); - Tcl_SetObjResult(interp, pRet); - - return TCL_OK; -} - -/* -** tclcmd: test_sqlite3_log ?SCRIPT? -*/ -static struct LogCallback { - Tcl_Interp *pInterp; - Tcl_Obj *pObj; -} logcallback = {0, 0}; -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(sqlite3ErrName(err), -1) - ); - Tcl_ListObjAppendElement(0, pNew, Tcl_NewStringObj(zMsg, -1)); - Tcl_EvalObjEx(logcallback.pInterp, pNew, TCL_EVAL_GLOBAL|TCL_EVAL_DIRECT); - Tcl_DecrRefCount(pNew); -} -static int test_sqlite3_log( - ClientData clientData, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int objc, /* Number of arguments */ - Tcl_Obj *CONST objv[] /* Command arguments */ -){ - if( objc>2 ){ - Tcl_WrongNumArgs(interp, 1, objv, "SCRIPT"); - return TCL_ERROR; - } - if( logcallback.pObj ){ - Tcl_DecrRefCount(logcallback.pObj); - logcallback.pObj = 0; - logcallback.pInterp = 0; - sqlite3_config(SQLITE_CONFIG_LOG, 0, 0); - } - if( objc>1 ){ - logcallback.pObj = objv[1]; - Tcl_IncrRefCount(logcallback.pObj); - logcallback.pInterp = interp; - sqlite3_config(SQLITE_CONFIG_LOG, xLogcallback, 0); - } - return TCL_OK; -} - -/* -** tcl_objproc COMMANDNAME ARGS... -** -** Run a TCL command using its objProc interface. Throw an error if -** the command has no objProc interface. -*/ -static int runAsObjProc( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - Tcl_CmdInfo cmdInfo; - if( objc<2 ){ - Tcl_WrongNumArgs(interp, 1, objv, "COMMAND ..."); - 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; - } - if( cmdInfo.objProc==0 ){ - Tcl_AppendResult(interp, "command has no objProc: ", - Tcl_GetString(objv[1]), (char*)0); - return TCL_ERROR; - } - return cmdInfo.objProc(cmdInfo.objClientData, interp, objc-1, objv+1); -} - -#ifndef SQLITE_OMIT_EXPLAIN -/* -** WARNING: The following function, printExplainQueryPlan() is an exact -** copy of example code from eqp.in (eqp.html). If this code is modified, -** then the documentation copy needs to be modified as well. -*/ -/* -** Argument pStmt is a prepared SQL statement. This function compiles -** an EXPLAIN QUERY PLAN command to report on the prepared statement, -** and prints the report to stdout using printf(). -*/ -int printExplainQueryPlan(sqlite3_stmt *pStmt){ - const char *zSql; /* Input SQL */ - char *zExplain; /* SQL with EXPLAIN QUERY PLAN prepended */ - sqlite3_stmt *pExplain; /* Compiled EXPLAIN QUERY PLAN command */ - int rc; /* Return code from sqlite3_prepare_v2() */ - - zSql = sqlite3_sql(pStmt); - if( zSql==0 ) return SQLITE_ERROR; - - zExplain = sqlite3_mprintf("EXPLAIN QUERY PLAN %s", zSql); - if( zExplain==0 ) return SQLITE_NOMEM; - - rc = sqlite3_prepare_v2(sqlite3_db_handle(pStmt), zExplain, -1, &pExplain, 0); - sqlite3_free(zExplain); - if( rc!=SQLITE_OK ) return rc; - - while( SQLITE_ROW==sqlite3_step(pExplain) ){ - int iSelectid = sqlite3_column_int(pExplain, 0); - int iOrder = sqlite3_column_int(pExplain, 1); - int iFrom = sqlite3_column_int(pExplain, 2); - const char *zDetail = (const char *)sqlite3_column_text(pExplain, 3); - - printf("%d %d %d %s\n", iSelectid, iOrder, iFrom, zDetail); - } - - return sqlite3_finalize(pExplain); -} - -static int test_print_eqp( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - int rc; - sqlite3_stmt *pStmt; - - if( objc!=2 ){ - Tcl_WrongNumArgs(interp, 1, objv, "STMT"); - return TCL_ERROR; - } - 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 */ - -/* -** sqlite3_test_control VERB ARGS... -*/ -static int test_test_control( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - struct Verb { - const char *zName; - int i; - } aVerb[] = { - { "SQLITE_TESTCTRL_LOCALTIME_FAULT", SQLITE_TESTCTRL_LOCALTIME_FAULT }, - }; - int iVerb; - int iFlag; - int rc; - - if( objc<2 ){ - Tcl_WrongNumArgs(interp, 1, objv, "VERB ARGS..."); - return TCL_ERROR; - } - - 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; - } - } - - 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 -/* -** Information passed from the main thread into the windows file locker -** background thread. -*/ -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 - - -#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 }, - { "real-as-int", SQLITE_IdxRealAsInt }, - { "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_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 }, - { "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; -} - - -/* -** 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 }, - { "sqlite3_mprintf_str", (Tcl_CmdProc*)sqlite3_mprintf_str }, - { "sqlite3_snprintf_str", (Tcl_CmdProc*)sqlite3_snprintf_str }, - { "sqlite3_mprintf_stronly", (Tcl_CmdProc*)sqlite3_mprintf_stronly}, - { "sqlite3_mprintf_double", (Tcl_CmdProc*)sqlite3_mprintf_double }, - { "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_snprintf_int", (Tcl_CmdProc*)test_snprintf_int }, - { "sqlite3_last_insert_rowid", (Tcl_CmdProc*)test_last_rowid }, - { "sqlite3_exec_printf", (Tcl_CmdProc*)test_exec_printf }, - { "sqlite3_exec_hex", (Tcl_CmdProc*)test_exec_hex }, - { "sqlite3_exec", (Tcl_CmdProc*)test_exec }, - { "sqlite3_exec_nr", (Tcl_CmdProc*)test_exec_nr }, -#ifndef SQLITE_OMIT_GET_TABLE - { "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 }, - { "sqlite_abort", (Tcl_CmdProc*)sqlite_abort }, - { "sqlite_bind", (Tcl_CmdProc*)test_bind }, - { "breakpoint", (Tcl_CmdProc*)test_breakpoint }, - { "sqlite3_key", (Tcl_CmdProc*)test_key }, - { "sqlite3_rekey", (Tcl_CmdProc*)test_rekey }, - { "sqlite_set_magic", (Tcl_CmdProc*)sqlite_set_magic }, - { "sqlite3_interrupt", (Tcl_CmdProc*)test_interrupt }, - { "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 }, - { "printf", (Tcl_CmdProc*)test_printf }, - { "sqlite3IoTrace", (Tcl_CmdProc*)test_io_trace }, - }; - 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_zeroblob", test_bind_zeroblob, 0 }, - { "sqlite3_bind_int64", test_bind_int64, 0 }, - { "sqlite3_bind_double", test_bind_double, 0 }, - { "sqlite3_bind_null", test_bind_null ,0 }, - { "sqlite3_bind_text", test_bind_text ,0 }, - { "sqlite3_bind_text16", test_bind_text16 ,0 }, - { "sqlite3_bind_blob", test_bind_blob ,0 }, - { "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}, - { "sqlite3_clear_bindings", test_clear_bindings, 0}, - { "sqlite3_sleep", test_sleep, 0}, - { "sqlite3_errcode", test_errcode ,0 }, - { "sqlite3_extended_errcode", test_ex_errcode ,0 }, - { "sqlite3_errmsg", test_errmsg ,0 }, - { "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 }, - { "sqlite3_prepare16", test_prepare16 ,0 }, - { "sqlite3_prepare_v2", test_prepare_v2 ,0 }, - { "sqlite3_prepare_tkt3134", test_prepare_tkt3134, 0}, - { "sqlite3_prepare16_v2", test_prepare16_v2 ,0 }, - { "sqlite3_finalize", test_finalize ,0 }, - { "sqlite3_stmt_status", test_stmt_status ,0 }, - { "sqlite3_reset", test_reset ,0 }, - { "sqlite3_expired", test_expired ,0 }, - { "sqlite3_transfer_bindings", test_transfer_bind ,0 }, - { "sqlite3_changes", test_changes ,0 }, - { "sqlite3_step", test_step ,0 }, - { "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}, - - { "sqlite3_load_extension", test_load_extension, 0}, - { "sqlite3_enable_load_extension", test_enable_load, 0}, - { "sqlite3_extended_result_codes", test_extended_result_codes, 0}, - { "sqlite3_limit", test_limit, 0}, - - { "save_prng_state", save_prng_state, 0 }, - { "restore_prng_state", restore_prng_state, 0 }, - { "reset_prng_state", reset_prng_state, 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 */ - { "sqlite3_column_count", test_column_count ,0 }, - { "sqlite3_data_count", test_data_count ,0 }, - { "sqlite3_column_type", test_column_type ,0 }, - { "sqlite3_column_blob", test_column_blob ,0 }, - { "sqlite3_column_double", test_column_double ,0 }, - { "sqlite3_column_int64", test_column_int64 ,0 }, - { "sqlite3_column_text", test_stmt_utf8, (void*)sqlite3_column_text }, - { "sqlite3_column_name", test_stmt_utf8, (void*)sqlite3_column_name }, - { "sqlite3_column_int", test_stmt_int, (void*)sqlite3_column_int }, - { "sqlite3_column_bytes", test_stmt_int, (void*)sqlite3_column_bytes}, -#ifndef SQLITE_OMIT_DECLTYPE - { "sqlite3_column_decltype",test_stmt_utf8,(void*)sqlite3_column_decltype}, -#endif -#ifdef SQLITE_ENABLE_COLUMN_METADATA -{ "sqlite3_column_database_name",test_stmt_utf8,(void*)sqlite3_column_database_name}, -{ "sqlite3_column_table_name",test_stmt_utf8,(void*)sqlite3_column_table_name}, -{ "sqlite3_column_origin_name",test_stmt_utf8,(void*)sqlite3_column_origin_name}, -#endif - -#ifndef SQLITE_OMIT_UTF16 - { "sqlite3_column_bytes16", test_stmt_int, (void*)sqlite3_column_bytes16 }, - { "sqlite3_column_text16", test_stmt_utf16, (void*)sqlite3_column_text16}, - { "sqlite3_column_name16", test_stmt_utf16, (void*)sqlite3_column_name16}, - { "add_alignment_test_collations", add_alignment_test_collations, 0 }, -#ifndef SQLITE_OMIT_DECLTYPE - { "sqlite3_column_decltype16",test_stmt_utf16,(void*)sqlite3_column_decltype16}, -#endif -#ifdef SQLITE_ENABLE_COLUMN_METADATA -{"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 -#endif - { "sqlite3_create_collation_v2", test_create_collation_v2, 0 }, - { "sqlite3_global_recover", test_global_recover, 0 }, - { "working_64bit_int", working_64bit_int, 0 }, - { "vfs_unlink_test", vfs_unlink_test, 0 }, - { "vfs_initfail_test", vfs_initfail_test, 0 }, - { "vfs_unregister_all", vfs_unregister_all, 0 }, - { "vfs_reregister_all", vfs_reregister_all, 0 }, - { "file_control_test", file_control_test, 0 }, - { "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_win32_av_retry", file_control_win32_av_retry, 0 }, - { "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 }, - - /* Functions from os.h */ -#ifndef SQLITE_OMIT_UTF16 - { "add_test_collate", test_collate, 0 }, - { "add_test_collate_needed", test_collate_needed, 0 }, - { "add_test_function", test_function, 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 }, - { "sqlite3_shared_cache_report", sqlite3BtreeSharedCacheReport, 0}, -#endif - { "sqlite3_libversion_number", test_libversion_number, 0 }, -#ifdef SQLITE_ENABLE_COLUMN_METADATA - { "sqlite3_table_column_metadata", test_table_column_metadata, 0 }, -#endif -#ifndef SQLITE_OMIT_INCRBLOB - { "sqlite3_blob_read", test_blob_read, 0 }, - { "sqlite3_blob_write", test_blob_write, 0 }, - { "sqlite3_blob_reopen", test_blob_reopen, 0 }, - { "sqlite3_blob_bytes", test_blob_bytes, 0 }, - { "sqlite3_blob_close", test_blob_close, 0 }, -#endif - { "pcache_stats", test_pcache_stats, 0 }, -#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY - { "sqlite3_unlock_notify", test_unlock_notify, 0 }, -#endif - { "sqlite3_wal_checkpoint", test_wal_checkpoint, 0 }, - { "sqlite3_wal_checkpoint_v2",test_wal_checkpoint_v2, 0 }, - { "test_sqlite3_log", test_sqlite3_log, 0 }, -#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 }, - }; - static int bitmask_size = sizeof(Bitmask)*8; - int i; - extern int sqlite3_sync_count, sqlite3_fullsync_count; - extern int sqlite3_opentemp_count; - extern int sqlite3_like_count; - extern int sqlite3_xferopt_count; - extern int sqlite3_pager_readdb_count; - extern int sqlite3_pager_writedb_count; - extern int sqlite3_pager_writej_count; -#if SQLITE_OS_WIN - extern int sqlite3_os_type; -#endif -#ifdef SQLITE_DEBUG - extern int sqlite3WhereTrace; - extern int sqlite3OSTrace; - extern int sqlite3WalTrace; -#endif -#ifdef SQLITE_TEST -#ifdef SQLITE_ENABLE_FTS3 - extern int sqlite3_fts3_enable_parentheses; -#endif -#endif - - for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){ - Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0); - } - for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){ - Tcl_CreateObjCommand(interp, aObjCmd[i].zName, - aObjCmd[i].xProc, aObjCmd[i].clientData, 0); - } - Tcl_LinkVar(interp, "sqlite_search_count", - (char*)&sqlite3_search_count, TCL_LINK_INT); - Tcl_LinkVar(interp, "sqlite_found_count", - (char*)&sqlite3_found_count, TCL_LINK_INT); - Tcl_LinkVar(interp, "sqlite_sort_count", - (char*)&sqlite3_sort_count, TCL_LINK_INT); - Tcl_LinkVar(interp, "sqlite3_max_blobsize", - (char*)&sqlite3_max_blobsize, TCL_LINK_INT); - Tcl_LinkVar(interp, "sqlite_like_count", - (char*)&sqlite3_like_count, TCL_LINK_INT); - Tcl_LinkVar(interp, "sqlite_interrupt_count", - (char*)&sqlite3_interrupt_count, TCL_LINK_INT); - Tcl_LinkVar(interp, "sqlite_open_file_count", - (char*)&sqlite3_open_file_count, TCL_LINK_INT); - Tcl_LinkVar(interp, "sqlite_current_time", - (char*)&sqlite3_current_time, TCL_LINK_INT); -#if SQLITE_OS_UNIX && defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE - Tcl_LinkVar(interp, "sqlite_hostid_num", - (char*)&sqlite3_hostid_num, TCL_LINK_INT); -#endif - Tcl_LinkVar(interp, "sqlite3_xferopt_count", - (char*)&sqlite3_xferopt_count, TCL_LINK_INT); - Tcl_LinkVar(interp, "sqlite3_pager_readdb_count", - (char*)&sqlite3_pager_readdb_count, TCL_LINK_INT); - Tcl_LinkVar(interp, "sqlite3_pager_writedb_count", - (char*)&sqlite3_pager_writedb_count, TCL_LINK_INT); - Tcl_LinkVar(interp, "sqlite3_pager_writej_count", - (char*)&sqlite3_pager_writej_count, TCL_LINK_INT); -#ifndef SQLITE_OMIT_UTF16 - Tcl_LinkVar(interp, "unaligned_string_counter", - (char*)&unaligned_string_counter, 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 -#if SQLITE_OS_WIN - Tcl_LinkVar(interp, "sqlite_os_type", - (char*)&sqlite3_os_type, TCL_LINK_INT); -#endif -#ifdef SQLITE_TEST - { - 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_where_trace", - (char*)&sqlite3WhereTrace, TCL_LINK_INT); - Tcl_LinkVar(interp, "sqlite_os_trace", - (char*)&sqlite3OSTrace, TCL_LINK_INT); -#ifndef SQLITE_OMIT_WAL - Tcl_LinkVar(interp, "sqlite_wal_trace", - (char*)&sqlite3WalTrace, TCL_LINK_INT); -#endif -#endif -#ifndef SQLITE_OMIT_DISKIO - Tcl_LinkVar(interp, "sqlite_opentemp_count", - (char*)&sqlite3_opentemp_count, TCL_LINK_INT); -#endif - Tcl_LinkVar(interp, "sqlite_static_bind_value", - (char*)&sqlite_static_bind_value, TCL_LINK_STRING); - Tcl_LinkVar(interp, "sqlite_static_bind_nbyte", - (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", - (char*)&sqlite3_sync_count, TCL_LINK_INT); - Tcl_LinkVar(interp, "sqlite_fullsync_count", - (char*)&sqlite3_fullsync_count, TCL_LINK_INT); -#if defined(SQLITE_ENABLE_FTS3) && defined(SQLITE_TEST) - Tcl_LinkVar(interp, "sqlite_fts3_enable_parentheses", - (char*)&sqlite3_fts3_enable_parentheses, TCL_LINK_INT); -#endif - return TCL_OK; -} diff --git a/components/external/SQLite-3.8.1/SQLiteLib/test/test10.c b/components/external/SQLite-3.8.1/SQLiteLib/test/test10.c deleted file mode 100644 index ca7b877b33..0000000000 --- a/components/external/SQLite-3.8.1/SQLiteLib/test/test10.c +++ /dev/null @@ -1,68 +0,0 @@ -#include <stdio.h> -#include <sqlite3.h> -#include "finsh.h" - -static int callback(void *NotUsed, int argc, char **argv, char **azColName){ - int i; - for(i=0; i<argc; i++){ - rt_kprintf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL"); - } - rt_kprintf("\n"); - return 0; -} - -int test10_main(void){ - static int step = 0; - int argc = 4; - char *argv[4] = {"test10_main", "test.db", - "create table mytable(entry1 int)", - "drop table mytable"}; - sqlite3 *db; - char *zErrMsg = 0; - int rc; - - if( argc<3 ){ - rt_kprintf("Usage: %s DATABASE SQL-STATEMENT\n", argv[0]); - return(1); - } - rt_kprintf("ready open %s\n", argv[1]); - rc = sqlite3_open(argv[1], &db); - - if( rc ){ - rt_kprintf("Can't open database: %s\n", sqlite3_errmsg(db)); - sqlite3_close(db); - return(1); - } - else{ - rt_kprintf("open %s success\n", argv[1]); - } - - if (step == 0) { - rt_kprintf("SQL exec: %s\n", argv[2]); - rc = sqlite3_exec(db, argv[2], callback, 0, &zErrMsg); - if( rc!=SQLITE_OK ){ - rt_kprintf("SQL error: %s\n", zErrMsg); - sqlite3_free(zErrMsg); - } - else{ - rt_kprintf("SQL exec: %s success\n", argv[2]); - } - } - else { - rt_kprintf("SQL exec: %s\n", argv[3]); - rc = sqlite3_exec(db, argv[3], callback, 0, &zErrMsg); - if( rc!=SQLITE_OK ){ - rt_kprintf("SQL error: %s\n", zErrMsg); - sqlite3_free(zErrMsg); - } - else{ - rt_kprintf("SQL exec: %s success\n", argv[3]); - } - } - - step = !step; - - sqlite3_close(db); - return 0; -} -FINSH_FUNCTION_EXPORT(test10_main, sqlite test)
\ No newline at end of file diff --git a/components/external/SQLite-3.8.1/SQLiteLib/test/test2.c b/components/external/SQLite-3.8.1/SQLiteLib/test/test2.c deleted file mode 100644 index d130e9d01b..0000000000 --- a/components/external/SQLite-3.8.1/SQLiteLib/test/test2.c +++ /dev/null @@ -1,664 +0,0 @@ -/* -** 2001 September 15 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** Code for testing the pager.c module in SQLite. This code -** is not included in the SQLite library. It is used for automated -** testing of the SQLite library. -*/ -#include "sqliteInt.h" -#include "tcl.h" -#include <stdlib.h> -#include <string.h> -#include <ctype.h> - -extern const char *sqlite3ErrName(int); - -/* -** Page size and reserved size used for testing. -*/ -static int test_pagesize = 1024; - -/* -** Dummy page reinitializer -*/ -static void pager_test_reiniter(DbPage *pNotUsed){ - return; -} - -/* -** Usage: pager_open FILENAME N-PAGE -** -** Open a new pager -*/ -static int pager_open( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - const char **argv /* Text of each argument */ -){ - u32 pageSize; - Pager *pPager; - int nPage; - int rc; - char zBuf[100]; - if( argc!=3 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " FILENAME N-PAGE\"", 0); - return TCL_ERROR; - } - if( Tcl_GetInt(interp, argv[2], &nPage) ) return TCL_ERROR; - rc = sqlite3PagerOpen(sqlite3_vfs_find(0), &pPager, argv[1], 0, 0, - SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_MAIN_DB, - pager_test_reiniter); - if( rc!=SQLITE_OK ){ - Tcl_AppendResult(interp, sqlite3ErrName(rc), 0); - return TCL_ERROR; - } - sqlite3PagerSetCachesize(pPager, nPage); - pageSize = test_pagesize; - sqlite3PagerSetPagesize(pPager, &pageSize, -1); - sqlite3_snprintf(sizeof(zBuf),zBuf,"%p",pPager); - Tcl_AppendResult(interp, zBuf, 0); - return TCL_OK; -} - -/* -** Usage: pager_close ID -** -** Close the given pager. -*/ -static int pager_close( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - const char **argv /* Text of each argument */ -){ - Pager *pPager; - int rc; - if( argc!=2 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " ID\"", 0); - return TCL_ERROR; - } - pPager = sqlite3TestTextToPtr(argv[1]); - rc = sqlite3PagerClose(pPager); - if( rc!=SQLITE_OK ){ - Tcl_AppendResult(interp, sqlite3ErrName(rc), 0); - return TCL_ERROR; - } - return TCL_OK; -} - -/* -** Usage: pager_rollback ID -** -** Rollback changes -*/ -static int pager_rollback( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - const char **argv /* Text of each argument */ -){ - Pager *pPager; - int rc; - if( argc!=2 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " ID\"", 0); - return TCL_ERROR; - } - pPager = sqlite3TestTextToPtr(argv[1]); - rc = sqlite3PagerRollback(pPager); - if( rc!=SQLITE_OK ){ - Tcl_AppendResult(interp, sqlite3ErrName(rc), 0); - return TCL_ERROR; - } - return TCL_OK; -} - -/* -** Usage: pager_commit ID -** -** Commit all changes -*/ -static int pager_commit( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - const char **argv /* Text of each argument */ -){ - Pager *pPager; - int rc; - if( argc!=2 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " ID\"", 0); - return TCL_ERROR; - } - pPager = sqlite3TestTextToPtr(argv[1]); - rc = sqlite3PagerCommitPhaseOne(pPager, 0, 0); - if( rc!=SQLITE_OK ){ - Tcl_AppendResult(interp, sqlite3ErrName(rc), 0); - return TCL_ERROR; - } - rc = sqlite3PagerCommitPhaseTwo(pPager); - if( rc!=SQLITE_OK ){ - Tcl_AppendResult(interp, sqlite3ErrName(rc), 0); - return TCL_ERROR; - } - return TCL_OK; -} - -/* -** Usage: pager_stmt_begin ID -** -** Start a new checkpoint. -*/ -static int pager_stmt_begin( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - const char **argv /* Text of each argument */ -){ - Pager *pPager; - int rc; - if( argc!=2 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " ID\"", 0); - return TCL_ERROR; - } - pPager = sqlite3TestTextToPtr(argv[1]); - rc = sqlite3PagerOpenSavepoint(pPager, 1); - if( rc!=SQLITE_OK ){ - Tcl_AppendResult(interp, sqlite3ErrName(rc), 0); - return TCL_ERROR; - } - return TCL_OK; -} - -/* -** Usage: pager_stmt_rollback ID -** -** Rollback changes to a checkpoint -*/ -static int pager_stmt_rollback( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - const char **argv /* Text of each argument */ -){ - Pager *pPager; - int rc; - if( argc!=2 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " ID\"", 0); - return TCL_ERROR; - } - pPager = sqlite3TestTextToPtr(argv[1]); - rc = sqlite3PagerSavepoint(pPager, SAVEPOINT_ROLLBACK, 0); - sqlite3PagerSavepoint(pPager, SAVEPOINT_RELEASE, 0); - if( rc!=SQLITE_OK ){ - Tcl_AppendResult(interp, sqlite3ErrName(rc), 0); - return TCL_ERROR; - } - return TCL_OK; -} - -/* -** Usage: pager_stmt_commit ID -** -** Commit changes to a checkpoint -*/ -static int pager_stmt_commit( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - const char **argv /* Text of each argument */ -){ - Pager *pPager; - int rc; - if( argc!=2 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " ID\"", 0); - return TCL_ERROR; - } - pPager = sqlite3TestTextToPtr(argv[1]); - rc = sqlite3PagerSavepoint(pPager, SAVEPOINT_RELEASE, 0); - if( rc!=SQLITE_OK ){ - Tcl_AppendResult(interp, sqlite3ErrName(rc), 0); - return TCL_ERROR; - } - return TCL_OK; -} - -/* -** Usage: pager_stats ID -** -** Return pager statistics. -*/ -static int pager_stats( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - const char **argv /* Text of each argument */ -){ - Pager *pPager; - int i, *a; - if( argc!=2 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " ID\"", 0); - return TCL_ERROR; - } - pPager = sqlite3TestTextToPtr(argv[1]); - a = sqlite3PagerStats(pPager); - for(i=0; i<9; i++){ - static char *zName[] = { - "ref", "page", "max", "size", "state", "err", - "hit", "miss", "ovfl", - }; - char zBuf[100]; - Tcl_AppendElement(interp, zName[i]); - sqlite3_snprintf(sizeof(zBuf),zBuf,"%d",a[i]); - Tcl_AppendElement(interp, zBuf); - } - return TCL_OK; -} - -/* -** Usage: pager_pagecount ID -** -** Return the size of the database file. -*/ -static int pager_pagecount( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - const char **argv /* Text of each argument */ -){ - Pager *pPager; - char zBuf[100]; - int nPage; - if( argc!=2 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " ID\"", 0); - return TCL_ERROR; - } - pPager = sqlite3TestTextToPtr(argv[1]); - sqlite3PagerPagecount(pPager, &nPage); - sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", nPage); - Tcl_AppendResult(interp, zBuf, 0); - return TCL_OK; -} - -/* -** Usage: page_get ID PGNO -** -** Return a pointer to a page from the database. -*/ -static int page_get( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - const char **argv /* Text of each argument */ -){ - Pager *pPager; - char zBuf[100]; - DbPage *pPage; - int pgno; - int rc; - if( argc!=3 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " ID PGNO\"", 0); - return TCL_ERROR; - } - pPager = sqlite3TestTextToPtr(argv[1]); - if( Tcl_GetInt(interp, argv[2], &pgno) ) return TCL_ERROR; - rc = sqlite3PagerSharedLock(pPager); - if( rc==SQLITE_OK ){ - rc = sqlite3PagerGet(pPager, pgno, &pPage); - } - if( rc!=SQLITE_OK ){ - Tcl_AppendResult(interp, sqlite3ErrName(rc), 0); - return TCL_ERROR; - } - sqlite3_snprintf(sizeof(zBuf),zBuf,"%p",pPage); - Tcl_AppendResult(interp, zBuf, 0); - return TCL_OK; -} - -/* -** Usage: page_lookup ID PGNO -** -** Return a pointer to a page if the page is already in cache. -** If not in cache, return an empty string. -*/ -static int page_lookup( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - const char **argv /* Text of each argument */ -){ - Pager *pPager; - char zBuf[100]; - DbPage *pPage; - int pgno; - if( argc!=3 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " ID PGNO\"", 0); - return TCL_ERROR; - } - pPager = sqlite3TestTextToPtr(argv[1]); - if( Tcl_GetInt(interp, argv[2], &pgno) ) return TCL_ERROR; - pPage = sqlite3PagerLookup(pPager, pgno); - if( pPage ){ - sqlite3_snprintf(sizeof(zBuf),zBuf,"%p",pPage); - Tcl_AppendResult(interp, zBuf, 0); - } - return TCL_OK; -} - -/* -** Usage: pager_truncate ID PGNO -*/ -static int pager_truncate( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - const char **argv /* Text of each argument */ -){ - Pager *pPager; - int pgno; - if( argc!=3 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " ID PGNO\"", 0); - return TCL_ERROR; - } - pPager = sqlite3TestTextToPtr(argv[1]); - if( Tcl_GetInt(interp, argv[2], &pgno) ) return TCL_ERROR; - sqlite3PagerTruncateImage(pPager, pgno); - return TCL_OK; -} - - -/* -** Usage: page_unref PAGE -** -** Drop a pointer to a page. -*/ -static int page_unref( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - const char **argv /* Text of each argument */ -){ - DbPage *pPage; - if( argc!=2 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " PAGE\"", 0); - return TCL_ERROR; - } - pPage = (DbPage *)sqlite3TestTextToPtr(argv[1]); - sqlite3PagerUnref(pPage); - return TCL_OK; -} - -/* -** Usage: page_read PAGE -** -** Return the content of a page -*/ -static int page_read( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - const char **argv /* Text of each argument */ -){ - char zBuf[100]; - DbPage *pPage; - if( argc!=2 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " PAGE\"", 0); - return TCL_ERROR; - } - pPage = sqlite3TestTextToPtr(argv[1]); - memcpy(zBuf, sqlite3PagerGetData(pPage), sizeof(zBuf)); - Tcl_AppendResult(interp, zBuf, 0); - return TCL_OK; -} - -/* -** Usage: page_number PAGE -** -** Return the page number for a page. -*/ -static int page_number( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - const char **argv /* Text of each argument */ -){ - char zBuf[100]; - DbPage *pPage; - if( argc!=2 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " PAGE\"", 0); - return TCL_ERROR; - } - pPage = (DbPage *)sqlite3TestTextToPtr(argv[1]); - sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", sqlite3PagerPagenumber(pPage)); - Tcl_AppendResult(interp, zBuf, 0); - return TCL_OK; -} - -/* -** Usage: page_write PAGE DATA -** -** Write something into a page. -*/ -static int page_write( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - const char **argv /* Text of each argument */ -){ - DbPage *pPage; - char *pData; - int rc; - if( argc!=3 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " PAGE DATA\"", 0); - return TCL_ERROR; - } - pPage = (DbPage *)sqlite3TestTextToPtr(argv[1]); - rc = sqlite3PagerWrite(pPage); - if( rc!=SQLITE_OK ){ - Tcl_AppendResult(interp, sqlite3ErrName(rc), 0); - return TCL_ERROR; - } - pData = sqlite3PagerGetData(pPage); - strncpy(pData, argv[2], test_pagesize-1); - pData[test_pagesize-1] = 0; - return TCL_OK; -} - -#ifndef SQLITE_OMIT_DISKIO -/* -** Usage: fake_big_file N FILENAME -** -** Write a few bytes at the N megabyte point of FILENAME. This will -** create a large file. If the file was a valid SQLite database, then -** the next time the database is opened, SQLite will begin allocating -** new pages after N. If N is 2096 or bigger, this will test the -** ability of SQLite to write to large files. -*/ -static int fake_big_file( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - const char **argv /* Text of each argument */ -){ - sqlite3_vfs *pVfs; - sqlite3_file *fd = 0; - int rc; - int n; - i64 offset; - char *zFile; - int nFile; - if( argc!=3 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " N-MEGABYTES FILE\"", 0); - return TCL_ERROR; - } - if( Tcl_GetInt(interp, argv[1], &n) ) return TCL_ERROR; - - pVfs = sqlite3_vfs_find(0); - nFile = (int)strlen(argv[2]); - zFile = sqlite3_malloc( nFile+2 ); - if( zFile==0 ) return TCL_ERROR; - memcpy(zFile, argv[2], nFile+1); - zFile[nFile+1] = 0; - rc = sqlite3OsOpenMalloc(pVfs, zFile, &fd, - (SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE|SQLITE_OPEN_MAIN_DB), 0 - ); - if( rc ){ - Tcl_AppendResult(interp, "open failed: ", sqlite3ErrName(rc), 0); - sqlite3_free(zFile); - return TCL_ERROR; - } - offset = n; - offset *= 1024*1024; - rc = sqlite3OsWrite(fd, "Hello, World!", 14, offset); - sqlite3OsCloseFree(fd); - sqlite3_free(zFile); - if( rc ){ - Tcl_AppendResult(interp, "write failed: ", sqlite3ErrName(rc), 0); - return TCL_ERROR; - } - return TCL_OK; -} -#endif - - -/* -** test_control_pending_byte PENDING_BYTE -** -** Set the PENDING_BYTE using the sqlite3_test_control() interface. -*/ -static int testPendingByte( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - const char **argv /* Text of each argument */ -){ - int pbyte; - int rc; - if( argc!=2 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " PENDING-BYTE\"", (void*)0); - return TCL_ERROR; - } - if( Tcl_GetInt(interp, argv[1], &pbyte) ) return TCL_ERROR; - rc = sqlite3_test_control(SQLITE_TESTCTRL_PENDING_BYTE, pbyte); - Tcl_SetObjResult(interp, Tcl_NewIntObj(rc)); - return TCL_OK; -} - -/* -** sqlite3BitvecBuiltinTest SIZE PROGRAM -** -** Invoke the SQLITE_TESTCTRL_BITVEC_TEST operator on test_control. -** See comments on sqlite3BitvecBuiltinTest() for additional information. -*/ -static int testBitvecBuiltinTest( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - const char **argv /* Text of each argument */ -){ - int sz, rc; - int nProg = 0; - int aProg[100]; - const char *z; - if( argc!=3 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " SIZE PROGRAM\"", (void*)0); - } - if( Tcl_GetInt(interp, argv[1], &sz) ) return TCL_ERROR; - z = argv[2]; - while( nProg<99 && *z ){ - while( *z && !sqlite3Isdigit(*z) ){ z++; } - if( *z==0 ) break; - aProg[nProg++] = atoi(z); - while( sqlite3Isdigit(*z) ){ z++; } - } - aProg[nProg] = 0; - rc = sqlite3_test_control(SQLITE_TESTCTRL_BITVEC_TEST, sz, aProg); - Tcl_SetObjResult(interp, Tcl_NewIntObj(rc)); - return TCL_OK; -} - -/* -** Register commands with the TCL interpreter. -*/ -int Sqlitetest2_Init(Tcl_Interp *interp){ - extern int sqlite3_io_error_persist; - extern int sqlite3_io_error_pending; - extern int sqlite3_io_error_hit; - extern int sqlite3_io_error_hardhit; - extern int sqlite3_diskfull_pending; - extern int sqlite3_diskfull; - static struct { - char *zName; - Tcl_CmdProc *xProc; - } aCmd[] = { - { "pager_open", (Tcl_CmdProc*)pager_open }, - { "pager_close", (Tcl_CmdProc*)pager_close }, - { "pager_commit", (Tcl_CmdProc*)pager_commit }, - { "pager_rollback", (Tcl_CmdProc*)pager_rollback }, - { "pager_stmt_begin", (Tcl_CmdProc*)pager_stmt_begin }, - { "pager_stmt_commit", (Tcl_CmdProc*)pager_stmt_commit }, - { "pager_stmt_rollback", (Tcl_CmdProc*)pager_stmt_rollback }, - { "pager_stats", (Tcl_CmdProc*)pager_stats }, - { "pager_pagecount", (Tcl_CmdProc*)pager_pagecount }, - { "page_get", (Tcl_CmdProc*)page_get }, - { "page_lookup", (Tcl_CmdProc*)page_lookup }, - { "page_unref", (Tcl_CmdProc*)page_unref }, - { "page_read", (Tcl_CmdProc*)page_read }, - { "page_write", (Tcl_CmdProc*)page_write }, - { "page_number", (Tcl_CmdProc*)page_number }, - { "pager_truncate", (Tcl_CmdProc*)pager_truncate }, -#ifndef SQLITE_OMIT_DISKIO - { "fake_big_file", (Tcl_CmdProc*)fake_big_file }, -#endif - { "sqlite3BitvecBuiltinTest",(Tcl_CmdProc*)testBitvecBuiltinTest }, - { "sqlite3_test_control_pending_byte", (Tcl_CmdProc*)testPendingByte }, - }; - int i; - for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){ - Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0); - } - Tcl_LinkVar(interp, "sqlite_io_error_pending", - (char*)&sqlite3_io_error_pending, TCL_LINK_INT); - Tcl_LinkVar(interp, "sqlite_io_error_persist", - (char*)&sqlite3_io_error_persist, TCL_LINK_INT); - Tcl_LinkVar(interp, "sqlite_io_error_hit", - (char*)&sqlite3_io_error_hit, TCL_LINK_INT); - Tcl_LinkVar(interp, "sqlite_io_error_hardhit", - (char*)&sqlite3_io_error_hardhit, TCL_LINK_INT); - Tcl_LinkVar(interp, "sqlite_diskfull_pending", - (char*)&sqlite3_diskfull_pending, TCL_LINK_INT); - Tcl_LinkVar(interp, "sqlite_diskfull", - (char*)&sqlite3_diskfull, TCL_LINK_INT); -#ifndef SQLITE_OMIT_WSD - Tcl_LinkVar(interp, "sqlite_pending_byte", - (char*)&sqlite3PendingByte, TCL_LINK_INT | TCL_LINK_READ_ONLY); -#endif - return TCL_OK; -} diff --git a/components/external/SQLite-3.8.1/SQLiteLib/test/test3.c b/components/external/SQLite-3.8.1/SQLiteLib/test/test3.c deleted file mode 100644 index e3ed310c81..0000000000 --- a/components/external/SQLite-3.8.1/SQLiteLib/test/test3.c +++ /dev/null @@ -1,628 +0,0 @@ -/* -** 2001 September 15 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** Code for testing the btree.c module in SQLite. This code -** is not included in the SQLite library. It is used for automated -** testing of the SQLite library. -*/ -#include "sqliteInt.h" -#include "btreeInt.h" -#include "tcl.h" -#include <stdlib.h> -#include <string.h> - -extern const char *sqlite3ErrName(int); - -/* -** A bogus sqlite3 connection structure for use in the btree -** tests. -*/ -static sqlite3 sDb; -static int nRefSqlite3 = 0; - -/* -** Usage: btree_open FILENAME NCACHE -** -** Open a new database -*/ -static int btree_open( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - const char **argv /* Text of each argument */ -){ - Btree *pBt; - int rc, nCache; - char zBuf[100]; - int n; - char *zFilename; - if( argc!=3 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " FILENAME NCACHE FLAGS\"", 0); - return TCL_ERROR; - } - if( Tcl_GetInt(interp, argv[2], &nCache) ) return TCL_ERROR; - nRefSqlite3++; - if( nRefSqlite3==1 ){ - sDb.pVfs = sqlite3_vfs_find(0); - sDb.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_RECURSIVE); - sqlite3_mutex_enter(sDb.mutex); - } - n = (int)strlen(argv[1]); - zFilename = sqlite3_malloc( n+2 ); - if( zFilename==0 ) return TCL_ERROR; - memcpy(zFilename, argv[1], n+1); - zFilename[n+1] = 0; - rc = sqlite3BtreeOpen(sDb.pVfs, zFilename, &sDb, &pBt, 0, - SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_MAIN_DB); - sqlite3_free(zFilename); - if( rc!=SQLITE_OK ){ - Tcl_AppendResult(interp, sqlite3ErrName(rc), 0); - return TCL_ERROR; - } - sqlite3BtreeSetCacheSize(pBt, nCache); - sqlite3_snprintf(sizeof(zBuf), zBuf,"%p", pBt); - Tcl_AppendResult(interp, zBuf, 0); - return TCL_OK; -} - -/* -** Usage: btree_close ID -** -** Close the given database. -*/ -static int btree_close( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - const char **argv /* Text of each argument */ -){ - Btree *pBt; - int rc; - if( argc!=2 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " ID\"", 0); - return TCL_ERROR; - } - pBt = sqlite3TestTextToPtr(argv[1]); - rc = sqlite3BtreeClose(pBt); - if( rc!=SQLITE_OK ){ - Tcl_AppendResult(interp, sqlite3ErrName(rc), 0); - return TCL_ERROR; - } - nRefSqlite3--; - if( nRefSqlite3==0 ){ - sqlite3_mutex_leave(sDb.mutex); - sqlite3_mutex_free(sDb.mutex); - sDb.mutex = 0; - sDb.pVfs = 0; - } - return TCL_OK; -} - - -/* -** Usage: btree_begin_transaction ID -** -** Start a new transaction -*/ -static int btree_begin_transaction( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - const char **argv /* Text of each argument */ -){ - Btree *pBt; - int rc; - if( argc!=2 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " ID\"", 0); - return TCL_ERROR; - } - pBt = sqlite3TestTextToPtr(argv[1]); - sqlite3BtreeEnter(pBt); - rc = sqlite3BtreeBeginTrans(pBt, 1); - sqlite3BtreeLeave(pBt); - if( rc!=SQLITE_OK ){ - Tcl_AppendResult(interp, sqlite3ErrName(rc), 0); - return TCL_ERROR; - } - return TCL_OK; -} - -/* -** Usage: btree_pager_stats ID -** -** Returns pager statistics -*/ -static int btree_pager_stats( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - const char **argv /* Text of each argument */ -){ - Btree *pBt; - int i; - int *a; - - if( argc!=2 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " ID\"", 0); - return TCL_ERROR; - } - pBt = sqlite3TestTextToPtr(argv[1]); - - /* Normally in this file, with a b-tree handle opened using the - ** [btree_open] command it is safe to call sqlite3BtreeEnter() directly. - ** But this function is sometimes called with a btree handle obtained - ** from an open SQLite connection (using [btree_from_db]). In this case - ** we need to obtain the mutex for the controlling SQLite handle before - ** it is safe to call sqlite3BtreeEnter(). - */ - sqlite3_mutex_enter(pBt->db->mutex); - - sqlite3BtreeEnter(pBt); - a = sqlite3PagerStats(sqlite3BtreePager(pBt)); - for(i=0; i<11; i++){ - static char *zName[] = { - "ref", "page", "max", "size", "state", "err", - "hit", "miss", "ovfl", "read", "write" - }; - char zBuf[100]; - Tcl_AppendElement(interp, zName[i]); - sqlite3_snprintf(sizeof(zBuf), zBuf,"%d",a[i]); - Tcl_AppendElement(interp, zBuf); - } - sqlite3BtreeLeave(pBt); - - /* Release the mutex on the SQLite handle that controls this b-tree */ - sqlite3_mutex_leave(pBt->db->mutex); - return TCL_OK; -} - -/* -** Usage: btree_cursor ID TABLENUM WRITEABLE -** -** Create a new cursor. Return the ID for the cursor. -*/ -static int btree_cursor( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - const char **argv /* Text of each argument */ -){ - Btree *pBt; - int iTable; - BtCursor *pCur; - int rc = SQLITE_OK; - int wrFlag; - char zBuf[30]; - - if( argc!=4 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " ID TABLENUM WRITEABLE\"", 0); - return TCL_ERROR; - } - pBt = sqlite3TestTextToPtr(argv[1]); - if( Tcl_GetInt(interp, argv[2], &iTable) ) return TCL_ERROR; - if( Tcl_GetBoolean(interp, argv[3], &wrFlag) ) return TCL_ERROR; - pCur = (BtCursor *)ckalloc(sqlite3BtreeCursorSize()); - memset(pCur, 0, sqlite3BtreeCursorSize()); - sqlite3BtreeEnter(pBt); -#ifndef SQLITE_OMIT_SHARED_CACHE - rc = sqlite3BtreeLockTable(pBt, iTable, wrFlag); -#endif - if( rc==SQLITE_OK ){ - rc = sqlite3BtreeCursor(pBt, iTable, wrFlag, 0, pCur); - } - sqlite3BtreeLeave(pBt); - if( rc ){ - ckfree((char *)pCur); - Tcl_AppendResult(interp, sqlite3ErrName(rc), 0); - return TCL_ERROR; - } - sqlite3_snprintf(sizeof(zBuf), zBuf,"%p", pCur); - Tcl_AppendResult(interp, zBuf, 0); - return SQLITE_OK; -} - -/* -** Usage: btree_close_cursor ID -** -** Close a cursor opened using btree_cursor. -*/ -static int btree_close_cursor( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - const char **argv /* Text of each argument */ -){ - BtCursor *pCur; - Btree *pBt; - int rc; - - if( argc!=2 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " ID\"", 0); - return TCL_ERROR; - } - pCur = sqlite3TestTextToPtr(argv[1]); - pBt = pCur->pBtree; - sqlite3BtreeEnter(pBt); - rc = sqlite3BtreeCloseCursor(pCur); - sqlite3BtreeLeave(pBt); - ckfree((char *)pCur); - if( rc ){ - Tcl_AppendResult(interp, sqlite3ErrName(rc), 0); - return TCL_ERROR; - } - return SQLITE_OK; -} - -/* -** Usage: btree_next ID -** -** Move the cursor to the next entry in the table. Return 0 on success -** or 1 if the cursor was already on the last entry in the table or if -** the table is empty. -*/ -static int btree_next( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - const char **argv /* Text of each argument */ -){ - BtCursor *pCur; - int rc; - int res = 0; - char zBuf[100]; - - if( argc!=2 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " ID\"", 0); - return TCL_ERROR; - } - pCur = sqlite3TestTextToPtr(argv[1]); - sqlite3BtreeEnter(pCur->pBtree); - rc = sqlite3BtreeNext(pCur, &res); - sqlite3BtreeLeave(pCur->pBtree); - if( rc ){ - Tcl_AppendResult(interp, sqlite3ErrName(rc), 0); - return TCL_ERROR; - } - sqlite3_snprintf(sizeof(zBuf),zBuf,"%d",res); - Tcl_AppendResult(interp, zBuf, 0); - return SQLITE_OK; -} - -/* -** Usage: btree_first ID -** -** Move the cursor to the first entry in the table. Return 0 if the -** cursor was left point to something and 1 if the table is empty. -*/ -static int btree_first( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - const char **argv /* Text of each argument */ -){ - BtCursor *pCur; - int rc; - int res = 0; - char zBuf[100]; - - if( argc!=2 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " ID\"", 0); - return TCL_ERROR; - } - pCur = sqlite3TestTextToPtr(argv[1]); - sqlite3BtreeEnter(pCur->pBtree); - rc = sqlite3BtreeFirst(pCur, &res); - sqlite3BtreeLeave(pCur->pBtree); - if( rc ){ - Tcl_AppendResult(interp, sqlite3ErrName(rc), 0); - return TCL_ERROR; - } - sqlite3_snprintf(sizeof(zBuf),zBuf,"%d",res); - Tcl_AppendResult(interp, zBuf, 0); - return SQLITE_OK; -} - -/* -** Usage: btree_eof ID -** -** Return TRUE if the given cursor is not pointing at a valid entry. -** Return FALSE if the cursor does point to a valid entry. -*/ -static int btree_eof( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - const char **argv /* Text of each argument */ -){ - BtCursor *pCur; - int rc; - char zBuf[50]; - - if( argc!=2 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " ID\"", 0); - return TCL_ERROR; - } - pCur = sqlite3TestTextToPtr(argv[1]); - sqlite3BtreeEnter(pCur->pBtree); - rc = sqlite3BtreeEof(pCur); - sqlite3BtreeLeave(pCur->pBtree); - sqlite3_snprintf(sizeof(zBuf),zBuf, "%d", rc); - Tcl_AppendResult(interp, zBuf, 0); - return SQLITE_OK; -} - -/* -** Usage: btree_payload_size ID -** -** Return the number of bytes of payload -*/ -static int btree_payload_size( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - const char **argv /* Text of each argument */ -){ - BtCursor *pCur; - int n2; - u64 n1; - char zBuf[50]; - - if( argc!=2 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " ID\"", 0); - return TCL_ERROR; - } - pCur = sqlite3TestTextToPtr(argv[1]); - sqlite3BtreeEnter(pCur->pBtree); - - /* The cursor may be in "require-seek" state. If this is the case, the - ** call to BtreeDataSize() will fix it. */ - sqlite3BtreeDataSize(pCur, (u32*)&n2); - if( pCur->apPage[pCur->iPage]->intKey ){ - n1 = 0; - }else{ - sqlite3BtreeKeySize(pCur, (i64*)&n1); - } - sqlite3BtreeLeave(pCur->pBtree); - sqlite3_snprintf(sizeof(zBuf),zBuf, "%d", (int)(n1+n2)); - Tcl_AppendResult(interp, zBuf, 0); - return SQLITE_OK; -} - -/* -** usage: varint_test START MULTIPLIER COUNT INCREMENT -** -** This command tests the putVarint() and getVarint() -** routines, both for accuracy and for speed. -** -** An integer is written using putVarint() and read back with -** getVarint() and varified to be unchanged. This repeats COUNT -** times. The first integer is START*MULTIPLIER. Each iteration -** increases the integer by INCREMENT. -** -** This command returns nothing if it works. It returns an error message -** if something goes wrong. -*/ -static int btree_varint_test( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - const char **argv /* Text of each argument */ -){ - u32 start, mult, count, incr; - u64 in, out; - int n1, n2, i, j; - unsigned char zBuf[100]; - if( argc!=5 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " START MULTIPLIER COUNT INCREMENT\"", 0); - return TCL_ERROR; - } - if( Tcl_GetInt(interp, argv[1], (int*)&start) ) return TCL_ERROR; - if( Tcl_GetInt(interp, argv[2], (int*)&mult) ) return TCL_ERROR; - if( Tcl_GetInt(interp, argv[3], (int*)&count) ) return TCL_ERROR; - if( Tcl_GetInt(interp, argv[4], (int*)&incr) ) return TCL_ERROR; - in = start; - in *= mult; - for(i=0; i<(int)count; i++){ - char zErr[200]; - n1 = putVarint(zBuf, in); - if( n1>9 || n1<1 ){ - sprintf(zErr, "putVarint returned %d - should be between 1 and 9", n1); - Tcl_AppendResult(interp, zErr, 0); - return TCL_ERROR; - } - n2 = getVarint(zBuf, &out); - if( n1!=n2 ){ - sprintf(zErr, "putVarint returned %d and getVarint returned %d", n1, n2); - Tcl_AppendResult(interp, zErr, 0); - return TCL_ERROR; - } - if( in!=out ){ - sprintf(zErr, "Wrote 0x%016llx and got back 0x%016llx", in, out); - Tcl_AppendResult(interp, zErr, 0); - return TCL_ERROR; - } - if( (in & 0xffffffff)==in ){ - u32 out32; - n2 = getVarint32(zBuf, out32); - out = out32; - if( n1!=n2 ){ - sprintf(zErr, "putVarint returned %d and GetVarint32 returned %d", - n1, n2); - Tcl_AppendResult(interp, zErr, 0); - return TCL_ERROR; - } - if( in!=out ){ - sprintf(zErr, "Wrote 0x%016llx and got back 0x%016llx from GetVarint32", - in, out); - Tcl_AppendResult(interp, zErr, 0); - return TCL_ERROR; - } - } - - /* In order to get realistic timings, run getVarint 19 more times. - ** This is because getVarint is called about 20 times more often - ** than putVarint. - */ - for(j=0; j<19; j++){ - getVarint(zBuf, &out); - } - in += incr; - } - return TCL_OK; -} - -/* -** usage: btree_from_db DB-HANDLE -** -** This command returns the btree handle for the main database associated -** with the database-handle passed as the argument. Example usage: -** -** sqlite3 db test.db -** set bt [btree_from_db db] -*/ -static int btree_from_db( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - const char **argv /* Text of each argument */ -){ - char zBuf[100]; - Tcl_CmdInfo info; - sqlite3 *db; - Btree *pBt; - int iDb = 0; - - if( argc!=2 && argc!=3 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " DB-HANDLE ?N?\"", 0); - return TCL_ERROR; - } - - if( 1!=Tcl_GetCommandInfo(interp, argv[1], &info) ){ - Tcl_AppendResult(interp, "No such db-handle: \"", argv[1], "\"", 0); - return TCL_ERROR; - } - if( argc==3 ){ - iDb = atoi(argv[2]); - } - - db = *((sqlite3 **)info.objClientData); - assert( db ); - - pBt = db->aDb[iDb].pBt; - sqlite3_snprintf(sizeof(zBuf), zBuf, "%p", pBt); - Tcl_SetResult(interp, zBuf, TCL_VOLATILE); - return TCL_OK; -} - -/* -** Usage: btree_ismemdb ID -** -** Return true if the B-Tree is in-memory. -*/ -static int btree_ismemdb( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - const char **argv /* Text of each argument */ -){ - Btree *pBt; - int res; - - if( argc!=2 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " ID\"", 0); - return TCL_ERROR; - } - pBt = sqlite3TestTextToPtr(argv[1]); - sqlite3_mutex_enter(pBt->db->mutex); - sqlite3BtreeEnter(pBt); - res = sqlite3PagerIsMemdb(sqlite3BtreePager(pBt)); - sqlite3BtreeLeave(pBt); - sqlite3_mutex_leave(pBt->db->mutex); - Tcl_SetObjResult(interp, Tcl_NewBooleanObj(res)); - return SQLITE_OK; -} - -/* -** usage: btree_set_cache_size ID NCACHE -** -** Set the size of the cache used by btree $ID. -*/ -static int btree_set_cache_size( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - const char **argv /* Text of each argument */ -){ - int nCache; - Btree *pBt; - - if( argc!=3 ){ - Tcl_AppendResult( - interp, "wrong # args: should be \"", argv[0], " BT NCACHE\"", 0); - return TCL_ERROR; - } - pBt = sqlite3TestTextToPtr(argv[1]); - if( Tcl_GetInt(interp, argv[2], &nCache) ) return TCL_ERROR; - - sqlite3_mutex_enter(pBt->db->mutex); - sqlite3BtreeEnter(pBt); - sqlite3BtreeSetCacheSize(pBt, nCache); - sqlite3BtreeLeave(pBt); - sqlite3_mutex_leave(pBt->db->mutex); - return TCL_OK; -} - - - -/* -** Register commands with the TCL interpreter. -*/ -int Sqlitetest3_Init(Tcl_Interp *interp){ - static struct { - char *zName; - Tcl_CmdProc *xProc; - } aCmd[] = { - { "btree_open", (Tcl_CmdProc*)btree_open }, - { "btree_close", (Tcl_CmdProc*)btree_close }, - { "btree_begin_transaction", (Tcl_CmdProc*)btree_begin_transaction }, - { "btree_pager_stats", (Tcl_CmdProc*)btree_pager_stats }, - { "btree_cursor", (Tcl_CmdProc*)btree_cursor }, - { "btree_close_cursor", (Tcl_CmdProc*)btree_close_cursor }, - { "btree_next", (Tcl_CmdProc*)btree_next }, - { "btree_eof", (Tcl_CmdProc*)btree_eof }, - { "btree_payload_size", (Tcl_CmdProc*)btree_payload_size }, - { "btree_first", (Tcl_CmdProc*)btree_first }, - { "btree_varint_test", (Tcl_CmdProc*)btree_varint_test }, - { "btree_from_db", (Tcl_CmdProc*)btree_from_db }, - { "btree_ismemdb", (Tcl_CmdProc*)btree_ismemdb }, - { "btree_set_cache_size", (Tcl_CmdProc*)btree_set_cache_size } - }; - int i; - - for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){ - Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0); - } - - return TCL_OK; -} diff --git a/components/external/SQLite-3.8.1/SQLiteLib/test/test4.c b/components/external/SQLite-3.8.1/SQLiteLib/test/test4.c deleted file mode 100644 index a6375c7cc4..0000000000 --- a/components/external/SQLite-3.8.1/SQLiteLib/test/test4.c +++ /dev/null @@ -1,722 +0,0 @@ -/* -** 2003 December 18 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** Code for testing the SQLite library in a multithreaded environment. -*/ -#include "sqliteInt.h" -#include "tcl.h" -#if SQLITE_OS_UNIX && SQLITE_THREADSAFE -#include <stdlib.h> -#include <string.h> -#include <pthread.h> -#include <sched.h> -#include <ctype.h> - -extern const char *sqlite3ErrName(int); - -/* -** Each thread is controlled by an instance of the following -** structure. -*/ -typedef struct Thread Thread; -struct Thread { - /* The first group of fields are writable by the master and read-only - ** to the thread. */ - char *zFilename; /* Name of database file */ - void (*xOp)(Thread*); /* next operation to do */ - char *zArg; /* argument usable by xOp */ - int opnum; /* Operation number */ - int busy; /* True if this thread is in use */ - - /* The next group of fields are writable by the thread but read-only to the - ** master. */ - int completed; /* Number of operations completed */ - sqlite3 *db; /* Open database */ - sqlite3_stmt *pStmt; /* Pending operation */ - char *zErr; /* operation error */ - char *zStaticErr; /* Static error message */ - int rc; /* operation return code */ - int argc; /* number of columns in result */ - const char *argv[100]; /* result columns */ - const char *colv[100]; /* result column names */ -}; - -/* -** There can be as many as 26 threads running at once. Each is named -** by a capital letter: A, B, C, ..., Y, Z. -*/ -#define N_THREAD 26 -static Thread threadset[N_THREAD]; - - -/* -** The main loop for a thread. Threads use busy waiting. -*/ -static void *thread_main(void *pArg){ - Thread *p = (Thread*)pArg; - if( p->db ){ - sqlite3_close(p->db); - } - sqlite3_open(p->zFilename, &p->db); - if( SQLITE_OK!=sqlite3_errcode(p->db) ){ - p->zErr = strdup(sqlite3_errmsg(p->db)); - sqlite3_close(p->db); - p->db = 0; - } - p->pStmt = 0; - p->completed = 1; - while( p->opnum<=p->completed ) sched_yield(); - while( p->xOp ){ - if( p->zErr && p->zErr!=p->zStaticErr ){ - sqlite3_free(p->zErr); - p->zErr = 0; - } - (*p->xOp)(p); - p->completed++; - while( p->opnum<=p->completed ) sched_yield(); - } - if( p->pStmt ){ - sqlite3_finalize(p->pStmt); - p->pStmt = 0; - } - if( p->db ){ - sqlite3_close(p->db); - p->db = 0; - } - if( p->zErr && p->zErr!=p->zStaticErr ){ - sqlite3_free(p->zErr); - p->zErr = 0; - } - p->completed++; -#ifndef SQLITE_OMIT_DEPRECATED - sqlite3_thread_cleanup(); -#endif - return 0; -} - -/* -** Get a thread ID which is an upper case letter. Return the index. -** If the argument is not a valid thread ID put an error message in -** the interpreter and return -1. -*/ -static int parse_thread_id(Tcl_Interp *interp, const char *zArg){ - if( zArg==0 || zArg[0]==0 || zArg[1]!=0 || !isupper((unsigned char)zArg[0]) ){ - Tcl_AppendResult(interp, "thread ID must be an upper case letter", 0); - return -1; - } - return zArg[0] - 'A'; -} - -/* -** Usage: thread_create NAME FILENAME -** -** NAME should be an upper case letter. Start the thread running with -** an open connection to the given database. -*/ -static int tcl_thread_create( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - const char **argv /* Text of each argument */ -){ - int i; - pthread_t x; - int rc; - - if( argc!=3 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " ID FILENAME", 0); - return TCL_ERROR; - } - i = parse_thread_id(interp, argv[1]); - if( i<0 ) return TCL_ERROR; - if( threadset[i].busy ){ - Tcl_AppendResult(interp, "thread ", argv[1], " is already running", 0); - return TCL_ERROR; - } - threadset[i].busy = 1; - sqlite3_free(threadset[i].zFilename); - threadset[i].zFilename = sqlite3_mprintf("%s", argv[2]); - threadset[i].opnum = 1; - threadset[i].completed = 0; - rc = pthread_create(&x, 0, thread_main, &threadset[i]); - if( rc ){ - Tcl_AppendResult(interp, "failed to create the thread", 0); - sqlite3_free(threadset[i].zFilename); - threadset[i].busy = 0; - return TCL_ERROR; - } - pthread_detach(x); - return TCL_OK; -} - -/* -** Wait for a thread to reach its idle state. -*/ -static void thread_wait(Thread *p){ - while( p->opnum>p->completed ) sched_yield(); -} - -/* -** Usage: thread_wait ID -** -** Wait on thread ID to reach its idle state. -*/ -static int tcl_thread_wait( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - const char **argv /* Text of each argument */ -){ - int i; - - if( argc!=2 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " ID", 0); - return TCL_ERROR; - } - i = parse_thread_id(interp, argv[1]); - if( i<0 ) return TCL_ERROR; - if( !threadset[i].busy ){ - Tcl_AppendResult(interp, "no such thread", 0); - return TCL_ERROR; - } - thread_wait(&threadset[i]); - return TCL_OK; -} - -/* -** Stop a thread. -*/ -static void stop_thread(Thread *p){ - thread_wait(p); - p->xOp = 0; - p->opnum++; - thread_wait(p); - sqlite3_free(p->zArg); - p->zArg = 0; - sqlite3_free(p->zFilename); - p->zFilename = 0; - p->busy = 0; -} - -/* -** Usage: thread_halt ID -** -** Cause a thread to shut itself down. Wait for the shutdown to be -** completed. If ID is "*" then stop all threads. -*/ -static int tcl_thread_halt( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - const char **argv /* Text of each argument */ -){ - int i; - - if( argc!=2 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " ID", 0); - return TCL_ERROR; - } - if( argv[1][0]=='*' && argv[1][1]==0 ){ - for(i=0; i<N_THREAD; i++){ - if( threadset[i].busy ) stop_thread(&threadset[i]); - } - }else{ - i = parse_thread_id(interp, argv[1]); - if( i<0 ) return TCL_ERROR; - if( !threadset[i].busy ){ - Tcl_AppendResult(interp, "no such thread", 0); - return TCL_ERROR; - } - stop_thread(&threadset[i]); - } - return TCL_OK; -} - -/* -** Usage: thread_argc ID -** -** Wait on the most recent thread_step to complete, then return the -** number of columns in the result set. -*/ -static int tcl_thread_argc( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - const char **argv /* Text of each argument */ -){ - int i; - char zBuf[100]; - - if( argc!=2 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " ID", 0); - return TCL_ERROR; - } - i = parse_thread_id(interp, argv[1]); - if( i<0 ) return TCL_ERROR; - if( !threadset[i].busy ){ - Tcl_AppendResult(interp, "no such thread", 0); - return TCL_ERROR; - } - thread_wait(&threadset[i]); - sprintf(zBuf, "%d", threadset[i].argc); - Tcl_AppendResult(interp, zBuf, 0); - return TCL_OK; -} - -/* -** Usage: thread_argv ID N -** -** Wait on the most recent thread_step to complete, then return the -** value of the N-th columns in the result set. -*/ -static int tcl_thread_argv( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - const char **argv /* Text of each argument */ -){ - int i; - int n; - - if( argc!=3 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " ID N", 0); - return TCL_ERROR; - } - i = parse_thread_id(interp, argv[1]); - if( i<0 ) return TCL_ERROR; - if( !threadset[i].busy ){ - Tcl_AppendResult(interp, "no such thread", 0); - return TCL_ERROR; - } - if( Tcl_GetInt(interp, argv[2], &n) ) return TCL_ERROR; - thread_wait(&threadset[i]); - if( n<0 || n>=threadset[i].argc ){ - Tcl_AppendResult(interp, "column number out of range", 0); - return TCL_ERROR; - } - Tcl_AppendResult(interp, threadset[i].argv[n], 0); - return TCL_OK; -} - -/* -** Usage: thread_colname ID N -** -** Wait on the most recent thread_step to complete, then return the -** name of the N-th columns in the result set. -*/ -static int tcl_thread_colname( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - const char **argv /* Text of each argument */ -){ - int i; - int n; - - if( argc!=3 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " ID N", 0); - return TCL_ERROR; - } - i = parse_thread_id(interp, argv[1]); - if( i<0 ) return TCL_ERROR; - if( !threadset[i].busy ){ - Tcl_AppendResult(interp, "no such thread", 0); - return TCL_ERROR; - } - if( Tcl_GetInt(interp, argv[2], &n) ) return TCL_ERROR; - thread_wait(&threadset[i]); - if( n<0 || n>=threadset[i].argc ){ - Tcl_AppendResult(interp, "column number out of range", 0); - return TCL_ERROR; - } - Tcl_AppendResult(interp, threadset[i].colv[n], 0); - return TCL_OK; -} - -/* -** Usage: thread_result ID -** -** Wait on the most recent operation to complete, then return the -** result code from that operation. -*/ -static int tcl_thread_result( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - const char **argv /* Text of each argument */ -){ - int i; - const char *zName; - - if( argc!=2 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " ID", 0); - return TCL_ERROR; - } - i = parse_thread_id(interp, argv[1]); - if( i<0 ) return TCL_ERROR; - if( !threadset[i].busy ){ - Tcl_AppendResult(interp, "no such thread", 0); - return TCL_ERROR; - } - thread_wait(&threadset[i]); - zName = sqlite3ErrName(threadset[i].rc); - Tcl_AppendResult(interp, zName, 0); - return TCL_OK; -} - -/* -** Usage: thread_error ID -** -** Wait on the most recent operation to complete, then return the -** error string. -*/ -static int tcl_thread_error( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - const char **argv /* Text of each argument */ -){ - int i; - - if( argc!=2 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " ID", 0); - return TCL_ERROR; - } - i = parse_thread_id(interp, argv[1]); - if( i<0 ) return TCL_ERROR; - if( !threadset[i].busy ){ - Tcl_AppendResult(interp, "no such thread", 0); - return TCL_ERROR; - } - thread_wait(&threadset[i]); - Tcl_AppendResult(interp, threadset[i].zErr, 0); - return TCL_OK; -} - -/* -** This procedure runs in the thread to compile an SQL statement. -*/ -static void do_compile(Thread *p){ - if( p->db==0 ){ - p->zErr = p->zStaticErr = "no database is open"; - p->rc = SQLITE_ERROR; - return; - } - if( p->pStmt ){ - sqlite3_finalize(p->pStmt); - p->pStmt = 0; - } - p->rc = sqlite3_prepare(p->db, p->zArg, -1, &p->pStmt, 0); -} - -/* -** Usage: thread_compile ID SQL -** -** Compile a new virtual machine. -*/ -static int tcl_thread_compile( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - const char **argv /* Text of each argument */ -){ - int i; - if( argc!=3 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " ID SQL", 0); - return TCL_ERROR; - } - i = parse_thread_id(interp, argv[1]); - if( i<0 ) return TCL_ERROR; - if( !threadset[i].busy ){ - Tcl_AppendResult(interp, "no such thread", 0); - return TCL_ERROR; - } - thread_wait(&threadset[i]); - threadset[i].xOp = do_compile; - sqlite3_free(threadset[i].zArg); - threadset[i].zArg = sqlite3_mprintf("%s", argv[2]); - threadset[i].opnum++; - return TCL_OK; -} - -/* -** This procedure runs in the thread to step the virtual machine. -*/ -static void do_step(Thread *p){ - int i; - if( p->pStmt==0 ){ - p->zErr = p->zStaticErr = "no virtual machine available"; - p->rc = SQLITE_ERROR; - return; - } - p->rc = sqlite3_step(p->pStmt); - if( p->rc==SQLITE_ROW ){ - p->argc = sqlite3_column_count(p->pStmt); - for(i=0; i<sqlite3_data_count(p->pStmt); i++){ - p->argv[i] = (char*)sqlite3_column_text(p->pStmt, i); - } - for(i=0; i<p->argc; i++){ - p->colv[i] = sqlite3_column_name(p->pStmt, i); - } - } -} - -/* -** Usage: thread_step ID -** -** Advance the virtual machine by one step -*/ -static int tcl_thread_step( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - const char **argv /* Text of each argument */ -){ - int i; - if( argc!=2 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " IDL", 0); - return TCL_ERROR; - } - i = parse_thread_id(interp, argv[1]); - if( i<0 ) return TCL_ERROR; - if( !threadset[i].busy ){ - Tcl_AppendResult(interp, "no such thread", 0); - return TCL_ERROR; - } - thread_wait(&threadset[i]); - threadset[i].xOp = do_step; - threadset[i].opnum++; - return TCL_OK; -} - -/* -** This procedure runs in the thread to finalize a virtual machine. -*/ -static void do_finalize(Thread *p){ - if( p->pStmt==0 ){ - p->zErr = p->zStaticErr = "no virtual machine available"; - p->rc = SQLITE_ERROR; - return; - } - p->rc = sqlite3_finalize(p->pStmt); - p->pStmt = 0; -} - -/* -** Usage: thread_finalize ID -** -** Finalize the virtual machine. -*/ -static int tcl_thread_finalize( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - const char **argv /* Text of each argument */ -){ - int i; - if( argc!=2 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " IDL", 0); - return TCL_ERROR; - } - i = parse_thread_id(interp, argv[1]); - if( i<0 ) return TCL_ERROR; - if( !threadset[i].busy ){ - Tcl_AppendResult(interp, "no such thread", 0); - return TCL_ERROR; - } - thread_wait(&threadset[i]); - threadset[i].xOp = do_finalize; - sqlite3_free(threadset[i].zArg); - threadset[i].zArg = 0; - threadset[i].opnum++; - return TCL_OK; -} - -/* -** Usage: thread_swap ID ID -** -** Interchange the sqlite* pointer between two threads. -*/ -static int tcl_thread_swap( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - const char **argv /* Text of each argument */ -){ - int i, j; - sqlite3 *temp; - if( argc!=3 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " ID1 ID2", 0); - return TCL_ERROR; - } - i = parse_thread_id(interp, argv[1]); - if( i<0 ) return TCL_ERROR; - if( !threadset[i].busy ){ - Tcl_AppendResult(interp, "no such thread", 0); - return TCL_ERROR; - } - thread_wait(&threadset[i]); - j = parse_thread_id(interp, argv[2]); - if( j<0 ) return TCL_ERROR; - if( !threadset[j].busy ){ - Tcl_AppendResult(interp, "no such thread", 0); - return TCL_ERROR; - } - thread_wait(&threadset[j]); - temp = threadset[i].db; - threadset[i].db = threadset[j].db; - threadset[j].db = temp; - return TCL_OK; -} - -/* -** Usage: thread_db_get ID -** -** Return the database connection pointer for the given thread. Then -** remove the pointer from the thread itself. Afterwards, the thread -** can be stopped and the connection can be used by the main thread. -*/ -static int tcl_thread_db_get( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - const char **argv /* Text of each argument */ -){ - int i; - char zBuf[100]; - extern int sqlite3TestMakePointerStr(Tcl_Interp*, char*, void*); - if( argc!=2 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " ID", 0); - return TCL_ERROR; - } - i = parse_thread_id(interp, argv[1]); - if( i<0 ) return TCL_ERROR; - if( !threadset[i].busy ){ - Tcl_AppendResult(interp, "no such thread", 0); - return TCL_ERROR; - } - thread_wait(&threadset[i]); - sqlite3TestMakePointerStr(interp, zBuf, threadset[i].db); - threadset[i].db = 0; - Tcl_AppendResult(interp, zBuf, (char*)0); - return TCL_OK; -} - -/* -** Usage: thread_db_put ID DB -** -*/ -static int tcl_thread_db_put( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - const char **argv /* Text of each argument */ -){ - int i; - extern int sqlite3TestMakePointerStr(Tcl_Interp*, char*, void*); - extern void *sqlite3TestTextToPtr(const char *); - if( argc!=3 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " ID DB", 0); - return TCL_ERROR; - } - i = parse_thread_id(interp, argv[1]); - if( i<0 ) return TCL_ERROR; - if( !threadset[i].busy ){ - Tcl_AppendResult(interp, "no such thread", 0); - return TCL_ERROR; - } - thread_wait(&threadset[i]); - assert( !threadset[i].db ); - threadset[i].db = (sqlite3*)sqlite3TestTextToPtr(argv[2]); - return TCL_OK; -} - -/* -** Usage: thread_stmt_get ID -** -** Return the database stmt pointer for the given thread. Then -** remove the pointer from the thread itself. -*/ -static int tcl_thread_stmt_get( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - const char **argv /* Text of each argument */ -){ - int i; - char zBuf[100]; - extern int sqlite3TestMakePointerStr(Tcl_Interp*, char*, void*); - if( argc!=2 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " ID", 0); - return TCL_ERROR; - } - i = parse_thread_id(interp, argv[1]); - if( i<0 ) return TCL_ERROR; - if( !threadset[i].busy ){ - Tcl_AppendResult(interp, "no such thread", 0); - return TCL_ERROR; - } - thread_wait(&threadset[i]); - sqlite3TestMakePointerStr(interp, zBuf, threadset[i].pStmt); - threadset[i].pStmt = 0; - Tcl_AppendResult(interp, zBuf, (char*)0); - return TCL_OK; -} - -/* -** Register commands with the TCL interpreter. -*/ -int Sqlitetest4_Init(Tcl_Interp *interp){ - static struct { - char *zName; - Tcl_CmdProc *xProc; - } aCmd[] = { - { "thread_create", (Tcl_CmdProc*)tcl_thread_create }, - { "thread_wait", (Tcl_CmdProc*)tcl_thread_wait }, - { "thread_halt", (Tcl_CmdProc*)tcl_thread_halt }, - { "thread_argc", (Tcl_CmdProc*)tcl_thread_argc }, - { "thread_argv", (Tcl_CmdProc*)tcl_thread_argv }, - { "thread_colname", (Tcl_CmdProc*)tcl_thread_colname }, - { "thread_result", (Tcl_CmdProc*)tcl_thread_result }, - { "thread_error", (Tcl_CmdProc*)tcl_thread_error }, - { "thread_compile", (Tcl_CmdProc*)tcl_thread_compile }, - { "thread_step", (Tcl_CmdProc*)tcl_thread_step }, - { "thread_finalize", (Tcl_CmdProc*)tcl_thread_finalize }, - { "thread_swap", (Tcl_CmdProc*)tcl_thread_swap }, - { "thread_db_get", (Tcl_CmdProc*)tcl_thread_db_get }, - { "thread_db_put", (Tcl_CmdProc*)tcl_thread_db_put }, - { "thread_stmt_get", (Tcl_CmdProc*)tcl_thread_stmt_get }, - }; - int i; - - for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){ - Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0); - } - return TCL_OK; -} -#else -int Sqlitetest4_Init(Tcl_Interp *interp){ return TCL_OK; } -#endif /* SQLITE_OS_UNIX */ diff --git a/components/external/SQLite-3.8.1/SQLiteLib/test/test5.c b/components/external/SQLite-3.8.1/SQLiteLib/test/test5.c deleted file mode 100644 index 303d1205b2..0000000000 --- a/components/external/SQLite-3.8.1/SQLiteLib/test/test5.c +++ /dev/null @@ -1,217 +0,0 @@ -/* -** 2001 September 15 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** Code for testing the utf.c module in SQLite. This code -** is not included in the SQLite library. It is used for automated -** testing of the SQLite library. Specifically, the code in this file -** is used for testing the SQLite routines for converting between -** the various supported unicode encodings. -*/ -#include "sqliteInt.h" -#include "vdbeInt.h" -#include "tcl.h" -#include <stdlib.h> -#include <string.h> - -/* -** The first argument is a TCL UTF-8 string. Return the byte array -** object with the encoded representation of the string, including -** the NULL terminator. -*/ -static int binarize( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - int len; - char *bytes; - Tcl_Obj *pRet; - assert(objc==2); - - bytes = Tcl_GetStringFromObj(objv[1], &len); - pRet = Tcl_NewByteArrayObj((u8*)bytes, len+1); - Tcl_SetObjResult(interp, pRet); - return TCL_OK; -} - -/* -** Usage: test_value_overhead <repeat-count> <do-calls>. -** -** This routine is used to test the overhead of calls to -** sqlite3_value_text(), on a value that contains a UTF-8 string. The idea -** is to figure out whether or not it is a problem to use sqlite3_value -** structures with collation sequence functions. -** -** If <do-calls> is 0, then the calls to sqlite3_value_text() are not -** actually made. -*/ -static int test_value_overhead( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - int do_calls; - int repeat_count; - int i; - Mem val; - - if( objc!=3 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", - Tcl_GetStringFromObj(objv[0], 0), " <repeat-count> <do-calls>", 0); - return TCL_ERROR; - } - - if( Tcl_GetIntFromObj(interp, objv[1], &repeat_count) ) return TCL_ERROR; - if( Tcl_GetIntFromObj(interp, objv[2], &do_calls) ) return TCL_ERROR; - - val.flags = MEM_Str|MEM_Term|MEM_Static; - val.z = "hello world"; - val.type = SQLITE_TEXT; - val.enc = SQLITE_UTF8; - - for(i=0; i<repeat_count; i++){ - if( do_calls ){ - sqlite3_value_text(&val); - } - } - - return TCL_OK; -} - -static u8 name_to_enc(Tcl_Interp *interp, Tcl_Obj *pObj){ - struct EncName { - char *zName; - u8 enc; - } encnames[] = { - { "UTF8", SQLITE_UTF8 }, - { "UTF16LE", SQLITE_UTF16LE }, - { "UTF16BE", SQLITE_UTF16BE }, - { "UTF16", SQLITE_UTF16 }, - { 0, 0 } - }; - struct EncName *pEnc; - char *z = Tcl_GetString(pObj); - for(pEnc=&encnames[0]; pEnc->zName; pEnc++){ - if( 0==sqlite3StrICmp(z, pEnc->zName) ){ - break; - } - } - if( !pEnc->enc ){ - Tcl_AppendResult(interp, "No such encoding: ", z, 0); - } - if( pEnc->enc==SQLITE_UTF16 ){ - return SQLITE_UTF16NATIVE; - } - return pEnc->enc; -} - -/* -** Usage: test_translate <string/blob> <from enc> <to enc> ?<transient>? -** -*/ -static int test_translate( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - u8 enc_from; - u8 enc_to; - sqlite3_value *pVal; - - char *z; - int len; - void (*xDel)(void *p) = SQLITE_STATIC; - - if( objc!=4 && objc!=5 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", - Tcl_GetStringFromObj(objv[0], 0), - " <string/blob> <from enc> <to enc>", 0 - ); - return TCL_ERROR; - } - if( objc==5 ){ - xDel = sqlite3_free; - } - - enc_from = name_to_enc(interp, objv[2]); - if( !enc_from ) return TCL_ERROR; - enc_to = name_to_enc(interp, objv[3]); - if( !enc_to ) return TCL_ERROR; - - pVal = sqlite3ValueNew(0); - - if( enc_from==SQLITE_UTF8 ){ - z = Tcl_GetString(objv[1]); - if( objc==5 ){ - z = sqlite3_mprintf("%s", z); - } - sqlite3ValueSetStr(pVal, -1, z, enc_from, xDel); - }else{ - z = (char*)Tcl_GetByteArrayFromObj(objv[1], &len); - if( objc==5 ){ - char *zTmp = z; - z = sqlite3_malloc(len); - memcpy(z, zTmp, len); - } - sqlite3ValueSetStr(pVal, -1, z, enc_from, xDel); - } - - z = (char *)sqlite3ValueText(pVal, enc_to); - len = sqlite3ValueBytes(pVal, enc_to) + (enc_to==SQLITE_UTF8?1:2); - Tcl_SetObjResult(interp, Tcl_NewByteArrayObj((u8*)z, len)); - - sqlite3ValueFree(pVal); - - return TCL_OK; -} - -/* -** Usage: translate_selftest -** -** Call sqlite3UtfSelfTest() to run the internal tests for unicode -** translation. If there is a problem an assert() will fail. -**/ -void sqlite3UtfSelfTest(void); -static int test_translate_selftest( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ -#ifndef SQLITE_OMIT_UTF16 - sqlite3UtfSelfTest(); -#endif - return SQLITE_OK; -} - - -/* -** Register commands with the TCL interpreter. -*/ -int Sqlitetest5_Init(Tcl_Interp *interp){ - static struct { - char *zName; - Tcl_ObjCmdProc *xProc; - } aCmd[] = { - { "binarize", (Tcl_ObjCmdProc*)binarize }, - { "test_value_overhead", (Tcl_ObjCmdProc*)test_value_overhead }, - { "test_translate", (Tcl_ObjCmdProc*)test_translate }, - { "translate_selftest", (Tcl_ObjCmdProc*)test_translate_selftest}, - }; - int i; - for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){ - Tcl_CreateObjCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0); - } - return SQLITE_OK; -} diff --git a/components/external/SQLite-3.8.1/SQLiteLib/test/test6.c b/components/external/SQLite-3.8.1/SQLiteLib/test/test6.c deleted file mode 100644 index 2020885c46..0000000000 --- a/components/external/SQLite-3.8.1/SQLiteLib/test/test6.c +++ /dev/null @@ -1,1020 +0,0 @@ -/* -** 2004 May 22 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -****************************************************************************** -** -** This file contains code that modified the OS layer in order to simulate -** the effect on the database file of an OS crash or power failure. This -** is used to test the ability of SQLite to recover from those situations. -*/ -#if SQLITE_TEST /* This file is used for testing only */ -#include "sqliteInt.h" -#include "tcl.h" - -#ifndef SQLITE_OMIT_DISKIO /* This file is a no-op if disk I/O is disabled */ - -/* #define TRACE_CRASHTEST */ - -typedef struct CrashFile CrashFile; -typedef struct CrashGlobal CrashGlobal; -typedef struct WriteBuffer WriteBuffer; - -/* -** Method: -** -** This layer is implemented as a wrapper around the "real" -** sqlite3_file object for the host system. Each time data is -** written to the file object, instead of being written to the -** underlying file, the write operation is stored in an in-memory -** structure (type WriteBuffer). This structure is placed at the -** end of a global ordered list (the write-list). -** -** When data is read from a file object, the requested region is -** first retrieved from the real file. The write-list is then -** traversed and data copied from any overlapping WriteBuffer -** structures to the output buffer. i.e. a read() operation following -** one or more write() operations works as expected, even if no -** data has actually been written out to the real file. -** -** When a fsync() operation is performed, an operating system crash -** may be simulated, in which case exit(-1) is called (the call to -** xSync() never returns). Whether or not a crash is simulated, -** the data associated with a subset of the WriteBuffer structures -** stored in the write-list is written to the real underlying files -** and the entries removed from the write-list. If a crash is simulated, -** a subset of the buffers may be corrupted before the data is written. -** -** The exact subset of the write-list written and/or corrupted is -** determined by the simulated device characteristics and sector-size. -** -** "Normal" mode: -** -** Normal mode is used when the simulated device has none of the -** SQLITE_IOCAP_XXX flags set. -** -** In normal mode, if the fsync() is not a simulated crash, the -** write-list is traversed from beginning to end. Each WriteBuffer -** structure associated with the file handle used to call xSync() -** is written to the real file and removed from the write-list. -** -** If a crash is simulated, one of the following takes place for -** each WriteBuffer in the write-list, regardless of which -** file-handle it is associated with: -** -** 1. The buffer is correctly written to the file, just as if -** a crash were not being simulated. -** -** 2. Nothing is done. -** -** 3. Garbage data is written to all sectors of the file that -** overlap the region specified by the WriteBuffer. Or garbage -** data is written to some contiguous section within the -** overlapped sectors. -** -** Device Characteristic flag handling: -** -** If the IOCAP_ATOMIC flag is set, then option (3) above is -** never selected. -** -** If the IOCAP_ATOMIC512 flag is set, and the WriteBuffer represents -** an aligned write() of an integer number of 512 byte regions, then -** option (3) above is never selected. Instead, each 512 byte region -** is either correctly written or left completely untouched. Similar -** logic governs the behavior if any of the other ATOMICXXX flags -** is set. -** -** If either the IOCAP_SAFEAPPEND or IOCAP_SEQUENTIAL flags are set -** and a crash is being simulated, then an entry of the write-list is -** selected at random. Everything in the list after the selected entry -** is discarded before processing begins. -** -** If IOCAP_SEQUENTIAL is set and a crash is being simulated, option -** (1) is selected for all write-list entries except the last. If a -** crash is not being simulated, then all entries in the write-list -** that occur before at least one write() on the file-handle specified -** as part of the xSync() are written to their associated real files. -** -** If IOCAP_SAFEAPPEND is set and the first byte written by the write() -** operation is one byte past the current end of the file, then option -** (1) is always selected. -*/ - -/* -** Each write operation in the write-list is represented by an instance -** of the following structure. -** -** If zBuf is 0, then this structure represents a call to xTruncate(), -** not xWrite(). In that case, iOffset is the size that the file is -** truncated to. -*/ -struct WriteBuffer { - i64 iOffset; /* Byte offset of the start of this write() */ - int nBuf; /* Number of bytes written */ - u8 *zBuf; /* Pointer to copy of written data */ - CrashFile *pFile; /* File this write() applies to */ - - WriteBuffer *pNext; /* Next in CrashGlobal.pWriteList */ -}; - -struct CrashFile { - const sqlite3_io_methods *pMethod; /* Must be first */ - sqlite3_file *pRealFile; /* Underlying "real" file handle */ - char *zName; - int flags; /* Flags the file was opened with */ - - /* Cache of the entire file. This is used to speed up OsRead() and - ** OsFileSize() calls. Although both could be done by traversing the - ** write-list, in practice this is impractically slow. - */ - u8 *zData; /* Buffer containing file contents */ - int nData; /* Size of buffer allocated at zData */ - i64 iSize; /* Size of file in bytes */ -}; - -struct CrashGlobal { - WriteBuffer *pWriteList; /* Head of write-list */ - WriteBuffer *pWriteListEnd; /* End of write-list */ - - int iSectorSize; /* Value of simulated sector size */ - int iDeviceCharacteristics; /* Value of simulated device characteristics */ - - int iCrash; /* Crash on the iCrash'th call to xSync() */ - char zCrashFile[500]; /* Crash during an xSync() on this file */ -}; - -static CrashGlobal g = {0, 0, SQLITE_DEFAULT_SECTOR_SIZE, 0, 0}; - -/* -** Set this global variable to 1 to enable crash testing. -*/ -static int sqlite3CrashTestEnable = 0; - -static void *crash_malloc(int nByte){ - return (void *)Tcl_Alloc((size_t)nByte); -} -static void crash_free(void *p){ - Tcl_Free(p); -} -static void *crash_realloc(void *p, int n){ - return (void *)Tcl_Realloc(p, (size_t)n); -} - -/* -** Wrapper around the sqlite3OsWrite() function that avoids writing to the -** 512 byte block begining at offset PENDING_BYTE. -*/ -static int writeDbFile(CrashFile *p, u8 *z, i64 iAmt, i64 iOff){ - int rc = SQLITE_OK; - int iSkip = 0; - if( iOff==PENDING_BYTE && (p->flags&SQLITE_OPEN_MAIN_DB) ){ - iSkip = 512; - } - if( (iAmt-iSkip)>0 ){ - rc = sqlite3OsWrite(p->pRealFile, &z[iSkip], (int)(iAmt-iSkip), iOff+iSkip); - } - return rc; -} - -/* -** Flush the write-list as if xSync() had been called on file handle -** pFile. If isCrash is true, simulate a crash. -*/ -static int writeListSync(CrashFile *pFile, int isCrash){ - int rc = SQLITE_OK; - int iDc = g.iDeviceCharacteristics; - - WriteBuffer *pWrite; - WriteBuffer **ppPtr; - - /* If this is not a crash simulation, set pFinal to point to the - ** last element of the write-list that is associated with file handle - ** pFile. - ** - ** If this is a crash simulation, set pFinal to an arbitrarily selected - ** element of the write-list. - */ - WriteBuffer *pFinal = 0; - if( !isCrash ){ - for(pWrite=g.pWriteList; pWrite; pWrite=pWrite->pNext){ - if( pWrite->pFile==pFile ){ - pFinal = pWrite; - } - } - }else if( iDc&(SQLITE_IOCAP_SEQUENTIAL|SQLITE_IOCAP_SAFE_APPEND) ){ - int nWrite = 0; - int iFinal; - for(pWrite=g.pWriteList; pWrite; pWrite=pWrite->pNext) nWrite++; - sqlite3_randomness(sizeof(int), &iFinal); - iFinal = ((iFinal<0)?-1*iFinal:iFinal)%nWrite; - for(pWrite=g.pWriteList; iFinal>0; pWrite=pWrite->pNext) iFinal--; - pFinal = pWrite; - } - -#ifdef TRACE_CRASHTEST - printf("Sync %s (is %s crash)\n", pFile->zName, (isCrash?"a":"not a")); -#endif - - ppPtr = &g.pWriteList; - for(pWrite=*ppPtr; rc==SQLITE_OK && pWrite; pWrite=*ppPtr){ - sqlite3_file *pRealFile = pWrite->pFile->pRealFile; - - /* (eAction==1) -> write block out normally, - ** (eAction==2) -> do nothing, - ** (eAction==3) -> trash sectors. - */ - int eAction = 0; - if( !isCrash ){ - eAction = 2; - if( (pWrite->pFile==pFile || iDc&SQLITE_IOCAP_SEQUENTIAL) ){ - eAction = 1; - } - }else{ - char random; - sqlite3_randomness(1, &random); - - /* Do not select option 3 (sector trashing) if the IOCAP_ATOMIC flag - ** is set or this is an OsTruncate(), not an Oswrite(). - */ - if( (iDc&SQLITE_IOCAP_ATOMIC) || (pWrite->zBuf==0) ){ - random &= 0x01; - } - - /* If IOCAP_SEQUENTIAL is set and this is not the final entry - ** in the truncated write-list, always select option 1 (write - ** out correctly). - */ - if( (iDc&SQLITE_IOCAP_SEQUENTIAL && pWrite!=pFinal) ){ - random = 0; - } - - /* If IOCAP_SAFE_APPEND is set and this OsWrite() operation is - ** an append (first byte of the written region is 1 byte past the - ** current EOF), always select option 1 (write out correctly). - */ - if( iDc&SQLITE_IOCAP_SAFE_APPEND && pWrite->zBuf ){ - i64 iSize; - sqlite3OsFileSize(pRealFile, &iSize); - if( iSize==pWrite->iOffset ){ - random = 0; - } - } - - if( (random&0x06)==0x06 ){ - eAction = 3; - }else{ - eAction = ((random&0x01)?2:1); - } - } - - switch( eAction ){ - case 1: { /* Write out correctly */ - if( pWrite->zBuf ){ - rc = writeDbFile( - pWrite->pFile, pWrite->zBuf, pWrite->nBuf, pWrite->iOffset - ); - }else{ - rc = sqlite3OsTruncate(pRealFile, pWrite->iOffset); - } - *ppPtr = pWrite->pNext; -#ifdef TRACE_CRASHTEST - if( isCrash ){ - printf("Writing %d bytes @ %d (%s)\n", - pWrite->nBuf, (int)pWrite->iOffset, pWrite->pFile->zName - ); - } -#endif - crash_free(pWrite); - break; - } - case 2: { /* Do nothing */ - ppPtr = &pWrite->pNext; -#ifdef TRACE_CRASHTEST - if( isCrash ){ - printf("Omiting %d bytes @ %d (%s)\n", - pWrite->nBuf, (int)pWrite->iOffset, pWrite->pFile->zName - ); - } -#endif - break; - } - case 3: { /* Trash sectors */ - u8 *zGarbage; - int iFirst = (int)(pWrite->iOffset/g.iSectorSize); - int iLast = (int)((pWrite->iOffset+pWrite->nBuf-1)/g.iSectorSize); - - assert(pWrite->zBuf); - -#ifdef TRACE_CRASHTEST - printf("Trashing %d sectors @ %lld (sector %d) (%s)\n", - 1+iLast-iFirst, pWrite->iOffset, iFirst, pWrite->pFile->zName - ); -#endif - - zGarbage = crash_malloc(g.iSectorSize); - if( zGarbage ){ - sqlite3_int64 i; - for(i=iFirst; rc==SQLITE_OK && i<=iLast; i++){ - sqlite3_randomness(g.iSectorSize, zGarbage); - rc = writeDbFile( - pWrite->pFile, zGarbage, g.iSectorSize, i*g.iSectorSize - ); - } - crash_free(zGarbage); - }else{ - rc = SQLITE_NOMEM; - } - - ppPtr = &pWrite->pNext; - break; - } - - default: - assert(!"Cannot happen"); - } - - if( pWrite==pFinal ) break; - } - - if( rc==SQLITE_OK && isCrash ){ - exit(-1); - } - - for(pWrite=g.pWriteList; pWrite && pWrite->pNext; pWrite=pWrite->pNext); - g.pWriteListEnd = pWrite; - - return rc; -} - -/* -** Add an entry to the end of the write-list. -*/ -static int writeListAppend( - sqlite3_file *pFile, - sqlite3_int64 iOffset, - const u8 *zBuf, - int nBuf -){ - WriteBuffer *pNew; - - assert((zBuf && nBuf) || (!nBuf && !zBuf)); - - pNew = (WriteBuffer *)crash_malloc(sizeof(WriteBuffer) + nBuf); - if( pNew==0 ){ - fprintf(stderr, "out of memory in the crash simulator\n"); - } - memset(pNew, 0, sizeof(WriteBuffer)+nBuf); - pNew->iOffset = iOffset; - pNew->nBuf = nBuf; - pNew->pFile = (CrashFile *)pFile; - if( zBuf ){ - pNew->zBuf = (u8 *)&pNew[1]; - memcpy(pNew->zBuf, zBuf, nBuf); - } - - if( g.pWriteList ){ - assert(g.pWriteListEnd); - g.pWriteListEnd->pNext = pNew; - }else{ - g.pWriteList = pNew; - } - g.pWriteListEnd = pNew; - - return SQLITE_OK; -} - -/* -** Close a crash-file. -*/ -static int cfClose(sqlite3_file *pFile){ - CrashFile *pCrash = (CrashFile *)pFile; - writeListSync(pCrash, 0); - sqlite3OsClose(pCrash->pRealFile); - return SQLITE_OK; -} - -/* -** Read data from a crash-file. -*/ -static int cfRead( - sqlite3_file *pFile, - void *zBuf, - int iAmt, - sqlite_int64 iOfst -){ - CrashFile *pCrash = (CrashFile *)pFile; - - /* Check the file-size to see if this is a short-read */ - if( pCrash->iSize<(iOfst+iAmt) ){ - return SQLITE_IOERR_SHORT_READ; - } - - memcpy(zBuf, &pCrash->zData[iOfst], iAmt); - return SQLITE_OK; -} - -/* -** Write data to a crash-file. -*/ -static int cfWrite( - sqlite3_file *pFile, - const void *zBuf, - int iAmt, - sqlite_int64 iOfst -){ - CrashFile *pCrash = (CrashFile *)pFile; - if( iAmt+iOfst>pCrash->iSize ){ - pCrash->iSize = (int)(iAmt+iOfst); - } - while( pCrash->iSize>pCrash->nData ){ - u8 *zNew; - int nNew = (pCrash->nData*2) + 4096; - zNew = crash_realloc(pCrash->zData, nNew); - if( !zNew ){ - return SQLITE_NOMEM; - } - memset(&zNew[pCrash->nData], 0, nNew-pCrash->nData); - pCrash->nData = nNew; - pCrash->zData = zNew; - } - memcpy(&pCrash->zData[iOfst], zBuf, iAmt); - return writeListAppend(pFile, iOfst, zBuf, iAmt); -} - -/* -** Truncate a crash-file. -*/ -static int cfTruncate(sqlite3_file *pFile, sqlite_int64 size){ - CrashFile *pCrash = (CrashFile *)pFile; - assert(size>=0); - if( pCrash->iSize>size ){ - pCrash->iSize = (int)size; - } - return writeListAppend(pFile, size, 0, 0); -} - -/* -** Sync a crash-file. -*/ -static int cfSync(sqlite3_file *pFile, int flags){ - CrashFile *pCrash = (CrashFile *)pFile; - int isCrash = 0; - - const char *zName = pCrash->zName; - const char *zCrashFile = g.zCrashFile; - int nName = (int)strlen(zName); - int nCrashFile = (int)strlen(zCrashFile); - - if( nCrashFile>0 && zCrashFile[nCrashFile-1]=='*' ){ - nCrashFile--; - if( nName>nCrashFile ) nName = nCrashFile; - } - -#ifdef TRACE_CRASHTEST - printf("cfSync(): nName = %d, nCrashFile = %d, zName = %s, zCrashFile = %s\n", - nName, nCrashFile, zName, zCrashFile); -#endif - - if( nName==nCrashFile && 0==memcmp(zName, zCrashFile, nName) ){ -#ifdef TRACE_CRASHTEST - printf("cfSync(): name matched, g.iCrash = %d\n", g.iCrash); -#endif - if( (--g.iCrash)==0 ) isCrash = 1; - } - - return writeListSync(pCrash, isCrash); -} - -/* -** Return the current file-size of the crash-file. -*/ -static int cfFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){ - CrashFile *pCrash = (CrashFile *)pFile; - *pSize = (i64)pCrash->iSize; - return SQLITE_OK; -} - -/* -** Calls related to file-locks are passed on to the real file handle. -*/ -static int cfLock(sqlite3_file *pFile, int eLock){ - return sqlite3OsLock(((CrashFile *)pFile)->pRealFile, eLock); -} -static int cfUnlock(sqlite3_file *pFile, int eLock){ - return sqlite3OsUnlock(((CrashFile *)pFile)->pRealFile, eLock); -} -static int cfCheckReservedLock(sqlite3_file *pFile, int *pResOut){ - return sqlite3OsCheckReservedLock(((CrashFile *)pFile)->pRealFile, pResOut); -} -static int cfFileControl(sqlite3_file *pFile, int op, void *pArg){ - if( op==SQLITE_FCNTL_SIZE_HINT ){ - CrashFile *pCrash = (CrashFile *)pFile; - i64 nByte = *(i64 *)pArg; - if( nByte>pCrash->iSize ){ - if( SQLITE_OK==writeListAppend(pFile, nByte, 0, 0) ){ - pCrash->iSize = (int)nByte; - } - } - return SQLITE_OK; - } - return sqlite3OsFileControl(((CrashFile *)pFile)->pRealFile, op, pArg); -} - -/* -** The xSectorSize() and xDeviceCharacteristics() functions return -** the global values configured by the [sqlite_crashparams] tcl -* interface. -*/ -static int cfSectorSize(sqlite3_file *pFile){ - return g.iSectorSize; -} -static int cfDeviceCharacteristics(sqlite3_file *pFile){ - return g.iDeviceCharacteristics; -} - -/* -** Pass-throughs for WAL support. -*/ -static int cfShmLock(sqlite3_file *pFile, int ofst, int n, int flags){ - return sqlite3OsShmLock(((CrashFile*)pFile)->pRealFile, ofst, n, flags); -} -static void cfShmBarrier(sqlite3_file *pFile){ - sqlite3OsShmBarrier(((CrashFile*)pFile)->pRealFile); -} -static int cfShmUnmap(sqlite3_file *pFile, int delFlag){ - return sqlite3OsShmUnmap(((CrashFile*)pFile)->pRealFile, delFlag); -} -static int cfShmMap( - sqlite3_file *pFile, /* Handle open on database file */ - int iRegion, /* Region to retrieve */ - int sz, /* Size of regions */ - int w, /* True to extend file if necessary */ - void volatile **pp /* OUT: Mapped memory */ -){ - return sqlite3OsShmMap(((CrashFile*)pFile)->pRealFile, iRegion, sz, w, pp); -} - -static const sqlite3_io_methods CrashFileVtab = { - 2, /* iVersion */ - cfClose, /* xClose */ - cfRead, /* xRead */ - cfWrite, /* xWrite */ - cfTruncate, /* xTruncate */ - cfSync, /* xSync */ - cfFileSize, /* xFileSize */ - cfLock, /* xLock */ - cfUnlock, /* xUnlock */ - cfCheckReservedLock, /* xCheckReservedLock */ - cfFileControl, /* xFileControl */ - cfSectorSize, /* xSectorSize */ - cfDeviceCharacteristics, /* xDeviceCharacteristics */ - cfShmMap, /* xShmMap */ - cfShmLock, /* xShmLock */ - cfShmBarrier, /* xShmBarrier */ - cfShmUnmap /* xShmUnmap */ -}; - -/* -** Application data for the crash VFS -*/ -struct crashAppData { - sqlite3_vfs *pOrig; /* Wrapped vfs structure */ -}; - -/* -** Open a crash-file file handle. -** -** The caller will have allocated pVfs->szOsFile bytes of space -** at pFile. This file uses this space for the CrashFile structure -** and allocates space for the "real" file structure using -** sqlite3_malloc(). The assumption here is (pVfs->szOsFile) is -** equal or greater than sizeof(CrashFile). -*/ -static int cfOpen( - sqlite3_vfs *pCfVfs, - const char *zName, - sqlite3_file *pFile, - int flags, - int *pOutFlags -){ - sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData; - int rc; - CrashFile *pWrapper = (CrashFile *)pFile; - sqlite3_file *pReal = (sqlite3_file*)&pWrapper[1]; - - memset(pWrapper, 0, sizeof(CrashFile)); - rc = sqlite3OsOpen(pVfs, zName, pReal, flags, pOutFlags); - - if( rc==SQLITE_OK ){ - i64 iSize; - pWrapper->pMethod = &CrashFileVtab; - pWrapper->zName = (char *)zName; - pWrapper->pRealFile = pReal; - rc = sqlite3OsFileSize(pReal, &iSize); - pWrapper->iSize = (int)iSize; - pWrapper->flags = flags; - } - if( rc==SQLITE_OK ){ - pWrapper->nData = (4096 + pWrapper->iSize); - pWrapper->zData = crash_malloc(pWrapper->nData); - if( pWrapper->zData ){ - /* os_unix.c contains an assert() that fails if the caller attempts - ** to read data from the 512-byte locking region of a file opened - ** with the SQLITE_OPEN_MAIN_DB flag. This region of a database file - ** never contains valid data anyhow. So avoid doing such a read here. - ** - ** UPDATE: It also contains an assert() verifying that each call - ** to the xRead() method reads less than 128KB of data. - */ - const int isDb = (flags&SQLITE_OPEN_MAIN_DB); - i64 iOff; - - memset(pWrapper->zData, 0, pWrapper->nData); - for(iOff=0; iOff<pWrapper->iSize; iOff += 512){ - int nRead = pWrapper->iSize - (int)iOff; - if( nRead>512 ) nRead = 512; - if( isDb && iOff==PENDING_BYTE ) continue; - rc = sqlite3OsRead(pReal, &pWrapper->zData[iOff], nRead, iOff); - } - }else{ - rc = SQLITE_NOMEM; - } - } - if( rc!=SQLITE_OK && pWrapper->pMethod ){ - sqlite3OsClose(pFile); - } - return rc; -} - -static int cfDelete(sqlite3_vfs *pCfVfs, const char *zPath, int dirSync){ - sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData; - return pVfs->xDelete(pVfs, zPath, dirSync); -} -static int cfAccess( - sqlite3_vfs *pCfVfs, - const char *zPath, - int flags, - int *pResOut -){ - sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData; - return pVfs->xAccess(pVfs, zPath, flags, pResOut); -} -static int cfFullPathname( - sqlite3_vfs *pCfVfs, - const char *zPath, - int nPathOut, - char *zPathOut -){ - sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData; - return pVfs->xFullPathname(pVfs, zPath, nPathOut, zPathOut); -} -static void *cfDlOpen(sqlite3_vfs *pCfVfs, const char *zPath){ - sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData; - return pVfs->xDlOpen(pVfs, zPath); -} -static void cfDlError(sqlite3_vfs *pCfVfs, int nByte, char *zErrMsg){ - sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData; - pVfs->xDlError(pVfs, nByte, zErrMsg); -} -static void (*cfDlSym(sqlite3_vfs *pCfVfs, void *pH, const char *zSym))(void){ - sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData; - return pVfs->xDlSym(pVfs, pH, zSym); -} -static void cfDlClose(sqlite3_vfs *pCfVfs, void *pHandle){ - sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData; - pVfs->xDlClose(pVfs, pHandle); -} -static int cfRandomness(sqlite3_vfs *pCfVfs, int nByte, char *zBufOut){ - sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData; - return pVfs->xRandomness(pVfs, nByte, zBufOut); -} -static int cfSleep(sqlite3_vfs *pCfVfs, int nMicro){ - sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData; - return pVfs->xSleep(pVfs, nMicro); -} -static int cfCurrentTime(sqlite3_vfs *pCfVfs, double *pTimeOut){ - sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData; - return pVfs->xCurrentTime(pVfs, pTimeOut); -} - -static int processDevSymArgs( - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[], - int *piDeviceChar, - int *piSectorSize -){ - struct DeviceFlag { - char *zName; - int iValue; - } aFlag[] = { - { "atomic", SQLITE_IOCAP_ATOMIC }, - { "atomic512", SQLITE_IOCAP_ATOMIC512 }, - { "atomic1k", SQLITE_IOCAP_ATOMIC1K }, - { "atomic2k", SQLITE_IOCAP_ATOMIC2K }, - { "atomic4k", SQLITE_IOCAP_ATOMIC4K }, - { "atomic8k", SQLITE_IOCAP_ATOMIC8K }, - { "atomic16k", SQLITE_IOCAP_ATOMIC16K }, - { "atomic32k", SQLITE_IOCAP_ATOMIC32K }, - { "atomic64k", SQLITE_IOCAP_ATOMIC64K }, - { "sequential", SQLITE_IOCAP_SEQUENTIAL }, - { "safe_append", SQLITE_IOCAP_SAFE_APPEND }, - { "powersafe_overwrite", SQLITE_IOCAP_POWERSAFE_OVERWRITE }, - { 0, 0 } - }; - - int i; - int iDc = 0; - int iSectorSize = 0; - int setSectorsize = 0; - int setDeviceChar = 0; - - for(i=0; i<objc; i+=2){ - int nOpt; - char *zOpt = Tcl_GetStringFromObj(objv[i], &nOpt); - - if( (nOpt>11 || nOpt<2 || strncmp("-sectorsize", zOpt, nOpt)) - && (nOpt>16 || nOpt<2 || strncmp("-characteristics", zOpt, nOpt)) - ){ - Tcl_AppendResult(interp, - "Bad option: \"", zOpt, - "\" - must be \"-characteristics\" or \"-sectorsize\"", 0 - ); - return TCL_ERROR; - } - if( i==objc-1 ){ - Tcl_AppendResult(interp, "Option requires an argument: \"", zOpt, "\"",0); - return TCL_ERROR; - } - - if( zOpt[1]=='s' ){ - if( Tcl_GetIntFromObj(interp, objv[i+1], &iSectorSize) ){ - return TCL_ERROR; - } - setSectorsize = 1; - }else{ - int j; - Tcl_Obj **apObj; - int nObj; - if( Tcl_ListObjGetElements(interp, objv[i+1], &nObj, &apObj) ){ - return TCL_ERROR; - } - for(j=0; j<nObj; j++){ - int rc; - int iChoice; - Tcl_Obj *pFlag = Tcl_DuplicateObj(apObj[j]); - Tcl_IncrRefCount(pFlag); - Tcl_UtfToLower(Tcl_GetString(pFlag)); - - rc = Tcl_GetIndexFromObjStruct( - interp, pFlag, aFlag, sizeof(aFlag[0]), "no such flag", 0, &iChoice - ); - Tcl_DecrRefCount(pFlag); - if( rc ){ - return TCL_ERROR; - } - - iDc |= aFlag[iChoice].iValue; - } - setDeviceChar = 1; - } - } - - if( setDeviceChar ){ - *piDeviceChar = iDc; - } - if( setSectorsize ){ - *piSectorSize = iSectorSize; - } - - return TCL_OK; -} - -/* -** tclcmd: sqlite_crash_enable ENABLE -** -** Parameter ENABLE must be a boolean value. If true, then the "crash" -** vfs is added to the system. If false, it is removed. -*/ -static int crashEnableCmd( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - int isEnable; - static sqlite3_vfs crashVfs = { - 2, /* iVersion */ - 0, /* szOsFile */ - 0, /* mxPathname */ - 0, /* pNext */ - "crash", /* zName */ - 0, /* pAppData */ - - cfOpen, /* xOpen */ - cfDelete, /* xDelete */ - cfAccess, /* xAccess */ - cfFullPathname, /* xFullPathname */ - cfDlOpen, /* xDlOpen */ - cfDlError, /* xDlError */ - cfDlSym, /* xDlSym */ - cfDlClose, /* xDlClose */ - cfRandomness, /* xRandomness */ - cfSleep, /* xSleep */ - cfCurrentTime, /* xCurrentTime */ - 0, /* xGetlastError */ - 0, /* xCurrentTimeInt64 */ - }; - - if( objc!=2 ){ - Tcl_WrongNumArgs(interp, 1, objv, "ENABLE"); - return TCL_ERROR; - } - - if( Tcl_GetBooleanFromObj(interp, objv[1], &isEnable) ){ - return TCL_ERROR; - } - - if( (isEnable && crashVfs.pAppData) || (!isEnable && !crashVfs.pAppData) ){ - return TCL_OK; - } - - if( crashVfs.pAppData==0 ){ - sqlite3_vfs *pOriginalVfs = sqlite3_vfs_find(0); - crashVfs.mxPathname = pOriginalVfs->mxPathname; - crashVfs.pAppData = (void *)pOriginalVfs; - crashVfs.szOsFile = sizeof(CrashFile) + pOriginalVfs->szOsFile; - sqlite3_vfs_register(&crashVfs, 0); - }else{ - crashVfs.pAppData = 0; - sqlite3_vfs_unregister(&crashVfs); - } - - return TCL_OK; -} - -/* -** tclcmd: sqlite_crashparams ?OPTIONS? DELAY CRASHFILE -** -** This procedure implements a TCL command that enables crash testing -** in testfixture. Once enabled, crash testing cannot be disabled. -** -** Available options are "-characteristics" and "-sectorsize". Both require -** an argument. For -sectorsize, this is the simulated sector size in -** bytes. For -characteristics, the argument must be a list of io-capability -** flags to simulate. Valid flags are "atomic", "atomic512", "atomic1K", -** "atomic2K", "atomic4K", "atomic8K", "atomic16K", "atomic32K", -** "atomic64K", "sequential" and "safe_append". -** -** Example: -** -** sqlite_crashparams -sect 1024 -char {atomic sequential} ./test.db 1 -** -*/ -static int crashParamsObjCmd( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - int iDelay; - const char *zCrashFile; - int nCrashFile, iDc, iSectorSize; - - iDc = -1; - iSectorSize = -1; - - if( objc<3 ){ - Tcl_WrongNumArgs(interp, 1, objv, "?OPTIONS? DELAY CRASHFILE"); - goto error; - } - - zCrashFile = Tcl_GetStringFromObj(objv[objc-1], &nCrashFile); - if( nCrashFile>=sizeof(g.zCrashFile) ){ - Tcl_AppendResult(interp, "Filename is too long: \"", zCrashFile, "\"", 0); - goto error; - } - if( Tcl_GetIntFromObj(interp, objv[objc-2], &iDelay) ){ - goto error; - } - - if( processDevSymArgs(interp, objc-3, &objv[1], &iDc, &iSectorSize) ){ - return TCL_ERROR; - } - - if( iDc>=0 ){ - g.iDeviceCharacteristics = iDc; - } - if( iSectorSize>=0 ){ - g.iSectorSize = iSectorSize; - } - - g.iCrash = iDelay; - memcpy(g.zCrashFile, zCrashFile, nCrashFile+1); - sqlite3CrashTestEnable = 1; - return TCL_OK; - -error: - return TCL_ERROR; -} - -static int devSymObjCmd( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - void devsym_register(int iDeviceChar, int iSectorSize); - - int iDc = -1; - int iSectorSize = -1; - - if( processDevSymArgs(interp, objc-1, &objv[1], &iDc, &iSectorSize) ){ - return TCL_ERROR; - } - devsym_register(iDc, iSectorSize); - - return TCL_OK; -} - -/* -** tclcmd: register_jt_vfs ?-default? PARENT-VFS -*/ -static int jtObjCmd( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - int jt_register(char *, int); - char *zParent = 0; - - if( objc!=2 && objc!=3 ){ - Tcl_WrongNumArgs(interp, 1, objv, "?-default? PARENT-VFS"); - return TCL_ERROR; - } - zParent = Tcl_GetString(objv[1]); - if( objc==3 ){ - if( strcmp(zParent, "-default") ){ - Tcl_AppendResult(interp, - "bad option \"", zParent, "\": must be -default", 0 - ); - return TCL_ERROR; - } - zParent = Tcl_GetString(objv[2]); - } - - if( !(*zParent) ){ - zParent = 0; - } - if( jt_register(zParent, objc==3) ){ - Tcl_AppendResult(interp, "Error in jt_register", 0); - return TCL_ERROR; - } - - return TCL_OK; -} - -/* -** tclcmd: unregister_jt_vfs -*/ -static int jtUnregisterObjCmd( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - void jt_unregister(void); - - if( objc!=1 ){ - Tcl_WrongNumArgs(interp, 1, objv, ""); - return TCL_ERROR; - } - - jt_unregister(); - return TCL_OK; -} - -#endif /* SQLITE_OMIT_DISKIO */ - -/* -** This procedure registers the TCL procedures defined in this file. -*/ -int Sqlitetest6_Init(Tcl_Interp *interp){ -#ifndef SQLITE_OMIT_DISKIO - Tcl_CreateObjCommand(interp, "sqlite3_crash_enable", crashEnableCmd, 0, 0); - Tcl_CreateObjCommand(interp, "sqlite3_crashparams", crashParamsObjCmd, 0, 0); - Tcl_CreateObjCommand(interp, "sqlite3_simulate_device", devSymObjCmd, 0, 0); - Tcl_CreateObjCommand(interp, "register_jt_vfs", jtObjCmd, 0, 0); - Tcl_CreateObjCommand(interp, "unregister_jt_vfs", jtUnregisterObjCmd, 0, 0); -#endif - return TCL_OK; -} - -#endif /* SQLITE_TEST */ diff --git a/components/external/SQLite-3.8.1/SQLiteLib/test/test7.c b/components/external/SQLite-3.8.1/SQLiteLib/test/test7.c deleted file mode 100644 index 93bf1e4898..0000000000 --- a/components/external/SQLite-3.8.1/SQLiteLib/test/test7.c +++ /dev/null @@ -1,714 +0,0 @@ -/* -** 2006 January 09 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** Code for testing the client/server version of the SQLite library. -** Derived from test4.c. -*/ -#include "sqliteInt.h" -#include "tcl.h" - -/* -** This test only works on UNIX with a SQLITE_THREADSAFE build that includes -** the SQLITE_SERVER option. -*/ -#if defined(SQLITE_SERVER) && !defined(SQLITE_OMIT_SHARED_CACHE) && \ - SQLITE_OS_UNIX && SQLITE_THREADSAFE - -#include <stdlib.h> -#include <string.h> -#include <pthread.h> -#include <sched.h> -#include <ctype.h> - -/* -** Interfaces defined in server.c -*/ -int sqlite3_client_open(const char*, sqlite3**); -int sqlite3_client_prepare(sqlite3*,const char*,int, - sqlite3_stmt**,const char**); -int sqlite3_client_step(sqlite3_stmt*); -int sqlite3_client_reset(sqlite3_stmt*); -int sqlite3_client_finalize(sqlite3_stmt*); -int sqlite3_client_close(sqlite3*); -int sqlite3_server_start(void); -int sqlite3_server_stop(void); -void sqlite3_server_start2(int *pnDecr); - -/* -** Each thread is controlled by an instance of the following -** structure. -*/ -typedef struct Thread Thread; -struct Thread { - /* The first group of fields are writable by the supervisor thread - ** and read-only to the client threads - */ - char *zFilename; /* Name of database file */ - void (*xOp)(Thread*); /* next operation to do */ - char *zArg; /* argument usable by xOp */ - volatile int opnum; /* Operation number */ - volatile int busy; /* True if this thread is in use */ - - /* The next group of fields are writable by the client threads - ** but read-only to the superviser thread. - */ - volatile int completed; /* Number of operations completed */ - sqlite3 *db; /* Open database */ - sqlite3_stmt *pStmt; /* Pending operation */ - char *zErr; /* operation error */ - char *zStaticErr; /* Static error message */ - int rc; /* operation return code */ - int argc; /* number of columns in result */ - const char *argv[100]; /* result columns */ - const char *colv[100]; /* result column names */ - - /* Initialized to 1 by the supervisor thread when the client is - ** created, and then deemed read-only to the supervisor thread. - ** Is set to 0 by the server thread belonging to this client - ** just before it exits. - */ - int nServer; /* Number of server threads running */ -}; - -/* -** There can be as many as 26 threads running at once. Each is named -** by a capital letter: A, B, C, ..., Y, Z. -*/ -#define N_THREAD 26 -static Thread threadset[N_THREAD]; - -/* -** The main loop for a thread. Threads use busy waiting. -*/ -static void *client_main(void *pArg){ - Thread *p = (Thread*)pArg; - if( p->db ){ - sqlite3_client_close(p->db); - } - sqlite3_client_open(p->zFilename, &p->db); - if( SQLITE_OK!=sqlite3_errcode(p->db) ){ - p->zErr = strdup(sqlite3_errmsg(p->db)); - sqlite3_client_close(p->db); - p->db = 0; - } - p->pStmt = 0; - p->completed = 1; - while( p->opnum<=p->completed ) sched_yield(); - while( p->xOp ){ - if( p->zErr && p->zErr!=p->zStaticErr ){ - sqlite3_free(p->zErr); - p->zErr = 0; - } - (*p->xOp)(p); - p->completed++; - while( p->opnum<=p->completed ) sched_yield(); - } - if( p->pStmt ){ - sqlite3_client_finalize(p->pStmt); - p->pStmt = 0; - } - if( p->db ){ - sqlite3_client_close(p->db); - p->db = 0; - } - if( p->zErr && p->zErr!=p->zStaticErr ){ - sqlite3_free(p->zErr); - p->zErr = 0; - } - p->completed++; -#ifndef SQLITE_OMIT_DEPRECATED - sqlite3_thread_cleanup(); -#endif - return 0; -} - -/* -** Get a thread ID which is an upper case letter. Return the index. -** If the argument is not a valid thread ID put an error message in -** the interpreter and return -1. -*/ -static int parse_client_id(Tcl_Interp *interp, const char *zArg){ - if( zArg==0 || zArg[0]==0 || zArg[1]!=0 || !isupper((unsigned char)zArg[0]) ){ - Tcl_AppendResult(interp, "thread ID must be an upper case letter", 0); - return -1; - } - return zArg[0] - 'A'; -} - -/* -** Usage: client_create NAME FILENAME -** -** NAME should be an upper case letter. Start the thread running with -** an open connection to the given database. -*/ -static int tcl_client_create( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - const char **argv /* Text of each argument */ -){ - int i; - pthread_t x; - int rc; - - if( argc!=3 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " ID FILENAME", 0); - return TCL_ERROR; - } - i = parse_client_id(interp, argv[1]); - if( i<0 ) return TCL_ERROR; - if( threadset[i].busy ){ - Tcl_AppendResult(interp, "thread ", argv[1], " is already running", 0); - return TCL_ERROR; - } - threadset[i].busy = 1; - sqlite3_free(threadset[i].zFilename); - threadset[i].zFilename = sqlite3_mprintf("%s", argv[2]); - threadset[i].opnum = 1; - threadset[i].completed = 0; - rc = pthread_create(&x, 0, client_main, &threadset[i]); - if( rc ){ - Tcl_AppendResult(interp, "failed to create the thread", 0); - sqlite3_free(threadset[i].zFilename); - threadset[i].busy = 0; - return TCL_ERROR; - } - pthread_detach(x); - if( threadset[i].nServer==0 ){ - threadset[i].nServer = 1; - sqlite3_server_start2(&threadset[i].nServer); - } - return TCL_OK; -} - -/* -** Wait for a thread to reach its idle state. -*/ -static void client_wait(Thread *p){ - while( p->opnum>p->completed ) sched_yield(); -} - -/* -** Usage: client_wait ID -** -** Wait on thread ID to reach its idle state. -*/ -static int tcl_client_wait( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - const char **argv /* Text of each argument */ -){ - int i; - - if( argc!=2 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " ID", 0); - return TCL_ERROR; - } - i = parse_client_id(interp, argv[1]); - if( i<0 ) return TCL_ERROR; - if( !threadset[i].busy ){ - Tcl_AppendResult(interp, "no such thread", 0); - return TCL_ERROR; - } - client_wait(&threadset[i]); - return TCL_OK; -} - -/* -** Stop a thread. -*/ -static void stop_thread(Thread *p){ - client_wait(p); - p->xOp = 0; - p->opnum++; - client_wait(p); - sqlite3_free(p->zArg); - p->zArg = 0; - sqlite3_free(p->zFilename); - p->zFilename = 0; - p->busy = 0; -} - -/* -** Usage: client_halt ID -** -** Cause a client thread to shut itself down. Wait for the shutdown to be -** completed. If ID is "*" then stop all client threads. -*/ -static int tcl_client_halt( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - const char **argv /* Text of each argument */ -){ - int i; - - if( argc!=2 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " ID", 0); - return TCL_ERROR; - } - if( argv[1][0]=='*' && argv[1][1]==0 ){ - for(i=0; i<N_THREAD; i++){ - if( threadset[i].busy ){ - stop_thread(&threadset[i]); - } - } - }else{ - i = parse_client_id(interp, argv[1]); - if( i<0 ) return TCL_ERROR; - if( !threadset[i].busy ){ - Tcl_AppendResult(interp, "no such thread", 0); - return TCL_ERROR; - } - stop_thread(&threadset[i]); - } - - /* If no client threads are still running, also stop the server */ - for(i=0; i<N_THREAD && threadset[i].busy==0; i++){} - if( i>=N_THREAD ){ - sqlite3_server_stop(); - while( 1 ){ - for(i=0; i<N_THREAD && threadset[i].nServer==0; i++); - if( i==N_THREAD ) break; - sched_yield(); - } - } - return TCL_OK; -} - -/* -** Usage: client_argc ID -** -** Wait on the most recent client_step to complete, then return the -** number of columns in the result set. -*/ -static int tcl_client_argc( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - const char **argv /* Text of each argument */ -){ - int i; - char zBuf[100]; - - if( argc!=2 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " ID", 0); - return TCL_ERROR; - } - i = parse_client_id(interp, argv[1]); - if( i<0 ) return TCL_ERROR; - if( !threadset[i].busy ){ - Tcl_AppendResult(interp, "no such thread", 0); - return TCL_ERROR; - } - client_wait(&threadset[i]); - sprintf(zBuf, "%d", threadset[i].argc); - Tcl_AppendResult(interp, zBuf, 0); - return TCL_OK; -} - -/* -** Usage: client_argv ID N -** -** Wait on the most recent client_step to complete, then return the -** value of the N-th columns in the result set. -*/ -static int tcl_client_argv( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - const char **argv /* Text of each argument */ -){ - int i; - int n; - - if( argc!=3 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " ID N", 0); - return TCL_ERROR; - } - i = parse_client_id(interp, argv[1]); - if( i<0 ) return TCL_ERROR; - if( !threadset[i].busy ){ - Tcl_AppendResult(interp, "no such thread", 0); - return TCL_ERROR; - } - if( Tcl_GetInt(interp, argv[2], &n) ) return TCL_ERROR; - client_wait(&threadset[i]); - if( n<0 || n>=threadset[i].argc ){ - Tcl_AppendResult(interp, "column number out of range", 0); - return TCL_ERROR; - } - Tcl_AppendResult(interp, threadset[i].argv[n], 0); - return TCL_OK; -} - -/* -** Usage: client_colname ID N -** -** Wait on the most recent client_step to complete, then return the -** name of the N-th columns in the result set. -*/ -static int tcl_client_colname( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - const char **argv /* Text of each argument */ -){ - int i; - int n; - - if( argc!=3 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " ID N", 0); - return TCL_ERROR; - } - i = parse_client_id(interp, argv[1]); - if( i<0 ) return TCL_ERROR; - if( !threadset[i].busy ){ - Tcl_AppendResult(interp, "no such thread", 0); - return TCL_ERROR; - } - if( Tcl_GetInt(interp, argv[2], &n) ) return TCL_ERROR; - client_wait(&threadset[i]); - if( n<0 || n>=threadset[i].argc ){ - Tcl_AppendResult(interp, "column number out of range", 0); - return TCL_ERROR; - } - Tcl_AppendResult(interp, threadset[i].colv[n], 0); - return TCL_OK; -} - -extern const char *sqlite3ErrName(int); - -/* -** Usage: client_result ID -** -** Wait on the most recent operation to complete, then return the -** result code from that operation. -*/ -static int tcl_client_result( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - const char **argv /* Text of each argument */ -){ - int i; - const char *zName; - - if( argc!=2 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " ID", 0); - return TCL_ERROR; - } - i = parse_client_id(interp, argv[1]); - if( i<0 ) return TCL_ERROR; - if( !threadset[i].busy ){ - Tcl_AppendResult(interp, "no such thread", 0); - return TCL_ERROR; - } - client_wait(&threadset[i]); - zName = sqlite3ErrName(threadset[i].rc); - Tcl_AppendResult(interp, zName, 0); - return TCL_OK; -} - -/* -** Usage: client_error ID -** -** Wait on the most recent operation to complete, then return the -** error string. -*/ -static int tcl_client_error( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - const char **argv /* Text of each argument */ -){ - int i; - - if( argc!=2 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " ID", 0); - return TCL_ERROR; - } - i = parse_client_id(interp, argv[1]); - if( i<0 ) return TCL_ERROR; - if( !threadset[i].busy ){ - Tcl_AppendResult(interp, "no such thread", 0); - return TCL_ERROR; - } - client_wait(&threadset[i]); - Tcl_AppendResult(interp, threadset[i].zErr, 0); - return TCL_OK; -} - -/* -** This procedure runs in the thread to compile an SQL statement. -*/ -static void do_compile(Thread *p){ - if( p->db==0 ){ - p->zErr = p->zStaticErr = "no database is open"; - p->rc = SQLITE_ERROR; - return; - } - if( p->pStmt ){ - sqlite3_client_finalize(p->pStmt); - p->pStmt = 0; - } - p->rc = sqlite3_client_prepare(p->db, p->zArg, -1, &p->pStmt, 0); -} - -/* -** Usage: client_compile ID SQL -** -** Compile a new virtual machine. -*/ -static int tcl_client_compile( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - const char **argv /* Text of each argument */ -){ - int i; - if( argc!=3 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " ID SQL", 0); - return TCL_ERROR; - } - i = parse_client_id(interp, argv[1]); - if( i<0 ) return TCL_ERROR; - if( !threadset[i].busy ){ - Tcl_AppendResult(interp, "no such thread", 0); - return TCL_ERROR; - } - client_wait(&threadset[i]); - threadset[i].xOp = do_compile; - sqlite3_free(threadset[i].zArg); - threadset[i].zArg = sqlite3_mprintf("%s", argv[2]); - threadset[i].opnum++; - return TCL_OK; -} - -/* -** This procedure runs in the thread to step the virtual machine. -*/ -static void do_step(Thread *p){ - int i; - if( p->pStmt==0 ){ - p->zErr = p->zStaticErr = "no virtual machine available"; - p->rc = SQLITE_ERROR; - return; - } - p->rc = sqlite3_client_step(p->pStmt); - if( p->rc==SQLITE_ROW ){ - p->argc = sqlite3_column_count(p->pStmt); - for(i=0; i<sqlite3_data_count(p->pStmt); i++){ - p->argv[i] = (char*)sqlite3_column_text(p->pStmt, i); - } - for(i=0; i<p->argc; i++){ - p->colv[i] = sqlite3_column_name(p->pStmt, i); - } - } -} - -/* -** Usage: client_step ID -** -** Advance the virtual machine by one step -*/ -static int tcl_client_step( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - const char **argv /* Text of each argument */ -){ - int i; - if( argc!=2 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " IDL", 0); - return TCL_ERROR; - } - i = parse_client_id(interp, argv[1]); - if( i<0 ) return TCL_ERROR; - if( !threadset[i].busy ){ - Tcl_AppendResult(interp, "no such thread", 0); - return TCL_ERROR; - } - client_wait(&threadset[i]); - threadset[i].xOp = do_step; - threadset[i].opnum++; - return TCL_OK; -} - -/* -** This procedure runs in the thread to finalize a virtual machine. -*/ -static void do_finalize(Thread *p){ - if( p->pStmt==0 ){ - p->zErr = p->zStaticErr = "no virtual machine available"; - p->rc = SQLITE_ERROR; - return; - } - p->rc = sqlite3_client_finalize(p->pStmt); - p->pStmt = 0; -} - -/* -** Usage: client_finalize ID -** -** Finalize the virtual machine. -*/ -static int tcl_client_finalize( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - const char **argv /* Text of each argument */ -){ - int i; - if( argc!=2 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " IDL", 0); - return TCL_ERROR; - } - i = parse_client_id(interp, argv[1]); - if( i<0 ) return TCL_ERROR; - if( !threadset[i].busy ){ - Tcl_AppendResult(interp, "no such thread", 0); - return TCL_ERROR; - } - client_wait(&threadset[i]); - threadset[i].xOp = do_finalize; - sqlite3_free(threadset[i].zArg); - threadset[i].zArg = 0; - threadset[i].opnum++; - return TCL_OK; -} - -/* -** This procedure runs in the thread to reset a virtual machine. -*/ -static void do_reset(Thread *p){ - if( p->pStmt==0 ){ - p->zErr = p->zStaticErr = "no virtual machine available"; - p->rc = SQLITE_ERROR; - return; - } - p->rc = sqlite3_client_reset(p->pStmt); - p->pStmt = 0; -} - -/* -** Usage: client_reset ID -** -** Finalize the virtual machine. -*/ -static int tcl_client_reset( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - const char **argv /* Text of each argument */ -){ - int i; - if( argc!=2 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " IDL", 0); - return TCL_ERROR; - } - i = parse_client_id(interp, argv[1]); - if( i<0 ) return TCL_ERROR; - if( !threadset[i].busy ){ - Tcl_AppendResult(interp, "no such thread", 0); - return TCL_ERROR; - } - client_wait(&threadset[i]); - threadset[i].xOp = do_reset; - sqlite3_free(threadset[i].zArg); - threadset[i].zArg = 0; - threadset[i].opnum++; - return TCL_OK; -} - -/* -** Usage: client_swap ID ID -** -** Interchange the sqlite* pointer between two threads. -*/ -static int tcl_client_swap( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - const char **argv /* Text of each argument */ -){ - int i, j; - sqlite3 *temp; - if( argc!=3 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " ID1 ID2", 0); - return TCL_ERROR; - } - i = parse_client_id(interp, argv[1]); - if( i<0 ) return TCL_ERROR; - if( !threadset[i].busy ){ - Tcl_AppendResult(interp, "no such thread", 0); - return TCL_ERROR; - } - client_wait(&threadset[i]); - j = parse_client_id(interp, argv[2]); - if( j<0 ) return TCL_ERROR; - if( !threadset[j].busy ){ - Tcl_AppendResult(interp, "no such thread", 0); - return TCL_ERROR; - } - client_wait(&threadset[j]); - temp = threadset[i].db; - threadset[i].db = threadset[j].db; - threadset[j].db = temp; - return TCL_OK; -} - -/* -** Register commands with the TCL interpreter. -*/ -int Sqlitetest7_Init(Tcl_Interp *interp){ - static struct { - char *zName; - Tcl_CmdProc *xProc; - } aCmd[] = { - { "client_create", (Tcl_CmdProc*)tcl_client_create }, - { "client_wait", (Tcl_CmdProc*)tcl_client_wait }, - { "client_halt", (Tcl_CmdProc*)tcl_client_halt }, - { "client_argc", (Tcl_CmdProc*)tcl_client_argc }, - { "client_argv", (Tcl_CmdProc*)tcl_client_argv }, - { "client_colname", (Tcl_CmdProc*)tcl_client_colname }, - { "client_result", (Tcl_CmdProc*)tcl_client_result }, - { "client_error", (Tcl_CmdProc*)tcl_client_error }, - { "client_compile", (Tcl_CmdProc*)tcl_client_compile }, - { "client_step", (Tcl_CmdProc*)tcl_client_step }, - { "client_reset", (Tcl_CmdProc*)tcl_client_reset }, - { "client_finalize", (Tcl_CmdProc*)tcl_client_finalize }, - { "client_swap", (Tcl_CmdProc*)tcl_client_swap }, - }; - int i; - - for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){ - Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0); - } - return TCL_OK; -} -#else -int Sqlitetest7_Init(Tcl_Interp *interp){ return TCL_OK; } -#endif /* SQLITE_OS_UNIX */ diff --git a/components/external/SQLite-3.8.1/SQLiteLib/test/test8.c b/components/external/SQLite-3.8.1/SQLiteLib/test/test8.c deleted file mode 100644 index 9b8b545fa6..0000000000 --- a/components/external/SQLite-3.8.1/SQLiteLib/test/test8.c +++ /dev/null @@ -1,1396 +0,0 @@ -/* -** 2006 June 10 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** Code for testing the virtual table interfaces. This code -** is not included in the SQLite library. It is used for automated -** testing of the SQLite library. -*/ -#include "sqliteInt.h" -#include "tcl.h" -#include <stdlib.h> -#include <string.h> - -#ifndef SQLITE_OMIT_VIRTUALTABLE - -typedef struct echo_vtab echo_vtab; -typedef struct echo_cursor echo_cursor; - -/* -** The test module defined in this file uses four global Tcl variables to -** commicate with test-scripts: -** -** $::echo_module -** $::echo_module_sync_fail -** $::echo_module_begin_fail -** $::echo_module_cost -** -** The variable ::echo_module is a list. Each time one of the following -** methods is called, one or more elements are appended to the list. -** This is used for automated testing of virtual table modules. -** -** The ::echo_module_sync_fail variable is set by test scripts and read -** by code in this file. If it is set to the name of a real table in the -** the database, then all xSync operations on echo virtual tables that -** use the named table as a backing store will fail. -*/ - -/* -** Errors can be provoked within the following echo virtual table methods: -** -** xBestIndex xOpen xFilter xNext -** xColumn xRowid xUpdate xSync -** xBegin xRename -** -** This is done by setting the global tcl variable: -** -** echo_module_fail($method,$tbl) -** -** where $method is set to the name of the virtual table method to fail -** (i.e. "xBestIndex") and $tbl is the name of the table being echoed (not -** the name of the virtual table, the name of the underlying real table). -*/ - -/* -** An echo virtual-table object. -** -** echo.vtab.aIndex is an array of booleans. The nth entry is true if -** the nth column of the real table is the left-most column of an index -** (implicit or otherwise). In other words, if SQLite can optimize -** a query like "SELECT * FROM real_table WHERE col = ?". -** -** Member variable aCol[] contains copies of the column names of the real -** table. -*/ -struct echo_vtab { - sqlite3_vtab base; - Tcl_Interp *interp; /* Tcl interpreter containing debug variables */ - sqlite3 *db; /* Database connection */ - - int isPattern; - int inTransaction; /* True if within a transaction */ - char *zThis; /* Name of the echo table */ - char *zTableName; /* Name of the real table */ - char *zLogName; /* Name of the log table */ - int nCol; /* Number of columns in the real table */ - int *aIndex; /* Array of size nCol. True if column has an index */ - char **aCol; /* Array of size nCol. Column names */ -}; - -/* An echo cursor object */ -struct echo_cursor { - sqlite3_vtab_cursor base; - sqlite3_stmt *pStmt; -}; - -static int simulateVtabError(echo_vtab *p, const char *zMethod){ - const char *zErr; - char zVarname[128]; - zVarname[127] = '\0'; - sqlite3_snprintf(127, zVarname, "echo_module_fail(%s,%s)", zMethod, p->zTableName); - zErr = Tcl_GetVar(p->interp, zVarname, TCL_GLOBAL_ONLY); - if( zErr ){ - p->base.zErrMsg = sqlite3_mprintf("echo-vtab-error: %s", zErr); - } - return (zErr!=0); -} - -/* -** Convert an SQL-style quoted string into a normal string by removing -** the quote characters. The conversion is done in-place. If the -** input does not begin with a quote character, then this routine -** is a no-op. -** -** Examples: -** -** "abc" becomes abc -** 'xyz' becomes xyz -** [pqr] becomes pqr -** `mno` becomes mno -*/ -static void dequoteString(char *z){ - int quote; - int i, j; - if( z==0 ) return; - quote = z[0]; - switch( quote ){ - case '\'': break; - case '"': break; - case '`': break; /* For MySQL compatibility */ - case '[': quote = ']'; break; /* For MS SqlServer compatibility */ - default: return; - } - for(i=1, j=0; z[i]; i++){ - if( z[i]==quote ){ - if( z[i+1]==quote ){ - z[j++] = quote; - i++; - }else{ - z[j++] = 0; - break; - } - }else{ - z[j++] = z[i]; - } - } -} - -/* -** Retrieve the column names for the table named zTab via database -** connection db. SQLITE_OK is returned on success, or an sqlite error -** code otherwise. -** -** If successful, the number of columns is written to *pnCol. *paCol is -** set to point at sqlite3_malloc()'d space containing the array of -** nCol column names. The caller is responsible for calling sqlite3_free -** on *paCol. -*/ -static int getColumnNames( - sqlite3 *db, - const char *zTab, - char ***paCol, - int *pnCol -){ - char **aCol = 0; - char *zSql; - sqlite3_stmt *pStmt = 0; - int rc = SQLITE_OK; - int nCol = 0; - - /* Prepare the statement "SELECT * FROM <tbl>". The column names - ** of the result set of the compiled SELECT will be the same as - ** the column names of table <tbl>. - */ - zSql = sqlite3_mprintf("SELECT * FROM %Q", zTab); - if( !zSql ){ - rc = SQLITE_NOMEM; - goto out; - } - rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0); - sqlite3_free(zSql); - - if( rc==SQLITE_OK ){ - int ii; - int nBytes; - char *zSpace; - nCol = sqlite3_column_count(pStmt); - - /* Figure out how much space to allocate for the array of column names - ** (including space for the strings themselves). Then allocate it. - */ - nBytes = sizeof(char *) * nCol; - for(ii=0; ii<nCol; ii++){ - const char *zName = sqlite3_column_name(pStmt, ii); - if( !zName ){ - rc = SQLITE_NOMEM; - goto out; - } - nBytes += (int)strlen(zName)+1; - } - aCol = (char **)sqlite3MallocZero(nBytes); - if( !aCol ){ - rc = SQLITE_NOMEM; - goto out; - } - - /* Copy the column names into the allocated space and set up the - ** pointers in the aCol[] array. - */ - zSpace = (char *)(&aCol[nCol]); - for(ii=0; ii<nCol; ii++){ - aCol[ii] = zSpace; - zSpace += sprintf(zSpace, "%s", sqlite3_column_name(pStmt, ii)); - zSpace++; - } - assert( (zSpace-nBytes)==(char *)aCol ); - } - - *paCol = aCol; - *pnCol = nCol; - -out: - sqlite3_finalize(pStmt); - return rc; -} - -/* -** Parameter zTab is the name of a table in database db with nCol -** columns. This function allocates an array of integers nCol in -** size and populates it according to any implicit or explicit -** indices on table zTab. -** -** If successful, SQLITE_OK is returned and *paIndex set to point -** at the allocated array. Otherwise, an error code is returned. -** -** See comments associated with the member variable aIndex above -** "struct echo_vtab" for details of the contents of the array. -*/ -static int getIndexArray( - sqlite3 *db, /* Database connection */ - const char *zTab, /* Name of table in database db */ - int nCol, - int **paIndex -){ - sqlite3_stmt *pStmt = 0; - int *aIndex = 0; - int rc; - char *zSql; - - /* Allocate space for the index array */ - aIndex = (int *)sqlite3MallocZero(sizeof(int) * nCol); - if( !aIndex ){ - rc = SQLITE_NOMEM; - goto get_index_array_out; - } - - /* Compile an sqlite pragma to loop through all indices on table zTab */ - zSql = sqlite3_mprintf("PRAGMA index_list(%s)", zTab); - if( !zSql ){ - rc = SQLITE_NOMEM; - goto get_index_array_out; - } - rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0); - sqlite3_free(zSql); - - /* For each index, figure out the left-most column and set the - ** corresponding entry in aIndex[] to 1. - */ - while( pStmt && sqlite3_step(pStmt)==SQLITE_ROW ){ - const char *zIdx = (const char *)sqlite3_column_text(pStmt, 1); - sqlite3_stmt *pStmt2 = 0; - if( zIdx==0 ) continue; - zSql = sqlite3_mprintf("PRAGMA index_info(%s)", zIdx); - if( !zSql ){ - rc = SQLITE_NOMEM; - goto get_index_array_out; - } - rc = sqlite3_prepare(db, zSql, -1, &pStmt2, 0); - sqlite3_free(zSql); - if( pStmt2 && sqlite3_step(pStmt2)==SQLITE_ROW ){ - int cid = sqlite3_column_int(pStmt2, 1); - assert( cid>=0 && cid<nCol ); - aIndex[cid] = 1; - } - if( pStmt2 ){ - rc = sqlite3_finalize(pStmt2); - } - if( rc!=SQLITE_OK ){ - goto get_index_array_out; - } - } - - -get_index_array_out: - if( pStmt ){ - int rc2 = sqlite3_finalize(pStmt); - if( rc==SQLITE_OK ){ - rc = rc2; - } - } - if( rc!=SQLITE_OK ){ - sqlite3_free(aIndex); - aIndex = 0; - } - *paIndex = aIndex; - return rc; -} - -/* -** Global Tcl variable $echo_module is a list. This routine appends -** the string element zArg to that list in interpreter interp. -*/ -static void appendToEchoModule(Tcl_Interp *interp, const char *zArg){ - int flags = (TCL_APPEND_VALUE | TCL_LIST_ELEMENT | TCL_GLOBAL_ONLY); - Tcl_SetVar(interp, "echo_module", (zArg?zArg:""), flags); -} - -/* -** This function is called from within the echo-modules xCreate and -** xConnect methods. The argc and argv arguments are copies of those -** passed to the calling method. This function is responsible for -** calling sqlite3_declare_vtab() to declare the schema of the virtual -** table being created or connected. -** -** If the constructor was passed just one argument, i.e.: -** -** CREATE TABLE t1 AS echo(t2); -** -** Then t2 is assumed to be the name of a *real* database table. The -** schema of the virtual table is declared by passing a copy of the -** CREATE TABLE statement for the real table to sqlite3_declare_vtab(). -** Hence, the virtual table should have exactly the same column names and -** types as the real table. -*/ -static int echoDeclareVtab( - echo_vtab *pVtab, - sqlite3 *db -){ - int rc = SQLITE_OK; - - if( pVtab->zTableName ){ - sqlite3_stmt *pStmt = 0; - rc = sqlite3_prepare(db, - "SELECT sql FROM sqlite_master WHERE type = 'table' AND name = ?", - -1, &pStmt, 0); - if( rc==SQLITE_OK ){ - sqlite3_bind_text(pStmt, 1, pVtab->zTableName, -1, 0); - if( sqlite3_step(pStmt)==SQLITE_ROW ){ - int rc2; - const char *zCreateTable = (const char *)sqlite3_column_text(pStmt, 0); - rc = sqlite3_declare_vtab(db, zCreateTable); - rc2 = sqlite3_finalize(pStmt); - if( rc==SQLITE_OK ){ - rc = rc2; - } - } else { - rc = sqlite3_finalize(pStmt); - if( rc==SQLITE_OK ){ - rc = SQLITE_ERROR; - } - } - if( rc==SQLITE_OK ){ - rc = getColumnNames(db, pVtab->zTableName, &pVtab->aCol, &pVtab->nCol); - } - if( rc==SQLITE_OK ){ - rc = getIndexArray(db, pVtab->zTableName, pVtab->nCol, &pVtab->aIndex); - } - } - } - - return rc; -} - -/* -** This function frees all runtime structures associated with the virtual -** table pVtab. -*/ -static int echoDestructor(sqlite3_vtab *pVtab){ - echo_vtab *p = (echo_vtab*)pVtab; - sqlite3_free(p->aIndex); - sqlite3_free(p->aCol); - sqlite3_free(p->zThis); - sqlite3_free(p->zTableName); - sqlite3_free(p->zLogName); - sqlite3_free(p); - return 0; -} - -typedef struct EchoModule EchoModule; -struct EchoModule { - Tcl_Interp *interp; -}; - -/* -** This function is called to do the work of the xConnect() method - -** to allocate the required in-memory structures for a newly connected -** virtual table. -*/ -static int echoConstructor( - sqlite3 *db, - void *pAux, - int argc, const char *const*argv, - sqlite3_vtab **ppVtab, - char **pzErr -){ - int rc; - int i; - echo_vtab *pVtab; - - /* Allocate the sqlite3_vtab/echo_vtab structure itself */ - pVtab = sqlite3MallocZero( sizeof(*pVtab) ); - if( !pVtab ){ - return SQLITE_NOMEM; - } - pVtab->interp = ((EchoModule *)pAux)->interp; - pVtab->db = db; - - /* Allocate echo_vtab.zThis */ - pVtab->zThis = sqlite3_mprintf("%s", argv[2]); - if( !pVtab->zThis ){ - echoDestructor((sqlite3_vtab *)pVtab); - return SQLITE_NOMEM; - } - - /* Allocate echo_vtab.zTableName */ - if( argc>3 ){ - pVtab->zTableName = sqlite3_mprintf("%s", argv[3]); - dequoteString(pVtab->zTableName); - if( pVtab->zTableName && pVtab->zTableName[0]=='*' ){ - char *z = sqlite3_mprintf("%s%s", argv[2], &(pVtab->zTableName[1])); - sqlite3_free(pVtab->zTableName); - pVtab->zTableName = z; - pVtab->isPattern = 1; - } - if( !pVtab->zTableName ){ - echoDestructor((sqlite3_vtab *)pVtab); - return SQLITE_NOMEM; - } - } - - /* Log the arguments to this function to Tcl var ::echo_module */ - for(i=0; i<argc; i++){ - appendToEchoModule(pVtab->interp, argv[i]); - } - - /* Invoke sqlite3_declare_vtab and set up other members of the echo_vtab - ** structure. If an error occurs, delete the sqlite3_vtab structure and - ** return an error code. - */ - rc = echoDeclareVtab(pVtab, db); - if( rc!=SQLITE_OK ){ - echoDestructor((sqlite3_vtab *)pVtab); - return rc; - } - - /* Success. Set *ppVtab and return */ - *ppVtab = &pVtab->base; - return SQLITE_OK; -} - -/* -** Echo virtual table module xCreate method. -*/ -static int echoCreate( - sqlite3 *db, - void *pAux, - int argc, const char *const*argv, - sqlite3_vtab **ppVtab, - char **pzErr -){ - int rc = SQLITE_OK; - appendToEchoModule(((EchoModule *)pAux)->interp, "xCreate"); - rc = echoConstructor(db, pAux, argc, argv, ppVtab, pzErr); - - /* If there were two arguments passed to the module at the SQL level - ** (i.e. "CREATE VIRTUAL TABLE tbl USING echo(arg1, arg2)"), then - ** the second argument is used as a table name. Attempt to create - ** such a table with a single column, "logmsg". This table will - ** be used to log calls to the xUpdate method. It will be deleted - ** when the virtual table is DROPed. - ** - ** Note: The main point of this is to test that we can drop tables - ** from within an xDestroy method call. - */ - if( rc==SQLITE_OK && argc==5 ){ - char *zSql; - echo_vtab *pVtab = *(echo_vtab **)ppVtab; - pVtab->zLogName = sqlite3_mprintf("%s", argv[4]); - zSql = sqlite3_mprintf("CREATE TABLE %Q(logmsg)", pVtab->zLogName); - rc = sqlite3_exec(db, zSql, 0, 0, 0); - sqlite3_free(zSql); - if( rc!=SQLITE_OK ){ - *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db)); - } - } - - if( *ppVtab && rc!=SQLITE_OK ){ - echoDestructor(*ppVtab); - *ppVtab = 0; - } - - if( rc==SQLITE_OK ){ - (*(echo_vtab**)ppVtab)->inTransaction = 1; - } - - return rc; -} - -/* -** Echo virtual table module xConnect method. -*/ -static int echoConnect( - sqlite3 *db, - void *pAux, - int argc, const char *const*argv, - sqlite3_vtab **ppVtab, - char **pzErr -){ - appendToEchoModule(((EchoModule *)pAux)->interp, "xConnect"); - return echoConstructor(db, pAux, argc, argv, ppVtab, pzErr); -} - -/* -** Echo virtual table module xDisconnect method. -*/ -static int echoDisconnect(sqlite3_vtab *pVtab){ - appendToEchoModule(((echo_vtab *)pVtab)->interp, "xDisconnect"); - return echoDestructor(pVtab); -} - -/* -** Echo virtual table module xDestroy method. -*/ -static int echoDestroy(sqlite3_vtab *pVtab){ - int rc = SQLITE_OK; - echo_vtab *p = (echo_vtab *)pVtab; - appendToEchoModule(((echo_vtab *)pVtab)->interp, "xDestroy"); - - /* Drop the "log" table, if one exists (see echoCreate() for details) */ - if( p && p->zLogName ){ - char *zSql; - zSql = sqlite3_mprintf("DROP TABLE %Q", p->zLogName); - rc = sqlite3_exec(p->db, zSql, 0, 0, 0); - sqlite3_free(zSql); - } - - if( rc==SQLITE_OK ){ - rc = echoDestructor(pVtab); - } - return rc; -} - -/* -** Echo virtual table module xOpen method. -*/ -static int echoOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){ - echo_cursor *pCur; - if( simulateVtabError((echo_vtab *)pVTab, "xOpen") ){ - return SQLITE_ERROR; - } - pCur = sqlite3MallocZero(sizeof(echo_cursor)); - *ppCursor = (sqlite3_vtab_cursor *)pCur; - return (pCur ? SQLITE_OK : SQLITE_NOMEM); -} - -/* -** Echo virtual table module xClose method. -*/ -static int echoClose(sqlite3_vtab_cursor *cur){ - int rc; - echo_cursor *pCur = (echo_cursor *)cur; - sqlite3_stmt *pStmt = pCur->pStmt; - pCur->pStmt = 0; - sqlite3_free(pCur); - rc = sqlite3_finalize(pStmt); - return rc; -} - -/* -** Return non-zero if the cursor does not currently point to a valid record -** (i.e if the scan has finished), or zero otherwise. -*/ -static int echoEof(sqlite3_vtab_cursor *cur){ - return (((echo_cursor *)cur)->pStmt ? 0 : 1); -} - -/* -** Echo virtual table module xNext method. -*/ -static int echoNext(sqlite3_vtab_cursor *cur){ - int rc = SQLITE_OK; - echo_cursor *pCur = (echo_cursor *)cur; - - if( simulateVtabError((echo_vtab *)(cur->pVtab), "xNext") ){ - return SQLITE_ERROR; - } - - if( pCur->pStmt ){ - rc = sqlite3_step(pCur->pStmt); - if( rc==SQLITE_ROW ){ - rc = SQLITE_OK; - }else{ - rc = sqlite3_finalize(pCur->pStmt); - pCur->pStmt = 0; - } - } - - return rc; -} - -/* -** Echo virtual table module xColumn method. -*/ -static int echoColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){ - int iCol = i + 1; - sqlite3_stmt *pStmt = ((echo_cursor *)cur)->pStmt; - - if( simulateVtabError((echo_vtab *)(cur->pVtab), "xColumn") ){ - return SQLITE_ERROR; - } - - if( !pStmt ){ - sqlite3_result_null(ctx); - }else{ - assert( sqlite3_data_count(pStmt)>iCol ); - sqlite3_result_value(ctx, sqlite3_column_value(pStmt, iCol)); - } - return SQLITE_OK; -} - -/* -** Echo virtual table module xRowid method. -*/ -static int echoRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){ - sqlite3_stmt *pStmt = ((echo_cursor *)cur)->pStmt; - - if( simulateVtabError((echo_vtab *)(cur->pVtab), "xRowid") ){ - return SQLITE_ERROR; - } - - *pRowid = sqlite3_column_int64(pStmt, 0); - return SQLITE_OK; -} - -/* -** Compute a simple hash of the null terminated string zString. -** -** This module uses only sqlite3_index_info.idxStr, not -** sqlite3_index_info.idxNum. So to test idxNum, when idxStr is set -** in echoBestIndex(), idxNum is set to the corresponding hash value. -** In echoFilter(), code assert()s that the supplied idxNum value is -** indeed the hash of the supplied idxStr. -*/ -static int hashString(const char *zString){ - int val = 0; - int ii; - for(ii=0; zString[ii]; ii++){ - val = (val << 3) + (int)zString[ii]; - } - return val; -} - -/* -** Echo virtual table module xFilter method. -*/ -static int echoFilter( - sqlite3_vtab_cursor *pVtabCursor, - int idxNum, const char *idxStr, - int argc, sqlite3_value **argv -){ - int rc; - int i; - - echo_cursor *pCur = (echo_cursor *)pVtabCursor; - echo_vtab *pVtab = (echo_vtab *)pVtabCursor->pVtab; - sqlite3 *db = pVtab->db; - - if( simulateVtabError(pVtab, "xFilter") ){ - return SQLITE_ERROR; - } - - /* Check that idxNum matches idxStr */ - assert( idxNum==hashString(idxStr) ); - - /* Log arguments to the ::echo_module Tcl variable */ - appendToEchoModule(pVtab->interp, "xFilter"); - appendToEchoModule(pVtab->interp, idxStr); - for(i=0; i<argc; i++){ - appendToEchoModule(pVtab->interp, (const char*)sqlite3_value_text(argv[i])); - } - - sqlite3_finalize(pCur->pStmt); - pCur->pStmt = 0; - - /* Prepare the SQL statement created by echoBestIndex and bind the - ** runtime parameters passed to this function to it. - */ - rc = sqlite3_prepare(db, idxStr, -1, &pCur->pStmt, 0); - assert( pCur->pStmt || rc!=SQLITE_OK ); - for(i=0; rc==SQLITE_OK && i<argc; i++){ - rc = sqlite3_bind_value(pCur->pStmt, i+1, argv[i]); - } - - /* If everything was successful, advance to the first row of the scan */ - if( rc==SQLITE_OK ){ - rc = echoNext(pVtabCursor); - } - - return rc; -} - - -/* -** A helper function used by echoUpdate() and echoBestIndex() for -** manipulating strings in concert with the sqlite3_mprintf() function. -** -** Parameter pzStr points to a pointer to a string allocated with -** sqlite3_mprintf. The second parameter, zAppend, points to another -** string. The two strings are concatenated together and *pzStr -** set to point at the result. The initial buffer pointed to by *pzStr -** is deallocated via sqlite3_free(). -** -** If the third argument, doFree, is true, then sqlite3_free() is -** also called to free the buffer pointed to by zAppend. -*/ -static void string_concat(char **pzStr, char *zAppend, int doFree, int *pRc){ - char *zIn = *pzStr; - if( !zAppend && doFree && *pRc==SQLITE_OK ){ - *pRc = SQLITE_NOMEM; - } - if( *pRc!=SQLITE_OK ){ - sqlite3_free(zIn); - zIn = 0; - }else{ - if( zIn ){ - char *zTemp = zIn; - zIn = sqlite3_mprintf("%s%s", zIn, zAppend); - sqlite3_free(zTemp); - }else{ - zIn = sqlite3_mprintf("%s", zAppend); - } - if( !zIn ){ - *pRc = SQLITE_NOMEM; - } - } - *pzStr = zIn; - if( doFree ){ - sqlite3_free(zAppend); - } -} - -/* -** The echo module implements the subset of query constraints and sort -** orders that may take advantage of SQLite indices on the underlying -** real table. For example, if the real table is declared as: -** -** CREATE TABLE real(a, b, c); -** CREATE INDEX real_index ON real(b); -** -** then the echo module handles WHERE or ORDER BY clauses that refer -** to the column "b", but not "a" or "c". If a multi-column index is -** present, only its left most column is considered. -** -** This xBestIndex method encodes the proposed search strategy as -** an SQL query on the real table underlying the virtual echo module -** table and stores the query in sqlite3_index_info.idxStr. The SQL -** statement is of the form: -** -** SELECT rowid, * FROM <real-table> ?<where-clause>? ?<order-by-clause>? -** -** where the <where-clause> and <order-by-clause> are determined -** by the contents of the structure pointed to by the pIdxInfo argument. -*/ -static int echoBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ - int ii; - char *zQuery = 0; - char *zNew; - int nArg = 0; - const char *zSep = "WHERE"; - echo_vtab *pVtab = (echo_vtab *)tab; - sqlite3_stmt *pStmt = 0; - Tcl_Interp *interp = pVtab->interp; - - int nRow; - int useIdx = 0; - int rc = SQLITE_OK; - int useCost = 0; - double cost; - int isIgnoreUsable = 0; - if( Tcl_GetVar(interp, "echo_module_ignore_usable", TCL_GLOBAL_ONLY) ){ - isIgnoreUsable = 1; - } - - if( simulateVtabError(pVtab, "xBestIndex") ){ - return SQLITE_ERROR; - } - - /* Determine the number of rows in the table and store this value in local - ** variable nRow. The 'estimated-cost' of the scan will be the number of - ** rows in the table for a linear scan, or the log (base 2) of the - ** number of rows if the proposed scan uses an index. - */ - if( Tcl_GetVar(interp, "echo_module_cost", TCL_GLOBAL_ONLY) ){ - cost = atof(Tcl_GetVar(interp, "echo_module_cost", TCL_GLOBAL_ONLY)); - useCost = 1; - } else { - zQuery = sqlite3_mprintf("SELECT count(*) FROM %Q", pVtab->zTableName); - if( !zQuery ){ - return SQLITE_NOMEM; - } - rc = sqlite3_prepare(pVtab->db, zQuery, -1, &pStmt, 0); - sqlite3_free(zQuery); - if( rc!=SQLITE_OK ){ - return rc; - } - sqlite3_step(pStmt); - nRow = sqlite3_column_int(pStmt, 0); - rc = sqlite3_finalize(pStmt); - if( rc!=SQLITE_OK ){ - return rc; - } - } - - zQuery = sqlite3_mprintf("SELECT rowid, * FROM %Q", pVtab->zTableName); - if( !zQuery ){ - return SQLITE_NOMEM; - } - for(ii=0; ii<pIdxInfo->nConstraint; ii++){ - const struct sqlite3_index_constraint *pConstraint; - struct sqlite3_index_constraint_usage *pUsage; - int iCol; - - pConstraint = &pIdxInfo->aConstraint[ii]; - pUsage = &pIdxInfo->aConstraintUsage[ii]; - - if( !isIgnoreUsable && !pConstraint->usable ) continue; - - iCol = pConstraint->iColumn; - if( iCol<0 || pVtab->aIndex[iCol] ){ - char *zCol = iCol>=0 ? pVtab->aCol[iCol] : "rowid"; - char *zOp = 0; - useIdx = 1; - switch( pConstraint->op ){ - case SQLITE_INDEX_CONSTRAINT_EQ: - zOp = "="; break; - case SQLITE_INDEX_CONSTRAINT_LT: - zOp = "<"; break; - case SQLITE_INDEX_CONSTRAINT_GT: - zOp = ">"; break; - case SQLITE_INDEX_CONSTRAINT_LE: - zOp = "<="; break; - case SQLITE_INDEX_CONSTRAINT_GE: - zOp = ">="; break; - case SQLITE_INDEX_CONSTRAINT_MATCH: - zOp = "LIKE"; break; - } - if( zOp[0]=='L' ){ - zNew = sqlite3_mprintf(" %s %s LIKE (SELECT '%%'||?||'%%')", - zSep, zCol); - } else { - zNew = sqlite3_mprintf(" %s %s %s ?", zSep, zCol, zOp); - } - string_concat(&zQuery, zNew, 1, &rc); - - zSep = "AND"; - pUsage->argvIndex = ++nArg; - pUsage->omit = 1; - } - } - - /* If there is only one term in the ORDER BY clause, and it is - ** on a column that this virtual table has an index for, then consume - ** the ORDER BY clause. - */ - if( pIdxInfo->nOrderBy==1 && ( - pIdxInfo->aOrderBy->iColumn<0 || - pVtab->aIndex[pIdxInfo->aOrderBy->iColumn]) ){ - int iCol = pIdxInfo->aOrderBy->iColumn; - char *zCol = iCol>=0 ? pVtab->aCol[iCol] : "rowid"; - char *zDir = pIdxInfo->aOrderBy->desc?"DESC":"ASC"; - zNew = sqlite3_mprintf(" ORDER BY %s %s", zCol, zDir); - string_concat(&zQuery, zNew, 1, &rc); - pIdxInfo->orderByConsumed = 1; - } - - appendToEchoModule(pVtab->interp, "xBestIndex");; - appendToEchoModule(pVtab->interp, zQuery); - - if( !zQuery ){ - return rc; - } - pIdxInfo->idxNum = hashString(zQuery); - pIdxInfo->idxStr = zQuery; - pIdxInfo->needToFreeIdxStr = 1; - if( useCost ){ - pIdxInfo->estimatedCost = cost; - }else if( useIdx ){ - /* Approximation of log2(nRow). */ - for( ii=0; ii<(sizeof(int)*8); ii++ ){ - if( nRow & (1<<ii) ){ - pIdxInfo->estimatedCost = (double)ii; - } - } - }else{ - pIdxInfo->estimatedCost = (double)nRow; - } - return rc; -} - -/* -** The xUpdate method for echo module virtual tables. -** -** apData[0] apData[1] apData[2..] -** -** INTEGER DELETE -** -** INTEGER NULL (nCol args) UPDATE (do not set rowid) -** INTEGER INTEGER (nCol args) UPDATE (with SET rowid = <arg1>) -** -** NULL NULL (nCol args) INSERT INTO (automatic rowid value) -** NULL INTEGER (nCol args) INSERT (incl. rowid value) -** -*/ -int echoUpdate( - sqlite3_vtab *tab, - int nData, - sqlite3_value **apData, - sqlite_int64 *pRowid -){ - echo_vtab *pVtab = (echo_vtab *)tab; - sqlite3 *db = pVtab->db; - int rc = SQLITE_OK; - - sqlite3_stmt *pStmt; - char *z = 0; /* SQL statement to execute */ - int bindArgZero = 0; /* True to bind apData[0] to sql var no. nData */ - int bindArgOne = 0; /* True to bind apData[1] to sql var no. 1 */ - int i; /* Counter variable used by for loops */ - - assert( nData==pVtab->nCol+2 || nData==1 ); - - /* Ticket #3083 - make sure we always start a transaction prior to - ** making any changes to a virtual table */ - assert( pVtab->inTransaction ); - - if( simulateVtabError(pVtab, "xUpdate") ){ - return SQLITE_ERROR; - } - - /* If apData[0] is an integer and nData>1 then do an UPDATE */ - if( nData>1 && sqlite3_value_type(apData[0])==SQLITE_INTEGER ){ - char *zSep = " SET"; - z = sqlite3_mprintf("UPDATE %Q", pVtab->zTableName); - if( !z ){ - rc = SQLITE_NOMEM; - } - - bindArgOne = (apData[1] && sqlite3_value_type(apData[1])==SQLITE_INTEGER); - bindArgZero = 1; - - if( bindArgOne ){ - string_concat(&z, " SET rowid=?1 ", 0, &rc); - zSep = ","; - } - for(i=2; i<nData; i++){ - if( apData[i]==0 ) continue; - string_concat(&z, sqlite3_mprintf( - "%s %Q=?%d", zSep, pVtab->aCol[i-2], i), 1, &rc); - zSep = ","; - } - string_concat(&z, sqlite3_mprintf(" WHERE rowid=?%d", nData), 1, &rc); - } - - /* If apData[0] is an integer and nData==1 then do a DELETE */ - else if( nData==1 && sqlite3_value_type(apData[0])==SQLITE_INTEGER ){ - z = sqlite3_mprintf("DELETE FROM %Q WHERE rowid = ?1", pVtab->zTableName); - if( !z ){ - rc = SQLITE_NOMEM; - } - bindArgZero = 1; - } - - /* If the first argument is NULL and there are more than two args, INSERT */ - else if( nData>2 && sqlite3_value_type(apData[0])==SQLITE_NULL ){ - int ii; - char *zInsert = 0; - char *zValues = 0; - - zInsert = sqlite3_mprintf("INSERT INTO %Q (", pVtab->zTableName); - if( !zInsert ){ - rc = SQLITE_NOMEM; - } - if( sqlite3_value_type(apData[1])==SQLITE_INTEGER ){ - bindArgOne = 1; - zValues = sqlite3_mprintf("?"); - string_concat(&zInsert, "rowid", 0, &rc); - } - - assert((pVtab->nCol+2)==nData); - for(ii=2; ii<nData; ii++){ - string_concat(&zInsert, - sqlite3_mprintf("%s%Q", zValues?", ":"", pVtab->aCol[ii-2]), 1, &rc); - string_concat(&zValues, - sqlite3_mprintf("%s?%d", zValues?", ":"", ii), 1, &rc); - } - - string_concat(&z, zInsert, 1, &rc); - string_concat(&z, ") VALUES(", 0, &rc); - string_concat(&z, zValues, 1, &rc); - string_concat(&z, ")", 0, &rc); - } - - /* Anything else is an error */ - else{ - assert(0); - return SQLITE_ERROR; - } - - if( rc==SQLITE_OK ){ - rc = sqlite3_prepare(db, z, -1, &pStmt, 0); - } - assert( rc!=SQLITE_OK || pStmt ); - sqlite3_free(z); - if( rc==SQLITE_OK ) { - if( bindArgZero ){ - sqlite3_bind_value(pStmt, nData, apData[0]); - } - if( bindArgOne ){ - sqlite3_bind_value(pStmt, 1, apData[1]); - } - for(i=2; i<nData && rc==SQLITE_OK; i++){ - if( apData[i] ) rc = sqlite3_bind_value(pStmt, i, apData[i]); - } - if( rc==SQLITE_OK ){ - sqlite3_step(pStmt); - rc = sqlite3_finalize(pStmt); - }else{ - sqlite3_finalize(pStmt); - } - } - - if( pRowid && rc==SQLITE_OK ){ - *pRowid = sqlite3_last_insert_rowid(db); - } - if( rc!=SQLITE_OK ){ - tab->zErrMsg = sqlite3_mprintf("echo-vtab-error: %s", sqlite3_errmsg(db)); - } - - return rc; -} - -/* -** xBegin, xSync, xCommit and xRollback callbacks for echo module -** virtual tables. Do nothing other than add the name of the callback -** to the $::echo_module Tcl variable. -*/ -static int echoTransactionCall(sqlite3_vtab *tab, const char *zCall){ - char *z; - echo_vtab *pVtab = (echo_vtab *)tab; - z = sqlite3_mprintf("echo(%s)", pVtab->zTableName); - if( z==0 ) return SQLITE_NOMEM; - appendToEchoModule(pVtab->interp, zCall); - appendToEchoModule(pVtab->interp, z); - sqlite3_free(z); - return SQLITE_OK; -} -static int echoBegin(sqlite3_vtab *tab){ - int rc; - echo_vtab *pVtab = (echo_vtab *)tab; - Tcl_Interp *interp = pVtab->interp; - const char *zVal; - - /* Ticket #3083 - do not start a transaction if we are already in - ** a transaction */ - assert( !pVtab->inTransaction ); - - if( simulateVtabError(pVtab, "xBegin") ){ - return SQLITE_ERROR; - } - - rc = echoTransactionCall(tab, "xBegin"); - - if( rc==SQLITE_OK ){ - /* Check if the $::echo_module_begin_fail variable is defined. If it is, - ** and it is set to the name of the real table underlying this virtual - ** echo module table, then cause this xSync operation to fail. - */ - zVal = Tcl_GetVar(interp, "echo_module_begin_fail", TCL_GLOBAL_ONLY); - if( zVal && 0==strcmp(zVal, pVtab->zTableName) ){ - rc = SQLITE_ERROR; - } - } - if( rc==SQLITE_OK ){ - pVtab->inTransaction = 1; - } - return rc; -} -static int echoSync(sqlite3_vtab *tab){ - int rc; - echo_vtab *pVtab = (echo_vtab *)tab; - Tcl_Interp *interp = pVtab->interp; - const char *zVal; - - /* Ticket #3083 - Only call xSync if we have previously started a - ** transaction */ - assert( pVtab->inTransaction ); - - if( simulateVtabError(pVtab, "xSync") ){ - return SQLITE_ERROR; - } - - rc = echoTransactionCall(tab, "xSync"); - - if( rc==SQLITE_OK ){ - /* Check if the $::echo_module_sync_fail variable is defined. If it is, - ** and it is set to the name of the real table underlying this virtual - ** echo module table, then cause this xSync operation to fail. - */ - zVal = Tcl_GetVar(interp, "echo_module_sync_fail", TCL_GLOBAL_ONLY); - if( zVal && 0==strcmp(zVal, pVtab->zTableName) ){ - rc = -1; - } - } - return rc; -} -static int echoCommit(sqlite3_vtab *tab){ - echo_vtab *pVtab = (echo_vtab*)tab; - int rc; - - /* Ticket #3083 - Only call xCommit if we have previously started - ** a transaction */ - assert( pVtab->inTransaction ); - - if( simulateVtabError(pVtab, "xCommit") ){ - return SQLITE_ERROR; - } - - sqlite3BeginBenignMalloc(); - rc = echoTransactionCall(tab, "xCommit"); - sqlite3EndBenignMalloc(); - pVtab->inTransaction = 0; - return rc; -} -static int echoRollback(sqlite3_vtab *tab){ - int rc; - echo_vtab *pVtab = (echo_vtab*)tab; - - /* Ticket #3083 - Only call xRollback if we have previously started - ** a transaction */ - assert( pVtab->inTransaction ); - - rc = echoTransactionCall(tab, "xRollback"); - pVtab->inTransaction = 0; - return rc; -} - -/* -** Implementation of "GLOB" function on the echo module. Pass -** all arguments to the ::echo_glob_overload procedure of TCL -** and return the result of that procedure as a string. -*/ -static void overloadedGlobFunction( - sqlite3_context *pContext, - int nArg, - sqlite3_value **apArg -){ - Tcl_Interp *interp = sqlite3_user_data(pContext); - Tcl_DString str; - int i; - int rc; - Tcl_DStringInit(&str); - Tcl_DStringAppendElement(&str, "::echo_glob_overload"); - for(i=0; i<nArg; i++){ - Tcl_DStringAppendElement(&str, (char*)sqlite3_value_text(apArg[i])); - } - rc = Tcl_Eval(interp, Tcl_DStringValue(&str)); - Tcl_DStringFree(&str); - if( rc ){ - sqlite3_result_error(pContext, Tcl_GetStringResult(interp), -1); - }else{ - sqlite3_result_text(pContext, Tcl_GetStringResult(interp), - -1, SQLITE_TRANSIENT); - } - Tcl_ResetResult(interp); -} - -/* -** This is the xFindFunction implementation for the echo module. -** SQLite calls this routine when the first argument of a function -** is a column of an echo virtual table. This routine can optionally -** override the implementation of that function. It will choose to -** do so if the function is named "glob", and a TCL command named -** ::echo_glob_overload exists. -*/ -static int echoFindFunction( - sqlite3_vtab *vtab, - int nArg, - const char *zFuncName, - void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), - void **ppArg -){ - echo_vtab *pVtab = (echo_vtab *)vtab; - Tcl_Interp *interp = pVtab->interp; - Tcl_CmdInfo info; - if( strcmp(zFuncName,"glob")!=0 ){ - return 0; - } - if( Tcl_GetCommandInfo(interp, "::echo_glob_overload", &info)==0 ){ - return 0; - } - *pxFunc = overloadedGlobFunction; - *ppArg = interp; - return 1; -} - -static int echoRename(sqlite3_vtab *vtab, const char *zNewName){ - int rc = SQLITE_OK; - echo_vtab *p = (echo_vtab *)vtab; - - if( simulateVtabError(p, "xRename") ){ - return SQLITE_ERROR; - } - - if( p->isPattern ){ - int nThis = (int)strlen(p->zThis); - char *zSql = sqlite3_mprintf("ALTER TABLE %s RENAME TO %s%s", - p->zTableName, zNewName, &p->zTableName[nThis] - ); - rc = sqlite3_exec(p->db, zSql, 0, 0, 0); - sqlite3_free(zSql); - } - - return rc; -} - -static int echoSavepoint(sqlite3_vtab *pVTab, int iSavepoint){ - assert( pVTab ); - return SQLITE_OK; -} - -static int echoRelease(sqlite3_vtab *pVTab, int iSavepoint){ - assert( pVTab ); - return SQLITE_OK; -} - -static int echoRollbackTo(sqlite3_vtab *pVTab, int iSavepoint){ - assert( pVTab ); - return SQLITE_OK; -} - -/* -** A virtual table module that merely "echos" the contents of another -** table (like an SQL VIEW). -*/ -static sqlite3_module echoModule = { - 1, /* iVersion */ - echoCreate, - echoConnect, - echoBestIndex, - echoDisconnect, - echoDestroy, - echoOpen, /* xOpen - open a cursor */ - echoClose, /* xClose - close a cursor */ - echoFilter, /* xFilter - configure scan constraints */ - echoNext, /* xNext - advance a cursor */ - echoEof, /* xEof */ - echoColumn, /* xColumn - read data */ - echoRowid, /* xRowid - read data */ - echoUpdate, /* xUpdate - write data */ - echoBegin, /* xBegin - begin transaction */ - echoSync, /* xSync - sync transaction */ - echoCommit, /* xCommit - commit transaction */ - echoRollback, /* xRollback - rollback transaction */ - echoFindFunction, /* xFindFunction - function overloading */ - echoRename /* xRename - rename the table */ -}; - -static sqlite3_module echoModuleV2 = { - 2, /* iVersion */ - echoCreate, - echoConnect, - echoBestIndex, - echoDisconnect, - echoDestroy, - echoOpen, /* xOpen - open a cursor */ - echoClose, /* xClose - close a cursor */ - echoFilter, /* xFilter - configure scan constraints */ - echoNext, /* xNext - advance a cursor */ - echoEof, /* xEof */ - echoColumn, /* xColumn - read data */ - echoRowid, /* xRowid - read data */ - echoUpdate, /* xUpdate - write data */ - echoBegin, /* xBegin - begin transaction */ - echoSync, /* xSync - sync transaction */ - echoCommit, /* xCommit - commit transaction */ - echoRollback, /* xRollback - rollback transaction */ - echoFindFunction, /* xFindFunction - function overloading */ - echoRename, /* xRename - rename the table */ - echoSavepoint, - echoRelease, - echoRollbackTo -}; - -/* -** Decode a pointer to an sqlite3 object. -*/ -extern int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb); -extern const char *sqlite3ErrName(int); - -static void moduleDestroy(void *p){ - sqlite3_free(p); -} - -/* -** Register the echo virtual table module. -*/ -static int register_echo_module( - 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; - sqlite3 *db; - EchoModule *pMod; - if( objc!=2 ){ - Tcl_WrongNumArgs(interp, 1, objv, "DB"); - return TCL_ERROR; - } - if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; - - /* Virtual table module "echo" */ - pMod = sqlite3_malloc(sizeof(EchoModule)); - pMod->interp = interp; - rc = sqlite3_create_module_v2( - db, "echo", &echoModule, (void*)pMod, moduleDestroy - ); - - /* Virtual table module "echo_v2" */ - if( rc==SQLITE_OK ){ - pMod = sqlite3_malloc(sizeof(EchoModule)); - pMod->interp = interp; - rc = sqlite3_create_module_v2(db, "echo_v2", - &echoModuleV2, (void*)pMod, moduleDestroy - ); - } - - Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_STATIC); - return TCL_OK; -} - -/* -** Tcl interface to sqlite3_declare_vtab, invoked as follows from Tcl: -** -** sqlite3_declare_vtab DB SQL -*/ -static int declare_vtab( - 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; - if( objc!=3 ){ - Tcl_WrongNumArgs(interp, 1, objv, "DB SQL"); - return TCL_ERROR; - } - if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; - rc = sqlite3_declare_vtab(db, Tcl_GetString(objv[2])); - if( rc!=SQLITE_OK ){ - Tcl_SetResult(interp, (char *)sqlite3_errmsg(db), TCL_VOLATILE); - return TCL_ERROR; - } - return TCL_OK; -} - -#endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */ - -/* -** Register commands with the TCL interpreter. -*/ -int Sqlitetest8_Init(Tcl_Interp *interp){ -#ifndef SQLITE_OMIT_VIRTUALTABLE - static struct { - char *zName; - Tcl_ObjCmdProc *xProc; - void *clientData; - } aObjCmd[] = { - { "register_echo_module", register_echo_module, 0 }, - { "sqlite3_declare_vtab", declare_vtab, 0 }, - }; - int i; - for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){ - Tcl_CreateObjCommand(interp, aObjCmd[i].zName, - aObjCmd[i].xProc, aObjCmd[i].clientData, 0); - } -#endif - return TCL_OK; -} diff --git a/components/external/SQLite-3.8.1/SQLiteLib/test/test9.c b/components/external/SQLite-3.8.1/SQLiteLib/test/test9.c deleted file mode 100644 index e5993e8ff7..0000000000 --- a/components/external/SQLite-3.8.1/SQLiteLib/test/test9.c +++ /dev/null @@ -1,200 +0,0 @@ -/* -** 2007 March 29 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** -** This file contains obscure tests of the C-interface required -** for completeness. Test code is written in C for these cases -** as there is not much point in binding to Tcl. -*/ -#include "sqliteInt.h" -#include "tcl.h" -#include <stdlib.h> -#include <string.h> - -/* -** c_collation_test -*/ -static int c_collation_test( - 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 */ -){ - const char *zErrFunction = "N/A"; - sqlite3 *db; - - int rc; - if( objc!=1 ){ - Tcl_WrongNumArgs(interp, 1, objv, ""); - return TCL_ERROR; - } - - /* Open a database. */ - rc = sqlite3_open(":memory:", &db); - if( rc!=SQLITE_OK ){ - zErrFunction = "sqlite3_open"; - goto error_out; - } - - rc = sqlite3_create_collation(db, "collate", 456, 0, 0); - if( rc!=SQLITE_MISUSE ){ - sqlite3_close(db); - zErrFunction = "sqlite3_create_collation"; - goto error_out; - } - - sqlite3_close(db); - return TCL_OK; - -error_out: - Tcl_ResetResult(interp); - Tcl_AppendResult(interp, "Error testing function: ", zErrFunction, 0); - return TCL_ERROR; -} - -/* -** c_realloc_test -*/ -static int c_realloc_test( - 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 */ -){ - void *p; - const char *zErrFunction = "N/A"; - - if( objc!=1 ){ - Tcl_WrongNumArgs(interp, 1, objv, ""); - return TCL_ERROR; - } - - p = sqlite3_malloc(5); - if( !p ){ - zErrFunction = "sqlite3_malloc"; - goto error_out; - } - - /* Test that realloc()ing a block of memory to a negative size is - ** the same as free()ing that memory. - */ - p = sqlite3_realloc(p, -1); - if( p ){ - zErrFunction = "sqlite3_realloc"; - goto error_out; - } - - return TCL_OK; - -error_out: - Tcl_ResetResult(interp); - Tcl_AppendResult(interp, "Error testing function: ", zErrFunction, 0); - return TCL_ERROR; -} - - -/* -** c_misuse_test -*/ -static int c_misuse_test( - 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 */ -){ - const char *zErrFunction = "N/A"; - sqlite3 *db = 0; - sqlite3_stmt *pStmt; - int rc; - - if( objc!=1 ){ - Tcl_WrongNumArgs(interp, 1, objv, ""); - return TCL_ERROR; - } - - /* Open a database. Then close it again. We need to do this so that - ** we have a "closed database handle" to pass to various API functions. - */ - rc = sqlite3_open(":memory:", &db); - if( rc!=SQLITE_OK ){ - zErrFunction = "sqlite3_open"; - goto error_out; - } - sqlite3_close(db); - - - rc = sqlite3_errcode(db); - if( rc!=SQLITE_MISUSE ){ - zErrFunction = "sqlite3_errcode"; - goto error_out; - } - - pStmt = (sqlite3_stmt*)1234; - rc = sqlite3_prepare(db, 0, 0, &pStmt, 0); - if( rc!=SQLITE_MISUSE ){ - zErrFunction = "sqlite3_prepare"; - goto error_out; - } - assert( pStmt==0 ); /* Verify that pStmt is zeroed even on a MISUSE error */ - - pStmt = (sqlite3_stmt*)1234; - rc = sqlite3_prepare_v2(db, 0, 0, &pStmt, 0); - if( rc!=SQLITE_MISUSE ){ - zErrFunction = "sqlite3_prepare_v2"; - goto error_out; - } - assert( pStmt==0 ); - -#ifndef SQLITE_OMIT_UTF16 - pStmt = (sqlite3_stmt*)1234; - rc = sqlite3_prepare16(db, 0, 0, &pStmt, 0); - if( rc!=SQLITE_MISUSE ){ - zErrFunction = "sqlite3_prepare16"; - goto error_out; - } - assert( pStmt==0 ); - pStmt = (sqlite3_stmt*)1234; - rc = sqlite3_prepare16_v2(db, 0, 0, &pStmt, 0); - if( rc!=SQLITE_MISUSE ){ - zErrFunction = "sqlite3_prepare16_v2"; - goto error_out; - } - assert( pStmt==0 ); -#endif - - return TCL_OK; - -error_out: - Tcl_ResetResult(interp); - Tcl_AppendResult(interp, "Error testing function: ", zErrFunction, 0); - return TCL_ERROR; -} - -/* -** Register commands with the TCL interpreter. -*/ -int Sqlitetest9_Init(Tcl_Interp *interp){ - static struct { - char *zName; - Tcl_ObjCmdProc *xProc; - void *clientData; - } aObjCmd[] = { - { "c_misuse_test", c_misuse_test, 0 }, - { "c_realloc_test", c_realloc_test, 0 }, - { "c_collation_test", c_collation_test, 0 }, - }; - int i; - for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){ - Tcl_CreateObjCommand(interp, aObjCmd[i].zName, - aObjCmd[i].xProc, aObjCmd[i].clientData, 0); - } - return TCL_OK; -} diff --git a/components/external/SQLite-3.8.1/SQLiteLib/test/test_async.c b/components/external/SQLite-3.8.1/SQLiteLib/test/test_async.c deleted file mode 100644 index b0b943185b..0000000000 --- a/components/external/SQLite-3.8.1/SQLiteLib/test/test_async.c +++ /dev/null @@ -1,241 +0,0 @@ -/* -** 2005 December 14 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** -** This file contains a binding of the asynchronous IO extension interface -** (defined in ext/async/sqlite3async.h) to Tcl. -*/ - -#define TCL_THREADS -#include <tcl.h> - -#ifdef SQLITE_ENABLE_ASYNCIO - -#include "sqlite3async.h" -#include "sqlite3.h" -#include <assert.h> - -/* From main.c */ -extern const char *sqlite3ErrName(int); - - -struct TestAsyncGlobal { - int isInstalled; /* True when async VFS is installed */ -} testasync_g = { 0 }; - -TCL_DECLARE_MUTEX(testasync_g_writerMutex); - -/* -** sqlite3async_initialize PARENT-VFS ISDEFAULT -*/ -static int testAsyncInit( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - const char *zParent; - int isDefault; - int rc; - - if( objc!=3 ){ - Tcl_WrongNumArgs(interp, 1, objv, "PARENT-VFS ISDEFAULT"); - return TCL_ERROR; - } - zParent = Tcl_GetString(objv[1]); - if( !*zParent ) { - zParent = 0; - } - if( Tcl_GetBooleanFromObj(interp, objv[2], &isDefault) ){ - return TCL_ERROR; - } - - rc = sqlite3async_initialize(zParent, isDefault); - if( rc!=SQLITE_OK ){ - Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1)); - return TCL_ERROR; - } - return TCL_OK; -} - -/* -** sqlite3async_shutdown -*/ -static int testAsyncShutdown( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - sqlite3async_shutdown(); - return TCL_OK; -} - -static Tcl_ThreadCreateType tclWriterThread(ClientData pIsStarted){ - Tcl_MutexLock(&testasync_g_writerMutex); - *((int *)pIsStarted) = 1; - sqlite3async_run(); - Tcl_MutexUnlock(&testasync_g_writerMutex); - Tcl_ExitThread(0); - TCL_THREAD_CREATE_RETURN; -} - -/* -** sqlite3async_start -** -** Start a new writer thread. -*/ -static int testAsyncStart( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - volatile int isStarted = 0; - ClientData threadData = (ClientData)&isStarted; - - Tcl_ThreadId x; - const int nStack = TCL_THREAD_STACK_DEFAULT; - const int flags = TCL_THREAD_NOFLAGS; - int rc; - - rc = Tcl_CreateThread(&x, tclWriterThread, threadData, nStack, flags); - if( rc!=TCL_OK ){ - Tcl_AppendResult(interp, "Tcl_CreateThread() failed", 0); - return TCL_ERROR; - } - - while( isStarted==0 ) { /* Busy loop */ } - return TCL_OK; -} - -/* -** sqlite3async_wait -** -** Wait for the current writer thread to terminate. -** -** If the current writer thread is set to run forever then this -** command would block forever. To prevent that, an error is returned. -*/ -static int testAsyncWait( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - int eCond; - if( objc!=1 ){ - Tcl_WrongNumArgs(interp, 1, objv, ""); - return TCL_ERROR; - } - - sqlite3async_control(SQLITEASYNC_GET_HALT, &eCond); - if( eCond==SQLITEASYNC_HALT_NEVER ){ - Tcl_AppendResult(interp, "would block forever", (char*)0); - return TCL_ERROR; - } - - Tcl_MutexLock(&testasync_g_writerMutex); - Tcl_MutexUnlock(&testasync_g_writerMutex); - return TCL_OK; -} - -/* -** sqlite3async_control OPTION ?VALUE? -*/ -static int testAsyncControl( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - int rc = SQLITE_OK; - int aeOpt[] = { SQLITEASYNC_HALT, SQLITEASYNC_DELAY, SQLITEASYNC_LOCKFILES }; - const char *azOpt[] = { "halt", "delay", "lockfiles", 0 }; - const char *az[] = { "never", "now", "idle", 0 }; - int iVal; - int eOpt; - - if( objc!=2 && objc!=3 ){ - Tcl_WrongNumArgs(interp, 1, objv, "OPTION ?VALUE?"); - return TCL_ERROR; - } - if( Tcl_GetIndexFromObj(interp, objv[1], azOpt, "option", 0, &eOpt) ){ - return TCL_ERROR; - } - eOpt = aeOpt[eOpt]; - - if( objc==3 ){ - switch( eOpt ){ - case SQLITEASYNC_HALT: { - assert( SQLITEASYNC_HALT_NEVER==0 ); - assert( SQLITEASYNC_HALT_NOW==1 ); - assert( SQLITEASYNC_HALT_IDLE==2 ); - if( Tcl_GetIndexFromObj(interp, objv[2], az, "value", 0, &iVal) ){ - return TCL_ERROR; - } - break; - } - case SQLITEASYNC_DELAY: - if( Tcl_GetIntFromObj(interp, objv[2], &iVal) ){ - return TCL_ERROR; - } - break; - - case SQLITEASYNC_LOCKFILES: - if( Tcl_GetBooleanFromObj(interp, objv[2], &iVal) ){ - return TCL_ERROR; - } - break; - } - - rc = sqlite3async_control(eOpt, iVal); - } - - if( rc==SQLITE_OK ){ - rc = sqlite3async_control( - eOpt==SQLITEASYNC_HALT ? SQLITEASYNC_GET_HALT : - eOpt==SQLITEASYNC_DELAY ? SQLITEASYNC_GET_DELAY : - SQLITEASYNC_GET_LOCKFILES, &iVal); - } - - if( rc!=SQLITE_OK ){ - Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1)); - return TCL_ERROR; - } - - if( eOpt==SQLITEASYNC_HALT ){ - Tcl_SetObjResult(interp, Tcl_NewStringObj(az[iVal], -1)); - }else{ - Tcl_SetObjResult(interp, Tcl_NewIntObj(iVal)); - } - - return TCL_OK; -} - -#endif /* SQLITE_ENABLE_ASYNCIO */ - -/* -** This routine registers the custom TCL commands defined in this -** module. This should be the only procedure visible from outside -** of this module. -*/ -int Sqlitetestasync_Init(Tcl_Interp *interp){ -#ifdef SQLITE_ENABLE_ASYNCIO - Tcl_CreateObjCommand(interp,"sqlite3async_start",testAsyncStart,0,0); - Tcl_CreateObjCommand(interp,"sqlite3async_wait",testAsyncWait,0,0); - - Tcl_CreateObjCommand(interp,"sqlite3async_control",testAsyncControl,0,0); - Tcl_CreateObjCommand(interp,"sqlite3async_initialize",testAsyncInit,0,0); - Tcl_CreateObjCommand(interp,"sqlite3async_shutdown",testAsyncShutdown,0,0); -#endif /* SQLITE_ENABLE_ASYNCIO */ - return TCL_OK; -} diff --git a/components/external/SQLite-3.8.1/SQLiteLib/test/test_autoext.c b/components/external/SQLite-3.8.1/SQLiteLib/test/test_autoext.c deleted file mode 100644 index a5236d2390..0000000000 --- a/components/external/SQLite-3.8.1/SQLiteLib/test/test_autoext.c +++ /dev/null @@ -1,221 +0,0 @@ -/* -** 2006 August 23 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** Test extension for testing the sqlite3_auto_extension() function. -*/ -#include "tcl.h" -#include "sqlite3ext.h" - -#ifndef SQLITE_OMIT_LOAD_EXTENSION -SQLITE_EXTENSION_INIT1 - -/* -** The sqr() SQL function returns the square of its input value. -*/ -static void sqrFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - double r = sqlite3_value_double(argv[0]); - sqlite3_result_double(context, r*r); -} - -/* -** This is the entry point to register the extension for the sqr() function. -*/ -static int sqr_init( - sqlite3 *db, - char **pzErrMsg, - const sqlite3_api_routines *pApi -){ - SQLITE_EXTENSION_INIT2(pApi); - sqlite3_create_function(db, "sqr", 1, SQLITE_ANY, 0, sqrFunc, 0, 0); - return 0; -} - -/* -** The cube() SQL function returns the cube of its input value. -*/ -static void cubeFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - double r = sqlite3_value_double(argv[0]); - sqlite3_result_double(context, r*r*r); -} - -/* -** This is the entry point to register the extension for the cube() function. -*/ -static int cube_init( - sqlite3 *db, - char **pzErrMsg, - const sqlite3_api_routines *pApi -){ - SQLITE_EXTENSION_INIT2(pApi); - sqlite3_create_function(db, "cube", 1, SQLITE_ANY, 0, cubeFunc, 0, 0); - return 0; -} - -/* -** This is a broken extension entry point -*/ -static int broken_init( - sqlite3 *db, - char **pzErrMsg, - const sqlite3_api_routines *pApi -){ - char *zErr; - SQLITE_EXTENSION_INIT2(pApi); - zErr = sqlite3_mprintf("broken autoext!"); - *pzErrMsg = zErr; - return 1; -} - -/* -** tclcmd: sqlite3_auto_extension_sqr -** -** Register the "sqr" extension to be loaded automatically. -*/ -static int autoExtSqrObjCmd( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - int rc = sqlite3_auto_extension((void*)sqr_init); - Tcl_SetObjResult(interp, Tcl_NewIntObj(rc)); - return SQLITE_OK; -} - -/* -** tclcmd: sqlite3_cancel_auto_extension_sqr -** -** Unregister the "sqr" extension. -*/ -static int cancelAutoExtSqrObjCmd( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - int rc = sqlite3_cancel_auto_extension((void*)sqr_init); - Tcl_SetObjResult(interp, Tcl_NewIntObj(rc)); - return SQLITE_OK; -} - -/* -** tclcmd: sqlite3_auto_extension_cube -** -** Register the "cube" extension to be loaded automatically. -*/ -static int autoExtCubeObjCmd( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - int rc = sqlite3_auto_extension((void*)cube_init); - Tcl_SetObjResult(interp, Tcl_NewIntObj(rc)); - return SQLITE_OK; -} - -/* -** tclcmd: sqlite3_cancel_auto_extension_cube -** -** Unregister the "cube" extension. -*/ -static int cancelAutoExtCubeObjCmd( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - int rc = sqlite3_cancel_auto_extension((void*)cube_init); - Tcl_SetObjResult(interp, Tcl_NewIntObj(rc)); - return SQLITE_OK; -} - -/* -** tclcmd: sqlite3_auto_extension_broken -** -** Register the broken extension to be loaded automatically. -*/ -static int autoExtBrokenObjCmd( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - int rc = sqlite3_auto_extension((void*)broken_init); - Tcl_SetObjResult(interp, Tcl_NewIntObj(rc)); - return SQLITE_OK; -} - -/* -** tclcmd: sqlite3_cancel_auto_extension_broken -** -** Unregister the broken extension. -*/ -static int cancelAutoExtBrokenObjCmd( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - int rc = sqlite3_cancel_auto_extension((void*)broken_init); - Tcl_SetObjResult(interp, Tcl_NewIntObj(rc)); - return SQLITE_OK; -} - -#endif /* SQLITE_OMIT_LOAD_EXTENSION */ - - -/* -** tclcmd: sqlite3_reset_auto_extension -** -** Reset all auto-extensions -*/ -static int resetAutoExtObjCmd( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - sqlite3_reset_auto_extension(); - return SQLITE_OK; -} - - -/* -** This procedure registers the TCL procs defined in this file. -*/ -int Sqlitetest_autoext_Init(Tcl_Interp *interp){ -#ifndef SQLITE_OMIT_LOAD_EXTENSION - Tcl_CreateObjCommand(interp, "sqlite3_auto_extension_sqr", - autoExtSqrObjCmd, 0, 0); - Tcl_CreateObjCommand(interp, "sqlite3_auto_extension_cube", - autoExtCubeObjCmd, 0, 0); - Tcl_CreateObjCommand(interp, "sqlite3_auto_extension_broken", - autoExtBrokenObjCmd, 0, 0); - Tcl_CreateObjCommand(interp, "sqlite3_cancel_auto_extension_sqr", - cancelAutoExtSqrObjCmd, 0, 0); - Tcl_CreateObjCommand(interp, "sqlite3_cancel_auto_extension_cube", - cancelAutoExtCubeObjCmd, 0, 0); - Tcl_CreateObjCommand(interp, "sqlite3_cancel_auto_extension_broken", - cancelAutoExtBrokenObjCmd, 0, 0); -#endif - Tcl_CreateObjCommand(interp, "sqlite3_reset_auto_extension", - resetAutoExtObjCmd, 0, 0); - return TCL_OK; -} diff --git a/components/external/SQLite-3.8.1/SQLiteLib/test/test_backup.c b/components/external/SQLite-3.8.1/SQLiteLib/test/test_backup.c deleted file mode 100644 index e967424a29..0000000000 --- a/components/external/SQLite-3.8.1/SQLiteLib/test/test_backup.c +++ /dev/null @@ -1,150 +0,0 @@ -/* -** 2009 January 28 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This file contains test logic for the sqlite3_backup() interface. -** -*/ - -#include "tcl.h" -#include <sqlite3.h> -#include <assert.h> - -/* These functions are implemented in main.c. */ -extern const char *sqlite3ErrName(int); - -/* These functions are implemented in test1.c. */ -extern int getDbPointer(Tcl_Interp *, const char *, sqlite3 **); - -static int backupTestCmd( - ClientData clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *const*objv -){ - enum BackupSubCommandEnum { - BACKUP_STEP, BACKUP_FINISH, BACKUP_REMAINING, BACKUP_PAGECOUNT - }; - struct BackupSubCommand { - const char *zCmd; - enum BackupSubCommandEnum eCmd; - int nArg; - const char *zArg; - } aSub[] = { - {"step", BACKUP_STEP , 1, "npage" }, - {"finish", BACKUP_FINISH , 0, "" }, - {"remaining", BACKUP_REMAINING , 0, "" }, - {"pagecount", BACKUP_PAGECOUNT , 0, "" }, - {0, 0, 0, 0} - }; - - sqlite3_backup *p = (sqlite3_backup *)clientData; - int iCmd; - int rc; - - rc = Tcl_GetIndexFromObjStruct( - interp, objv[1], aSub, sizeof(aSub[0]), "option", 0, &iCmd - ); - if( rc!=TCL_OK ){ - return rc; - } - if( objc!=(2 + aSub[iCmd].nArg) ){ - Tcl_WrongNumArgs(interp, 2, objv, aSub[iCmd].zArg); - return TCL_ERROR; - } - - switch( aSub[iCmd].eCmd ){ - - case BACKUP_FINISH: { - const char *zCmdName; - Tcl_CmdInfo cmdInfo; - zCmdName = Tcl_GetString(objv[0]); - Tcl_GetCommandInfo(interp, zCmdName, &cmdInfo); - cmdInfo.deleteProc = 0; - Tcl_SetCommandInfo(interp, zCmdName, &cmdInfo); - Tcl_DeleteCommand(interp, zCmdName); - - rc = sqlite3_backup_finish(p); - Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_STATIC); - break; - } - - case BACKUP_STEP: { - int nPage; - if( TCL_OK!=Tcl_GetIntFromObj(interp, objv[2], &nPage) ){ - return TCL_ERROR; - } - rc = sqlite3_backup_step(p, nPage); - Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_STATIC); - break; - } - - case BACKUP_REMAINING: - Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_backup_remaining(p))); - break; - - case BACKUP_PAGECOUNT: - Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_backup_pagecount(p))); - break; - } - - return TCL_OK; -} - -static void backupTestFinish(ClientData clientData){ - sqlite3_backup *pBackup = (sqlite3_backup *)clientData; - sqlite3_backup_finish(pBackup); -} - -/* -** sqlite3_backup CMDNAME DESTHANDLE DESTNAME SRCHANDLE SRCNAME -** -*/ -static int backupTestInit( - ClientData clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *const*objv -){ - sqlite3_backup *pBackup; - sqlite3 *pDestDb; - sqlite3 *pSrcDb; - const char *zDestName; - const char *zSrcName; - const char *zCmd; - - if( objc!=6 ){ - Tcl_WrongNumArgs( - interp, 1, objv, "CMDNAME DESTHANDLE DESTNAME SRCHANDLE SRCNAME" - ); - return TCL_ERROR; - } - - zCmd = Tcl_GetString(objv[1]); - getDbPointer(interp, Tcl_GetString(objv[2]), &pDestDb); - zDestName = Tcl_GetString(objv[3]); - getDbPointer(interp, Tcl_GetString(objv[4]), &pSrcDb); - zSrcName = Tcl_GetString(objv[5]); - - pBackup = sqlite3_backup_init(pDestDb, zDestName, pSrcDb, zSrcName); - if( !pBackup ){ - Tcl_AppendResult(interp, "sqlite3_backup_init() failed", 0); - return TCL_ERROR; - } - - Tcl_CreateObjCommand(interp, zCmd, backupTestCmd, pBackup, backupTestFinish); - Tcl_SetObjResult(interp, objv[1]); - return TCL_OK; -} - -int Sqlitetestbackup_Init(Tcl_Interp *interp){ - Tcl_CreateObjCommand(interp, "sqlite3_backup", backupTestInit, 0, 0); - return TCL_OK; -} diff --git a/components/external/SQLite-3.8.1/SQLiteLib/test/test_btree.c b/components/external/SQLite-3.8.1/SQLiteLib/test/test_btree.c deleted file mode 100644 index db72889b2a..0000000000 --- a/components/external/SQLite-3.8.1/SQLiteLib/test/test_btree.c +++ /dev/null @@ -1,62 +0,0 @@ -/* -** 2007 May 05 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** Code for testing the btree.c module in SQLite. This code -** is not included in the SQLite library. It is used for automated -** testing of the SQLite library. -*/ -#include "btreeInt.h" -#include <tcl.h> - -/* -** Usage: sqlite3_shared_cache_report -** -** Return a list of file that are shared and the number of -** references to each file. -*/ -int sqlite3BtreeSharedCacheReport( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ -#ifndef SQLITE_OMIT_SHARED_CACHE - extern BtShared *sqlite3SharedCacheList; - BtShared *pBt; - Tcl_Obj *pRet = Tcl_NewObj(); - for(pBt=GLOBAL(BtShared*,sqlite3SharedCacheList); pBt; pBt=pBt->pNext){ - const char *zFile = sqlite3PagerFilename(pBt->pPager, 1); - Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj(zFile, -1)); - Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(pBt->nRef)); - } - Tcl_SetObjResult(interp, pRet); -#endif - return TCL_OK; -} - -/* -** Print debugging information about all cursors to standard output. -*/ -void sqlite3BtreeCursorList(Btree *p){ -#ifdef SQLITE_DEBUG - BtCursor *pCur; - BtShared *pBt = p->pBt; - for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){ - MemPage *pPage = pCur->apPage[pCur->iPage]; - char *zMode = pCur->wrFlag ? "rw" : "ro"; - sqlite3DebugPrintf("CURSOR %p rooted at %4d(%s) currently at %d.%d%s\n", - pCur, pCur->pgnoRoot, zMode, - pPage ? pPage->pgno : 0, pCur->aiIdx[pCur->iPage], - (pCur->eState==CURSOR_VALID) ? "" : " eof" - ); - } -#endif -} diff --git a/components/external/SQLite-3.8.1/SQLiteLib/test/test_config.c b/components/external/SQLite-3.8.1/SQLiteLib/test/test_config.c deleted file mode 100644 index de1822e3b1..0000000000 --- a/components/external/SQLite-3.8.1/SQLiteLib/test/test_config.c +++ /dev/null @@ -1,656 +0,0 @@ -/* -** 2007 May 7 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** -** This file contains code used for testing the SQLite system. -** None of the code in this file goes into a deliverable build. -** -** The focus of this file is providing the TCL testing layer -** access to compile-time constants. -*/ - -#include "sqliteLimit.h" - -#include "sqliteInt.h" -#include "tcl.h" -#include <stdlib.h> -#include <string.h> - -/* -** Macro to stringify the results of the evaluation a pre-processor -** macro. i.e. so that STRINGVALUE(SQLITE_NOMEM) -> "7". -*/ -#define STRINGVALUE2(x) #x -#define STRINGVALUE(x) STRINGVALUE2(x) - -/* -** 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. -*/ -static void set_options(Tcl_Interp *interp){ -#ifdef HAVE_MALLOC_USABLE_SIZE - Tcl_SetVar2(interp, "sqlite_options", "malloc_usable_size", "1", - TCL_GLOBAL_ONLY); -#else - Tcl_SetVar2(interp, "sqlite_options", "malloc_usable_size", "0", - TCL_GLOBAL_ONLY); -#endif - -#ifdef SQLITE_32BIT_ROWID - Tcl_SetVar2(interp, "sqlite_options", "rowid32", "1", TCL_GLOBAL_ONLY); -#else - Tcl_SetVar2(interp, "sqlite_options", "rowid32", "0", TCL_GLOBAL_ONLY); -#endif - -#ifdef SQLITE_CASE_SENSITIVE_LIKE - Tcl_SetVar2(interp, "sqlite_options","casesensitivelike","1",TCL_GLOBAL_ONLY); -#else - Tcl_SetVar2(interp, "sqlite_options","casesensitivelike","0",TCL_GLOBAL_ONLY); -#endif - -#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT - Tcl_SetVar2(interp, "sqlite_options", "curdir", "1", TCL_GLOBAL_ONLY); -#else - Tcl_SetVar2(interp, "sqlite_options", "curdir", "0", TCL_GLOBAL_ONLY); -#endif - -#ifdef SQLITE_DEBUG - Tcl_SetVar2(interp, "sqlite_options", "debug", "1", TCL_GLOBAL_ONLY); -#else - Tcl_SetVar2(interp, "sqlite_options", "debug", "0", TCL_GLOBAL_ONLY); -#endif - -#ifdef SQLITE_DIRECT_OVERFLOW_READ - Tcl_SetVar2(interp, "sqlite_options", "direct_read", "1", TCL_GLOBAL_ONLY); -#else - Tcl_SetVar2(interp, "sqlite_options", "direct_read", "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 - -#if SQLITE_MAX_MMAP_SIZE>0 - Tcl_SetVar2(interp, "sqlite_options", "mmap", "1", TCL_GLOBAL_ONLY); -#else - Tcl_SetVar2(interp, "sqlite_options", "mmap", "0", TCL_GLOBAL_ONLY); -#endif - -#if 1 /* def SQLITE_MEMDEBUG */ - Tcl_SetVar2(interp, "sqlite_options", "memdebug", "1", TCL_GLOBAL_ONLY); -#else - Tcl_SetVar2(interp, "sqlite_options", "memdebug", "0", TCL_GLOBAL_ONLY); -#endif - -#ifdef SQLITE_ENABLE_8_3_NAMES - Tcl_SetVar2(interp, "sqlite_options", "8_3_names", "1", TCL_GLOBAL_ONLY); -#else - Tcl_SetVar2(interp, "sqlite_options", "8_3_names", "0", TCL_GLOBAL_ONLY); -#endif - -#ifdef SQLITE_ENABLE_MEMSYS3 - Tcl_SetVar2(interp, "sqlite_options", "mem3", "1", TCL_GLOBAL_ONLY); -#else - Tcl_SetVar2(interp, "sqlite_options", "mem3", "0", TCL_GLOBAL_ONLY); -#endif - -#ifdef SQLITE_ENABLE_MEMSYS5 - Tcl_SetVar2(interp, "sqlite_options", "mem5", "1", TCL_GLOBAL_ONLY); -#else - Tcl_SetVar2(interp, "sqlite_options", "mem5", "0", TCL_GLOBAL_ONLY); -#endif - -#ifdef SQLITE_MUTEX_OMIT - Tcl_SetVar2(interp, "sqlite_options", "mutex", "0", TCL_GLOBAL_ONLY); -#else - Tcl_SetVar2(interp, "sqlite_options", "mutex", "1", TCL_GLOBAL_ONLY); -#endif - -#ifdef SQLITE_MUTEX_NOOP - Tcl_SetVar2(interp, "sqlite_options", "mutex_noop", "1", TCL_GLOBAL_ONLY); -#else - Tcl_SetVar2(interp, "sqlite_options", "mutex_noop", "0", TCL_GLOBAL_ONLY); -#endif - -#ifdef SQLITE_OMIT_ALTERTABLE - Tcl_SetVar2(interp, "sqlite_options", "altertable", "0", TCL_GLOBAL_ONLY); -#else - Tcl_SetVar2(interp, "sqlite_options", "altertable", "1", TCL_GLOBAL_ONLY); -#endif - -#ifdef SQLITE_OMIT_ANALYZE - Tcl_SetVar2(interp, "sqlite_options", "analyze", "0", TCL_GLOBAL_ONLY); -#else - Tcl_SetVar2(interp, "sqlite_options", "analyze", "1", TCL_GLOBAL_ONLY); -#endif - -#ifdef SQLITE_ENABLE_ATOMIC_WRITE - Tcl_SetVar2(interp, "sqlite_options", "atomicwrite", "1", TCL_GLOBAL_ONLY); -#else - Tcl_SetVar2(interp, "sqlite_options", "atomicwrite", "0", TCL_GLOBAL_ONLY); -#endif - -#ifdef SQLITE_OMIT_ATTACH - Tcl_SetVar2(interp, "sqlite_options", "attach", "0", TCL_GLOBAL_ONLY); -#else - Tcl_SetVar2(interp, "sqlite_options", "attach", "1", TCL_GLOBAL_ONLY); -#endif - -#ifdef SQLITE_OMIT_AUTHORIZATION - Tcl_SetVar2(interp, "sqlite_options", "auth", "0", TCL_GLOBAL_ONLY); -#else - Tcl_SetVar2(interp, "sqlite_options", "auth", "1", TCL_GLOBAL_ONLY); -#endif - -#ifdef SQLITE_OMIT_AUTOINCREMENT - Tcl_SetVar2(interp, "sqlite_options", "autoinc", "0", TCL_GLOBAL_ONLY); -#else - Tcl_SetVar2(interp, "sqlite_options", "autoinc", "1", TCL_GLOBAL_ONLY); -#endif - -#ifdef SQLITE_OMIT_AUTOMATIC_INDEX - Tcl_SetVar2(interp, "sqlite_options", "autoindex", "0", TCL_GLOBAL_ONLY); -#else - Tcl_SetVar2(interp, "sqlite_options", "autoindex", "1", TCL_GLOBAL_ONLY); -#endif - -#ifdef SQLITE_OMIT_AUTORESET - Tcl_SetVar2(interp, "sqlite_options", "autoreset", "0", TCL_GLOBAL_ONLY); -#else - Tcl_SetVar2(interp, "sqlite_options", "autoreset", "1", TCL_GLOBAL_ONLY); -#endif - -#ifdef SQLITE_OMIT_AUTOVACUUM - Tcl_SetVar2(interp, "sqlite_options", "autovacuum", "0", TCL_GLOBAL_ONLY); -#else - Tcl_SetVar2(interp, "sqlite_options", "autovacuum", "1", TCL_GLOBAL_ONLY); -#endif /* SQLITE_OMIT_AUTOVACUUM */ -#if !defined(SQLITE_DEFAULT_AUTOVACUUM) - Tcl_SetVar2(interp,"sqlite_options","default_autovacuum","0",TCL_GLOBAL_ONLY); -#else - Tcl_SetVar2(interp, "sqlite_options", "default_autovacuum", - STRINGVALUE(SQLITE_DEFAULT_AUTOVACUUM), TCL_GLOBAL_ONLY); -#endif - -#ifdef SQLITE_OMIT_BETWEEN_OPTIMIZATION - Tcl_SetVar2(interp, "sqlite_options", "between_opt", "0", TCL_GLOBAL_ONLY); -#else - Tcl_SetVar2(interp, "sqlite_options", "between_opt", "1", TCL_GLOBAL_ONLY); -#endif - -#ifdef SQLITE_OMIT_BUILTIN_TEST - Tcl_SetVar2(interp, "sqlite_options", "builtin_test", "0", TCL_GLOBAL_ONLY); -#else - Tcl_SetVar2(interp, "sqlite_options", "builtin_test", "1", TCL_GLOBAL_ONLY); -#endif - -#ifdef SQLITE_OMIT_BLOB_LITERAL - Tcl_SetVar2(interp, "sqlite_options", "bloblit", "0", TCL_GLOBAL_ONLY); -#else - Tcl_SetVar2(interp, "sqlite_options", "bloblit", "1", TCL_GLOBAL_ONLY); -#endif - -#ifdef SQLITE_OMIT_CAST - Tcl_SetVar2(interp, "sqlite_options", "cast", "0", TCL_GLOBAL_ONLY); -#else - 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_ENABLE_OVERSIZE_CELL_CHECK - Tcl_SetVar2(interp, "sqlite_options", "oversize_cell_check", "1", - TCL_GLOBAL_ONLY); -#else - Tcl_SetVar2(interp, "sqlite_options", "oversize_cell_check", "0", - TCL_GLOBAL_ONLY); -#endif - -#ifdef SQLITE_OMIT_COMPILEOPTION_DIAGS - Tcl_SetVar2(interp, "sqlite_options", "compileoption_diags", "0", TCL_GLOBAL_ONLY); -#else - Tcl_SetVar2(interp, "sqlite_options", "compileoption_diags", "1", TCL_GLOBAL_ONLY); -#endif - -#ifdef SQLITE_OMIT_COMPLETE - Tcl_SetVar2(interp, "sqlite_options", "complete", "0", TCL_GLOBAL_ONLY); -#else - Tcl_SetVar2(interp, "sqlite_options", "complete", "1", TCL_GLOBAL_ONLY); -#endif - -#ifdef SQLITE_OMIT_COMPOUND_SELECT - Tcl_SetVar2(interp, "sqlite_options", "compound", "0", TCL_GLOBAL_ONLY); -#else - Tcl_SetVar2(interp, "sqlite_options", "compound", "1", TCL_GLOBAL_ONLY); -#endif - - Tcl_SetVar2(interp, "sqlite_options", "conflict", "1", TCL_GLOBAL_ONLY); - -#if SQLITE_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 - Tcl_SetVar2(interp, "sqlite_options", "datetime", "1", TCL_GLOBAL_ONLY); -#endif - -#ifdef SQLITE_OMIT_DECLTYPE - Tcl_SetVar2(interp, "sqlite_options", "decltype", "0", TCL_GLOBAL_ONLY); -#else - Tcl_SetVar2(interp, "sqlite_options", "decltype", "1", TCL_GLOBAL_ONLY); -#endif - -#ifdef SQLITE_OMIT_DEPRECATED - Tcl_SetVar2(interp, "sqlite_options", "deprecated", "0", TCL_GLOBAL_ONLY); -#else - Tcl_SetVar2(interp, "sqlite_options", "deprecated", "1", TCL_GLOBAL_ONLY); -#endif - -#ifdef SQLITE_OMIT_DISKIO - Tcl_SetVar2(interp, "sqlite_options", "diskio", "0", TCL_GLOBAL_ONLY); -#else - Tcl_SetVar2(interp, "sqlite_options", "diskio", "1", TCL_GLOBAL_ONLY); -#endif - -#ifdef SQLITE_OMIT_EXPLAIN - Tcl_SetVar2(interp, "sqlite_options", "explain", "0", TCL_GLOBAL_ONLY); -#else - Tcl_SetVar2(interp, "sqlite_options", "explain", "1", TCL_GLOBAL_ONLY); -#endif - -#ifdef SQLITE_OMIT_FLOATING_POINT - Tcl_SetVar2(interp, "sqlite_options", "floatingpoint", "0", TCL_GLOBAL_ONLY); -#else - Tcl_SetVar2(interp, "sqlite_options", "floatingpoint", "1", TCL_GLOBAL_ONLY); -#endif - -#ifdef SQLITE_OMIT_FOREIGN_KEY - Tcl_SetVar2(interp, "sqlite_options", "foreignkey", "0", TCL_GLOBAL_ONLY); -#else - Tcl_SetVar2(interp, "sqlite_options", "foreignkey", "1", TCL_GLOBAL_ONLY); -#endif - -#ifdef SQLITE_ENABLE_FTS1 - Tcl_SetVar2(interp, "sqlite_options", "fts1", "1", TCL_GLOBAL_ONLY); -#else - Tcl_SetVar2(interp, "sqlite_options", "fts1", "0", TCL_GLOBAL_ONLY); -#endif - -#ifdef SQLITE_ENABLE_FTS2 - Tcl_SetVar2(interp, "sqlite_options", "fts2", "1", TCL_GLOBAL_ONLY); -#else - Tcl_SetVar2(interp, "sqlite_options", "fts2", "0", TCL_GLOBAL_ONLY); -#endif - -#ifdef SQLITE_ENABLE_FTS3 - Tcl_SetVar2(interp, "sqlite_options", "fts3", "1", TCL_GLOBAL_ONLY); -#else - Tcl_SetVar2(interp, "sqlite_options", "fts3", "0", TCL_GLOBAL_ONLY); -#endif - -#if defined(SQLITE_ENABLE_FTS3) && defined(SQLITE_ENABLE_FTS4_UNICODE61) - Tcl_SetVar2(interp, "sqlite_options", "fts3_unicode", "1", TCL_GLOBAL_ONLY); -#else - Tcl_SetVar2(interp, "sqlite_options", "fts3_unicode", "0", TCL_GLOBAL_ONLY); -#endif - -#ifdef SQLITE_DISABLE_FTS4_DEFERRED - Tcl_SetVar2(interp, "sqlite_options", "fts4_deferred", "0", TCL_GLOBAL_ONLY); -#else - Tcl_SetVar2(interp, "sqlite_options", "fts4_deferred", "1", TCL_GLOBAL_ONLY); -#endif - -#ifdef SQLITE_OMIT_GET_TABLE - Tcl_SetVar2(interp, "sqlite_options", "gettable", "0", TCL_GLOBAL_ONLY); -#else - Tcl_SetVar2(interp, "sqlite_options", "gettable", "1", TCL_GLOBAL_ONLY); -#endif - -#ifdef SQLITE_ENABLE_ICU - Tcl_SetVar2(interp, "sqlite_options", "icu", "1", TCL_GLOBAL_ONLY); -#else - Tcl_SetVar2(interp, "sqlite_options", "icu", "0", TCL_GLOBAL_ONLY); -#endif - -#ifdef SQLITE_OMIT_INCRBLOB - Tcl_SetVar2(interp, "sqlite_options", "incrblob", "0", TCL_GLOBAL_ONLY); -#else - Tcl_SetVar2(interp, "sqlite_options", "incrblob", "1", TCL_GLOBAL_ONLY); -#endif /* SQLITE_OMIT_AUTOVACUUM */ - -#ifdef SQLITE_OMIT_INTEGRITY_CHECK - Tcl_SetVar2(interp, "sqlite_options", "integrityck", "0", TCL_GLOBAL_ONLY); -#else - 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 - Tcl_SetVar2(interp, "sqlite_options", "like_opt", "1", TCL_GLOBAL_ONLY); -#endif - -#ifdef SQLITE_OMIT_LOAD_EXTENSION - Tcl_SetVar2(interp, "sqlite_options", "load_ext", "0", TCL_GLOBAL_ONLY); -#else - Tcl_SetVar2(interp, "sqlite_options", "load_ext", "1", TCL_GLOBAL_ONLY); -#endif - -#ifdef SQLITE_OMIT_LOCALTIME - Tcl_SetVar2(interp, "sqlite_options", "localtime", "0", TCL_GLOBAL_ONLY); -#else - Tcl_SetVar2(interp, "sqlite_options", "localtime", "1", TCL_GLOBAL_ONLY); -#endif - -#ifdef SQLITE_OMIT_LOOKASIDE - Tcl_SetVar2(interp, "sqlite_options", "lookaside", "0", TCL_GLOBAL_ONLY); -#else - Tcl_SetVar2(interp, "sqlite_options", "lookaside", "1", TCL_GLOBAL_ONLY); -#endif - -Tcl_SetVar2(interp, "sqlite_options", "long_double", - sizeof(LONGDOUBLE_TYPE)>sizeof(double) ? "1" : "0", - TCL_GLOBAL_ONLY); - -#ifdef SQLITE_OMIT_MEMORYDB - Tcl_SetVar2(interp, "sqlite_options", "memorydb", "0", TCL_GLOBAL_ONLY); -#else - 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 - -Tcl_SetVar2(interp, "sqlite_options", "mergesort", "1", TCL_GLOBAL_ONLY); - -#ifdef SQLITE_OMIT_OR_OPTIMIZATION - Tcl_SetVar2(interp, "sqlite_options", "or_opt", "0", TCL_GLOBAL_ONLY); -#else - Tcl_SetVar2(interp, "sqlite_options", "or_opt", "1", TCL_GLOBAL_ONLY); -#endif - -#ifdef SQLITE_OMIT_PAGER_PRAGMAS - Tcl_SetVar2(interp, "sqlite_options", "pager_pragmas", "0", TCL_GLOBAL_ONLY); -#else - Tcl_SetVar2(interp, "sqlite_options", "pager_pragmas", "1", TCL_GLOBAL_ONLY); -#endif - -#if defined(SQLITE_OMIT_PRAGMA) || defined(SQLITE_OMIT_FLAG_PRAGMAS) - Tcl_SetVar2(interp, "sqlite_options", "pragma", "0", TCL_GLOBAL_ONLY); - Tcl_SetVar2(interp, "sqlite_options", "integrityck", "0", TCL_GLOBAL_ONLY); -#else - Tcl_SetVar2(interp, "sqlite_options", "pragma", "1", TCL_GLOBAL_ONLY); -#endif - -#ifdef SQLITE_OMIT_PROGRESS_CALLBACK - Tcl_SetVar2(interp, "sqlite_options", "progress", "0", TCL_GLOBAL_ONLY); -#else - Tcl_SetVar2(interp, "sqlite_options", "progress", "1", TCL_GLOBAL_ONLY); -#endif - -#ifdef SQLITE_OMIT_REINDEX - Tcl_SetVar2(interp, "sqlite_options", "reindex", "0", TCL_GLOBAL_ONLY); -#else - Tcl_SetVar2(interp, "sqlite_options", "reindex", "1", TCL_GLOBAL_ONLY); -#endif - -#ifdef SQLITE_ENABLE_RTREE - Tcl_SetVar2(interp, "sqlite_options", "rtree", "1", TCL_GLOBAL_ONLY); -#else - Tcl_SetVar2(interp, "sqlite_options", "rtree", "0", TCL_GLOBAL_ONLY); -#endif - -#ifdef SQLITE_RTREE_INT_ONLY - Tcl_SetVar2(interp, "sqlite_options", "rtree_int_only", "1", TCL_GLOBAL_ONLY); -#else - Tcl_SetVar2(interp, "sqlite_options", "rtree_int_only", "0", TCL_GLOBAL_ONLY); -#endif - -#ifdef SQLITE_OMIT_SCHEMA_PRAGMAS - Tcl_SetVar2(interp, "sqlite_options", "schema_pragmas", "0", TCL_GLOBAL_ONLY); -#else - Tcl_SetVar2(interp, "sqlite_options", "schema_pragmas", "1", TCL_GLOBAL_ONLY); -#endif - -#ifdef SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS - Tcl_SetVar2(interp, "sqlite_options", "schema_version", "0", TCL_GLOBAL_ONLY); -#else - Tcl_SetVar2(interp, "sqlite_options", "schema_version", "1", TCL_GLOBAL_ONLY); -#endif - -#ifdef SQLITE_ENABLE_STAT4 - Tcl_SetVar2(interp, "sqlite_options", "stat4", "1", TCL_GLOBAL_ONLY); -#else - Tcl_SetVar2(interp, "sqlite_options", "stat4", "0", TCL_GLOBAL_ONLY); -#endif -#if defined(SQLITE_ENABLE_STAT3) && !defined(SQLITE_ENABLE_STAT4) - Tcl_SetVar2(interp, "sqlite_options", "stat3", "1", TCL_GLOBAL_ONLY); -#else - Tcl_SetVar2(interp, "sqlite_options", "stat3", "0", TCL_GLOBAL_ONLY); -#endif - -#if !defined(SQLITE_ENABLE_LOCKING_STYLE) -# if defined(__APPLE__) -# define SQLITE_ENABLE_LOCKING_STYLE 1 -# else -# define SQLITE_ENABLE_LOCKING_STYLE 0 -# endif -#endif -#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) - Tcl_SetVar2(interp,"sqlite_options","lock_proxy_pragmas","1",TCL_GLOBAL_ONLY); -#else - Tcl_SetVar2(interp,"sqlite_options","lock_proxy_pragmas","0",TCL_GLOBAL_ONLY); -#endif -#if defined(SQLITE_PREFER_PROXY_LOCKING) && defined(__APPLE__) - Tcl_SetVar2(interp,"sqlite_options","prefer_proxy_locking","1",TCL_GLOBAL_ONLY); -#else - Tcl_SetVar2(interp,"sqlite_options","prefer_proxy_locking","0",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 - Tcl_SetVar2(interp, "sqlite_options", "subquery", "1", TCL_GLOBAL_ONLY); -#endif - -#ifdef SQLITE_OMIT_TCL_VARIABLE - Tcl_SetVar2(interp, "sqlite_options", "tclvar", "0", TCL_GLOBAL_ONLY); -#else - Tcl_SetVar2(interp, "sqlite_options", "tclvar", "1", TCL_GLOBAL_ONLY); -#endif - - Tcl_SetVar2(interp, "sqlite_options", "threadsafe", - STRINGVALUE(SQLITE_THREADSAFE), TCL_GLOBAL_ONLY); - assert( sqlite3_threadsafe()==SQLITE_THREADSAFE ); - -#ifdef SQLITE_OMIT_TEMPDB - Tcl_SetVar2(interp, "sqlite_options", "tempdb", "0", TCL_GLOBAL_ONLY); -#else - Tcl_SetVar2(interp, "sqlite_options", "tempdb", "1", TCL_GLOBAL_ONLY); -#endif - -#ifdef SQLITE_OMIT_TRACE - Tcl_SetVar2(interp, "sqlite_options", "trace", "0", TCL_GLOBAL_ONLY); -#else - Tcl_SetVar2(interp, "sqlite_options", "trace", "1", TCL_GLOBAL_ONLY); -#endif - -#ifdef SQLITE_OMIT_TRIGGER - Tcl_SetVar2(interp, "sqlite_options", "trigger", "0", TCL_GLOBAL_ONLY); -#else - Tcl_SetVar2(interp, "sqlite_options", "trigger", "1", TCL_GLOBAL_ONLY); -#endif - -#ifdef SQLITE_OMIT_TRUNCATE_OPTIMIZATION - Tcl_SetVar2(interp, "sqlite_options", "truncate_opt", "0", TCL_GLOBAL_ONLY); -#else - Tcl_SetVar2(interp, "sqlite_options", "truncate_opt", "1", TCL_GLOBAL_ONLY); -#endif - -#ifdef SQLITE_OMIT_UTF16 - Tcl_SetVar2(interp, "sqlite_options", "utf16", "0", TCL_GLOBAL_ONLY); -#else - Tcl_SetVar2(interp, "sqlite_options", "utf16", "1", TCL_GLOBAL_ONLY); -#endif - -#if defined(SQLITE_OMIT_VACUUM) || defined(SQLITE_OMIT_ATTACH) - Tcl_SetVar2(interp, "sqlite_options", "vacuum", "0", TCL_GLOBAL_ONLY); -#else - Tcl_SetVar2(interp, "sqlite_options", "vacuum", "1", TCL_GLOBAL_ONLY); -#endif - -#ifdef SQLITE_OMIT_VIEW - Tcl_SetVar2(interp, "sqlite_options", "view", "0", TCL_GLOBAL_ONLY); -#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 - -#ifdef SQLITE_OMIT_WAL - Tcl_SetVar2(interp, "sqlite_options", "wal", "0", TCL_GLOBAL_ONLY); -#else - Tcl_SetVar2(interp, "sqlite_options", "wal", "1", TCL_GLOBAL_ONLY); -#endif - -#ifdef SQLITE_OMIT_WSD - Tcl_SetVar2(interp, "sqlite_options", "wsd", "0", TCL_GLOBAL_ONLY); -#else - Tcl_SetVar2(interp, "sqlite_options", "wsd", "1", TCL_GLOBAL_ONLY); -#endif - -#if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY) - Tcl_SetVar2(interp, "sqlite_options", "update_delete_limit", "1", TCL_GLOBAL_ONLY); -#else - Tcl_SetVar2(interp, "sqlite_options", "update_delete_limit", "0", TCL_GLOBAL_ONLY); -#endif - -#if defined(SQLITE_ENABLE_UNLOCK_NOTIFY) - Tcl_SetVar2(interp, "sqlite_options", "unlock_notify", "1", TCL_GLOBAL_ONLY); -#else - Tcl_SetVar2(interp, "sqlite_options", "unlock_notify", "0", TCL_GLOBAL_ONLY); -#endif - -#ifdef SQLITE_SECURE_DELETE - Tcl_SetVar2(interp, "sqlite_options", "secure_delete", "1", TCL_GLOBAL_ONLY); -#else - Tcl_SetVar2(interp, "sqlite_options", "secure_delete", "0", TCL_GLOBAL_ONLY); -#endif - -#ifdef SQLITE_MULTIPLEX_EXT_OVWR - Tcl_SetVar2(interp, "sqlite_options", "multiplex_ext_overwrite", "1", TCL_GLOBAL_ONLY); -#else - Tcl_SetVar2(interp, "sqlite_options", "multiplex_ext_overwrite", "0", TCL_GLOBAL_ONLY); -#endif - -#ifdef YYTRACKMAXSTACKDEPTH - Tcl_SetVar2(interp, "sqlite_options", "yytrackmaxstackdepth", "1", TCL_GLOBAL_ONLY); -#else - Tcl_SetVar2(interp, "sqlite_options", "yytrackmaxstackdepth", "0", TCL_GLOBAL_ONLY); -#endif - -#define LINKVAR(x) { \ - static const int cv_ ## x = SQLITE_ ## x; \ - Tcl_LinkVar(interp, "SQLITE_" #x, (char *)&(cv_ ## x), \ - TCL_LINK_INT | TCL_LINK_READ_ONLY); } - - LINKVAR( MAX_LENGTH ); - LINKVAR( MAX_COLUMN ); - LINKVAR( MAX_SQL_LENGTH ); - LINKVAR( MAX_EXPR_DEPTH ); - LINKVAR( MAX_COMPOUND_SELECT ); - LINKVAR( MAX_VDBE_OP ); - LINKVAR( MAX_FUNCTION_ARG ); - LINKVAR( MAX_VARIABLE_NUMBER ); - LINKVAR( MAX_PAGE_SIZE ); - LINKVAR( MAX_PAGE_COUNT ); - LINKVAR( MAX_LIKE_PATTERN_LENGTH ); - LINKVAR( MAX_TRIGGER_DEPTH ); - LINKVAR( DEFAULT_TEMP_CACHE_SIZE ); - LINKVAR( DEFAULT_CACHE_SIZE ); - LINKVAR( DEFAULT_PAGE_SIZE ); - LINKVAR( DEFAULT_FILE_FORMAT ); - LINKVAR( MAX_ATTACHED ); - LINKVAR( MAX_DEFAULT_PAGE_SIZE ); - - { - static const int cv_TEMP_STORE = SQLITE_TEMP_STORE; - Tcl_LinkVar(interp, "TEMP_STORE", (char *)&(cv_TEMP_STORE), - TCL_LINK_INT | TCL_LINK_READ_ONLY); - } - -#ifdef _MSC_VER - { - static const int cv__MSC_VER = 1; - Tcl_LinkVar(interp, "_MSC_VER", (char *)&(cv__MSC_VER), - TCL_LINK_INT | TCL_LINK_READ_ONLY); - } -#endif -#ifdef __GNUC__ - { - static const int cv___GNUC__ = 1; - Tcl_LinkVar(interp, "__GNUC__", (char *)&(cv___GNUC__), - TCL_LINK_INT | TCL_LINK_READ_ONLY); - } -#endif -} - - -/* -** Register commands with the TCL interpreter. -*/ -int Sqliteconfig_Init(Tcl_Interp *interp){ - set_options(interp); - return TCL_OK; -} diff --git a/components/external/SQLite-3.8.1/SQLiteLib/test/test_demovfs.c b/components/external/SQLite-3.8.1/SQLiteLib/test/test_demovfs.c deleted file mode 100644 index c63b0a8b7a..0000000000 --- a/components/external/SQLite-3.8.1/SQLiteLib/test/test_demovfs.c +++ /dev/null @@ -1,679 +0,0 @@ -/* -** 2010 April 7 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** -** This file implements an example of a simple VFS implementation that -** omits complex features often not required or not possible on embedded -** platforms. Code is included to buffer writes to the journal file, -** which can be a significant performance improvement on some embedded -** platforms. -** -** OVERVIEW -** -** The code in this file implements a minimal SQLite VFS that can be -** used on Linux and other posix-like operating systems. The following -** system calls are used: -** -** File-system: access(), unlink(), getcwd() -** File IO: open(), read(), write(), fsync(), close(), fstat() -** Other: sleep(), usleep(), time() -** -** The following VFS features are omitted: -** -** 1. File locking. The user must ensure that there is at most one -** connection to each database when using this VFS. Multiple -** connections to a single shared-cache count as a single connection -** for the purposes of the previous statement. -** -** 2. The loading of dynamic extensions (shared libraries). -** -** 3. Temporary files. The user must configure SQLite to use in-memory -** temp files when using this VFS. The easiest way to do this is to -** compile with: -** -** -DSQLITE_TEMP_STORE=3 -** -** 4. File truncation. As of version 3.6.24, SQLite may run without -** a working xTruncate() call, providing the user does not configure -** SQLite to use "journal_mode=truncate", or use both -** "journal_mode=persist" and ATTACHed databases. -** -** It is assumed that the system uses UNIX-like path-names. Specifically, -** that '/' characters are used to separate path components and that -** a path-name is a relative path unless it begins with a '/'. And that -** no UTF-8 encoded paths are greater than 512 bytes in length. -** -** JOURNAL WRITE-BUFFERING -** -** To commit a transaction to the database, SQLite first writes rollback -** information into the journal file. This usually consists of 4 steps: -** -** 1. The rollback information is sequentially written into the journal -** file, starting at the start of the file. -** 2. The journal file is synced to disk. -** 3. A modification is made to the first few bytes of the journal file. -** 4. The journal file is synced to disk again. -** -** Most of the data is written in step 1 using a series of calls to the -** VFS xWrite() method. The buffers passed to the xWrite() calls are of -** various sizes. For example, as of version 3.6.24, when committing a -** transaction that modifies 3 pages of a database file that uses 4096 -** byte pages residing on a media with 512 byte sectors, SQLite makes -** eleven calls to the xWrite() method to create the rollback journal, -** as follows: -** -** Write offset | Bytes written -** ---------------------------- -** 0 512 -** 512 4 -** 516 4096 -** 4612 4 -** 4616 4 -** 4620 4096 -** 8716 4 -** 8720 4 -** 8724 4096 -** 12820 4 -** ++++++++++++SYNC+++++++++++ -** 0 12 -** ++++++++++++SYNC+++++++++++ -** -** On many operating systems, this is an efficient way to write to a file. -** However, on some embedded systems that do not cache writes in OS -** buffers it is much more efficient to write data in blocks that are -** an integer multiple of the sector-size in size and aligned at the -** start of a sector. -** -** To work around this, the code in this file allocates a fixed size -** buffer of SQLITE_DEMOVFS_BUFFERSZ using sqlite3_malloc() whenever a -** journal file is opened. It uses the buffer to coalesce sequential -** writes into aligned SQLITE_DEMOVFS_BUFFERSZ blocks. When SQLite -** invokes the xSync() method to sync the contents of the file to disk, -** all accumulated data is written out, even if it does not constitute -** a complete block. This means the actual IO to create the rollback -** journal for the example transaction above is this: -** -** Write offset | Bytes written -** ---------------------------- -** 0 8192 -** 8192 4632 -** ++++++++++++SYNC+++++++++++ -** 0 12 -** ++++++++++++SYNC+++++++++++ -** -** Much more efficient if the underlying OS is not caching write -** operations. -*/ - -#if !defined(SQLITE_TEST) || SQLITE_OS_UNIX - -#include <sqlite3.h> - -#include <assert.h> -#include <string.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/file.h> -#include <sys/param.h> -#include <unistd.h> -#include <time.h> -#include <errno.h> -#include <fcntl.h> - -/* -** Size of the write buffer used by journal files in bytes. -*/ -#ifndef SQLITE_DEMOVFS_BUFFERSZ -# define SQLITE_DEMOVFS_BUFFERSZ 8192 -#endif - -/* -** The maximum pathname length supported by this VFS. -*/ -#define MAXPATHNAME 512 - -/* -** When using this VFS, the sqlite3_file* handles that SQLite uses are -** actually pointers to instances of type DemoFile. -*/ -typedef struct DemoFile DemoFile; -struct DemoFile { - sqlite3_file base; /* Base class. Must be first. */ - int fd; /* File descriptor */ - - char *aBuffer; /* Pointer to malloc'd buffer */ - int nBuffer; /* Valid bytes of data in zBuffer */ - sqlite3_int64 iBufferOfst; /* Offset in file of zBuffer[0] */ -}; - -/* -** Write directly to the file passed as the first argument. Even if the -** file has a write-buffer (DemoFile.aBuffer), ignore it. -*/ -static int demoDirectWrite( - DemoFile *p, /* File handle */ - const void *zBuf, /* Buffer containing data to write */ - int iAmt, /* Size of data to write in bytes */ - sqlite_int64 iOfst /* File offset to write to */ -){ - off_t ofst; /* Return value from lseek() */ - size_t nWrite; /* Return value from write() */ - - ofst = lseek(p->fd, iOfst, SEEK_SET); - if( ofst!=iOfst ){ - return SQLITE_IOERR_WRITE; - } - - nWrite = write(p->fd, zBuf, iAmt); - if( nWrite!=iAmt ){ - return SQLITE_IOERR_WRITE; - } - - return SQLITE_OK; -} - -/* -** Flush the contents of the DemoFile.aBuffer buffer to disk. This is a -** no-op if this particular file does not have a buffer (i.e. it is not -** a journal file) or if the buffer is currently empty. -*/ -static int demoFlushBuffer(DemoFile *p){ - int rc = SQLITE_OK; - if( p->nBuffer ){ - rc = demoDirectWrite(p, p->aBuffer, p->nBuffer, p->iBufferOfst); - p->nBuffer = 0; - } - return rc; -} - -/* -** Close a file. -*/ -static int demoClose(sqlite3_file *pFile){ - int rc; - DemoFile *p = (DemoFile*)pFile; - rc = demoFlushBuffer(p); - sqlite3_free(p->aBuffer); - close(p->fd); - return rc; -} - -/* -** Read data from a file. -*/ -static int demoRead( - sqlite3_file *pFile, - void *zBuf, - int iAmt, - sqlite_int64 iOfst -){ - DemoFile *p = (DemoFile*)pFile; - off_t ofst; /* Return value from lseek() */ - int nRead; /* Return value from read() */ - int rc; /* Return code from demoFlushBuffer() */ - - /* Flush any data in the write buffer to disk in case this operation - ** is trying to read data the file-region currently cached in the buffer. - ** It would be possible to detect this case and possibly save an - ** unnecessary write here, but in practice SQLite will rarely read from - ** a journal file when there is data cached in the write-buffer. - */ - rc = demoFlushBuffer(p); - if( rc!=SQLITE_OK ){ - return rc; - } - - ofst = lseek(p->fd, iOfst, SEEK_SET); - if( ofst!=iOfst ){ - return SQLITE_IOERR_READ; - } - nRead = read(p->fd, zBuf, iAmt); - - if( nRead==iAmt ){ - return SQLITE_OK; - }else if( nRead>=0 ){ - return SQLITE_IOERR_SHORT_READ; - } - - return SQLITE_IOERR_READ; -} - -/* -** Write data to a crash-file. -*/ -static int demoWrite( - sqlite3_file *pFile, - const void *zBuf, - int iAmt, - sqlite_int64 iOfst -){ - DemoFile *p = (DemoFile*)pFile; - - if( p->aBuffer ){ - char *z = (char *)zBuf; /* Pointer to remaining data to write */ - int n = iAmt; /* Number of bytes at z */ - sqlite3_int64 i = iOfst; /* File offset to write to */ - - while( n>0 ){ - int nCopy; /* Number of bytes to copy into buffer */ - - /* If the buffer is full, or if this data is not being written directly - ** following the data already buffered, flush the buffer. Flushing - ** the buffer is a no-op if it is empty. - */ - if( p->nBuffer==SQLITE_DEMOVFS_BUFFERSZ || p->iBufferOfst+p->nBuffer!=i ){ - int rc = demoFlushBuffer(p); - if( rc!=SQLITE_OK ){ - return rc; - } - } - assert( p->nBuffer==0 || p->iBufferOfst+p->nBuffer==i ); - p->iBufferOfst = i - p->nBuffer; - - /* Copy as much data as possible into the buffer. */ - nCopy = SQLITE_DEMOVFS_BUFFERSZ - p->nBuffer; - if( nCopy>n ){ - nCopy = n; - } - memcpy(&p->aBuffer[p->nBuffer], z, nCopy); - p->nBuffer += nCopy; - - n -= nCopy; - i += nCopy; - z += nCopy; - } - }else{ - return demoDirectWrite(p, zBuf, iAmt, iOfst); - } - - return SQLITE_OK; -} - -/* -** Truncate a file. This is a no-op for this VFS (see header comments at -** the top of the file). -*/ -static int demoTruncate(sqlite3_file *pFile, sqlite_int64 size){ -#if 0 - if( ftruncate(((DemoFile *)pFile)->fd, size) ) return SQLITE_IOERR_TRUNCATE; -#endif - return SQLITE_OK; -} - -/* -** Sync the contents of the file to the persistent media. -*/ -static int demoSync(sqlite3_file *pFile, int flags){ - DemoFile *p = (DemoFile*)pFile; - int rc; - - rc = demoFlushBuffer(p); - if( rc!=SQLITE_OK ){ - return rc; - } - - rc = fsync(p->fd); - return (rc==0 ? SQLITE_OK : SQLITE_IOERR_FSYNC); -} - -/* -** Write the size of the file in bytes to *pSize. -*/ -static int demoFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){ - DemoFile *p = (DemoFile*)pFile; - int rc; /* Return code from fstat() call */ - struct stat sStat; /* Output of fstat() call */ - - /* Flush the contents of the buffer to disk. As with the flush in the - ** demoRead() method, it would be possible to avoid this and save a write - ** here and there. But in practice this comes up so infrequently it is - ** not worth the trouble. - */ - rc = demoFlushBuffer(p); - if( rc!=SQLITE_OK ){ - return rc; - } - - rc = fstat(p->fd, &sStat); - if( rc!=0 ) return SQLITE_IOERR_FSTAT; - *pSize = sStat.st_size; - return SQLITE_OK; -} - -/* -** Locking functions. The xLock() and xUnlock() methods are both no-ops. -** The xCheckReservedLock() always indicates that no other process holds -** a reserved lock on the database file. This ensures that if a hot-journal -** file is found in the file-system it is rolled back. -*/ -static int demoLock(sqlite3_file *pFile, int eLock){ - return SQLITE_OK; -} -static int demoUnlock(sqlite3_file *pFile, int eLock){ - return SQLITE_OK; -} -static int demoCheckReservedLock(sqlite3_file *pFile, int *pResOut){ - *pResOut = 0; - return SQLITE_OK; -} - -/* -** No xFileControl() verbs are implemented by this VFS. -*/ -static int demoFileControl(sqlite3_file *pFile, int op, void *pArg){ - return SQLITE_OK; -} - -/* -** The xSectorSize() and xDeviceCharacteristics() methods. These two -** may return special values allowing SQLite to optimize file-system -** access to some extent. But it is also safe to simply return 0. -*/ -static int demoSectorSize(sqlite3_file *pFile){ - return 0; -} -static int demoDeviceCharacteristics(sqlite3_file *pFile){ - return 0; -} - -/* -** Open a file handle. -*/ -static int demoOpen( - sqlite3_vfs *pVfs, /* VFS */ - const char *zName, /* File to open, or 0 for a temp file */ - sqlite3_file *pFile, /* Pointer to DemoFile struct to populate */ - int flags, /* Input SQLITE_OPEN_XXX flags */ - int *pOutFlags /* Output SQLITE_OPEN_XXX flags (or NULL) */ -){ - static const sqlite3_io_methods demoio = { - 1, /* iVersion */ - demoClose, /* xClose */ - demoRead, /* xRead */ - demoWrite, /* xWrite */ - demoTruncate, /* xTruncate */ - demoSync, /* xSync */ - demoFileSize, /* xFileSize */ - demoLock, /* xLock */ - demoUnlock, /* xUnlock */ - demoCheckReservedLock, /* xCheckReservedLock */ - demoFileControl, /* xFileControl */ - demoSectorSize, /* xSectorSize */ - demoDeviceCharacteristics /* xDeviceCharacteristics */ - }; - - DemoFile *p = (DemoFile*)pFile; /* Populate this structure */ - int oflags = 0; /* flags to pass to open() call */ - char *aBuf = 0; - - if( zName==0 ){ - return SQLITE_IOERR; - } - - if( flags&SQLITE_OPEN_MAIN_JOURNAL ){ - aBuf = (char *)sqlite3_malloc(SQLITE_DEMOVFS_BUFFERSZ); - if( !aBuf ){ - return SQLITE_NOMEM; - } - } - - if( flags&SQLITE_OPEN_EXCLUSIVE ) oflags |= O_EXCL; - if( flags&SQLITE_OPEN_CREATE ) oflags |= O_CREAT; - if( flags&SQLITE_OPEN_READONLY ) oflags |= O_RDONLY; - if( flags&SQLITE_OPEN_READWRITE ) oflags |= O_RDWR; - - memset(p, 0, sizeof(DemoFile)); - p->fd = open(zName, oflags, 0600); - if( p->fd<0 ){ - sqlite3_free(aBuf); - return SQLITE_CANTOPEN; - } - p->aBuffer = aBuf; - - if( pOutFlags ){ - *pOutFlags = flags; - } - p->base.pMethods = &demoio; - return SQLITE_OK; -} - -/* -** Delete the file identified by argument zPath. If the dirSync parameter -** is non-zero, then ensure the file-system modification to delete the -** file has been synced to disk before returning. -*/ -static int demoDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){ - int rc; /* Return code */ - - rc = unlink(zPath); - if( rc!=0 && errno==ENOENT ) return SQLITE_OK; - - if( rc==0 && dirSync ){ - int dfd; /* File descriptor open on directory */ - int i; /* Iterator variable */ - char zDir[MAXPATHNAME+1]; /* Name of directory containing file zPath */ - - /* Figure out the directory name from the path of the file deleted. */ - sqlite3_snprintf(MAXPATHNAME, zDir, "%s", zPath); - zDir[MAXPATHNAME] = '\0'; - for(i=strlen(zDir); i>1 && zDir[i]!='/'; i++); - zDir[i] = '\0'; - - /* Open a file-descriptor on the directory. Sync. Close. */ - dfd = open(zDir, O_RDONLY, 0); - if( dfd<0 ){ - rc = -1; - }else{ - rc = fsync(dfd); - close(dfd); - } - } - return (rc==0 ? SQLITE_OK : SQLITE_IOERR_DELETE); -} - -#ifndef F_OK -# define F_OK 0 -#endif -#ifndef R_OK -# define R_OK 4 -#endif -#ifndef W_OK -# define W_OK 2 -#endif - -/* -** Query the file-system to see if the named file exists, is readable or -** is both readable and writable. -*/ -static int demoAccess( - sqlite3_vfs *pVfs, - const char *zPath, - int flags, - int *pResOut -){ - int rc; /* access() return code */ - int eAccess = F_OK; /* Second argument to access() */ - - assert( flags==SQLITE_ACCESS_EXISTS /* access(zPath, F_OK) */ - || flags==SQLITE_ACCESS_READ /* access(zPath, R_OK) */ - || flags==SQLITE_ACCESS_READWRITE /* access(zPath, R_OK|W_OK) */ - ); - - if( flags==SQLITE_ACCESS_READWRITE ) eAccess = R_OK|W_OK; - if( flags==SQLITE_ACCESS_READ ) eAccess = R_OK; - - rc = access(zPath, eAccess); - *pResOut = (rc==0); - return SQLITE_OK; -} - -/* -** Argument zPath points to a nul-terminated string containing a file path. -** If zPath is an absolute path, then it is copied as is into the output -** buffer. Otherwise, if it is a relative path, then the equivalent full -** path is written to the output buffer. -** -** This function assumes that paths are UNIX style. Specifically, that: -** -** 1. Path components are separated by a '/'. and -** 2. Full paths begin with a '/' character. -*/ -static int demoFullPathname( - sqlite3_vfs *pVfs, /* VFS */ - const char *zPath, /* Input path (possibly a relative path) */ - int nPathOut, /* Size of output buffer in bytes */ - char *zPathOut /* Pointer to output buffer */ -){ - char zDir[MAXPATHNAME+1]; - if( zPath[0]=='/' ){ - zDir[0] = '\0'; - }else{ - if( getcwd(zDir, sizeof(zDir))==0 ) return SQLITE_IOERR; - } - zDir[MAXPATHNAME] = '\0'; - - sqlite3_snprintf(nPathOut, zPathOut, "%s/%s", zDir, zPath); - zPathOut[nPathOut-1] = '\0'; - - return SQLITE_OK; -} - -/* -** The following four VFS methods: -** -** xDlOpen -** xDlError -** xDlSym -** xDlClose -** -** are supposed to implement the functionality needed by SQLite to load -** extensions compiled as shared objects. This simple VFS does not support -** this functionality, so the following functions are no-ops. -*/ -static void *demoDlOpen(sqlite3_vfs *pVfs, const char *zPath){ - return 0; -} -static void demoDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){ - sqlite3_snprintf(nByte, zErrMsg, "Loadable extensions are not supported"); - zErrMsg[nByte-1] = '\0'; -} -static void (*demoDlSym(sqlite3_vfs *pVfs, void *pH, const char *z))(void){ - return 0; -} -static void demoDlClose(sqlite3_vfs *pVfs, void *pHandle){ - return; -} - -/* -** Parameter zByte points to a buffer nByte bytes in size. Populate this -** buffer with pseudo-random data. -*/ -static int demoRandomness(sqlite3_vfs *pVfs, int nByte, char *zByte){ - return SQLITE_OK; -} - -/* -** Sleep for at least nMicro microseconds. Return the (approximate) number -** of microseconds slept for. -*/ -static int demoSleep(sqlite3_vfs *pVfs, int nMicro){ - sleep(nMicro / 1000000); - usleep(nMicro % 1000000); - return nMicro; -} - -/* -** Set *pTime to the current UTC time expressed as a Julian day. Return -** SQLITE_OK if successful, or an error code otherwise. -** -** http://en.wikipedia.org/wiki/Julian_day -** -** This implementation is not very good. The current time is rounded to -** an integer number of seconds. Also, assuming time_t is a signed 32-bit -** value, it will stop working some time in the year 2038 AD (the so-called -** "year 2038" problem that afflicts systems that store time this way). -*/ -static int demoCurrentTime(sqlite3_vfs *pVfs, double *pTime){ - time_t t = time(0); - *pTime = t/86400.0 + 2440587.5; - return SQLITE_OK; -} - -/* -** This function returns a pointer to the VFS implemented in this file. -** To make the VFS available to SQLite: -** -** sqlite3_vfs_register(sqlite3_demovfs(), 0); -*/ -sqlite3_vfs *sqlite3_demovfs(void){ - static sqlite3_vfs demovfs = { - 1, /* iVersion */ - sizeof(DemoFile), /* szOsFile */ - MAXPATHNAME, /* mxPathname */ - 0, /* pNext */ - "demo", /* zName */ - 0, /* pAppData */ - demoOpen, /* xOpen */ - demoDelete, /* xDelete */ - demoAccess, /* xAccess */ - demoFullPathname, /* xFullPathname */ - demoDlOpen, /* xDlOpen */ - demoDlError, /* xDlError */ - demoDlSym, /* xDlSym */ - demoDlClose, /* xDlClose */ - demoRandomness, /* xRandomness */ - demoSleep, /* xSleep */ - demoCurrentTime, /* xCurrentTime */ - }; - return &demovfs; -} - -#endif /* !defined(SQLITE_TEST) || SQLITE_OS_UNIX */ - - -#ifdef SQLITE_TEST - -#include <tcl.h> - -#if SQLITE_OS_UNIX -static int register_demovfs( - 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_register(sqlite3_demovfs(), 1); - return TCL_OK; -} -static int unregister_demovfs( - 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_unregister(sqlite3_demovfs()); - return TCL_OK; -} - -/* -** Register commands with the TCL interpreter. -*/ -int Sqlitetest_demovfs_Init(Tcl_Interp *interp){ - Tcl_CreateObjCommand(interp, "register_demovfs", register_demovfs, 0, 0); - Tcl_CreateObjCommand(interp, "unregister_demovfs", unregister_demovfs, 0, 0); - return TCL_OK; -} - -#else -int Sqlitetest_demovfs_Init(Tcl_Interp *interp){ return TCL_OK; } -#endif - -#endif /* SQLITE_TEST */ diff --git a/components/external/SQLite-3.8.1/SQLiteLib/test/test_devsym.c b/components/external/SQLite-3.8.1/SQLiteLib/test/test_devsym.c deleted file mode 100644 index 21f0f684d8..0000000000 --- a/components/external/SQLite-3.8.1/SQLiteLib/test/test_devsym.c +++ /dev/null @@ -1,398 +0,0 @@ -/* -** 2008 Jan 22 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -****************************************************************************** -** -** This file contains code that modified the OS layer in order to simulate -** different device types (by overriding the return values of the -** xDeviceCharacteristics() and xSectorSize() methods). -*/ -#if SQLITE_TEST /* This file is used for testing only */ - -#include "sqlite3.h" -#include "sqliteInt.h" - -/* -** Maximum pathname length supported by the devsym backend. -*/ -#define DEVSYM_MAX_PATHNAME 512 - -/* -** Name used to identify this VFS. -*/ -#define DEVSYM_VFS_NAME "devsym" - -typedef struct devsym_file devsym_file; -struct devsym_file { - sqlite3_file base; - sqlite3_file *pReal; -}; - -/* -** Method declarations for devsym_file. -*/ -static int devsymClose(sqlite3_file*); -static int devsymRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst); -static int devsymWrite(sqlite3_file*,const void*,int iAmt, sqlite3_int64 iOfst); -static int devsymTruncate(sqlite3_file*, sqlite3_int64 size); -static int devsymSync(sqlite3_file*, int flags); -static int devsymFileSize(sqlite3_file*, sqlite3_int64 *pSize); -static int devsymLock(sqlite3_file*, int); -static int devsymUnlock(sqlite3_file*, int); -static int devsymCheckReservedLock(sqlite3_file*, int *); -static int devsymFileControl(sqlite3_file*, int op, void *pArg); -static int devsymSectorSize(sqlite3_file*); -static int devsymDeviceCharacteristics(sqlite3_file*); -static int devsymShmLock(sqlite3_file*,int,int,int); -static int devsymShmMap(sqlite3_file*,int,int,int, void volatile **); -static void devsymShmBarrier(sqlite3_file*); -static int devsymShmUnmap(sqlite3_file*,int); - -/* -** Method declarations for devsym_vfs. -*/ -static int devsymOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *); -static int devsymDelete(sqlite3_vfs*, const char *zName, int syncDir); -static int devsymAccess(sqlite3_vfs*, const char *zName, int flags, int *); -static int devsymFullPathname(sqlite3_vfs*, const char *zName, int, char *zOut); -#ifndef SQLITE_OMIT_LOAD_EXTENSION -static void *devsymDlOpen(sqlite3_vfs*, const char *zFilename); -static void devsymDlError(sqlite3_vfs*, int nByte, char *zErrMsg); -static void (*devsymDlSym(sqlite3_vfs*,void*, const char *zSymbol))(void); -static void devsymDlClose(sqlite3_vfs*, void*); -#endif /* SQLITE_OMIT_LOAD_EXTENSION */ -static int devsymRandomness(sqlite3_vfs*, int nByte, char *zOut); -static int devsymSleep(sqlite3_vfs*, int microseconds); -static int devsymCurrentTime(sqlite3_vfs*, double*); - -static sqlite3_vfs devsym_vfs = { - 2, /* iVersion */ - sizeof(devsym_file), /* szOsFile */ - DEVSYM_MAX_PATHNAME, /* mxPathname */ - 0, /* pNext */ - DEVSYM_VFS_NAME, /* zName */ - 0, /* pAppData */ - devsymOpen, /* xOpen */ - devsymDelete, /* xDelete */ - devsymAccess, /* xAccess */ - devsymFullPathname, /* xFullPathname */ -#ifndef SQLITE_OMIT_LOAD_EXTENSION - devsymDlOpen, /* xDlOpen */ - devsymDlError, /* xDlError */ - devsymDlSym, /* xDlSym */ - devsymDlClose, /* xDlClose */ -#else - 0, /* xDlOpen */ - 0, /* xDlError */ - 0, /* xDlSym */ - 0, /* xDlClose */ -#endif /* SQLITE_OMIT_LOAD_EXTENSION */ - devsymRandomness, /* xRandomness */ - devsymSleep, /* xSleep */ - devsymCurrentTime, /* xCurrentTime */ - 0, /* xGetLastError */ - 0 /* xCurrentTimeInt64 */ -}; - -static sqlite3_io_methods devsym_io_methods = { - 2, /* iVersion */ - devsymClose, /* xClose */ - devsymRead, /* xRead */ - devsymWrite, /* xWrite */ - devsymTruncate, /* xTruncate */ - devsymSync, /* xSync */ - devsymFileSize, /* xFileSize */ - devsymLock, /* xLock */ - devsymUnlock, /* xUnlock */ - devsymCheckReservedLock, /* xCheckReservedLock */ - devsymFileControl, /* xFileControl */ - devsymSectorSize, /* xSectorSize */ - devsymDeviceCharacteristics, /* xDeviceCharacteristics */ - devsymShmMap, /* xShmMap */ - devsymShmLock, /* xShmLock */ - devsymShmBarrier, /* xShmBarrier */ - devsymShmUnmap /* xShmUnmap */ -}; - -struct DevsymGlobal { - sqlite3_vfs *pVfs; - int iDeviceChar; - int iSectorSize; -}; -struct DevsymGlobal g = {0, 0, 512}; - -/* -** Close an devsym-file. -*/ -static int devsymClose(sqlite3_file *pFile){ - devsym_file *p = (devsym_file *)pFile; - return sqlite3OsClose(p->pReal); -} - -/* -** Read data from an devsym-file. -*/ -static int devsymRead( - sqlite3_file *pFile, - void *zBuf, - int iAmt, - sqlite_int64 iOfst -){ - devsym_file *p = (devsym_file *)pFile; - return sqlite3OsRead(p->pReal, zBuf, iAmt, iOfst); -} - -/* -** Write data to an devsym-file. -*/ -static int devsymWrite( - sqlite3_file *pFile, - const void *zBuf, - int iAmt, - sqlite_int64 iOfst -){ - devsym_file *p = (devsym_file *)pFile; - return sqlite3OsWrite(p->pReal, zBuf, iAmt, iOfst); -} - -/* -** Truncate an devsym-file. -*/ -static int devsymTruncate(sqlite3_file *pFile, sqlite_int64 size){ - devsym_file *p = (devsym_file *)pFile; - return sqlite3OsTruncate(p->pReal, size); -} - -/* -** Sync an devsym-file. -*/ -static int devsymSync(sqlite3_file *pFile, int flags){ - devsym_file *p = (devsym_file *)pFile; - return sqlite3OsSync(p->pReal, flags); -} - -/* -** Return the current file-size of an devsym-file. -*/ -static int devsymFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){ - devsym_file *p = (devsym_file *)pFile; - return sqlite3OsFileSize(p->pReal, pSize); -} - -/* -** Lock an devsym-file. -*/ -static int devsymLock(sqlite3_file *pFile, int eLock){ - devsym_file *p = (devsym_file *)pFile; - return sqlite3OsLock(p->pReal, eLock); -} - -/* -** Unlock an devsym-file. -*/ -static int devsymUnlock(sqlite3_file *pFile, int eLock){ - devsym_file *p = (devsym_file *)pFile; - return sqlite3OsUnlock(p->pReal, eLock); -} - -/* -** Check if another file-handle holds a RESERVED lock on an devsym-file. -*/ -static int devsymCheckReservedLock(sqlite3_file *pFile, int *pResOut){ - devsym_file *p = (devsym_file *)pFile; - return sqlite3OsCheckReservedLock(p->pReal, pResOut); -} - -/* -** File control method. For custom operations on an devsym-file. -*/ -static int devsymFileControl(sqlite3_file *pFile, int op, void *pArg){ - devsym_file *p = (devsym_file *)pFile; - return sqlite3OsFileControl(p->pReal, op, pArg); -} - -/* -** Return the sector-size in bytes for an devsym-file. -*/ -static int devsymSectorSize(sqlite3_file *pFile){ - return g.iSectorSize; -} - -/* -** Return the device characteristic flags supported by an devsym-file. -*/ -static int devsymDeviceCharacteristics(sqlite3_file *pFile){ - return g.iDeviceChar; -} - -/* -** Shared-memory methods are all pass-thrus. -*/ -static int devsymShmLock(sqlite3_file *pFile, int ofst, int n, int flags){ - devsym_file *p = (devsym_file *)pFile; - return sqlite3OsShmLock(p->pReal, ofst, n, flags); -} -static int devsymShmMap( - sqlite3_file *pFile, - int iRegion, - int szRegion, - int isWrite, - void volatile **pp -){ - devsym_file *p = (devsym_file *)pFile; - return sqlite3OsShmMap(p->pReal, iRegion, szRegion, isWrite, pp); -} -static void devsymShmBarrier(sqlite3_file *pFile){ - devsym_file *p = (devsym_file *)pFile; - sqlite3OsShmBarrier(p->pReal); -} -static int devsymShmUnmap(sqlite3_file *pFile, int delFlag){ - devsym_file *p = (devsym_file *)pFile; - return sqlite3OsShmUnmap(p->pReal, delFlag); -} - - - -/* -** Open an devsym file handle. -*/ -static int devsymOpen( - sqlite3_vfs *pVfs, - const char *zName, - sqlite3_file *pFile, - int flags, - int *pOutFlags -){ - int rc; - devsym_file *p = (devsym_file *)pFile; - p->pReal = (sqlite3_file *)&p[1]; - rc = sqlite3OsOpen(g.pVfs, zName, p->pReal, flags, pOutFlags); - if( p->pReal->pMethods ){ - pFile->pMethods = &devsym_io_methods; - } - return rc; -} - -/* -** Delete the file located at zPath. If the dirSync argument is true, -** ensure the file-system modifications are synced to disk before -** returning. -*/ -static int devsymDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){ - return sqlite3OsDelete(g.pVfs, zPath, dirSync); -} - -/* -** Test for access permissions. Return true if the requested permission -** is available, or false otherwise. -*/ -static int devsymAccess( - sqlite3_vfs *pVfs, - const char *zPath, - int flags, - int *pResOut -){ - return sqlite3OsAccess(g.pVfs, zPath, flags, pResOut); -} - -/* -** Populate buffer zOut with the full canonical pathname corresponding -** to the pathname in zPath. zOut is guaranteed to point to a buffer -** of at least (DEVSYM_MAX_PATHNAME+1) bytes. -*/ -static int devsymFullPathname( - sqlite3_vfs *pVfs, - const char *zPath, - int nOut, - char *zOut -){ - return sqlite3OsFullPathname(g.pVfs, zPath, nOut, zOut); -} - -#ifndef SQLITE_OMIT_LOAD_EXTENSION -/* -** Open the dynamic library located at zPath and return a handle. -*/ -static void *devsymDlOpen(sqlite3_vfs *pVfs, const char *zPath){ - return sqlite3OsDlOpen(g.pVfs, zPath); -} - -/* -** Populate the buffer zErrMsg (size nByte bytes) with a human readable -** utf-8 string describing the most recent error encountered associated -** with dynamic libraries. -*/ -static void devsymDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){ - sqlite3OsDlError(g.pVfs, nByte, zErrMsg); -} - -/* -** Return a pointer to the symbol zSymbol in the dynamic library pHandle. -*/ -static void (*devsymDlSym(sqlite3_vfs *pVfs, void *p, const char *zSym))(void){ - return sqlite3OsDlSym(g.pVfs, p, zSym); -} - -/* -** Close the dynamic library handle pHandle. -*/ -static void devsymDlClose(sqlite3_vfs *pVfs, void *pHandle){ - sqlite3OsDlClose(g.pVfs, pHandle); -} -#endif /* SQLITE_OMIT_LOAD_EXTENSION */ - -/* -** Populate the buffer pointed to by zBufOut with nByte bytes of -** random data. -*/ -static int devsymRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){ - return sqlite3OsRandomness(g.pVfs, nByte, zBufOut); -} - -/* -** Sleep for nMicro microseconds. Return the number of microseconds -** actually slept. -*/ -static int devsymSleep(sqlite3_vfs *pVfs, int nMicro){ - return sqlite3OsSleep(g.pVfs, nMicro); -} - -/* -** Return the current time as a Julian Day number in *pTimeOut. -*/ -static int devsymCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){ - return g.pVfs->xCurrentTime(g.pVfs, pTimeOut); -} - - -/* -** This procedure registers the devsym vfs with SQLite. If the argument is -** true, the devsym vfs becomes the new default vfs. It is the only publicly -** available function in this file. -*/ -void devsym_register(int iDeviceChar, int iSectorSize){ - if( g.pVfs==0 ){ - g.pVfs = sqlite3_vfs_find(0); - devsym_vfs.szOsFile += g.pVfs->szOsFile; - sqlite3_vfs_register(&devsym_vfs, 0); - } - if( iDeviceChar>=0 ){ - g.iDeviceChar = iDeviceChar; - }else{ - g.iDeviceChar = 0; - } - if( iSectorSize>=0 ){ - g.iSectorSize = iSectorSize; - }else{ - g.iSectorSize = 512; - } -} - -#endif diff --git a/components/external/SQLite-3.8.1/SQLiteLib/test/test_fs.c b/components/external/SQLite-3.8.1/SQLiteLib/test/test_fs.c deleted file mode 100644 index 417c81b49f..0000000000 --- a/components/external/SQLite-3.8.1/SQLiteLib/test/test_fs.c +++ /dev/null @@ -1,335 +0,0 @@ -/* -** 2013 Jan 11 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** Code for testing the virtual table interfaces. This code -** is not included in the SQLite library. It is used for automated -** testing of the SQLite library. -** -** The FS virtual table is created as follows: -** -** CREATE VIRTUAL TABLE tbl USING fs(idx); -** -** where idx is the name of a table in the db with 2 columns. The virtual -** table also has two columns - file path and file contents. -** -** The first column of table idx must be an IPK, and the second contains file -** paths. For example: -** -** CREATE TABLE idx(id INTEGER PRIMARY KEY, path TEXT); -** INSERT INTO idx VALUES(4, '/etc/passwd'); -** -** Adding the row to the idx table automatically creates a row in the -** virtual table with rowid=4, path=/etc/passwd and a text field that -** contains data read from file /etc/passwd on disk. -*/ -#include "sqliteInt.h" -#include "tcl.h" - -#include <stdlib.h> -#include <string.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> - -#if SQLITE_OS_UNIX -# include <unistd.h> -#endif -#if SQLITE_OS_WIN -# include <io.h> -#endif - -#ifndef SQLITE_OMIT_VIRTUALTABLE - -typedef struct fs_vtab fs_vtab; -typedef struct fs_cursor fs_cursor; - -/* -** A fs virtual-table object -*/ -struct fs_vtab { - sqlite3_vtab base; - sqlite3 *db; - char *zDb; /* Name of db containing zTbl */ - char *zTbl; /* Name of docid->file map table */ -}; - -/* A fs cursor object */ -struct fs_cursor { - sqlite3_vtab_cursor base; - sqlite3_stmt *pStmt; - char *zBuf; - int nBuf; - int nAlloc; -}; - -/* -** This function is the implementation of both the xConnect and xCreate -** methods of the fs virtual table. -** -** The argv[] array contains the following: -** -** argv[0] -> module name ("fs") -** argv[1] -> database name -** argv[2] -> table name -** argv[...] -> other module argument fields. -*/ -static int fsConnect( - sqlite3 *db, - void *pAux, - int argc, const char *const*argv, - sqlite3_vtab **ppVtab, - char **pzErr -){ - fs_vtab *pVtab; - int nByte; - const char *zTbl; - const char *zDb = argv[1]; - - if( argc!=4 ){ - *pzErr = sqlite3_mprintf("wrong number of arguments"); - return SQLITE_ERROR; - } - zTbl = argv[3]; - - nByte = sizeof(fs_vtab) + (int)strlen(zTbl) + 1 + (int)strlen(zDb) + 1; - pVtab = (fs_vtab *)sqlite3MallocZero( nByte ); - if( !pVtab ) return SQLITE_NOMEM; - - pVtab->zTbl = (char *)&pVtab[1]; - pVtab->zDb = &pVtab->zTbl[strlen(zTbl)+1]; - pVtab->db = db; - memcpy(pVtab->zTbl, zTbl, strlen(zTbl)); - memcpy(pVtab->zDb, zDb, strlen(zDb)); - *ppVtab = &pVtab->base; - sqlite3_declare_vtab(db, "CREATE TABLE xyz(path TEXT, data TEXT)"); - - return SQLITE_OK; -} -/* Note that for this virtual table, the xCreate and xConnect -** methods are identical. */ - -static int fsDisconnect(sqlite3_vtab *pVtab){ - sqlite3_free(pVtab); - return SQLITE_OK; -} -/* The xDisconnect and xDestroy methods are also the same */ - -/* -** Open a new fs cursor. -*/ -static int fsOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){ - fs_cursor *pCur; - pCur = sqlite3MallocZero(sizeof(fs_cursor)); - *ppCursor = &pCur->base; - return SQLITE_OK; -} - -/* -** Close a fs cursor. -*/ -static int fsClose(sqlite3_vtab_cursor *cur){ - fs_cursor *pCur = (fs_cursor *)cur; - sqlite3_finalize(pCur->pStmt); - sqlite3_free(pCur->zBuf); - sqlite3_free(pCur); - return SQLITE_OK; -} - -static int fsNext(sqlite3_vtab_cursor *cur){ - fs_cursor *pCur = (fs_cursor *)cur; - int rc; - - rc = sqlite3_step(pCur->pStmt); - if( rc==SQLITE_ROW || rc==SQLITE_DONE ) rc = SQLITE_OK; - - return rc; -} - -static int fsFilter( - sqlite3_vtab_cursor *pVtabCursor, - int idxNum, const char *idxStr, - int argc, sqlite3_value **argv -){ - int rc; - fs_cursor *pCur = (fs_cursor *)pVtabCursor; - fs_vtab *p = (fs_vtab *)(pVtabCursor->pVtab); - - assert( (idxNum==0 && argc==0) || (idxNum==1 && argc==1) ); - if( idxNum==1 ){ - char *zStmt = sqlite3_mprintf( - "SELECT * FROM %Q.%Q WHERE rowid=?", p->zDb, p->zTbl); - if( !zStmt ) return SQLITE_NOMEM; - rc = sqlite3_prepare_v2(p->db, zStmt, -1, &pCur->pStmt, 0); - sqlite3_free(zStmt); - if( rc==SQLITE_OK ){ - sqlite3_bind_value(pCur->pStmt, 1, argv[0]); - } - }else{ - char *zStmt = sqlite3_mprintf("SELECT * FROM %Q.%Q", p->zDb, p->zTbl); - if( !zStmt ) return SQLITE_NOMEM; - rc = sqlite3_prepare_v2(p->db, zStmt, -1, &pCur->pStmt, 0); - sqlite3_free(zStmt); - } - - if( rc==SQLITE_OK ){ - rc = fsNext(pVtabCursor); - } - return rc; -} - -static int fsColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){ - fs_cursor *pCur = (fs_cursor*)cur; - - assert( i==0 || i==1 ); - if( i==0 ){ - sqlite3_result_value(ctx, sqlite3_column_value(pCur->pStmt, 0)); - }else{ - const char *zFile = (const char *)sqlite3_column_text(pCur->pStmt, 1); - struct stat sbuf; - int fd; - int n; - - fd = open(zFile, O_RDONLY); - if( fd<0 ) return SQLITE_IOERR; - fstat(fd, &sbuf); - - if( sbuf.st_size>=pCur->nAlloc ){ - int nNew = sbuf.st_size*2; - char *zNew; - if( nNew<1024 ) nNew = 1024; - - zNew = sqlite3Realloc(pCur->zBuf, nNew); - if( zNew==0 ){ - close(fd); - return SQLITE_NOMEM; - } - pCur->zBuf = zNew; - pCur->nAlloc = nNew; - } - - n = (int)read(fd, pCur->zBuf, sbuf.st_size); - close(fd); - if( n!=sbuf.st_size ) return SQLITE_ERROR; - pCur->nBuf = sbuf.st_size; - pCur->zBuf[pCur->nBuf] = '\0'; - - sqlite3_result_text(ctx, pCur->zBuf, -1, SQLITE_TRANSIENT); - } - return SQLITE_OK; -} - -static int fsRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){ - fs_cursor *pCur = (fs_cursor*)cur; - *pRowid = sqlite3_column_int64(pCur->pStmt, 0); - return SQLITE_OK; -} - -static int fsEof(sqlite3_vtab_cursor *cur){ - fs_cursor *pCur = (fs_cursor*)cur; - return (sqlite3_data_count(pCur->pStmt)==0); -} - -static int fsBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ - int ii; - - for(ii=0; ii<pIdxInfo->nConstraint; ii++){ - struct sqlite3_index_constraint const *pCons = &pIdxInfo->aConstraint[ii]; - if( pCons->iColumn<0 && pCons->usable - && pCons->op==SQLITE_INDEX_CONSTRAINT_EQ ){ - struct sqlite3_index_constraint_usage *pUsage; - pUsage = &pIdxInfo->aConstraintUsage[ii]; - pUsage->omit = 0; - pUsage->argvIndex = 1; - pIdxInfo->idxNum = 1; - pIdxInfo->estimatedCost = 1.0; - break; - } - } - - return SQLITE_OK; -} - -/* -** A virtual table module that provides read-only access to a -** Tcl global variable namespace. -*/ -static sqlite3_module fsModule = { - 0, /* iVersion */ - fsConnect, - fsConnect, - fsBestIndex, - fsDisconnect, - fsDisconnect, - fsOpen, /* xOpen - open a cursor */ - fsClose, /* xClose - close a cursor */ - fsFilter, /* xFilter - configure scan constraints */ - fsNext, /* xNext - advance a cursor */ - fsEof, /* xEof - check for end of scan */ - fsColumn, /* xColumn - read data */ - fsRowid, /* xRowid - read data */ - 0, /* xUpdate */ - 0, /* xBegin */ - 0, /* xSync */ - 0, /* xCommit */ - 0, /* xRollback */ - 0, /* xFindMethod */ - 0, /* xRename */ -}; - -/* -** Decode a pointer to an sqlite3 object. -*/ -extern int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb); - -/* -** Register the echo virtual table module. -*/ -static int register_fs_module( - 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; - if( objc!=2 ){ - Tcl_WrongNumArgs(interp, 1, objv, "DB"); - return TCL_ERROR; - } - if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; -#ifndef SQLITE_OMIT_VIRTUALTABLE - sqlite3_create_module(db, "fs", &fsModule, (void *)interp); -#endif - return TCL_OK; -} - -#endif - - -/* -** Register commands with the TCL interpreter. -*/ -int Sqlitetestfs_Init(Tcl_Interp *interp){ -#ifndef SQLITE_OMIT_VIRTUALTABLE - static struct { - char *zName; - Tcl_ObjCmdProc *xProc; - void *clientData; - } aObjCmd[] = { - { "register_fs_module", register_fs_module, 0 }, - }; - int i; - for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){ - Tcl_CreateObjCommand(interp, aObjCmd[i].zName, - aObjCmd[i].xProc, aObjCmd[i].clientData, 0); - } -#endif - return TCL_OK; -} diff --git a/components/external/SQLite-3.8.1/SQLiteLib/test/test_func.c b/components/external/SQLite-3.8.1/SQLiteLib/test/test_func.c deleted file mode 100644 index b250e33106..0000000000 --- a/components/external/SQLite-3.8.1/SQLiteLib/test/test_func.c +++ /dev/null @@ -1,767 +0,0 @@ -/* -** 2008 March 19 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** Code for testing all sorts of SQLite interfaces. This code -** implements new SQL functions used by the test scripts. -*/ -#include "sqlite3.h" -#include "tcl.h" -#include <stdlib.h> -#include <string.h> -#include <assert.h> - -#include "sqliteInt.h" -#include "vdbeInt.h" - - -/* -** Allocate nByte bytes of space using sqlite3_malloc(). If the -** allocation fails, call sqlite3_result_error_nomem() to notify -** the database handle that malloc() has failed. -*/ -static void *testContextMalloc(sqlite3_context *context, int nByte){ - char *z = sqlite3_malloc(nByte); - if( !z && nByte>0 ){ - sqlite3_result_error_nomem(context); - } - return z; -} - -/* -** This function generates a string of random characters. Used for -** generating test data. -*/ -static void randStr(sqlite3_context *context, int argc, sqlite3_value **argv){ - static const unsigned char zSrc[] = - "abcdefghijklmnopqrstuvwxyz" - "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "0123456789" - ".-!,:*^+=_|?/<> "; - int iMin, iMax, n, r, i; - unsigned char zBuf[1000]; - - /* It used to be possible to call randstr() with any number of arguments, - ** but now it is registered with SQLite as requiring exactly 2. - */ - assert(argc==2); - - iMin = sqlite3_value_int(argv[0]); - if( iMin<0 ) iMin = 0; - if( iMin>=sizeof(zBuf) ) iMin = sizeof(zBuf)-1; - iMax = sqlite3_value_int(argv[1]); - if( iMax<iMin ) iMax = iMin; - if( iMax>=sizeof(zBuf) ) iMax = sizeof(zBuf)-1; - n = iMin; - if( iMax>iMin ){ - sqlite3_randomness(sizeof(r), &r); - r &= 0x7fffffff; - n += r%(iMax + 1 - iMin); - } - assert( n<sizeof(zBuf) ); - sqlite3_randomness(n, zBuf); - for(i=0; i<n; i++){ - zBuf[i] = zSrc[zBuf[i]%(sizeof(zSrc)-1)]; - } - zBuf[n] = 0; - sqlite3_result_text(context, (char*)zBuf, n, SQLITE_TRANSIENT); -} - -/* -** The following two SQL functions are used to test returning a text -** result with a destructor. Function 'test_destructor' takes one argument -** and returns the same argument interpreted as TEXT. A destructor is -** passed with the sqlite3_result_text() call. -** -** SQL function 'test_destructor_count' returns the number of outstanding -** allocations made by 'test_destructor'; -** -** WARNING: Not threadsafe. -*/ -static int test_destructor_count_var = 0; -static void destructor(void *p){ - char *zVal = (char *)p; - assert(zVal); - zVal--; - sqlite3_free(zVal); - test_destructor_count_var--; -} -static void test_destructor( - sqlite3_context *pCtx, - int nArg, - sqlite3_value **argv -){ - char *zVal; - int len; - - test_destructor_count_var++; - assert( nArg==1 ); - if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return; - len = sqlite3_value_bytes(argv[0]); - zVal = testContextMalloc(pCtx, len+3); - if( !zVal ){ - return; - } - zVal[len+1] = 0; - zVal[len+2] = 0; - zVal++; - memcpy(zVal, sqlite3_value_text(argv[0]), len); - sqlite3_result_text(pCtx, zVal, -1, destructor); -} -#ifndef SQLITE_OMIT_UTF16 -static void test_destructor16( - sqlite3_context *pCtx, - int nArg, - sqlite3_value **argv -){ - char *zVal; - int len; - - test_destructor_count_var++; - assert( nArg==1 ); - if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return; - len = sqlite3_value_bytes16(argv[0]); - zVal = testContextMalloc(pCtx, len+3); - if( !zVal ){ - return; - } - zVal[len+1] = 0; - zVal[len+2] = 0; - zVal++; - memcpy(zVal, sqlite3_value_text16(argv[0]), len); - sqlite3_result_text16(pCtx, zVal, -1, destructor); -} -#endif -static void test_destructor_count( - sqlite3_context *pCtx, - int nArg, - sqlite3_value **argv -){ - sqlite3_result_int(pCtx, test_destructor_count_var); -} - -/* -** The following aggregate function, test_agg_errmsg16(), takes zero -** arguments. It returns the text value returned by the sqlite3_errmsg16() -** API function. -*/ -#ifndef SQLITE_OMIT_BUILTIN_TEST -void sqlite3BeginBenignMalloc(void); -void sqlite3EndBenignMalloc(void); -#else - #define sqlite3BeginBenignMalloc() - #define sqlite3EndBenignMalloc() -#endif -static void test_agg_errmsg16_step(sqlite3_context *a, int b,sqlite3_value **c){ -} -static void test_agg_errmsg16_final(sqlite3_context *ctx){ -#ifndef SQLITE_OMIT_UTF16 - const void *z; - sqlite3 * db = sqlite3_context_db_handle(ctx); - sqlite3_aggregate_context(ctx, 2048); - sqlite3BeginBenignMalloc(); - z = sqlite3_errmsg16(db); - sqlite3EndBenignMalloc(); - sqlite3_result_text16(ctx, z, -1, SQLITE_TRANSIENT); -#endif -} - -/* -** Routines for testing the sqlite3_get_auxdata() and sqlite3_set_auxdata() -** interface. -** -** The test_auxdata() SQL function attempts to register each of its arguments -** as auxiliary data. If there are no prior registrations of aux data for -** that argument (meaning the argument is not a constant or this is its first -** call) then the result for that argument is 0. If there is a prior -** registration, the result for that argument is 1. The overall result -** is the individual argument results separated by spaces. -*/ -static void free_test_auxdata(void *p) {sqlite3_free(p);} -static void test_auxdata( - sqlite3_context *pCtx, - int nArg, - sqlite3_value **argv -){ - int i; - char *zRet = testContextMalloc(pCtx, nArg*2); - if( !zRet ) return; - memset(zRet, 0, nArg*2); - for(i=0; i<nArg; i++){ - char const *z = (char*)sqlite3_value_text(argv[i]); - if( z ){ - int n; - char *zAux = sqlite3_get_auxdata(pCtx, i); - if( zAux ){ - zRet[i*2] = '1'; - assert( strcmp(zAux,z)==0 ); - }else { - zRet[i*2] = '0'; - } - n = (int)strlen(z) + 1; - zAux = testContextMalloc(pCtx, n); - if( zAux ){ - memcpy(zAux, z, n); - sqlite3_set_auxdata(pCtx, i, zAux, free_test_auxdata); - } - zRet[i*2+1] = ' '; - } - } - sqlite3_result_text(pCtx, zRet, 2*nArg-1, free_test_auxdata); -} - -/* -** A function to test error reporting from user functions. This function -** returns a copy of its first argument as the error message. If the -** second argument exists, it becomes the error code. -*/ -static void test_error( - sqlite3_context *pCtx, - int nArg, - sqlite3_value **argv -){ - sqlite3_result_error(pCtx, (char*)sqlite3_value_text(argv[0]), -1); - if( nArg==2 ){ - sqlite3_result_error_code(pCtx, sqlite3_value_int(argv[1])); - } -} - -/* -** Implementation of the counter(X) function. If X is an integer -** constant, then the first invocation will return X. The second X+1. -** and so forth. Can be used (for example) to provide a sequence number -** in a result set. -*/ -static void counterFunc( - sqlite3_context *pCtx, /* Function context */ - int nArg, /* Number of function arguments */ - sqlite3_value **argv /* Values for all function arguments */ -){ - int *pCounter = (int*)sqlite3_get_auxdata(pCtx, 0); - if( pCounter==0 ){ - pCounter = sqlite3_malloc( sizeof(*pCounter) ); - if( pCounter==0 ){ - sqlite3_result_error_nomem(pCtx); - return; - } - *pCounter = sqlite3_value_int(argv[0]); - sqlite3_set_auxdata(pCtx, 0, pCounter, sqlite3_free); - }else{ - ++*pCounter; - } - sqlite3_result_int(pCtx, *pCounter); -} - - -/* -** This function takes two arguments. It performance UTF-8/16 type -** conversions on the first argument then returns a copy of the second -** argument. -** -** This function is used in cases such as the following: -** -** SELECT test_isolation(x,x) FROM t1; -** -** We want to verify that the type conversions that occur on the -** first argument do not invalidate the second argument. -*/ -static void test_isolation( - sqlite3_context *pCtx, - int nArg, - sqlite3_value **argv -){ -#ifndef SQLITE_OMIT_UTF16 - sqlite3_value_text16(argv[0]); - sqlite3_value_text(argv[0]); - sqlite3_value_text16(argv[0]); - sqlite3_value_text(argv[0]); -#endif - sqlite3_result_value(pCtx, argv[1]); -} - -/* -** Invoke an SQL statement recursively. The function result is the -** first column of the first row of the result set. -*/ -static void test_eval( - sqlite3_context *pCtx, - int nArg, - sqlite3_value **argv -){ - sqlite3_stmt *pStmt; - int rc; - sqlite3 *db = sqlite3_context_db_handle(pCtx); - const char *zSql; - - zSql = (char*)sqlite3_value_text(argv[0]); - rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); - if( rc==SQLITE_OK ){ - rc = sqlite3_step(pStmt); - if( rc==SQLITE_ROW ){ - sqlite3_result_value(pCtx, sqlite3_column_value(pStmt, 0)); - } - rc = sqlite3_finalize(pStmt); - } - if( rc ){ - char *zErr; - assert( pStmt==0 ); - zErr = sqlite3_mprintf("sqlite3_prepare_v2() error: %s",sqlite3_errmsg(db)); - sqlite3_result_text(pCtx, zErr, -1, sqlite3_free); - sqlite3_result_error_code(pCtx, rc); - } -} - - -/* -** convert one character from hex to binary -*/ -static int testHexChar(char c){ - if( c>='0' && c<='9' ){ - return c - '0'; - }else if( c>='a' && c<='f' ){ - return c - 'a' + 10; - }else if( c>='A' && c<='F' ){ - return c - 'A' + 10; - } - return 0; -} - -/* -** Convert hex to binary. -*/ -static void testHexToBin(const char *zIn, char *zOut){ - while( zIn[0] && zIn[1] ){ - *(zOut++) = (testHexChar(zIn[0])<<4) + testHexChar(zIn[1]); - zIn += 2; - } -} - -/* -** hex_to_utf16be(HEX) -** -** Convert the input string from HEX into binary. Then return the -** result using sqlite3_result_text16le(). -*/ -#ifndef SQLITE_OMIT_UTF16 -static void testHexToUtf16be( - sqlite3_context *pCtx, - int nArg, - sqlite3_value **argv -){ - int n; - const char *zIn; - char *zOut; - assert( nArg==1 ); - n = sqlite3_value_bytes(argv[0]); - zIn = (const char*)sqlite3_value_text(argv[0]); - zOut = sqlite3_malloc( n/2 ); - if( zOut==0 ){ - sqlite3_result_error_nomem(pCtx); - }else{ - testHexToBin(zIn, zOut); - sqlite3_result_text16be(pCtx, zOut, n/2, sqlite3_free); - } -} -#endif - -/* -** hex_to_utf8(HEX) -** -** Convert the input string from HEX into binary. Then return the -** result using sqlite3_result_text16le(). -*/ -static void testHexToUtf8( - sqlite3_context *pCtx, - int nArg, - sqlite3_value **argv -){ - int n; - const char *zIn; - char *zOut; - assert( nArg==1 ); - n = sqlite3_value_bytes(argv[0]); - zIn = (const char*)sqlite3_value_text(argv[0]); - zOut = sqlite3_malloc( n/2 ); - if( zOut==0 ){ - sqlite3_result_error_nomem(pCtx); - }else{ - testHexToBin(zIn, zOut); - sqlite3_result_text(pCtx, zOut, n/2, sqlite3_free); - } -} - -/* -** hex_to_utf16le(HEX) -** -** Convert the input string from HEX into binary. Then return the -** result using sqlite3_result_text16le(). -*/ -#ifndef SQLITE_OMIT_UTF16 -static void testHexToUtf16le( - sqlite3_context *pCtx, - int nArg, - sqlite3_value **argv -){ - int n; - const char *zIn; - char *zOut; - assert( nArg==1 ); - n = sqlite3_value_bytes(argv[0]); - zIn = (const char*)sqlite3_value_text(argv[0]); - zOut = sqlite3_malloc( n/2 ); - if( zOut==0 ){ - sqlite3_result_error_nomem(pCtx); - }else{ - testHexToBin(zIn, zOut); - sqlite3_result_text16le(pCtx, zOut, n/2, sqlite3_free); - } -} -#endif - -/* -** SQL function: real2hex(X) -** -** If argument X is a real number, then convert it into a string which is -** the big-endian hexadecimal representation of the ieee754 encoding of -** that number. If X is not a real number, return NULL. -*/ -static void real2hex( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - union { - sqlite3_uint64 i; - double r; - unsigned char x[8]; - } v; - char zOut[20]; - int i; - int bigEndian; - v.i = 1; - bigEndian = v.x[0]==0; - v.r = sqlite3_value_double(argv[0]); - for(i=0; i<8; i++){ - if( bigEndian ){ - zOut[i*2] = "0123456789abcdef"[v.x[i]>>4]; - zOut[i*2+1] = "0123456789abcdef"[v.x[i]&0xf]; - }else{ - zOut[14-i*2] = "0123456789abcdef"[v.x[i]>>4]; - zOut[14-i*2+1] = "0123456789abcdef"[v.x[i]&0xf]; - } - } - zOut[16] = 0; - sqlite3_result_text(context, zOut, -1, SQLITE_TRANSIENT); -} - -/* -** tclcmd: test_extract(record, field) -** -** This function implements an SQL user-function that accepts a blob -** containing a formatted database record as the first argument. The -** second argument is the index of the field within that record to -** extract and return. -*/ -static void test_extract( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - sqlite3 *db = sqlite3_context_db_handle(context); - u8 *pRec; - u8 *pEndHdr; /* Points to one byte past record header */ - u8 *pHdr; /* Current point in record header */ - u8 *pBody; /* Current point in record data */ - u64 nHdr; /* Bytes in record header */ - int iIdx; /* Required field */ - int iCurrent = 0; /* Current field */ - - assert( argc==2 ); - pRec = (u8*)sqlite3_value_blob(argv[0]); - iIdx = sqlite3_value_int(argv[1]); - - pHdr = pRec + sqlite3GetVarint(pRec, &nHdr); - pBody = pEndHdr = &pRec[nHdr]; - - for(iCurrent=0; pHdr<pEndHdr && iCurrent<=iIdx; iCurrent++){ - u64 iSerialType; - Mem mem; - - memset(&mem, 0, sizeof(mem)); - mem.db = db; - mem.enc = ENC(db); - pHdr += sqlite3GetVarint(pHdr, &iSerialType); - pBody += sqlite3VdbeSerialGet(pBody, (u32)iSerialType, &mem); - sqlite3VdbeMemStoreType(&mem); - - if( iCurrent==iIdx ){ - sqlite3_result_value(context, &mem); - } - - sqlite3DbFree(db, mem.zMalloc); - } -} - -/* -** tclcmd: test_decode(record) -** -** This function implements an SQL user-function that accepts a blob -** containing a formatted database record as its only argument. It returns -** a tcl list (type SQLITE_TEXT) containing each of the values stored -** in the record. -*/ -static void test_decode( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - sqlite3 *db = sqlite3_context_db_handle(context); - u8 *pRec; - u8 *pEndHdr; /* Points to one byte past record header */ - u8 *pHdr; /* Current point in record header */ - u8 *pBody; /* Current point in record data */ - u64 nHdr; /* Bytes in record header */ - Tcl_Obj *pRet; /* Return value */ - - pRet = Tcl_NewObj(); - Tcl_IncrRefCount(pRet); - - assert( argc==1 ); - pRec = (u8*)sqlite3_value_blob(argv[0]); - - pHdr = pRec + sqlite3GetVarint(pRec, &nHdr); - pBody = pEndHdr = &pRec[nHdr]; - while( pHdr<pEndHdr ){ - Tcl_Obj *pVal = 0; - u64 iSerialType; - Mem mem; - - memset(&mem, 0, sizeof(mem)); - mem.db = db; - mem.enc = ENC(db); - pHdr += sqlite3GetVarint(pHdr, &iSerialType); - pBody += sqlite3VdbeSerialGet(pBody, (u32)iSerialType, &mem); - - sqlite3VdbeMemStoreType(&mem); - switch( sqlite3_value_type(&mem) ){ - case SQLITE_TEXT: - pVal = Tcl_NewStringObj((const char*)sqlite3_value_text(&mem), -1); - break; - - case SQLITE_BLOB: { - char hexdigit[] = { - '0', '1', '2', '3', '4', '5', '6', '7', - '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' - }; - int n = sqlite3_value_bytes(&mem); - u8 *z = (u8*)sqlite3_value_blob(&mem); - int i; - pVal = Tcl_NewStringObj("x'", -1); - for(i=0; i<n; i++){ - char hex[3]; - hex[0] = hexdigit[((z[i] >> 4) & 0x0F)]; - hex[1] = hexdigit[(z[i] & 0x0F)]; - hex[2] = '\0'; - Tcl_AppendStringsToObj(pVal, hex, 0); - } - Tcl_AppendStringsToObj(pVal, "'", 0); - break; - } - - case SQLITE_FLOAT: - pVal = Tcl_NewDoubleObj(sqlite3_value_double(&mem)); - break; - - case SQLITE_INTEGER: - pVal = Tcl_NewWideIntObj(sqlite3_value_int64(&mem)); - break; - - case SQLITE_NULL: - pVal = Tcl_NewStringObj("NULL", -1); - break; - - default: - assert( 0 ); - } - - Tcl_ListObjAppendElement(0, pRet, pVal); - - if( mem.zMalloc ){ - sqlite3DbFree(db, mem.zMalloc); - } - } - - sqlite3_result_text(context, Tcl_GetString(pRet), -1, SQLITE_TRANSIENT); - Tcl_DecrRefCount(pRet); -} - - -static int registerTestFunctions(sqlite3 *db){ - static const struct { - char *zName; - signed char nArg; - unsigned char eTextRep; /* 1: UTF-16. 0: UTF-8 */ - void (*xFunc)(sqlite3_context*,int,sqlite3_value **); - } aFuncs[] = { - { "randstr", 2, SQLITE_UTF8, randStr }, - { "test_destructor", 1, SQLITE_UTF8, test_destructor}, -#ifndef SQLITE_OMIT_UTF16 - { "test_destructor16", 1, SQLITE_UTF8, test_destructor16}, - { "hex_to_utf16be", 1, SQLITE_UTF8, testHexToUtf16be}, - { "hex_to_utf16le", 1, SQLITE_UTF8, testHexToUtf16le}, -#endif - { "hex_to_utf8", 1, SQLITE_UTF8, testHexToUtf8}, - { "test_destructor_count", 0, SQLITE_UTF8, test_destructor_count}, - { "test_auxdata", -1, SQLITE_UTF8, test_auxdata}, - { "test_error", 1, SQLITE_UTF8, test_error}, - { "test_error", 2, SQLITE_UTF8, test_error}, - { "test_eval", 1, SQLITE_UTF8, test_eval}, - { "test_isolation", 2, SQLITE_UTF8, test_isolation}, - { "test_counter", 1, SQLITE_UTF8, counterFunc}, - { "real2hex", 1, SQLITE_UTF8, real2hex}, - { "test_decode", 1, SQLITE_UTF8, test_decode}, - { "test_extract", 2, SQLITE_UTF8, test_extract}, - }; - int i; - - for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){ - sqlite3_create_function(db, aFuncs[i].zName, aFuncs[i].nArg, - aFuncs[i].eTextRep, 0, aFuncs[i].xFunc, 0, 0); - } - - sqlite3_create_function(db, "test_agg_errmsg16", 0, SQLITE_ANY, 0, 0, - test_agg_errmsg16_step, test_agg_errmsg16_final); - - return SQLITE_OK; -} - -/* -** TCLCMD: autoinstall_test_functions -** -** Invoke this TCL command to use sqlite3_auto_extension() to cause -** the standard set of test functions to be loaded into each new -** database connection. -*/ -static int autoinstall_test_funcs( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - extern int Md5_Register(sqlite3*); - int rc = sqlite3_auto_extension((void*)registerTestFunctions); - if( rc==SQLITE_OK ){ - rc = sqlite3_auto_extension((void*)Md5_Register); - } - Tcl_SetObjResult(interp, Tcl_NewIntObj(rc)); - return TCL_OK; -} - -/* -** A bogus step function and finalizer function. -*/ -static void tStep(sqlite3_context *a, int b, sqlite3_value **c){} -static void tFinal(sqlite3_context *a){} - - -/* -** tclcmd: abuse_create_function -** -** Make various calls to sqlite3_create_function that do not have valid -** parameters. Verify that the error condition is detected and reported. -*/ -static int abuse_create_function( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - extern int getDbPointer(Tcl_Interp*, const char*, sqlite3**); - sqlite3 *db; - int rc; - int mxArg; - - if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; - - rc = sqlite3_create_function(db, "tx", 1, SQLITE_UTF8, 0, tStep,tStep,tFinal); - if( rc!=SQLITE_MISUSE ) goto abuse_err; - - rc = sqlite3_create_function(db, "tx", 1, SQLITE_UTF8, 0, tStep, tStep, 0); - if( rc!=SQLITE_MISUSE ) goto abuse_err; - - rc = sqlite3_create_function(db, "tx", 1, SQLITE_UTF8, 0, tStep, 0, tFinal); - if( rc!=SQLITE_MISUSE) goto abuse_err; - - rc = sqlite3_create_function(db, "tx", 1, SQLITE_UTF8, 0, 0, 0, tFinal); - if( rc!=SQLITE_MISUSE ) goto abuse_err; - - rc = sqlite3_create_function(db, "tx", 1, SQLITE_UTF8, 0, 0, tStep, 0); - if( rc!=SQLITE_MISUSE ) goto abuse_err; - - rc = sqlite3_create_function(db, "tx", -2, SQLITE_UTF8, 0, tStep, 0, 0); - if( rc!=SQLITE_MISUSE ) goto abuse_err; - - rc = sqlite3_create_function(db, "tx", 128, SQLITE_UTF8, 0, tStep, 0, 0); - if( rc!=SQLITE_MISUSE ) goto abuse_err; - - rc = sqlite3_create_function(db, "funcxx" - "_123456789_123456789_123456789_123456789_123456789" - "_123456789_123456789_123456789_123456789_123456789" - "_123456789_123456789_123456789_123456789_123456789" - "_123456789_123456789_123456789_123456789_123456789" - "_123456789_123456789_123456789_123456789_123456789", - 1, SQLITE_UTF8, 0, tStep, 0, 0); - if( rc!=SQLITE_MISUSE ) goto abuse_err; - - /* This last function registration should actually work. Generate - ** a no-op function (that always returns NULL) and which has the - ** maximum-length function name and the maximum number of parameters. - */ - sqlite3_limit(db, SQLITE_LIMIT_FUNCTION_ARG, 10000); - mxArg = sqlite3_limit(db, SQLITE_LIMIT_FUNCTION_ARG, -1); - rc = sqlite3_create_function(db, "nullx" - "_123456789_123456789_123456789_123456789_123456789" - "_123456789_123456789_123456789_123456789_123456789" - "_123456789_123456789_123456789_123456789_123456789" - "_123456789_123456789_123456789_123456789_123456789" - "_123456789_123456789_123456789_123456789_123456789", - mxArg, SQLITE_UTF8, 0, tStep, 0, 0); - if( rc!=SQLITE_OK ) goto abuse_err; - - return TCL_OK; - -abuse_err: - Tcl_AppendResult(interp, "sqlite3_create_function abused test failed", - (char*)0); - return TCL_ERROR; -} - -/* -** Register commands with the TCL interpreter. -*/ -int Sqlitetest_func_Init(Tcl_Interp *interp){ - static struct { - char *zName; - Tcl_ObjCmdProc *xProc; - } aObjCmd[] = { - { "autoinstall_test_functions", autoinstall_test_funcs }, - { "abuse_create_function", abuse_create_function }, - }; - int i; - extern int Md5_Register(sqlite3*); - - for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){ - Tcl_CreateObjCommand(interp, aObjCmd[i].zName, aObjCmd[i].xProc, 0, 0); - } - sqlite3_initialize(); - sqlite3_auto_extension((void*)registerTestFunctions); - sqlite3_auto_extension((void*)Md5_Register); - return TCL_OK; -} diff --git a/components/external/SQLite-3.8.1/SQLiteLib/test/test_hexio.c b/components/external/SQLite-3.8.1/SQLiteLib/test/test_hexio.c deleted file mode 100644 index b20b5ce730..0000000000 --- a/components/external/SQLite-3.8.1/SQLiteLib/test/test_hexio.c +++ /dev/null @@ -1,388 +0,0 @@ -/* -** 2007 April 6 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** Code for testing all sorts of SQLite interfaces. This code -** implements TCL commands for reading and writing the binary -** database files and displaying the content of those files as -** hexadecimal. We could, in theory, use the built-in "binary" -** command of TCL to do a lot of this, but there are some issues -** with historical versions of the "binary" command. So it seems -** easier and safer to build our own mechanism. -*/ -#include "sqliteInt.h" -#include "tcl.h" -#include <stdlib.h> -#include <string.h> -#include <assert.h> - - -/* -** Convert binary to hex. The input zBuf[] contains N bytes of -** binary data. zBuf[] is 2*n+1 bytes long. Overwrite zBuf[] -** with a hexadecimal representation of its original binary input. -*/ -void sqlite3TestBinToHex(unsigned char *zBuf, int N){ - const unsigned char zHex[] = "0123456789ABCDEF"; - int i, j; - unsigned char c; - i = N*2; - zBuf[i--] = 0; - for(j=N-1; j>=0; j--){ - c = zBuf[j]; - zBuf[i--] = zHex[c&0xf]; - zBuf[i--] = zHex[c>>4]; - } - assert( i==-1 ); -} - -/* -** Convert hex to binary. The input zIn[] contains N bytes of -** hexadecimal. Convert this into binary and write aOut[] with -** the binary data. Spaces in the original input are ignored. -** Return the number of bytes of binary rendered. -*/ -int sqlite3TestHexToBin(const unsigned char *zIn, int N, unsigned char *aOut){ - const unsigned char aMap[] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 0, 0, 0, 0, 0, 0, - 0,11,12,13,14,15,16, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0,11,12,13,14,15,16, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - }; - int i, j; - int hi=1; - unsigned char c; - - for(i=j=0; i<N; i++){ - c = aMap[zIn[i]]; - if( c==0 ) continue; - if( hi ){ - aOut[j] = (c-1)<<4; - hi = 0; - }else{ - aOut[j++] |= c-1; - hi = 1; - } - } - return j; -} - - -/* -** Usage: hexio_read FILENAME OFFSET AMT -** -** Read AMT bytes from file FILENAME beginning at OFFSET from the -** beginning of the file. Convert that information to hexadecimal -** and return the resulting HEX string. -*/ -static int hexio_read( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - int offset; - int amt, got; - const char *zFile; - unsigned char *zBuf; - FILE *in; - - if( objc!=4 ){ - Tcl_WrongNumArgs(interp, 1, objv, "FILENAME OFFSET AMT"); - return TCL_ERROR; - } - if( Tcl_GetIntFromObj(interp, objv[2], &offset) ) return TCL_ERROR; - if( Tcl_GetIntFromObj(interp, objv[3], &amt) ) return TCL_ERROR; - zFile = Tcl_GetString(objv[1]); - zBuf = sqlite3_malloc( amt*2+1 ); - if( zBuf==0 ){ - return TCL_ERROR; - } - in = fopen(zFile, "rb"); - if( in==0 ){ - in = fopen(zFile, "r"); - } - if( in==0 ){ - Tcl_AppendResult(interp, "cannot open input file ", zFile, 0); - return TCL_ERROR; - } - fseek(in, offset, SEEK_SET); - got = (int)fread(zBuf, 1, amt, in); - fclose(in); - if( got<0 ){ - got = 0; - } - sqlite3TestBinToHex(zBuf, got); - Tcl_AppendResult(interp, zBuf, 0); - sqlite3_free(zBuf); - return TCL_OK; -} - - -/* -** Usage: hexio_write FILENAME OFFSET DATA -** -** Write DATA into file FILENAME beginning at OFFSET from the -** beginning of the file. DATA is expressed in hexadecimal. -*/ -static int hexio_write( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - int offset; - int nIn, nOut, written; - const char *zFile; - const unsigned char *zIn; - unsigned char *aOut; - FILE *out; - - if( objc!=4 ){ - Tcl_WrongNumArgs(interp, 1, objv, "FILENAME OFFSET HEXDATA"); - return TCL_ERROR; - } - if( Tcl_GetIntFromObj(interp, objv[2], &offset) ) return TCL_ERROR; - zFile = Tcl_GetString(objv[1]); - zIn = (const unsigned char *)Tcl_GetStringFromObj(objv[3], &nIn); - aOut = sqlite3_malloc( nIn/2 ); - if( aOut==0 ){ - return TCL_ERROR; - } - nOut = sqlite3TestHexToBin(zIn, nIn, aOut); - out = fopen(zFile, "r+b"); - if( out==0 ){ - out = fopen(zFile, "r+"); - } - if( out==0 ){ - Tcl_AppendResult(interp, "cannot open output file ", zFile, 0); - return TCL_ERROR; - } - fseek(out, offset, SEEK_SET); - written = (int)fwrite(aOut, 1, nOut, out); - sqlite3_free(aOut); - fclose(out); - Tcl_SetObjResult(interp, Tcl_NewIntObj(written)); - return TCL_OK; -} - -/* -** USAGE: hexio_get_int HEXDATA -** -** Interpret the HEXDATA argument as a big-endian integer. Return -** the value of that integer. HEXDATA can contain between 2 and 8 -** hexadecimal digits. -*/ -static int hexio_get_int( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - int val; - int nIn, nOut; - const unsigned char *zIn; - unsigned char *aOut; - unsigned char aNum[4]; - - if( objc!=2 ){ - Tcl_WrongNumArgs(interp, 1, objv, "HEXDATA"); - return TCL_ERROR; - } - zIn = (const unsigned char *)Tcl_GetStringFromObj(objv[1], &nIn); - aOut = sqlite3_malloc( nIn/2 ); - if( aOut==0 ){ - return TCL_ERROR; - } - nOut = sqlite3TestHexToBin(zIn, nIn, aOut); - if( nOut>=4 ){ - memcpy(aNum, aOut, 4); - }else{ - memset(aNum, 0, sizeof(aNum)); - memcpy(&aNum[4-nOut], aOut, nOut); - } - sqlite3_free(aOut); - val = (aNum[0]<<24) | (aNum[1]<<16) | (aNum[2]<<8) | aNum[3]; - Tcl_SetObjResult(interp, Tcl_NewIntObj(val)); - return TCL_OK; -} - - -/* -** USAGE: hexio_render_int16 INTEGER -** -** Render INTEGER has a 16-bit big-endian integer in hexadecimal. -*/ -static int hexio_render_int16( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - int val; - unsigned char aNum[10]; - - if( objc!=2 ){ - Tcl_WrongNumArgs(interp, 1, objv, "INTEGER"); - return TCL_ERROR; - } - if( Tcl_GetIntFromObj(interp, objv[1], &val) ) return TCL_ERROR; - aNum[0] = val>>8; - aNum[1] = val; - sqlite3TestBinToHex(aNum, 2); - Tcl_SetObjResult(interp, Tcl_NewStringObj((char*)aNum, 4)); - return TCL_OK; -} - - -/* -** USAGE: hexio_render_int32 INTEGER -** -** Render INTEGER has a 32-bit big-endian integer in hexadecimal. -*/ -static int hexio_render_int32( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - int val; - unsigned char aNum[10]; - - if( objc!=2 ){ - Tcl_WrongNumArgs(interp, 1, objv, "INTEGER"); - return TCL_ERROR; - } - if( Tcl_GetIntFromObj(interp, objv[1], &val) ) return TCL_ERROR; - aNum[0] = val>>24; - aNum[1] = val>>16; - aNum[2] = val>>8; - aNum[3] = val; - sqlite3TestBinToHex(aNum, 4); - Tcl_SetObjResult(interp, Tcl_NewStringObj((char*)aNum, 8)); - return TCL_OK; -} - -/* -** USAGE: utf8_to_utf8 HEX -** -** The argument is a UTF8 string represented in hexadecimal. -** The UTF8 might not be well-formed. Run this string through -** sqlite3Utf8to8() convert it back to hex and return the result. -*/ -static int utf8_to_utf8( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ -#ifdef SQLITE_DEBUG - int n; - int nOut; - const unsigned char *zOrig; - unsigned char *z; - if( objc!=2 ){ - Tcl_WrongNumArgs(interp, 1, objv, "HEX"); - return TCL_ERROR; - } - zOrig = (unsigned char *)Tcl_GetStringFromObj(objv[1], &n); - z = sqlite3_malloc( n+3 ); - n = sqlite3TestHexToBin(zOrig, n, z); - z[n] = 0; - nOut = sqlite3Utf8To8(z); - sqlite3TestBinToHex(z,nOut); - Tcl_AppendResult(interp, (char*)z, 0); - sqlite3_free(z); - return TCL_OK; -#else - Tcl_AppendResult(interp, - "[utf8_to_utf8] unavailable - SQLITE_DEBUG not defined", 0 - ); - return TCL_ERROR; -#endif -} - -static int getFts3Varint(const char *p, sqlite_int64 *v){ - const unsigned char *q = (const unsigned char *) p; - sqlite_uint64 x = 0, y = 1; - while( (*q & 0x80) == 0x80 ){ - x += y * (*q++ & 0x7f); - y <<= 7; - } - x += y * (*q++); - *v = (sqlite_int64) x; - return (int) (q - (unsigned char *)p); -} - - -/* -** USAGE: read_fts3varint BLOB VARNAME -** -** Read a varint from the start of BLOB. Set variable VARNAME to contain -** the interpreted value. Return the number of bytes of BLOB consumed. -*/ -static int read_fts3varint( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - int nBlob; - unsigned char *zBlob; - sqlite3_int64 iVal; - int nVal; - - if( objc!=3 ){ - Tcl_WrongNumArgs(interp, 1, objv, "BLOB VARNAME"); - return TCL_ERROR; - } - zBlob = Tcl_GetByteArrayFromObj(objv[1], &nBlob); - - nVal = getFts3Varint((char*)zBlob, (sqlite3_int64 *)(&iVal)); - Tcl_ObjSetVar2(interp, objv[2], 0, Tcl_NewWideIntObj(iVal), 0); - Tcl_SetObjResult(interp, Tcl_NewIntObj(nVal)); - return TCL_OK; -} - - -/* -** Register commands with the TCL interpreter. -*/ -int Sqlitetest_hexio_Init(Tcl_Interp *interp){ - static struct { - char *zName; - Tcl_ObjCmdProc *xProc; - } aObjCmd[] = { - { "hexio_read", hexio_read }, - { "hexio_write", hexio_write }, - { "hexio_get_int", hexio_get_int }, - { "hexio_render_int16", hexio_render_int16 }, - { "hexio_render_int32", hexio_render_int32 }, - { "utf8_to_utf8", utf8_to_utf8 }, - { "read_fts3varint", read_fts3varint }, - }; - int i; - for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){ - Tcl_CreateObjCommand(interp, aObjCmd[i].zName, aObjCmd[i].xProc, 0, 0); - } - return TCL_OK; -} diff --git a/components/external/SQLite-3.8.1/SQLiteLib/test/test_init.c b/components/external/SQLite-3.8.1/SQLiteLib/test/test_init.c deleted file mode 100644 index 502d95c052..0000000000 --- a/components/external/SQLite-3.8.1/SQLiteLib/test/test_init.c +++ /dev/null @@ -1,291 +0,0 @@ -/* -** 2009 August 17 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** -** The code in this file is used for testing SQLite. It is not part of -** the source code used in production systems. -** -** Specifically, this file tests the effect of errors while initializing -** the various pluggable sub-systems from within sqlite3_initialize(). -** If an error occurs in sqlite3_initialize() the following should be -** true: -** -** 1) An error code is returned to the user, and -** 2) A subsequent call to sqlite3_shutdown() calls the shutdown method -** of those subsystems that were initialized, and -** 3) A subsequent call to sqlite3_initialize() attempts to initialize -** the remaining, uninitialized, subsystems. -*/ - -#include "sqliteInt.h" -#include <string.h> -#include <tcl.h> - -static struct Wrapped { - sqlite3_pcache_methods2 pcache; - sqlite3_mem_methods mem; - sqlite3_mutex_methods mutex; - - int mem_init; /* True if mem subsystem is initalized */ - int mem_fail; /* True to fail mem subsystem inialization */ - int mutex_init; /* True if mutex subsystem is initalized */ - int mutex_fail; /* True to fail mutex subsystem inialization */ - int pcache_init; /* True if pcache subsystem is initalized */ - int pcache_fail; /* True to fail pcache subsystem inialization */ -} wrapped; - -static int wrMemInit(void *pAppData){ - int rc; - if( wrapped.mem_fail ){ - rc = SQLITE_ERROR; - }else{ - rc = wrapped.mem.xInit(wrapped.mem.pAppData); - } - if( rc==SQLITE_OK ){ - wrapped.mem_init = 1; - } - return rc; -} -static void wrMemShutdown(void *pAppData){ - wrapped.mem.xShutdown(wrapped.mem.pAppData); - wrapped.mem_init = 0; -} -static void *wrMemMalloc(int n) {return wrapped.mem.xMalloc(n);} -static void wrMemFree(void *p) {wrapped.mem.xFree(p);} -static void *wrMemRealloc(void *p, int n) {return wrapped.mem.xRealloc(p, n);} -static int wrMemSize(void *p) {return wrapped.mem.xSize(p);} -static int wrMemRoundup(int n) {return wrapped.mem.xRoundup(n);} - - -static int wrMutexInit(void){ - int rc; - if( wrapped.mutex_fail ){ - rc = SQLITE_ERROR; - }else{ - rc = wrapped.mutex.xMutexInit(); - } - if( rc==SQLITE_OK ){ - wrapped.mutex_init = 1; - } - return rc; -} -static int wrMutexEnd(void){ - wrapped.mutex.xMutexEnd(); - wrapped.mutex_init = 0; - return SQLITE_OK; -} -static sqlite3_mutex *wrMutexAlloc(int e){ - return wrapped.mutex.xMutexAlloc(e); -} -static void wrMutexFree(sqlite3_mutex *p){ - wrapped.mutex.xMutexFree(p); -} -static void wrMutexEnter(sqlite3_mutex *p){ - wrapped.mutex.xMutexEnter(p); -} -static int wrMutexTry(sqlite3_mutex *p){ - return wrapped.mutex.xMutexTry(p); -} -static void wrMutexLeave(sqlite3_mutex *p){ - wrapped.mutex.xMutexLeave(p); -} -static int wrMutexHeld(sqlite3_mutex *p){ - return wrapped.mutex.xMutexHeld(p); -} -static int wrMutexNotheld(sqlite3_mutex *p){ - return wrapped.mutex.xMutexNotheld(p); -} - - - -static int wrPCacheInit(void *pArg){ - int rc; - if( wrapped.pcache_fail ){ - rc = SQLITE_ERROR; - }else{ - rc = wrapped.pcache.xInit(wrapped.pcache.pArg); - } - if( rc==SQLITE_OK ){ - wrapped.pcache_init = 1; - } - return rc; -} -static void wrPCacheShutdown(void *pArg){ - wrapped.pcache.xShutdown(wrapped.pcache.pArg); - wrapped.pcache_init = 0; -} - -static sqlite3_pcache *wrPCacheCreate(int a, int b, int c){ - return wrapped.pcache.xCreate(a, b, c); -} -static void wrPCacheCachesize(sqlite3_pcache *p, int n){ - wrapped.pcache.xCachesize(p, n); -} -static int wrPCachePagecount(sqlite3_pcache *p){ - return wrapped.pcache.xPagecount(p); -} -static sqlite3_pcache_page *wrPCacheFetch(sqlite3_pcache *p, unsigned a, int b){ - return wrapped.pcache.xFetch(p, a, b); -} -static void wrPCacheUnpin(sqlite3_pcache *p, sqlite3_pcache_page *a, int b){ - wrapped.pcache.xUnpin(p, a, b); -} -static void wrPCacheRekey( - sqlite3_pcache *p, - sqlite3_pcache_page *a, - unsigned b, - unsigned c -){ - wrapped.pcache.xRekey(p, a, b, c); -} -static void wrPCacheTruncate(sqlite3_pcache *p, unsigned a){ - wrapped.pcache.xTruncate(p, a); -} -static void wrPCacheDestroy(sqlite3_pcache *p){ - wrapped.pcache.xDestroy(p); -} - -static void installInitWrappers(void){ - sqlite3_mutex_methods mutexmethods = { - wrMutexInit, wrMutexEnd, wrMutexAlloc, - wrMutexFree, wrMutexEnter, wrMutexTry, - wrMutexLeave, wrMutexHeld, wrMutexNotheld - }; - sqlite3_pcache_methods2 pcachemethods = { - 1, 0, - wrPCacheInit, wrPCacheShutdown, wrPCacheCreate, - wrPCacheCachesize, wrPCachePagecount, wrPCacheFetch, - wrPCacheUnpin, wrPCacheRekey, wrPCacheTruncate, - wrPCacheDestroy - }; - sqlite3_mem_methods memmethods = { - wrMemMalloc, wrMemFree, wrMemRealloc, - wrMemSize, wrMemRoundup, wrMemInit, - wrMemShutdown, - 0 - }; - - memset(&wrapped, 0, sizeof(wrapped)); - - sqlite3_shutdown(); - sqlite3_config(SQLITE_CONFIG_GETMUTEX, &wrapped.mutex); - sqlite3_config(SQLITE_CONFIG_GETMALLOC, &wrapped.mem); - sqlite3_config(SQLITE_CONFIG_GETPCACHE2, &wrapped.pcache); - sqlite3_config(SQLITE_CONFIG_MUTEX, &mutexmethods); - sqlite3_config(SQLITE_CONFIG_MALLOC, &memmethods); - sqlite3_config(SQLITE_CONFIG_PCACHE2, &pcachemethods); -} - -static int init_wrapper_install( - ClientData clientData, /* Unused */ - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int objc, /* Number of arguments */ - Tcl_Obj *CONST objv[] /* Command arguments */ -){ - int i; - installInitWrappers(); - for(i=1; i<objc; i++){ - char *z = Tcl_GetString(objv[i]); - if( strcmp(z, "mem")==0 ){ - wrapped.mem_fail = 1; - }else if( strcmp(z, "mutex")==0 ){ - wrapped.mutex_fail = 1; - }else if( strcmp(z, "pcache")==0 ){ - wrapped.pcache_fail = 1; - }else{ - Tcl_AppendResult(interp, "Unknown argument: \"", z, "\""); - return TCL_ERROR; - } - } - return TCL_OK; -} - -static int init_wrapper_uninstall( - ClientData clientData, /* Unused */ - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int objc, /* Number of arguments */ - Tcl_Obj *CONST objv[] /* Command arguments */ -){ - if( objc!=1 ){ - Tcl_WrongNumArgs(interp, 1, objv, ""); - return TCL_ERROR; - } - - sqlite3_shutdown(); - sqlite3_config(SQLITE_CONFIG_MUTEX, &wrapped.mutex); - sqlite3_config(SQLITE_CONFIG_MALLOC, &wrapped.mem); - sqlite3_config(SQLITE_CONFIG_PCACHE2, &wrapped.pcache); - return TCL_OK; -} - -static int init_wrapper_clear( - ClientData clientData, /* Unused */ - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int objc, /* Number of arguments */ - Tcl_Obj *CONST objv[] /* Command arguments */ -){ - if( objc!=1 ){ - Tcl_WrongNumArgs(interp, 1, objv, ""); - return TCL_ERROR; - } - - wrapped.mem_fail = 0; - wrapped.mutex_fail = 0; - wrapped.pcache_fail = 0; - return TCL_OK; -} - -static int init_wrapper_query( - ClientData clientData, /* Unused */ - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int objc, /* Number of arguments */ - Tcl_Obj *CONST objv[] /* Command arguments */ -){ - Tcl_Obj *pRet; - - if( objc!=1 ){ - Tcl_WrongNumArgs(interp, 1, objv, ""); - return TCL_ERROR; - } - - pRet = Tcl_NewObj(); - if( wrapped.mutex_init ){ - Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj("mutex", -1)); - } - if( wrapped.mem_init ){ - Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj("mem", -1)); - } - if( wrapped.pcache_init ){ - Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj("pcache", -1)); - } - - Tcl_SetObjResult(interp, pRet); - return TCL_OK; -} - -int Sqlitetest_init_Init(Tcl_Interp *interp){ - static struct { - char *zName; - Tcl_ObjCmdProc *xProc; - } aObjCmd[] = { - {"init_wrapper_install", init_wrapper_install}, - {"init_wrapper_query", init_wrapper_query }, - {"init_wrapper_uninstall", init_wrapper_uninstall}, - {"init_wrapper_clear", init_wrapper_clear} - }; - int i; - - for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){ - Tcl_CreateObjCommand(interp, aObjCmd[i].zName, aObjCmd[i].xProc, 0, 0); - } - - return TCL_OK; -} diff --git a/components/external/SQLite-3.8.1/SQLiteLib/test/test_intarray.c b/components/external/SQLite-3.8.1/SQLiteLib/test/test_intarray.c deleted file mode 100644 index f5c3d9e405..0000000000 --- a/components/external/SQLite-3.8.1/SQLiteLib/test/test_intarray.c +++ /dev/null @@ -1,382 +0,0 @@ -/* -** 2009 November 10 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** -** This file implements a read-only VIRTUAL TABLE that contains the -** content of a C-language array of integer values. See the corresponding -** header file for full details. -*/ -#include "test_intarray.h" -#include <string.h> -#include <assert.h> - - -/* -** Definition of the sqlite3_intarray object. -** -** The internal representation of an intarray object is subject -** to change, is not externally visible, and should be used by -** the implementation of intarray only. This object is opaque -** to users. -*/ -struct sqlite3_intarray { - int n; /* Number of elements in the array */ - sqlite3_int64 *a; /* Contents of the array */ - void (*xFree)(void*); /* Function used to free a[] */ -}; - -/* Objects used internally by the virtual table implementation */ -typedef struct intarray_vtab intarray_vtab; -typedef struct intarray_cursor intarray_cursor; - -/* A intarray table object */ -struct intarray_vtab { - sqlite3_vtab base; /* Base class */ - sqlite3_intarray *pContent; /* Content of the integer array */ -}; - -/* A intarray cursor object */ -struct intarray_cursor { - sqlite3_vtab_cursor base; /* Base class */ - int i; /* Current cursor position */ -}; - -/* -** None of this works unless we have virtual tables. -*/ -#ifndef SQLITE_OMIT_VIRTUALTABLE - -/* -** Free an sqlite3_intarray object. -*/ -static void intarrayFree(sqlite3_intarray *p){ - if( p->xFree ){ - p->xFree(p->a); - } - sqlite3_free(p); -} - -/* -** Table destructor for the intarray module. -*/ -static int intarrayDestroy(sqlite3_vtab *p){ - intarray_vtab *pVtab = (intarray_vtab*)p; - sqlite3_free(pVtab); - return 0; -} - -/* -** Table constructor for the intarray module. -*/ -static int intarrayCreate( - sqlite3 *db, /* Database where module is created */ - void *pAux, /* clientdata for the module */ - int argc, /* Number of arguments */ - const char *const*argv, /* Value for all arguments */ - sqlite3_vtab **ppVtab, /* Write the new virtual table object here */ - char **pzErr /* Put error message text here */ -){ - int rc = SQLITE_NOMEM; - intarray_vtab *pVtab = sqlite3_malloc(sizeof(intarray_vtab)); - - if( pVtab ){ - memset(pVtab, 0, sizeof(intarray_vtab)); - pVtab->pContent = (sqlite3_intarray*)pAux; - rc = sqlite3_declare_vtab(db, "CREATE TABLE x(value INTEGER PRIMARY KEY)"); - } - *ppVtab = (sqlite3_vtab *)pVtab; - return rc; -} - -/* -** Open a new cursor on the intarray table. -*/ -static int intarrayOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){ - int rc = SQLITE_NOMEM; - intarray_cursor *pCur; - pCur = sqlite3_malloc(sizeof(intarray_cursor)); - if( pCur ){ - memset(pCur, 0, sizeof(intarray_cursor)); - *ppCursor = (sqlite3_vtab_cursor *)pCur; - rc = SQLITE_OK; - } - return rc; -} - -/* -** Close a intarray table cursor. -*/ -static int intarrayClose(sqlite3_vtab_cursor *cur){ - intarray_cursor *pCur = (intarray_cursor *)cur; - sqlite3_free(pCur); - return SQLITE_OK; -} - -/* -** Retrieve a column of data. -*/ -static int intarrayColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){ - intarray_cursor *pCur = (intarray_cursor*)cur; - intarray_vtab *pVtab = (intarray_vtab*)cur->pVtab; - if( pCur->i>=0 && pCur->i<pVtab->pContent->n ){ - sqlite3_result_int64(ctx, pVtab->pContent->a[pCur->i]); - } - return SQLITE_OK; -} - -/* -** Retrieve the current rowid. -*/ -static int intarrayRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){ - intarray_cursor *pCur = (intarray_cursor *)cur; - *pRowid = pCur->i; - return SQLITE_OK; -} - -static int intarrayEof(sqlite3_vtab_cursor *cur){ - intarray_cursor *pCur = (intarray_cursor *)cur; - intarray_vtab *pVtab = (intarray_vtab *)cur->pVtab; - return pCur->i>=pVtab->pContent->n; -} - -/* -** Advance the cursor to the next row. -*/ -static int intarrayNext(sqlite3_vtab_cursor *cur){ - intarray_cursor *pCur = (intarray_cursor *)cur; - pCur->i++; - return SQLITE_OK; -} - -/* -** Reset a intarray table cursor. -*/ -static int intarrayFilter( - sqlite3_vtab_cursor *pVtabCursor, - int idxNum, const char *idxStr, - int argc, sqlite3_value **argv -){ - intarray_cursor *pCur = (intarray_cursor *)pVtabCursor; - pCur->i = 0; - return SQLITE_OK; -} - -/* -** Analyse the WHERE condition. -*/ -static int intarrayBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ - return SQLITE_OK; -} - -/* -** A virtual table module that merely echos method calls into TCL -** variables. -*/ -static sqlite3_module intarrayModule = { - 0, /* iVersion */ - intarrayCreate, /* xCreate - create a new virtual table */ - intarrayCreate, /* xConnect - connect to an existing vtab */ - intarrayBestIndex, /* xBestIndex - find the best query index */ - intarrayDestroy, /* xDisconnect - disconnect a vtab */ - intarrayDestroy, /* xDestroy - destroy a vtab */ - intarrayOpen, /* xOpen - open a cursor */ - intarrayClose, /* xClose - close a cursor */ - intarrayFilter, /* xFilter - configure scan constraints */ - intarrayNext, /* xNext - advance a cursor */ - intarrayEof, /* xEof */ - intarrayColumn, /* xColumn - read data */ - intarrayRowid, /* xRowid - read data */ - 0, /* xUpdate */ - 0, /* xBegin */ - 0, /* xSync */ - 0, /* xCommit */ - 0, /* xRollback */ - 0, /* xFindMethod */ - 0, /* xRename */ -}; - -#endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) */ - -/* -** Invoke this routine to create a specific instance of an intarray object. -** The new intarray object is returned by the 3rd parameter. -** -** Each intarray object corresponds to a virtual table in the TEMP table -** with a name of zName. -** -** Destroy the intarray object by dropping the virtual table. If not done -** explicitly by the application, the virtual table will be dropped implicitly -** by the system when the database connection is closed. -*/ -int sqlite3_intarray_create( - sqlite3 *db, - const char *zName, - sqlite3_intarray **ppReturn -){ - int rc = SQLITE_OK; -#ifndef SQLITE_OMIT_VIRTUALTABLE - sqlite3_intarray *p; - - *ppReturn = p = sqlite3_malloc( sizeof(*p) ); - if( p==0 ){ - return SQLITE_NOMEM; - } - memset(p, 0, sizeof(*p)); - rc = sqlite3_create_module_v2(db, zName, &intarrayModule, p, - (void(*)(void*))intarrayFree); - if( rc==SQLITE_OK ){ - char *zSql; - zSql = sqlite3_mprintf("CREATE VIRTUAL TABLE temp.%Q USING %Q", - zName, zName); - rc = sqlite3_exec(db, zSql, 0, 0, 0); - sqlite3_free(zSql); - } -#endif - return rc; -} - -/* -** Bind a new array array of integers to a specific intarray object. -** -** The array of integers bound must be unchanged for the duration of -** any query against the corresponding virtual table. If the integer -** array does change or is deallocated undefined behavior will result. -*/ -int sqlite3_intarray_bind( - sqlite3_intarray *pIntArray, /* The intarray object to bind to */ - int nElements, /* Number of elements in the intarray */ - sqlite3_int64 *aElements, /* Content of the intarray */ - void (*xFree)(void*) /* How to dispose of the intarray when done */ -){ - if( pIntArray->xFree ){ - pIntArray->xFree(pIntArray->a); - } - pIntArray->n = nElements; - pIntArray->a = aElements; - pIntArray->xFree = xFree; - return SQLITE_OK; -} - - -/***************************************************************************** -** Everything below is interface for testing this module. -*/ -#ifdef SQLITE_TEST -#include <tcl.h> - -/* -** Routines to encode and decode pointers -*/ -extern int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb); -extern void *sqlite3TestTextToPtr(const char*); -extern int sqlite3TestMakePointerStr(Tcl_Interp*, char *zPtr, void*); -extern const char *sqlite3ErrName(int); - -/* -** sqlite3_intarray_create DB NAME -** -** Invoke the sqlite3_intarray_create interface. A string that becomes -** the first parameter to sqlite3_intarray_bind. -*/ -static int test_intarray_create( - 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 */ -){ - sqlite3 *db; - const char *zName; - sqlite3_intarray *pArray; - int rc = SQLITE_OK; - char zPtr[100]; - - if( objc!=3 ){ - Tcl_WrongNumArgs(interp, 1, objv, "DB"); - return TCL_ERROR; - } - if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; - zName = Tcl_GetString(objv[2]); -#ifndef SQLITE_OMIT_VIRTUALTABLE - rc = sqlite3_intarray_create(db, zName, &pArray); -#endif - if( rc!=SQLITE_OK ){ - assert( pArray==0 ); - Tcl_AppendResult(interp, sqlite3ErrName(rc), (char*)0); - return TCL_ERROR; - } - sqlite3TestMakePointerStr(interp, zPtr, pArray); - Tcl_AppendResult(interp, zPtr, (char*)0); - return TCL_OK; -} - -/* -** sqlite3_intarray_bind INTARRAY ?VALUE ...? -** -** Invoke the sqlite3_intarray_bind interface on the given array of integers. -*/ -static int test_intarray_bind( - 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 */ -){ - sqlite3_intarray *pArray; - int rc = SQLITE_OK; - int i, n; - sqlite3_int64 *a; - - if( objc<2 ){ - Tcl_WrongNumArgs(interp, 1, objv, "INTARRAY"); - return TCL_ERROR; - } - pArray = (sqlite3_intarray*)sqlite3TestTextToPtr(Tcl_GetString(objv[1])); - n = objc - 2; -#ifndef SQLITE_OMIT_VIRTUALTABLE - a = sqlite3_malloc( sizeof(a[0])*n ); - if( a==0 ){ - Tcl_AppendResult(interp, "SQLITE_NOMEM", (char*)0); - return TCL_ERROR; - } - for(i=0; i<n; i++){ - Tcl_WideInt x = 0; - Tcl_GetWideIntFromObj(0, objv[i+2], &x); - a[i] = x; - } - rc = sqlite3_intarray_bind(pArray, n, a, sqlite3_free); - if( rc!=SQLITE_OK ){ - Tcl_AppendResult(interp, sqlite3ErrName(rc), (char*)0); - return TCL_ERROR; - } -#endif - return TCL_OK; -} - -/* -** Register commands with the TCL interpreter. -*/ -int Sqlitetestintarray_Init(Tcl_Interp *interp){ - static struct { - char *zName; - Tcl_ObjCmdProc *xProc; - void *clientData; - } aObjCmd[] = { - { "sqlite3_intarray_create", test_intarray_create, 0 }, - { "sqlite3_intarray_bind", test_intarray_bind, 0 }, - }; - int i; - for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){ - Tcl_CreateObjCommand(interp, aObjCmd[i].zName, - aObjCmd[i].xProc, aObjCmd[i].clientData, 0); - } - return TCL_OK; -} - -#endif /* SQLITE_TEST */ diff --git a/components/external/SQLite-3.8.1/SQLiteLib/test/test_intarray.h b/components/external/SQLite-3.8.1/SQLiteLib/test/test_intarray.h deleted file mode 100644 index 6d26235a87..0000000000 --- a/components/external/SQLite-3.8.1/SQLiteLib/test/test_intarray.h +++ /dev/null @@ -1,128 +0,0 @@ -/* -** 2009 November 10 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** -** This is the C-language interface definition for the "intarray" or -** integer array virtual table for SQLite. -** -** The intarray virtual table is designed to facilitate using an -** array of integers as the right-hand side of an IN operator. So -** instead of doing a prepared statement like this: -** -** SELECT * FROM table WHERE x IN (?,?,?,...,?); -** -** And then binding indivdual integers to each of ? slots, a C-language -** application can create an intarray object (named "ex1" in the following -** example), prepare a statement like this: -** -** SELECT * FROM table WHERE x IN ex1; -** -** Then bind an ordinary C/C++ array of integer values to the ex1 object -** to run the statement. -** -** USAGE: -** -** One or more intarray objects can be created as follows: -** -** sqlite3_intarray *p1, *p2, *p3; -** sqlite3_intarray_create(db, "ex1", &p1); -** sqlite3_intarray_create(db, "ex2", &p2); -** sqlite3_intarray_create(db, "ex3", &p3); -** -** Each call to sqlite3_intarray_create() generates a new virtual table -** module and a singleton of that virtual table module in the TEMP -** database. Both the module and the virtual table instance use the -** name given by the second parameter. The virtual tables can then be -** used in prepared statements: -** -** SELECT * FROM t1, t2, t3 -** WHERE t1.x IN ex1 -** AND t2.y IN ex2 -** AND t3.z IN ex3; -** -** Each integer array is initially empty. New arrays can be bound to -** an integer array as follows: -** -** sqlite3_int64 a1[] = { 1, 2, 3, 4 }; -** sqlite3_int64 a2[] = { 5, 6, 7, 8, 9, 10, 11 }; -** sqlite3_int64 *a3 = sqlite3_malloc( 100*sizeof(sqlite3_int64) ); -** // Fill in content of a3[] -** sqlite3_intarray_bind(p1, 4, a1, 0); -** sqlite3_intarray_bind(p2, 7, a2, 0); -** sqlite3_intarray_bind(p3, 100, a3, sqlite3_free); -** -** A single intarray object can be rebound multiple times. But do not -** attempt to change the bindings of an intarray while it is in the middle -** of a query. -** -** The array that holds the integers is automatically freed by the function -** in the fourth parameter to sqlite3_intarray_bind() when the array is no -** longer needed. The application must not change the intarray values -** while an intarray is in the middle of a query. -** -** The intarray object is automatically destroyed when its corresponding -** virtual table is dropped. Since the virtual tables are created in the -** TEMP database, they are automatically dropped when the database connection -** closes so the application does not normally need to take any special -** action to free the intarray objects. -*/ -#include "sqlite3.h" -#ifndef _INTARRAY_H_ -#define _INTARRAY_H_ - -/* -** Make sure we can call this stuff from C++. -*/ -#ifdef __cplusplus -extern "C" { -#endif - -/* -** An sqlite3_intarray is an abstract type to stores an instance of -** an integer array. -*/ -typedef struct sqlite3_intarray sqlite3_intarray; - -/* -** Invoke this routine to create a specific instance of an intarray object. -** The new intarray object is returned by the 3rd parameter. -** -** Each intarray object corresponds to a virtual table in the TEMP table -** with a name of zName. -** -** Destroy the intarray object by dropping the virtual table. If not done -** explicitly by the application, the virtual table will be dropped implicitly -** by the system when the database connection is closed. -*/ -int sqlite3_intarray_create( - sqlite3 *db, - const char *zName, - sqlite3_intarray **ppReturn -); - -/* -** Bind a new array array of integers to a specific intarray object. -** -** The array of integers bound must be unchanged for the duration of -** any query against the corresponding virtual table. If the integer -** array does change or is deallocated undefined behavior will result. -*/ -int sqlite3_intarray_bind( - sqlite3_intarray *pIntArray, /* The intarray object to bind to */ - int nElements, /* Number of elements in the intarray */ - sqlite3_int64 *aElements, /* Content of the intarray */ - void (*xFree)(void*) /* How to dispose of the intarray when done */ -); - -#ifdef __cplusplus -} /* End of the 'extern "C"' block */ -#endif -#endif /* _INTARRAY_H_ */ diff --git a/components/external/SQLite-3.8.1/SQLiteLib/test/test_journal.c b/components/external/SQLite-3.8.1/SQLiteLib/test/test_journal.c deleted file mode 100644 index e8701a4eea..0000000000 --- a/components/external/SQLite-3.8.1/SQLiteLib/test/test_journal.c +++ /dev/null @@ -1,857 +0,0 @@ -/* -** 2008 Jan 22 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -****************************************************************************** -** -** This file contains code for a VFS layer that acts as a wrapper around -** an existing VFS. The code in this file attempts to verify that SQLite -** correctly populates and syncs a journal file before writing to a -** corresponding database file. -** -** INTERFACE -** -** The public interface to this wrapper VFS is two functions: -** -** jt_register() -** jt_unregister() -** -** See header comments associated with those two functions below for -** details. -** -** LIMITATIONS -** -** This wrapper will not work if "PRAGMA synchronous = off" is used. -** -** OPERATION -** -** Starting a Transaction: -** -** When a write-transaction is started, the contents of the database is -** inspected and the following data stored as part of the database file -** handle (type struct jt_file): -** -** a) The page-size of the database file. -** b) The number of pages that are in the database file. -** c) The set of page numbers corresponding to free-list leaf pages. -** d) A check-sum for every page in the database file. -** -** The start of a write-transaction is deemed to have occurred when a -** 28-byte journal header is written to byte offset 0 of the journal -** file. -** -** Syncing the Journal File: -** -** Whenever the xSync method is invoked to sync a journal-file, the -** contents of the journal file are read. For each page written to -** the journal file, a check-sum is calculated and compared to the -** check-sum calculated for the corresponding database page when the -** write-transaction was initialized. The success of the comparison -** is assert()ed. So if SQLite has written something other than the -** original content to the database file, an assert() will fail. -** -** Additionally, the set of page numbers for which records exist in -** the journal file is added to (unioned with) the set of page numbers -** corresponding to free-list leaf pages collected when the -** write-transaction was initialized. This set comprises the page-numbers -** corresponding to those pages that SQLite may now safely modify. -** -** Writing to the Database File: -** -** When a block of data is written to a database file, the following -** invariants are asserted: -** -** a) That the block of data is an aligned block of page-size bytes. -** -** b) That if the page being written did not exist when the -** transaction was started (i.e. the database file is growing), then -** the journal-file must have been synced at least once since -** the start of the transaction. -** -** c) That if the page being written did exist when the transaction -** was started, then the page must have either been a free-list -** leaf page at the start of the transaction, or else must have -** been stored in the journal file prior to the most recent sync. -** -** Closing a Transaction: -** -** When a transaction is closed, all data collected at the start of -** the transaction, or following an xSync of a journal-file, is -** discarded. The end of a transaction is recognized when any one -** of the following occur: -** -** a) A block of zeroes (or anything else that is not a valid -** journal-header) is written to the start of the journal file. -** -** b) A journal file is truncated to zero bytes in size using xTruncate. -** -** c) The journal file is deleted using xDelete. -*/ -#if SQLITE_TEST /* This file is used for testing only */ - -#include "sqlite3.h" -#include "sqliteInt.h" - -/* -** Maximum pathname length supported by the jt backend. -*/ -#define JT_MAX_PATHNAME 512 - -/* -** Name used to identify this VFS. -*/ -#define JT_VFS_NAME "jt" - -typedef struct jt_file jt_file; -struct jt_file { - sqlite3_file base; - const char *zName; /* Name of open file */ - int flags; /* Flags the file was opened with */ - - /* The following are only used by database file file handles */ - int eLock; /* Current lock held on the file */ - u32 nPage; /* Size of file in pages when transaction started */ - u32 nPagesize; /* Page size when transaction started */ - Bitvec *pWritable; /* Bitvec of pages that may be written to the file */ - u32 *aCksum; /* Checksum for first nPage pages */ - int nSync; /* Number of times journal file has been synced */ - - /* Only used by journal file-handles */ - sqlite3_int64 iMaxOff; /* Maximum offset written to this transaction */ - - jt_file *pNext; /* All files are stored in a linked list */ - sqlite3_file *pReal; /* The file handle for the underlying vfs */ -}; - -/* -** Method declarations for jt_file. -*/ -static int jtClose(sqlite3_file*); -static int jtRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst); -static int jtWrite(sqlite3_file*,const void*,int iAmt, sqlite3_int64 iOfst); -static int jtTruncate(sqlite3_file*, sqlite3_int64 size); -static int jtSync(sqlite3_file*, int flags); -static int jtFileSize(sqlite3_file*, sqlite3_int64 *pSize); -static int jtLock(sqlite3_file*, int); -static int jtUnlock(sqlite3_file*, int); -static int jtCheckReservedLock(sqlite3_file*, int *); -static int jtFileControl(sqlite3_file*, int op, void *pArg); -static int jtSectorSize(sqlite3_file*); -static int jtDeviceCharacteristics(sqlite3_file*); - -/* -** Method declarations for jt_vfs. -*/ -static int jtOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *); -static int jtDelete(sqlite3_vfs*, const char *zName, int syncDir); -static int jtAccess(sqlite3_vfs*, const char *zName, int flags, int *); -static int jtFullPathname(sqlite3_vfs*, const char *zName, int, char *zOut); -static void *jtDlOpen(sqlite3_vfs*, const char *zFilename); -static void jtDlError(sqlite3_vfs*, int nByte, char *zErrMsg); -static void (*jtDlSym(sqlite3_vfs*,void*, const char *zSymbol))(void); -static void jtDlClose(sqlite3_vfs*, void*); -static int jtRandomness(sqlite3_vfs*, int nByte, char *zOut); -static int jtSleep(sqlite3_vfs*, int microseconds); -static int jtCurrentTime(sqlite3_vfs*, double*); -static int jtCurrentTimeInt64(sqlite3_vfs*, sqlite3_int64*); - -static sqlite3_vfs jt_vfs = { - 2, /* iVersion */ - sizeof(jt_file), /* szOsFile */ - JT_MAX_PATHNAME, /* mxPathname */ - 0, /* pNext */ - JT_VFS_NAME, /* zName */ - 0, /* pAppData */ - jtOpen, /* xOpen */ - jtDelete, /* xDelete */ - jtAccess, /* xAccess */ - jtFullPathname, /* xFullPathname */ - jtDlOpen, /* xDlOpen */ - jtDlError, /* xDlError */ - jtDlSym, /* xDlSym */ - jtDlClose, /* xDlClose */ - jtRandomness, /* xRandomness */ - jtSleep, /* xSleep */ - jtCurrentTime, /* xCurrentTime */ - 0, /* xGetLastError */ - jtCurrentTimeInt64 /* xCurrentTimeInt64 */ -}; - -static sqlite3_io_methods jt_io_methods = { - 1, /* iVersion */ - jtClose, /* xClose */ - jtRead, /* xRead */ - jtWrite, /* xWrite */ - jtTruncate, /* xTruncate */ - jtSync, /* xSync */ - jtFileSize, /* xFileSize */ - jtLock, /* xLock */ - jtUnlock, /* xUnlock */ - jtCheckReservedLock, /* xCheckReservedLock */ - jtFileControl, /* xFileControl */ - jtSectorSize, /* xSectorSize */ - jtDeviceCharacteristics /* xDeviceCharacteristics */ -}; - -struct JtGlobal { - sqlite3_vfs *pVfs; /* Parent VFS */ - jt_file *pList; /* List of all open files */ -}; -static struct JtGlobal g = {0, 0}; - -/* -** Functions to obtain and relinquish a mutex to protect g.pList. The -** STATIC_PRNG mutex is reused, purely for the sake of convenience. -*/ -static void enterJtMutex(void){ - sqlite3_mutex_enter(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_PRNG)); -} -static void leaveJtMutex(void){ - sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_PRNG)); -} - -extern int sqlite3_io_error_pending; -extern int sqlite3_io_error_hit; -static void stop_ioerr_simulation(int *piSave, int *piSave2){ - *piSave = sqlite3_io_error_pending; - *piSave2 = sqlite3_io_error_hit; - sqlite3_io_error_pending = -1; - sqlite3_io_error_hit = 0; -} -static void start_ioerr_simulation(int iSave, int iSave2){ - sqlite3_io_error_pending = iSave; - sqlite3_io_error_hit = iSave2; -} - -/* -** The jt_file pointed to by the argument may or may not be a file-handle -** open on a main database file. If it is, and a transaction is currently -** opened on the file, then discard all transaction related data. -*/ -static void closeTransaction(jt_file *p){ - sqlite3BitvecDestroy(p->pWritable); - sqlite3_free(p->aCksum); - p->pWritable = 0; - p->aCksum = 0; - p->nSync = 0; -} - -/* -** Close an jt-file. -*/ -static int jtClose(sqlite3_file *pFile){ - jt_file **pp; - jt_file *p = (jt_file *)pFile; - - closeTransaction(p); - enterJtMutex(); - if( p->zName ){ - for(pp=&g.pList; *pp!=p; pp=&(*pp)->pNext); - *pp = p->pNext; - } - leaveJtMutex(); - return sqlite3OsClose(p->pReal); -} - -/* -** Read data from an jt-file. -*/ -static int jtRead( - sqlite3_file *pFile, - void *zBuf, - int iAmt, - sqlite_int64 iOfst -){ - jt_file *p = (jt_file *)pFile; - return sqlite3OsRead(p->pReal, zBuf, iAmt, iOfst); -} - -/* -** Parameter zJournal is the name of a journal file that is currently -** open. This function locates and returns the handle opened on the -** corresponding database file by the pager that currently has the -** journal file opened. This file-handle is identified by the -** following properties: -** -** a) SQLITE_OPEN_MAIN_DB was specified when the file was opened. -** -** b) The file-name specified when the file was opened matches -** all but the final 8 characters of the journal file name. -** -** c) There is currently a reserved lock on the file. -**/ -static jt_file *locateDatabaseHandle(const char *zJournal){ - jt_file *pMain = 0; - enterJtMutex(); - for(pMain=g.pList; pMain; pMain=pMain->pNext){ - int nName = (int)(strlen(zJournal) - strlen("-journal")); - if( (pMain->flags&SQLITE_OPEN_MAIN_DB) - && ((int)strlen(pMain->zName)==nName) - && 0==memcmp(pMain->zName, zJournal, nName) - && (pMain->eLock>=SQLITE_LOCK_RESERVED) - ){ - break; - } - } - leaveJtMutex(); - return pMain; -} - -/* -** Parameter z points to a buffer of 4 bytes in size containing a -** unsigned 32-bit integer stored in big-endian format. Decode the -** integer and return its value. -*/ -static u32 decodeUint32(const unsigned char *z){ - return (z[0]<<24) + (z[1]<<16) + (z[2]<<8) + z[3]; -} - -/* -** Calculate a checksum from the buffer of length n bytes pointed to -** by parameter z. -*/ -static u32 genCksum(const unsigned char *z, int n){ - int i; - u32 cksum = 0; - for(i=0; i<n; i++){ - cksum = cksum + z[i] + (cksum<<3); - } - return cksum; -} - -/* -** The first argument, zBuf, points to a buffer containing a 28 byte -** serialized journal header. This function deserializes four of the -** integer fields contained in the journal header and writes their -** values to the output variables. -** -** SQLITE_OK is returned if the journal-header is successfully -** decoded. Otherwise, SQLITE_ERROR. -*/ -static int decodeJournalHdr( - const unsigned char *zBuf, /* Input: 28 byte journal header */ - u32 *pnRec, /* Out: Number of journalled records */ - u32 *pnPage, /* Out: Original database page count */ - u32 *pnSector, /* Out: Sector size in bytes */ - u32 *pnPagesize /* Out: Page size in bytes */ -){ - unsigned char aMagic[] = { 0xd9, 0xd5, 0x05, 0xf9, 0x20, 0xa1, 0x63, 0xd7 }; - if( memcmp(aMagic, zBuf, 8) ) return SQLITE_ERROR; - if( pnRec ) *pnRec = decodeUint32(&zBuf[8]); - if( pnPage ) *pnPage = decodeUint32(&zBuf[16]); - if( pnSector ) *pnSector = decodeUint32(&zBuf[20]); - if( pnPagesize ) *pnPagesize = decodeUint32(&zBuf[24]); - return SQLITE_OK; -} - -/* -** This function is called when a new transaction is opened, just after -** the first journal-header is written to the journal file. -*/ -static int openTransaction(jt_file *pMain, jt_file *pJournal){ - unsigned char *aData; - sqlite3_file *p = pMain->pReal; - int rc = SQLITE_OK; - - closeTransaction(pMain); - aData = sqlite3_malloc(pMain->nPagesize); - pMain->pWritable = sqlite3BitvecCreate(pMain->nPage); - pMain->aCksum = sqlite3_malloc(sizeof(u32) * (pMain->nPage + 1)); - pJournal->iMaxOff = 0; - - if( !pMain->pWritable || !pMain->aCksum || !aData ){ - rc = SQLITE_IOERR_NOMEM; - }else if( pMain->nPage>0 ){ - u32 iTrunk; - int iSave; - int iSave2; - - stop_ioerr_simulation(&iSave, &iSave2); - - /* Read the database free-list. Add the page-number for each free-list - ** leaf to the jt_file.pWritable bitvec. - */ - rc = sqlite3OsRead(p, aData, pMain->nPagesize, 0); - if( rc==SQLITE_OK ){ - u32 nDbsize = decodeUint32(&aData[28]); - if( nDbsize>0 && memcmp(&aData[24], &aData[92], 4)==0 ){ - u32 iPg; - for(iPg=nDbsize+1; iPg<=pMain->nPage; iPg++){ - sqlite3BitvecSet(pMain->pWritable, iPg); - } - } - } - iTrunk = decodeUint32(&aData[32]); - while( rc==SQLITE_OK && iTrunk>0 ){ - u32 nLeaf; - u32 iLeaf; - sqlite3_int64 iOff = (i64)(iTrunk-1)*pMain->nPagesize; - rc = sqlite3OsRead(p, aData, pMain->nPagesize, iOff); - nLeaf = decodeUint32(&aData[4]); - for(iLeaf=0; rc==SQLITE_OK && iLeaf<nLeaf; iLeaf++){ - u32 pgno = decodeUint32(&aData[8+4*iLeaf]); - sqlite3BitvecSet(pMain->pWritable, pgno); - } - iTrunk = decodeUint32(aData); - } - - /* Calculate and store a checksum for each page in the database file. */ - if( rc==SQLITE_OK ){ - int ii; - for(ii=0; rc==SQLITE_OK && ii<(int)pMain->nPage; ii++){ - i64 iOff = (i64)(pMain->nPagesize) * (i64)ii; - if( iOff==PENDING_BYTE ) continue; - rc = sqlite3OsRead(pMain->pReal, aData, pMain->nPagesize, iOff); - pMain->aCksum[ii] = genCksum(aData, pMain->nPagesize); - if( ii+1==pMain->nPage && rc==SQLITE_IOERR_SHORT_READ ) rc = SQLITE_OK; - } - } - - start_ioerr_simulation(iSave, iSave2); - } - - sqlite3_free(aData); - return rc; -} - -/* -** The first argument to this function is a handle open on a journal file. -** This function reads the journal file and adds the page number for each -** page in the journal to the Bitvec object passed as the second argument. -*/ -static int readJournalFile(jt_file *p, jt_file *pMain){ - int rc = SQLITE_OK; - unsigned char zBuf[28]; - sqlite3_file *pReal = p->pReal; - sqlite3_int64 iOff = 0; - sqlite3_int64 iSize = p->iMaxOff; - unsigned char *aPage; - int iSave; - int iSave2; - - aPage = sqlite3_malloc(pMain->nPagesize); - if( !aPage ){ - return SQLITE_IOERR_NOMEM; - } - - stop_ioerr_simulation(&iSave, &iSave2); - - while( rc==SQLITE_OK && iOff<iSize ){ - u32 nRec, nPage, nSector, nPagesize; - u32 ii; - - /* Read and decode the next journal-header from the journal file. */ - rc = sqlite3OsRead(pReal, zBuf, 28, iOff); - if( rc!=SQLITE_OK - || decodeJournalHdr(zBuf, &nRec, &nPage, &nSector, &nPagesize) - ){ - goto finish_rjf; - } - iOff += nSector; - - if( nRec==0 ){ - /* A trick. There might be another journal-header immediately - ** following this one. In this case, 0 records means 0 records, - ** not "read until the end of the file". See also ticket #2565. - */ - if( iSize>=(iOff+nSector) ){ - rc = sqlite3OsRead(pReal, zBuf, 28, iOff); - if( rc!=SQLITE_OK || 0==decodeJournalHdr(zBuf, 0, 0, 0, 0) ){ - continue; - } - } - nRec = (u32)((iSize-iOff) / (pMain->nPagesize+8)); - } - - /* Read all the records that follow the journal-header just read. */ - for(ii=0; rc==SQLITE_OK && ii<nRec && iOff<iSize; ii++){ - u32 pgno; - rc = sqlite3OsRead(pReal, zBuf, 4, iOff); - if( rc==SQLITE_OK ){ - pgno = decodeUint32(zBuf); - if( pgno>0 && pgno<=pMain->nPage ){ - if( 0==sqlite3BitvecTest(pMain->pWritable, pgno) ){ - rc = sqlite3OsRead(pReal, aPage, pMain->nPagesize, iOff+4); - if( rc==SQLITE_OK ){ - u32 cksum = genCksum(aPage, pMain->nPagesize); - assert( cksum==pMain->aCksum[pgno-1] ); - } - } - sqlite3BitvecSet(pMain->pWritable, pgno); - } - iOff += (8 + pMain->nPagesize); - } - } - - iOff = ((iOff + (nSector-1)) / nSector) * nSector; - } - -finish_rjf: - start_ioerr_simulation(iSave, iSave2); - sqlite3_free(aPage); - if( rc==SQLITE_IOERR_SHORT_READ ){ - rc = SQLITE_OK; - } - return rc; -} - -/* -** Write data to an jt-file. -*/ -static int jtWrite( - sqlite3_file *pFile, - const void *zBuf, - int iAmt, - sqlite_int64 iOfst -){ - int rc; - jt_file *p = (jt_file *)pFile; - if( p->flags&SQLITE_OPEN_MAIN_JOURNAL ){ - if( iOfst==0 ){ - jt_file *pMain = locateDatabaseHandle(p->zName); - assert( pMain ); - - if( iAmt==28 ){ - /* Zeroing the first journal-file header. This is the end of a - ** transaction. */ - closeTransaction(pMain); - }else if( iAmt!=12 ){ - /* Writing the first journal header to a journal file. This happens - ** when a transaction is first started. */ - u8 *z = (u8 *)zBuf; - pMain->nPage = decodeUint32(&z[16]); - pMain->nPagesize = decodeUint32(&z[24]); - if( SQLITE_OK!=(rc=openTransaction(pMain, p)) ){ - return rc; - } - } - } - if( p->iMaxOff<(iOfst + iAmt) ){ - p->iMaxOff = iOfst + iAmt; - } - } - - if( p->flags&SQLITE_OPEN_MAIN_DB && p->pWritable ){ - if( iAmt<(int)p->nPagesize - && p->nPagesize%iAmt==0 - && iOfst>=(PENDING_BYTE+512) - && iOfst+iAmt<=PENDING_BYTE+p->nPagesize - ){ - /* No-op. This special case is hit when the backup code is copying a - ** to a database with a larger page-size than the source database and - ** it needs to fill in the non-locking-region part of the original - ** pending-byte page. - */ - }else{ - u32 pgno = (u32)(iOfst/p->nPagesize + 1); - assert( (iAmt==1||iAmt==p->nPagesize) && ((iOfst+iAmt)%p->nPagesize)==0 ); - assert( pgno<=p->nPage || p->nSync>0 ); - assert( pgno>p->nPage || sqlite3BitvecTest(p->pWritable, pgno) ); - } - } - - rc = sqlite3OsWrite(p->pReal, zBuf, iAmt, iOfst); - if( (p->flags&SQLITE_OPEN_MAIN_JOURNAL) && iAmt==12 ){ - jt_file *pMain = locateDatabaseHandle(p->zName); - int rc2 = readJournalFile(p, pMain); - if( rc==SQLITE_OK ) rc = rc2; - } - return rc; -} - -/* -** Truncate an jt-file. -*/ -static int jtTruncate(sqlite3_file *pFile, sqlite_int64 size){ - jt_file *p = (jt_file *)pFile; - if( p->flags&SQLITE_OPEN_MAIN_JOURNAL && size==0 ){ - /* Truncating a journal file. This is the end of a transaction. */ - jt_file *pMain = locateDatabaseHandle(p->zName); - closeTransaction(pMain); - } - if( p->flags&SQLITE_OPEN_MAIN_DB && p->pWritable ){ - u32 pgno; - u32 locking_page = (u32)(PENDING_BYTE/p->nPagesize+1); - for(pgno=(u32)(size/p->nPagesize+1); pgno<=p->nPage; pgno++){ - assert( pgno==locking_page || sqlite3BitvecTest(p->pWritable, pgno) ); - } - } - return sqlite3OsTruncate(p->pReal, size); -} - -/* -** Sync an jt-file. -*/ -static int jtSync(sqlite3_file *pFile, int flags){ - jt_file *p = (jt_file *)pFile; - - if( p->flags&SQLITE_OPEN_MAIN_JOURNAL ){ - int rc; - jt_file *pMain; /* The associated database file */ - - /* The journal file is being synced. At this point, we inspect the - ** contents of the file up to this point and set each bit in the - ** jt_file.pWritable bitvec of the main database file associated with - ** this journal file. - */ - pMain = locateDatabaseHandle(p->zName); - assert(pMain); - - /* Set the bitvec values */ - if( pMain->pWritable ){ - pMain->nSync++; - rc = readJournalFile(p, pMain); - if( rc!=SQLITE_OK ){ - return rc; - } - } - } - - return sqlite3OsSync(p->pReal, flags); -} - -/* -** Return the current file-size of an jt-file. -*/ -static int jtFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){ - jt_file *p = (jt_file *)pFile; - return sqlite3OsFileSize(p->pReal, pSize); -} - -/* -** Lock an jt-file. -*/ -static int jtLock(sqlite3_file *pFile, int eLock){ - int rc; - jt_file *p = (jt_file *)pFile; - rc = sqlite3OsLock(p->pReal, eLock); - if( rc==SQLITE_OK && eLock>p->eLock ){ - p->eLock = eLock; - } - return rc; -} - -/* -** Unlock an jt-file. -*/ -static int jtUnlock(sqlite3_file *pFile, int eLock){ - int rc; - jt_file *p = (jt_file *)pFile; - rc = sqlite3OsUnlock(p->pReal, eLock); - if( rc==SQLITE_OK && eLock<p->eLock ){ - p->eLock = eLock; - } - return rc; -} - -/* -** Check if another file-handle holds a RESERVED lock on an jt-file. -*/ -static int jtCheckReservedLock(sqlite3_file *pFile, int *pResOut){ - jt_file *p = (jt_file *)pFile; - return sqlite3OsCheckReservedLock(p->pReal, pResOut); -} - -/* -** File control method. For custom operations on an jt-file. -*/ -static int jtFileControl(sqlite3_file *pFile, int op, void *pArg){ - jt_file *p = (jt_file *)pFile; - return p->pReal->pMethods->xFileControl(p->pReal, op, pArg); -} - -/* -** Return the sector-size in bytes for an jt-file. -*/ -static int jtSectorSize(sqlite3_file *pFile){ - jt_file *p = (jt_file *)pFile; - return sqlite3OsSectorSize(p->pReal); -} - -/* -** Return the device characteristic flags supported by an jt-file. -*/ -static int jtDeviceCharacteristics(sqlite3_file *pFile){ - jt_file *p = (jt_file *)pFile; - return sqlite3OsDeviceCharacteristics(p->pReal); -} - -/* -** Open an jt file handle. -*/ -static int jtOpen( - sqlite3_vfs *pVfs, - const char *zName, - sqlite3_file *pFile, - int flags, - int *pOutFlags -){ - int rc; - jt_file *p = (jt_file *)pFile; - pFile->pMethods = 0; - p->pReal = (sqlite3_file *)&p[1]; - p->pReal->pMethods = 0; - rc = sqlite3OsOpen(g.pVfs, zName, p->pReal, flags, pOutFlags); - assert( rc==SQLITE_OK || p->pReal->pMethods==0 ); - if( rc==SQLITE_OK ){ - pFile->pMethods = &jt_io_methods; - p->eLock = 0; - p->zName = zName; - p->flags = flags; - p->pNext = 0; - p->pWritable = 0; - p->aCksum = 0; - enterJtMutex(); - if( zName ){ - p->pNext = g.pList; - g.pList = p; - } - leaveJtMutex(); - } - return rc; -} - -/* -** Delete the file located at zPath. If the dirSync argument is true, -** ensure the file-system modifications are synced to disk before -** returning. -*/ -static int jtDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){ - int nPath = (int)strlen(zPath); - if( nPath>8 && 0==strcmp("-journal", &zPath[nPath-8]) ){ - /* Deleting a journal file. The end of a transaction. */ - jt_file *pMain = locateDatabaseHandle(zPath); - if( pMain ){ - closeTransaction(pMain); - } - } - - return sqlite3OsDelete(g.pVfs, zPath, dirSync); -} - -/* -** Test for access permissions. Return true if the requested permission -** is available, or false otherwise. -*/ -static int jtAccess( - sqlite3_vfs *pVfs, - const char *zPath, - int flags, - int *pResOut -){ - return sqlite3OsAccess(g.pVfs, zPath, flags, pResOut); -} - -/* -** Populate buffer zOut with the full canonical pathname corresponding -** to the pathname in zPath. zOut is guaranteed to point to a buffer -** of at least (JT_MAX_PATHNAME+1) bytes. -*/ -static int jtFullPathname( - sqlite3_vfs *pVfs, - const char *zPath, - int nOut, - char *zOut -){ - return sqlite3OsFullPathname(g.pVfs, zPath, nOut, zOut); -} - -/* -** Open the dynamic library located at zPath and return a handle. -*/ -static void *jtDlOpen(sqlite3_vfs *pVfs, const char *zPath){ - return g.pVfs->xDlOpen(g.pVfs, zPath); -} - -/* -** Populate the buffer zErrMsg (size nByte bytes) with a human readable -** utf-8 string describing the most recent error encountered associated -** with dynamic libraries. -*/ -static void jtDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){ - g.pVfs->xDlError(g.pVfs, nByte, zErrMsg); -} - -/* -** Return a pointer to the symbol zSymbol in the dynamic library pHandle. -*/ -static void (*jtDlSym(sqlite3_vfs *pVfs, void *p, const char *zSym))(void){ - return g.pVfs->xDlSym(g.pVfs, p, zSym); -} - -/* -** Close the dynamic library handle pHandle. -*/ -static void jtDlClose(sqlite3_vfs *pVfs, void *pHandle){ - g.pVfs->xDlClose(g.pVfs, pHandle); -} - -/* -** Populate the buffer pointed to by zBufOut with nByte bytes of -** random data. -*/ -static int jtRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){ - return sqlite3OsRandomness(g.pVfs, nByte, zBufOut); -} - -/* -** Sleep for nMicro microseconds. Return the number of microseconds -** actually slept. -*/ -static int jtSleep(sqlite3_vfs *pVfs, int nMicro){ - return sqlite3OsSleep(g.pVfs, nMicro); -} - -/* -** Return the current time as a Julian Day number in *pTimeOut. -*/ -static int jtCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){ - return g.pVfs->xCurrentTime(g.pVfs, pTimeOut); -} -/* -** Return the current time as a Julian Day number in *pTimeOut. -*/ -static int jtCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *pTimeOut){ - return g.pVfs->xCurrentTimeInt64(g.pVfs, pTimeOut); -} - -/************************************************************************** -** Start of public API. -*/ - -/* -** Configure the jt VFS as a wrapper around the VFS named by parameter -** zWrap. If the isDefault parameter is true, then the jt VFS is installed -** as the new default VFS for SQLite connections. If isDefault is not -** true, then the jt VFS is installed as non-default. In this case it -** is available via its name, "jt". -*/ -int jt_register(char *zWrap, int isDefault){ - g.pVfs = sqlite3_vfs_find(zWrap); - if( g.pVfs==0 ){ - return SQLITE_ERROR; - } - jt_vfs.szOsFile = sizeof(jt_file) + g.pVfs->szOsFile; - if( g.pVfs->iVersion==1 ){ - jt_vfs.iVersion = 1; - }else if( g.pVfs->xCurrentTimeInt64==0 ){ - jt_vfs.xCurrentTimeInt64 = 0; - } - sqlite3_vfs_register(&jt_vfs, isDefault); - return SQLITE_OK; -} - -/* -** Uninstall the jt VFS, if it is installed. -*/ -void jt_unregister(void){ - sqlite3_vfs_unregister(&jt_vfs); -} - -#endif diff --git a/components/external/SQLite-3.8.1/SQLiteLib/test/test_loadext.c b/components/external/SQLite-3.8.1/SQLiteLib/test/test_loadext.c deleted file mode 100644 index 1137e3a9aa..0000000000 --- a/components/external/SQLite-3.8.1/SQLiteLib/test/test_loadext.c +++ /dev/null @@ -1,122 +0,0 @@ -/* -** 2006 June 14 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** Test extension for testing the sqlite3_load_extension() function. -*/ -#include <string.h> -#include "sqlite3ext.h" -SQLITE_EXTENSION_INIT1 - -/* -** The half() SQL function returns half of its input value. -*/ -static void halfFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - sqlite3_result_double(context, 0.5*sqlite3_value_double(argv[0])); -} - -/* -** SQL functions to call the sqlite3_status function and return results. -*/ -static void statusFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - int op, mx, cur, resetFlag, rc; - if( sqlite3_value_type(argv[0])==SQLITE_INTEGER ){ - op = sqlite3_value_int(argv[0]); - }else if( sqlite3_value_type(argv[0])==SQLITE_TEXT ){ - int i; - const char *zName; - static const struct { - const char *zName; - int op; - } aOp[] = { - { "MEMORY_USED", SQLITE_STATUS_MEMORY_USED }, - { "PAGECACHE_USED", SQLITE_STATUS_PAGECACHE_USED }, - { "PAGECACHE_OVERFLOW", SQLITE_STATUS_PAGECACHE_OVERFLOW }, - { "SCRATCH_USED", SQLITE_STATUS_SCRATCH_USED }, - { "SCRATCH_OVERFLOW", SQLITE_STATUS_SCRATCH_OVERFLOW }, - { "MALLOC_SIZE", SQLITE_STATUS_MALLOC_SIZE }, - }; - int nOp = sizeof(aOp)/sizeof(aOp[0]); - zName = (const char*)sqlite3_value_text(argv[0]); - for(i=0; i<nOp; i++){ - if( strcmp(aOp[i].zName, zName)==0 ){ - op = aOp[i].op; - break; - } - } - if( i>=nOp ){ - char *zMsg = sqlite3_mprintf("unknown status property: %s", zName); - sqlite3_result_error(context, zMsg, -1); - sqlite3_free(zMsg); - return; - } - }else{ - sqlite3_result_error(context, "unknown status type", -1); - return; - } - if( argc==2 ){ - resetFlag = sqlite3_value_int(argv[1]); - }else{ - resetFlag = 0; - } - rc = sqlite3_status(op, &cur, &mx, resetFlag); - if( rc!=SQLITE_OK ){ - char *zMsg = sqlite3_mprintf("sqlite3_status(%d,...) returns %d", op, rc); - sqlite3_result_error(context, zMsg, -1); - sqlite3_free(zMsg); - return; - } - if( argc==2 ){ - sqlite3_result_int(context, mx); - }else{ - sqlite3_result_int(context, cur); - } -} - -/* -** Extension load function. -*/ -int testloadext_init( - sqlite3 *db, - char **pzErrMsg, - const sqlite3_api_routines *pApi -){ - int nErr = 0; - SQLITE_EXTENSION_INIT2(pApi); - nErr |= sqlite3_create_function(db, "half", 1, SQLITE_ANY, 0, halfFunc, 0, 0); - nErr |= sqlite3_create_function(db, "sqlite3_status", 1, SQLITE_ANY, 0, - statusFunc, 0, 0); - nErr |= sqlite3_create_function(db, "sqlite3_status", 2, SQLITE_ANY, 0, - statusFunc, 0, 0); - return nErr ? SQLITE_ERROR : SQLITE_OK; -} - -/* -** Another extension entry point. This one always fails. -*/ -int testbrokenext_init( - sqlite3 *db, - char **pzErrMsg, - const sqlite3_api_routines *pApi -){ - char *zErr; - SQLITE_EXTENSION_INIT2(pApi); - zErr = sqlite3_mprintf("broken!"); - *pzErrMsg = zErr; - return 1; -} diff --git a/components/external/SQLite-3.8.1/SQLiteLib/test/test_malloc.c b/components/external/SQLite-3.8.1/SQLiteLib/test/test_malloc.c deleted file mode 100644 index f513e24bf4..0000000000 --- a/components/external/SQLite-3.8.1/SQLiteLib/test/test_malloc.c +++ /dev/null @@ -1,1494 +0,0 @@ -/* -** 2007 August 15 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** -** This file contains code used to implement test interfaces to the -** memory allocation subsystem. -*/ -#include "sqliteInt.h" -#include "tcl.h" -#include <stdlib.h> -#include <string.h> -#include <assert.h> - -/* -** This structure is used to encapsulate the global state variables used -** by malloc() fault simulation. -*/ -static struct MemFault { - int iCountdown; /* Number of pending successes before a failure */ - int nRepeat; /* Number of times to repeat the failure */ - int nBenign; /* Number of benign failures seen since last config */ - int nFail; /* Number of failures seen since last config */ - u8 enable; /* True if enabled */ - int isInstalled; /* True if the fault simulation layer is installed */ - int isBenignMode; /* True if malloc failures are considered benign */ - sqlite3_mem_methods m; /* 'Real' malloc implementation */ -} memfault; - -/* -** This routine exists as a place to set a breakpoint that will -** fire on any simulated malloc() failure. -*/ -static void sqlite3Fault(void){ - static int cnt = 0; - cnt++; -} - -/* -** Check to see if a fault should be simulated. Return true to simulate -** the fault. Return false if the fault should not be simulated. -*/ -static int faultsimStep(void){ - if( likely(!memfault.enable) ){ - return 0; - } - if( memfault.iCountdown>0 ){ - memfault.iCountdown--; - return 0; - } - sqlite3Fault(); - memfault.nFail++; - if( memfault.isBenignMode>0 ){ - memfault.nBenign++; - } - memfault.nRepeat--; - if( memfault.nRepeat<=0 ){ - memfault.enable = 0; - } - return 1; -} - -/* -** A version of sqlite3_mem_methods.xMalloc() that includes fault simulation -** logic. -*/ -static void *faultsimMalloc(int n){ - void *p = 0; - if( !faultsimStep() ){ - p = memfault.m.xMalloc(n); - } - return p; -} - - -/* -** A version of sqlite3_mem_methods.xRealloc() that includes fault simulation -** logic. -*/ -static void *faultsimRealloc(void *pOld, int n){ - void *p = 0; - if( !faultsimStep() ){ - p = memfault.m.xRealloc(pOld, n); - } - return p; -} - -/* -** The following method calls are passed directly through to the underlying -** malloc system: -** -** xFree -** xSize -** xRoundup -** xInit -** xShutdown -*/ -static void faultsimFree(void *p){ - memfault.m.xFree(p); -} -static int faultsimSize(void *p){ - return memfault.m.xSize(p); -} -static int faultsimRoundup(int n){ - return memfault.m.xRoundup(n); -} -static int faultsimInit(void *p){ - return memfault.m.xInit(memfault.m.pAppData); -} -static void faultsimShutdown(void *p){ - memfault.m.xShutdown(memfault.m.pAppData); -} - -/* -** This routine configures the malloc failure simulation. After -** calling this routine, the next nDelay mallocs will succeed, followed -** by a block of nRepeat failures, after which malloc() calls will begin -** to succeed again. -*/ -static void faultsimConfig(int nDelay, int nRepeat){ - memfault.iCountdown = nDelay; - memfault.nRepeat = nRepeat; - memfault.nBenign = 0; - memfault.nFail = 0; - memfault.enable = nDelay>=0; - - /* Sometimes, when running multi-threaded tests, the isBenignMode - ** variable is not properly incremented/decremented so that it is - ** 0 when not inside a benign malloc block. This doesn't affect - ** the multi-threaded tests, as they do not use this system. But - ** it does affect OOM tests run later in the same process. So - ** zero the variable here, just to be sure. - */ - memfault.isBenignMode = 0; -} - -/* -** Return the number of faults (both hard and benign faults) that have -** occurred since the injector was last configured. -*/ -static int faultsimFailures(void){ - return memfault.nFail; -} - -/* -** Return the number of benign faults that have occurred since the -** injector was last configured. -*/ -static int faultsimBenignFailures(void){ - return memfault.nBenign; -} - -/* -** Return the number of successes that will occur before the next failure. -** If no failures are scheduled, return -1. -*/ -static int faultsimPending(void){ - if( memfault.enable ){ - return memfault.iCountdown; - }else{ - return -1; - } -} - - -static void faultsimBeginBenign(void){ - memfault.isBenignMode++; -} -static void faultsimEndBenign(void){ - memfault.isBenignMode--; -} - -/* -** Add or remove the fault-simulation layer using sqlite3_config(). If -** the argument is non-zero, the -*/ -static int faultsimInstall(int install){ - static struct sqlite3_mem_methods m = { - faultsimMalloc, /* xMalloc */ - faultsimFree, /* xFree */ - faultsimRealloc, /* xRealloc */ - faultsimSize, /* xSize */ - faultsimRoundup, /* xRoundup */ - faultsimInit, /* xInit */ - faultsimShutdown, /* xShutdown */ - 0 /* pAppData */ - }; - int rc; - - install = (install ? 1 : 0); - assert(memfault.isInstalled==1 || memfault.isInstalled==0); - - if( install==memfault.isInstalled ){ - return SQLITE_ERROR; - } - - if( install ){ - rc = sqlite3_config(SQLITE_CONFIG_GETMALLOC, &memfault.m); - assert(memfault.m.xMalloc); - if( rc==SQLITE_OK ){ - rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &m); - } - sqlite3_test_control(SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS, - faultsimBeginBenign, faultsimEndBenign - ); - }else{ - sqlite3_mem_methods m; - assert(memfault.m.xMalloc); - - /* One should be able to reset the default memory allocator by storing - ** a zeroed allocator then calling GETMALLOC. */ - memset(&m, 0, sizeof(m)); - sqlite3_config(SQLITE_CONFIG_MALLOC, &m); - sqlite3_config(SQLITE_CONFIG_GETMALLOC, &m); - assert( memcmp(&m, &memfault.m, sizeof(m))==0 ); - - rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &memfault.m); - sqlite3_test_control(SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS, 0, 0); - } - - if( rc==SQLITE_OK ){ - memfault.isInstalled = 1; - } - return rc; -} - -#ifdef SQLITE_TEST - -/* -** This function is implemented in main.c. Returns a pointer to a static -** buffer containing the symbolic SQLite error code that corresponds to -** the least-significant 8-bits of the integer passed as an argument. -** For example: -** -** sqlite3ErrName(1) -> "SQLITE_ERROR" -*/ -extern const char *sqlite3ErrName(int); - -/* -** Transform pointers to text and back again -*/ -static void pointerToText(void *p, char *z){ - static const char zHex[] = "0123456789abcdef"; - int i, k; - unsigned int u; - sqlite3_uint64 n; - if( p==0 ){ - strcpy(z, "0"); - return; - } - if( sizeof(n)==sizeof(p) ){ - memcpy(&n, &p, sizeof(p)); - }else if( sizeof(u)==sizeof(p) ){ - memcpy(&u, &p, sizeof(u)); - n = u; - }else{ - assert( 0 ); - } - for(i=0, k=sizeof(p)*2-1; i<sizeof(p)*2; i++, k--){ - z[k] = zHex[n&0xf]; - n >>= 4; - } - z[sizeof(p)*2] = 0; -} -static int hexToInt(int h){ - if( h>='0' && h<='9' ){ - return h - '0'; - }else if( h>='a' && h<='f' ){ - return h - 'a' + 10; - }else{ - return -1; - } -} -static int textToPointer(const char *z, void **pp){ - sqlite3_uint64 n = 0; - int i; - unsigned int u; - for(i=0; i<sizeof(void*)*2 && z[0]; i++){ - int v; - v = hexToInt(*z++); - if( v<0 ) return TCL_ERROR; - n = n*16 + v; - } - if( *z!=0 ) return TCL_ERROR; - if( sizeof(n)==sizeof(*pp) ){ - memcpy(pp, &n, sizeof(n)); - }else if( sizeof(u)==sizeof(*pp) ){ - u = (unsigned int)n; - memcpy(pp, &u, sizeof(u)); - }else{ - assert( 0 ); - } - return TCL_OK; -} - -/* -** Usage: sqlite3_malloc NBYTES -** -** Raw test interface for sqlite3_malloc(). -*/ -static int test_malloc( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - int nByte; - void *p; - char zOut[100]; - if( objc!=2 ){ - Tcl_WrongNumArgs(interp, 1, objv, "NBYTES"); - return TCL_ERROR; - } - if( Tcl_GetIntFromObj(interp, objv[1], &nByte) ) return TCL_ERROR; - p = sqlite3_malloc((unsigned)nByte); - pointerToText(p, zOut); - Tcl_AppendResult(interp, zOut, NULL); - return TCL_OK; -} - -/* -** Usage: sqlite3_realloc PRIOR NBYTES -** -** Raw test interface for sqlite3_realloc(). -*/ -static int test_realloc( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - int nByte; - void *pPrior, *p; - char zOut[100]; - if( objc!=3 ){ - Tcl_WrongNumArgs(interp, 1, objv, "PRIOR NBYTES"); - return TCL_ERROR; - } - if( Tcl_GetIntFromObj(interp, objv[2], &nByte) ) return TCL_ERROR; - if( textToPointer(Tcl_GetString(objv[1]), &pPrior) ){ - Tcl_AppendResult(interp, "bad pointer: ", Tcl_GetString(objv[1]), (char*)0); - return TCL_ERROR; - } - p = sqlite3_realloc(pPrior, (unsigned)nByte); - pointerToText(p, zOut); - Tcl_AppendResult(interp, zOut, NULL); - return TCL_OK; -} - -/* -** Usage: sqlite3_free PRIOR -** -** Raw test interface for sqlite3_free(). -*/ -static int test_free( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - void *pPrior; - if( objc!=2 ){ - Tcl_WrongNumArgs(interp, 1, objv, "PRIOR"); - return TCL_ERROR; - } - if( textToPointer(Tcl_GetString(objv[1]), &pPrior) ){ - Tcl_AppendResult(interp, "bad pointer: ", Tcl_GetString(objv[1]), (char*)0); - return TCL_ERROR; - } - sqlite3_free(pPrior); - return TCL_OK; -} - -/* -** These routines are in test_hexio.c -*/ -int sqlite3TestHexToBin(const char *, int, char *); -int sqlite3TestBinToHex(char*,int); - -/* -** Usage: memset ADDRESS SIZE HEX -** -** Set a chunk of memory (obtained from malloc, probably) to a -** specified hex pattern. -*/ -static int test_memset( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - void *p; - int size, n, i; - char *zHex; - char *zOut; - char zBin[100]; - - if( objc!=4 ){ - Tcl_WrongNumArgs(interp, 1, objv, "ADDRESS SIZE HEX"); - return TCL_ERROR; - } - if( textToPointer(Tcl_GetString(objv[1]), &p) ){ - Tcl_AppendResult(interp, "bad pointer: ", Tcl_GetString(objv[1]), (char*)0); - return TCL_ERROR; - } - if( Tcl_GetIntFromObj(interp, objv[2], &size) ){ - return TCL_ERROR; - } - if( size<=0 ){ - Tcl_AppendResult(interp, "size must be positive", (char*)0); - return TCL_ERROR; - } - zHex = Tcl_GetStringFromObj(objv[3], &n); - if( n>sizeof(zBin)*2 ) n = sizeof(zBin)*2; - n = sqlite3TestHexToBin(zHex, n, zBin); - if( n==0 ){ - Tcl_AppendResult(interp, "no data", (char*)0); - return TCL_ERROR; - } - zOut = p; - for(i=0; i<size; i++){ - zOut[i] = zBin[i%n]; - } - return TCL_OK; -} - -/* -** Usage: memget ADDRESS SIZE -** -** Return memory as hexadecimal text. -*/ -static int test_memget( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - void *p; - int size, n; - char *zBin; - char zHex[100]; - - if( objc!=3 ){ - Tcl_WrongNumArgs(interp, 1, objv, "ADDRESS SIZE"); - return TCL_ERROR; - } - if( textToPointer(Tcl_GetString(objv[1]), &p) ){ - Tcl_AppendResult(interp, "bad pointer: ", Tcl_GetString(objv[1]), (char*)0); - return TCL_ERROR; - } - if( Tcl_GetIntFromObj(interp, objv[2], &size) ){ - return TCL_ERROR; - } - if( size<=0 ){ - Tcl_AppendResult(interp, "size must be positive", (char*)0); - return TCL_ERROR; - } - zBin = p; - while( size>0 ){ - if( size>(sizeof(zHex)-1)/2 ){ - n = (sizeof(zHex)-1)/2; - }else{ - n = size; - } - memcpy(zHex, zBin, n); - zBin += n; - size -= n; - sqlite3TestBinToHex(zHex, n); - Tcl_AppendResult(interp, zHex, (char*)0); - } - return TCL_OK; -} - -/* -** Usage: sqlite3_memory_used -** -** Raw test interface for sqlite3_memory_used(). -*/ -static int test_memory_used( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - Tcl_SetObjResult(interp, Tcl_NewWideIntObj(sqlite3_memory_used())); - return TCL_OK; -} - -/* -** Usage: sqlite3_memory_highwater ?RESETFLAG? -** -** Raw test interface for sqlite3_memory_highwater(). -*/ -static int test_memory_highwater( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - int resetFlag = 0; - if( objc!=1 && objc!=2 ){ - Tcl_WrongNumArgs(interp, 1, objv, "?RESET?"); - return TCL_ERROR; - } - if( objc==2 ){ - if( Tcl_GetBooleanFromObj(interp, objv[1], &resetFlag) ) return TCL_ERROR; - } - Tcl_SetObjResult(interp, - Tcl_NewWideIntObj(sqlite3_memory_highwater(resetFlag))); - return TCL_OK; -} - -/* -** Usage: sqlite3_memdebug_backtrace DEPTH -** -** Set the depth of backtracing. If SQLITE_MEMDEBUG is not defined -** then this routine is a no-op. -*/ -static int test_memdebug_backtrace( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - int depth; - if( objc!=2 ){ - Tcl_WrongNumArgs(interp, 1, objv, "DEPT"); - return TCL_ERROR; - } - if( Tcl_GetIntFromObj(interp, objv[1], &depth) ) return TCL_ERROR; -#ifdef SQLITE_MEMDEBUG - { - extern void sqlite3MemdebugBacktrace(int); - sqlite3MemdebugBacktrace(depth); - } -#endif - return TCL_OK; -} - -/* -** Usage: sqlite3_memdebug_dump FILENAME -** -** Write a summary of unfreed memory to FILENAME. -*/ -static int test_memdebug_dump( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - if( objc!=2 ){ - Tcl_WrongNumArgs(interp, 1, objv, "FILENAME"); - return TCL_ERROR; - } -#if defined(SQLITE_MEMDEBUG) || defined(SQLITE_MEMORY_SIZE) \ - || defined(SQLITE_POW2_MEMORY_SIZE) - { - extern void sqlite3MemdebugDump(const char*); - sqlite3MemdebugDump(Tcl_GetString(objv[1])); - } -#endif - return TCL_OK; -} - -/* -** Usage: sqlite3_memdebug_malloc_count -** -** Return the total number of times malloc() has been called. -*/ -static int test_memdebug_malloc_count( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - int nMalloc = -1; - if( objc!=1 ){ - Tcl_WrongNumArgs(interp, 1, objv, ""); - return TCL_ERROR; - } -#if defined(SQLITE_MEMDEBUG) - { - extern int sqlite3MemdebugMallocCount(); - nMalloc = sqlite3MemdebugMallocCount(); - } -#endif - Tcl_SetObjResult(interp, Tcl_NewIntObj(nMalloc)); - return TCL_OK; -} - - -/* -** Usage: sqlite3_memdebug_fail COUNTER ?OPTIONS? -** -** where options are: -** -** -repeat <count> -** -benigncnt <varname> -** -** Arrange for a simulated malloc() failure after COUNTER successes. -** If a repeat count is specified, the fault is repeated that many -** times. -** -** Each call to this routine overrides the prior counter value. -** This routine returns the number of simulated failures that have -** happened since the previous call to this routine. -** -** To disable simulated failures, use a COUNTER of -1. -*/ -static int test_memdebug_fail( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - int ii; - int iFail; - int nRepeat = 1; - Tcl_Obj *pBenignCnt = 0; - int nBenign; - int nFail = 0; - - if( objc<2 ){ - Tcl_WrongNumArgs(interp, 1, objv, "COUNTER ?OPTIONS?"); - return TCL_ERROR; - } - if( Tcl_GetIntFromObj(interp, objv[1], &iFail) ) return TCL_ERROR; - - for(ii=2; ii<objc; ii+=2){ - int nOption; - char *zOption = Tcl_GetStringFromObj(objv[ii], &nOption); - char *zErr = 0; - - if( nOption>1 && strncmp(zOption, "-repeat", nOption)==0 ){ - if( ii==(objc-1) ){ - zErr = "option requires an argument: "; - }else{ - if( Tcl_GetIntFromObj(interp, objv[ii+1], &nRepeat) ){ - return TCL_ERROR; - } - } - }else if( nOption>1 && strncmp(zOption, "-benigncnt", nOption)==0 ){ - if( ii==(objc-1) ){ - zErr = "option requires an argument: "; - }else{ - pBenignCnt = objv[ii+1]; - } - }else{ - zErr = "unknown option: "; - } - - if( zErr ){ - Tcl_AppendResult(interp, zErr, zOption, 0); - return TCL_ERROR; - } - } - - nBenign = faultsimBenignFailures(); - nFail = faultsimFailures(); - faultsimConfig(iFail, nRepeat); - - if( pBenignCnt ){ - Tcl_ObjSetVar2(interp, pBenignCnt, 0, Tcl_NewIntObj(nBenign), 0); - } - Tcl_SetObjResult(interp, Tcl_NewIntObj(nFail)); - return TCL_OK; -} - -/* -** Usage: sqlite3_memdebug_pending -** -** Return the number of malloc() calls that will succeed before a -** simulated failure occurs. A negative return value indicates that -** no malloc() failure is scheduled. -*/ -static int test_memdebug_pending( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - int nPending; - if( objc!=1 ){ - Tcl_WrongNumArgs(interp, 1, objv, ""); - return TCL_ERROR; - } - nPending = faultsimPending(); - Tcl_SetObjResult(interp, Tcl_NewIntObj(nPending)); - return TCL_OK; -} - - -/* -** Usage: sqlite3_memdebug_settitle TITLE -** -** Set a title string stored with each allocation. The TITLE is -** typically the name of the test that was running when the -** allocation occurred. The TITLE is stored with the allocation -** and can be used to figure out which tests are leaking memory. -** -** Each title overwrite the previous. -*/ -static int test_memdebug_settitle( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - if( objc!=2 ){ - Tcl_WrongNumArgs(interp, 1, objv, "TITLE"); - return TCL_ERROR; - } -#ifdef SQLITE_MEMDEBUG - { - const char *zTitle; - extern int sqlite3MemdebugSettitle(const char*); - zTitle = Tcl_GetString(objv[1]); - sqlite3MemdebugSettitle(zTitle); - } -#endif - return TCL_OK; -} - -#define MALLOC_LOG_FRAMES 10 -#define MALLOC_LOG_KEYINTS ( \ - 10 * ((sizeof(int)>=sizeof(void*)) ? 1 : sizeof(void*)/sizeof(int)) \ -) -static Tcl_HashTable aMallocLog; -static int mallocLogEnabled = 0; - -typedef struct MallocLog MallocLog; -struct MallocLog { - int nCall; - int nByte; -}; - -#ifdef SQLITE_MEMDEBUG -static void test_memdebug_callback(int nByte, int nFrame, void **aFrame){ - if( mallocLogEnabled ){ - MallocLog *pLog; - Tcl_HashEntry *pEntry; - int isNew; - - int aKey[MALLOC_LOG_KEYINTS]; - unsigned int nKey = sizeof(int)*MALLOC_LOG_KEYINTS; - - memset(aKey, 0, nKey); - if( (sizeof(void*)*nFrame)<nKey ){ - nKey = nFrame*sizeof(void*); - } - memcpy(aKey, aFrame, nKey); - - pEntry = Tcl_CreateHashEntry(&aMallocLog, (const char *)aKey, &isNew); - if( isNew ){ - pLog = (MallocLog *)Tcl_Alloc(sizeof(MallocLog)); - memset(pLog, 0, sizeof(MallocLog)); - Tcl_SetHashValue(pEntry, (ClientData)pLog); - }else{ - pLog = (MallocLog *)Tcl_GetHashValue(pEntry); - } - - pLog->nCall++; - pLog->nByte += nByte; - } -} -#endif /* SQLITE_MEMDEBUG */ - -static void test_memdebug_log_clear(void){ - Tcl_HashSearch search; - Tcl_HashEntry *pEntry; - for( - pEntry=Tcl_FirstHashEntry(&aMallocLog, &search); - pEntry; - pEntry=Tcl_NextHashEntry(&search) - ){ - MallocLog *pLog = (MallocLog *)Tcl_GetHashValue(pEntry); - Tcl_Free((char *)pLog); - } - Tcl_DeleteHashTable(&aMallocLog); - Tcl_InitHashTable(&aMallocLog, MALLOC_LOG_KEYINTS); -} - -static int test_memdebug_log( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - static int isInit = 0; - int iSub; - - static const char *MB_strs[] = { "start", "stop", "dump", "clear", "sync" }; - enum MB_enum { - MB_LOG_START, MB_LOG_STOP, MB_LOG_DUMP, MB_LOG_CLEAR, MB_LOG_SYNC - }; - - if( !isInit ){ -#ifdef SQLITE_MEMDEBUG - extern void sqlite3MemdebugBacktraceCallback( - void (*xBacktrace)(int, int, void **)); - sqlite3MemdebugBacktraceCallback(test_memdebug_callback); -#endif - Tcl_InitHashTable(&aMallocLog, MALLOC_LOG_KEYINTS); - isInit = 1; - } - - if( objc<2 ){ - Tcl_WrongNumArgs(interp, 1, objv, "SUB-COMMAND ..."); - } - if( Tcl_GetIndexFromObj(interp, objv[1], MB_strs, "sub-command", 0, &iSub) ){ - return TCL_ERROR; - } - - switch( (enum MB_enum)iSub ){ - case MB_LOG_START: - mallocLogEnabled = 1; - break; - case MB_LOG_STOP: - mallocLogEnabled = 0; - break; - case MB_LOG_DUMP: { - Tcl_HashSearch search; - Tcl_HashEntry *pEntry; - Tcl_Obj *pRet = Tcl_NewObj(); - - assert(sizeof(Tcl_WideInt)>=sizeof(void*)); - - for( - pEntry=Tcl_FirstHashEntry(&aMallocLog, &search); - pEntry; - pEntry=Tcl_NextHashEntry(&search) - ){ - Tcl_Obj *apElem[MALLOC_LOG_FRAMES+2]; - MallocLog *pLog = (MallocLog *)Tcl_GetHashValue(pEntry); - Tcl_WideInt *aKey = (Tcl_WideInt *)Tcl_GetHashKey(&aMallocLog, pEntry); - int ii; - - apElem[0] = Tcl_NewIntObj(pLog->nCall); - apElem[1] = Tcl_NewIntObj(pLog->nByte); - for(ii=0; ii<MALLOC_LOG_FRAMES; ii++){ - apElem[ii+2] = Tcl_NewWideIntObj(aKey[ii]); - } - - Tcl_ListObjAppendElement(interp, pRet, - Tcl_NewListObj(MALLOC_LOG_FRAMES+2, apElem) - ); - } - - Tcl_SetObjResult(interp, pRet); - break; - } - case MB_LOG_CLEAR: { - test_memdebug_log_clear(); - break; - } - - case MB_LOG_SYNC: { -#ifdef SQLITE_MEMDEBUG - extern void sqlite3MemdebugSync(); - test_memdebug_log_clear(); - mallocLogEnabled = 1; - sqlite3MemdebugSync(); -#endif - break; - } - } - - return TCL_OK; -} - -/* -** Usage: sqlite3_config_scratch SIZE N -** -** Set the scratch memory buffer using SQLITE_CONFIG_SCRATCH. -** The buffer is static and is of limited size. N might be -** adjusted downward as needed to accomodate the requested size. -** The revised value of N is returned. -** -** A negative SIZE causes the buffer pointer to be NULL. -*/ -static int test_config_scratch( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - int sz, N, rc; - Tcl_Obj *pResult; - static char *buf = 0; - if( objc!=3 ){ - Tcl_WrongNumArgs(interp, 1, objv, "SIZE N"); - return TCL_ERROR; - } - if( Tcl_GetIntFromObj(interp, objv[1], &sz) ) return TCL_ERROR; - if( Tcl_GetIntFromObj(interp, objv[2], &N) ) return TCL_ERROR; - free(buf); - if( sz<0 ){ - buf = 0; - rc = sqlite3_config(SQLITE_CONFIG_SCRATCH, 0, 0, 0); - }else{ - buf = malloc( sz*N + 1 ); - rc = sqlite3_config(SQLITE_CONFIG_SCRATCH, buf, sz, N); - } - pResult = Tcl_NewObj(); - Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(rc)); - Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(N)); - Tcl_SetObjResult(interp, pResult); - return TCL_OK; -} - -/* -** Usage: sqlite3_config_pagecache SIZE N -** -** Set the page-cache memory buffer using SQLITE_CONFIG_PAGECACHE. -** The buffer is static and is of limited size. N might be -** adjusted downward as needed to accomodate the requested size. -** The revised value of N is returned. -** -** A negative SIZE causes the buffer pointer to be NULL. -*/ -static int test_config_pagecache( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - int sz, N, rc; - Tcl_Obj *pResult; - static char *buf = 0; - if( objc!=3 ){ - Tcl_WrongNumArgs(interp, 1, objv, "SIZE N"); - return TCL_ERROR; - } - if( Tcl_GetIntFromObj(interp, objv[1], &sz) ) return TCL_ERROR; - if( Tcl_GetIntFromObj(interp, objv[2], &N) ) return TCL_ERROR; - free(buf); - if( sz<0 ){ - buf = 0; - rc = sqlite3_config(SQLITE_CONFIG_PAGECACHE, 0, 0, 0); - }else{ - buf = malloc( sz*N ); - rc = sqlite3_config(SQLITE_CONFIG_PAGECACHE, buf, sz, N); - } - pResult = Tcl_NewObj(); - Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(rc)); - Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(N)); - Tcl_SetObjResult(interp, pResult); - return TCL_OK; -} - -/* -** Usage: sqlite3_config_alt_pcache INSTALL_FLAG DISCARD_CHANCE PRNG_SEED -** -** Set up the alternative test page cache. Install if INSTALL_FLAG is -** true and uninstall (reverting to the default page cache) if INSTALL_FLAG -** is false. DISCARD_CHANGE is an integer between 0 and 100 inclusive -** which determines the chance of discarding a page when unpinned. 100 -** is certainty. 0 is never. PRNG_SEED is the pseudo-random number generator -** seed. -*/ -static int test_alt_pcache( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - int installFlag; - int discardChance = 0; - int prngSeed = 0; - int highStress = 0; - extern void installTestPCache(int,unsigned,unsigned,unsigned); - if( objc<2 || objc>5 ){ - Tcl_WrongNumArgs(interp, 1, objv, - "INSTALLFLAG DISCARDCHANCE PRNGSEEED HIGHSTRESS"); - return TCL_ERROR; - } - if( Tcl_GetIntFromObj(interp, objv[1], &installFlag) ) return TCL_ERROR; - if( objc>=3 && Tcl_GetIntFromObj(interp, objv[2], &discardChance) ){ - return TCL_ERROR; - } - if( objc>=4 && Tcl_GetIntFromObj(interp, objv[3], &prngSeed) ){ - return TCL_ERROR; - } - if( objc>=5 && Tcl_GetIntFromObj(interp, objv[4], &highStress) ){ - return TCL_ERROR; - } - if( discardChance<0 || discardChance>100 ){ - Tcl_AppendResult(interp, "discard-chance should be between 0 and 100", - (char*)0); - return TCL_ERROR; - } - installTestPCache(installFlag, (unsigned)discardChance, (unsigned)prngSeed, - (unsigned)highStress); - return TCL_OK; -} - -/* -** Usage: sqlite3_config_memstatus BOOLEAN -** -** Enable or disable memory status reporting using SQLITE_CONFIG_MEMSTATUS. -*/ -static int test_config_memstatus( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - int enable, rc; - if( objc!=2 ){ - Tcl_WrongNumArgs(interp, 1, objv, "BOOLEAN"); - return TCL_ERROR; - } - if( Tcl_GetBooleanFromObj(interp, objv[1], &enable) ) return TCL_ERROR; - rc = sqlite3_config(SQLITE_CONFIG_MEMSTATUS, enable); - Tcl_SetObjResult(interp, Tcl_NewIntObj(rc)); - return TCL_OK; -} - -/* -** Usage: sqlite3_config_lookaside SIZE COUNT -** -*/ -static int test_config_lookaside( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - int sz, cnt; - Tcl_Obj *pRet; - if( objc!=3 ){ - Tcl_WrongNumArgs(interp, 1, objv, "SIZE COUNT"); - return TCL_ERROR; - } - if( Tcl_GetIntFromObj(interp, objv[1], &sz) ) return TCL_ERROR; - if( Tcl_GetIntFromObj(interp, objv[2], &cnt) ) return TCL_ERROR; - pRet = Tcl_NewObj(); - Tcl_ListObjAppendElement( - interp, pRet, Tcl_NewIntObj(sqlite3GlobalConfig.szLookaside) - ); - Tcl_ListObjAppendElement( - interp, pRet, Tcl_NewIntObj(sqlite3GlobalConfig.nLookaside) - ); - sqlite3_config(SQLITE_CONFIG_LOOKASIDE, sz, cnt); - Tcl_SetObjResult(interp, pRet); - return TCL_OK; -} - - -/* -** Usage: sqlite3_db_config_lookaside CONNECTION BUFID SIZE COUNT -** -** There are two static buffers with BUFID 1 and 2. Each static buffer -** is 10KB in size. A BUFID of 0 indicates that the buffer should be NULL -** which will cause sqlite3_db_config() to allocate space on its own. -*/ -static int test_db_config_lookaside( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - int rc; - int sz, cnt; - sqlite3 *db; - int bufid; - static char azBuf[2][10000]; - extern int getDbPointer(Tcl_Interp*, const char*, sqlite3**); - if( objc!=5 ){ - Tcl_WrongNumArgs(interp, 1, objv, "BUFID SIZE COUNT"); - return TCL_ERROR; - } - if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; - if( Tcl_GetIntFromObj(interp, objv[2], &bufid) ) return TCL_ERROR; - if( Tcl_GetIntFromObj(interp, objv[3], &sz) ) return TCL_ERROR; - if( Tcl_GetIntFromObj(interp, objv[4], &cnt) ) return TCL_ERROR; - if( bufid==0 ){ - rc = sqlite3_db_config(db, SQLITE_DBCONFIG_LOOKASIDE, 0, sz, cnt); - }else if( bufid>=1 && bufid<=2 && sz*cnt<=sizeof(azBuf[0]) ){ - rc = sqlite3_db_config(db, SQLITE_DBCONFIG_LOOKASIDE, azBuf[bufid], sz,cnt); - }else{ - Tcl_AppendResult(interp, "illegal arguments - see documentation", (char*)0); - return TCL_ERROR; - } - Tcl_SetObjResult(interp, Tcl_NewIntObj(rc)); - return TCL_OK; -} - -/* -** Usage: sqlite3_config_heap NBYTE NMINALLOC -*/ -static int test_config_heap( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - static char *zBuf; /* Use this memory */ - int nByte; /* Size of buffer to pass to sqlite3_config() */ - int nMinAlloc; /* Size of minimum allocation */ - int rc; /* Return code of sqlite3_config() */ - - Tcl_Obj * CONST *aArg = &objv[1]; - int nArg = objc-1; - - if( nArg!=2 ){ - Tcl_WrongNumArgs(interp, 1, objv, "NBYTE NMINALLOC"); - return TCL_ERROR; - } - if( Tcl_GetIntFromObj(interp, aArg[0], &nByte) ) return TCL_ERROR; - if( Tcl_GetIntFromObj(interp, aArg[1], &nMinAlloc) ) return TCL_ERROR; - - if( nByte==0 ){ - free( zBuf ); - zBuf = 0; - rc = sqlite3_config(SQLITE_CONFIG_HEAP, (void*)0, 0, 0); - }else{ - zBuf = realloc(zBuf, nByte); - rc = sqlite3_config(SQLITE_CONFIG_HEAP, zBuf, nByte, nMinAlloc); - } - - Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE); - return TCL_OK; -} - -/* -** Usage: sqlite3_config_error [DB] -** -** Invoke sqlite3_config() or sqlite3_db_config() with invalid -** opcodes and verify that they return errors. -*/ -static int test_config_error( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - sqlite3 *db; - extern int getDbPointer(Tcl_Interp*, const char*, sqlite3**); - - if( objc!=2 && objc!=1 ){ - Tcl_WrongNumArgs(interp, 1, objv, "[DB]"); - return TCL_ERROR; - } - if( objc==2 ){ - if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; - if( sqlite3_db_config(db, 99999)!=SQLITE_ERROR ){ - Tcl_AppendResult(interp, - "sqlite3_db_config(db, 99999) does not return SQLITE_ERROR", - (char*)0); - return TCL_ERROR; - } - }else{ - if( sqlite3_config(99999)!=SQLITE_ERROR ){ - Tcl_AppendResult(interp, - "sqlite3_config(99999) does not return SQLITE_ERROR", - (char*)0); - return TCL_ERROR; - } - } - return TCL_OK; -} - -/* -** Usage: sqlite3_config_uri BOOLEAN -** -** Enables or disables interpretation of URI parameters by default using -** SQLITE_CONFIG_URI. -*/ -static int test_config_uri( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - int rc; - int bOpenUri; - - if( objc!=2 ){ - Tcl_WrongNumArgs(interp, 1, objv, "BOOL"); - return TCL_ERROR; - } - if( Tcl_GetBooleanFromObj(interp, objv[1], &bOpenUri) ){ - return TCL_ERROR; - } - - rc = sqlite3_config(SQLITE_CONFIG_URI, bOpenUri); - Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE); - - return TCL_OK; -} - -/* -** Usage: sqlite3_config_cis BOOLEAN -** -** Enables or disables the use of the covering-index scan optimization. -** SQLITE_CONFIG_COVERING_INDEX_SCAN. -*/ -static int test_config_cis( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - int rc; - int bUseCis; - - if( objc!=2 ){ - Tcl_WrongNumArgs(interp, 1, objv, "BOOL"); - return TCL_ERROR; - } - if( Tcl_GetBooleanFromObj(interp, objv[1], &bUseCis) ){ - return TCL_ERROR; - } - - rc = sqlite3_config(SQLITE_CONFIG_COVERING_INDEX_SCAN, bUseCis); - Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE); - - return TCL_OK; -} - -/* -** Usage: sqlite3_dump_memsys3 FILENAME -** sqlite3_dump_memsys5 FILENAME -** -** Write a summary of unfreed memsys3 allocations to FILENAME. -*/ -static int test_dump_memsys3( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - if( objc!=2 ){ - Tcl_WrongNumArgs(interp, 1, objv, "FILENAME"); - return TCL_ERROR; - } - - switch( SQLITE_PTR_TO_INT(clientData) ){ - case 3: { -#ifdef SQLITE_ENABLE_MEMSYS3 - extern void sqlite3Memsys3Dump(const char*); - sqlite3Memsys3Dump(Tcl_GetString(objv[1])); - break; -#endif - } - case 5: { -#ifdef SQLITE_ENABLE_MEMSYS5 - extern void sqlite3Memsys5Dump(const char*); - sqlite3Memsys5Dump(Tcl_GetString(objv[1])); - break; -#endif - } - } - return TCL_OK; -} - -/* -** Usage: sqlite3_status OPCODE RESETFLAG -** -** Return a list of three elements which are the sqlite3_status() return -** code, the current value, and the high-water mark value. -*/ -static int test_status( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - int rc, iValue, mxValue; - int i, op, resetFlag; - const char *zOpName; - static const struct { - const char *zName; - int op; - } aOp[] = { - { "SQLITE_STATUS_MEMORY_USED", SQLITE_STATUS_MEMORY_USED }, - { "SQLITE_STATUS_MALLOC_SIZE", SQLITE_STATUS_MALLOC_SIZE }, - { "SQLITE_STATUS_PAGECACHE_USED", SQLITE_STATUS_PAGECACHE_USED }, - { "SQLITE_STATUS_PAGECACHE_OVERFLOW", SQLITE_STATUS_PAGECACHE_OVERFLOW }, - { "SQLITE_STATUS_PAGECACHE_SIZE", SQLITE_STATUS_PAGECACHE_SIZE }, - { "SQLITE_STATUS_SCRATCH_USED", SQLITE_STATUS_SCRATCH_USED }, - { "SQLITE_STATUS_SCRATCH_OVERFLOW", SQLITE_STATUS_SCRATCH_OVERFLOW }, - { "SQLITE_STATUS_SCRATCH_SIZE", SQLITE_STATUS_SCRATCH_SIZE }, - { "SQLITE_STATUS_PARSER_STACK", SQLITE_STATUS_PARSER_STACK }, - { "SQLITE_STATUS_MALLOC_COUNT", SQLITE_STATUS_MALLOC_COUNT }, - }; - Tcl_Obj *pResult; - if( objc!=3 ){ - Tcl_WrongNumArgs(interp, 1, objv, "PARAMETER RESETFLAG"); - return TCL_ERROR; - } - zOpName = Tcl_GetString(objv[1]); - for(i=0; i<ArraySize(aOp); i++){ - if( strcmp(aOp[i].zName, zOpName)==0 ){ - op = aOp[i].op; - break; - } - } - if( i>=ArraySize(aOp) ){ - if( Tcl_GetIntFromObj(interp, objv[1], &op) ) return TCL_ERROR; - } - if( Tcl_GetBooleanFromObj(interp, objv[2], &resetFlag) ) return TCL_ERROR; - iValue = 0; - mxValue = 0; - rc = sqlite3_status(op, &iValue, &mxValue, resetFlag); - pResult = Tcl_NewObj(); - Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(rc)); - Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(iValue)); - Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(mxValue)); - Tcl_SetObjResult(interp, pResult); - return TCL_OK; -} - -/* -** Usage: sqlite3_db_status DATABASE OPCODE RESETFLAG -** -** Return a list of three elements which are the sqlite3_db_status() return -** code, the current value, and the high-water mark value. -*/ -static int test_db_status( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - int rc, iValue, mxValue; - int i, op, resetFlag; - const char *zOpName; - sqlite3 *db; - extern int getDbPointer(Tcl_Interp*, const char*, sqlite3**); - static const struct { - const char *zName; - int op; - } aOp[] = { - { "LOOKASIDE_USED", SQLITE_DBSTATUS_LOOKASIDE_USED }, - { "CACHE_USED", SQLITE_DBSTATUS_CACHE_USED }, - { "SCHEMA_USED", SQLITE_DBSTATUS_SCHEMA_USED }, - { "STMT_USED", SQLITE_DBSTATUS_STMT_USED }, - { "LOOKASIDE_HIT", SQLITE_DBSTATUS_LOOKASIDE_HIT }, - { "LOOKASIDE_MISS_SIZE", SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE }, - { "LOOKASIDE_MISS_FULL", SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL }, - { "CACHE_HIT", SQLITE_DBSTATUS_CACHE_HIT }, - { "CACHE_MISS", SQLITE_DBSTATUS_CACHE_MISS }, - { "CACHE_WRITE", SQLITE_DBSTATUS_CACHE_WRITE }, - { "DEFERRED_FKS", SQLITE_DBSTATUS_DEFERRED_FKS } - }; - Tcl_Obj *pResult; - if( objc!=4 ){ - Tcl_WrongNumArgs(interp, 1, objv, "DB PARAMETER RESETFLAG"); - return TCL_ERROR; - } - if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; - zOpName = Tcl_GetString(objv[2]); - if( memcmp(zOpName, "SQLITE_", 7)==0 ) zOpName += 7; - if( memcmp(zOpName, "DBSTATUS_", 9)==0 ) zOpName += 9; - for(i=0; i<ArraySize(aOp); i++){ - if( strcmp(aOp[i].zName, zOpName)==0 ){ - op = aOp[i].op; - break; - } - } - if( i>=ArraySize(aOp) ){ - if( Tcl_GetIntFromObj(interp, objv[2], &op) ) return TCL_ERROR; - } - if( Tcl_GetBooleanFromObj(interp, objv[3], &resetFlag) ) return TCL_ERROR; - iValue = 0; - mxValue = 0; - rc = sqlite3_db_status(db, op, &iValue, &mxValue, resetFlag); - pResult = Tcl_NewObj(); - Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(rc)); - Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(iValue)); - Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(mxValue)); - Tcl_SetObjResult(interp, pResult); - return TCL_OK; -} - -/* -** install_malloc_faultsim BOOLEAN -*/ -static int test_install_malloc_faultsim( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - int rc; - int isInstall; - - if( objc!=2 ){ - Tcl_WrongNumArgs(interp, 1, objv, "BOOLEAN"); - return TCL_ERROR; - } - if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[1], &isInstall) ){ - return TCL_ERROR; - } - rc = faultsimInstall(isInstall); - Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE); - return TCL_OK; -} - -/* -** sqlite3_install_memsys3 -*/ -static int test_install_memsys3( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - int rc = SQLITE_MISUSE; -#ifdef SQLITE_ENABLE_MEMSYS3 - const sqlite3_mem_methods *sqlite3MemGetMemsys3(void); - rc = sqlite3_config(SQLITE_CONFIG_MALLOC, sqlite3MemGetMemsys3()); -#endif - Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE); - return TCL_OK; -} - -static int test_vfs_oom_test( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - extern int sqlite3_memdebug_vfs_oom_test; - if( objc>2 ){ - Tcl_WrongNumArgs(interp, 1, objv, "?INTEGER?"); - return TCL_ERROR; - }else if( objc==2 ){ - int iNew; - if( Tcl_GetIntFromObj(interp, objv[1], &iNew) ) return TCL_ERROR; - sqlite3_memdebug_vfs_oom_test = iNew; - } - Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_memdebug_vfs_oom_test)); - return TCL_OK; -} - -/* -** Register commands with the TCL interpreter. -*/ -int Sqlitetest_malloc_Init(Tcl_Interp *interp){ - static struct { - char *zName; - Tcl_ObjCmdProc *xProc; - int clientData; - } aObjCmd[] = { - { "sqlite3_malloc", test_malloc ,0 }, - { "sqlite3_realloc", test_realloc ,0 }, - { "sqlite3_free", test_free ,0 }, - { "memset", test_memset ,0 }, - { "memget", test_memget ,0 }, - { "sqlite3_memory_used", test_memory_used ,0 }, - { "sqlite3_memory_highwater", test_memory_highwater ,0 }, - { "sqlite3_memdebug_backtrace", test_memdebug_backtrace ,0 }, - { "sqlite3_memdebug_dump", test_memdebug_dump ,0 }, - { "sqlite3_memdebug_fail", test_memdebug_fail ,0 }, - { "sqlite3_memdebug_pending", test_memdebug_pending ,0 }, - { "sqlite3_memdebug_settitle", test_memdebug_settitle ,0 }, - { "sqlite3_memdebug_malloc_count", test_memdebug_malloc_count ,0 }, - { "sqlite3_memdebug_log", test_memdebug_log ,0 }, - { "sqlite3_config_scratch", test_config_scratch ,0 }, - { "sqlite3_config_pagecache", test_config_pagecache ,0 }, - { "sqlite3_config_alt_pcache", test_alt_pcache ,0 }, - { "sqlite3_status", test_status ,0 }, - { "sqlite3_db_status", test_db_status ,0 }, - { "install_malloc_faultsim", test_install_malloc_faultsim ,0 }, - { "sqlite3_config_heap", test_config_heap ,0 }, - { "sqlite3_config_memstatus", test_config_memstatus ,0 }, - { "sqlite3_config_lookaside", test_config_lookaside ,0 }, - { "sqlite3_config_error", test_config_error ,0 }, - { "sqlite3_config_uri", test_config_uri ,0 }, - { "sqlite3_config_cis", test_config_cis ,0 }, - { "sqlite3_db_config_lookaside",test_db_config_lookaside ,0 }, - { "sqlite3_dump_memsys3", test_dump_memsys3 ,3 }, - { "sqlite3_dump_memsys5", test_dump_memsys3 ,5 }, - { "sqlite3_install_memsys3", test_install_memsys3 ,0 }, - { "sqlite3_memdebug_vfs_oom_test", test_vfs_oom_test ,0 }, - }; - int i; - for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){ - ClientData c = (ClientData)SQLITE_INT_TO_PTR(aObjCmd[i].clientData); - Tcl_CreateObjCommand(interp, aObjCmd[i].zName, aObjCmd[i].xProc, c, 0); - } - return TCL_OK; -} -#endif diff --git a/components/external/SQLite-3.8.1/SQLiteLib/test/test_multiplex.c b/components/external/SQLite-3.8.1/SQLiteLib/test/test_multiplex.c deleted file mode 100644 index 624541b32a..0000000000 --- a/components/external/SQLite-3.8.1/SQLiteLib/test/test_multiplex.c +++ /dev/null @@ -1,1385 +0,0 @@ -/* -** 2010 October 28 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** -** This file contains a VFS "shim" - a layer that sits in between the -** pager and the real VFS - that breaks up a very large database file -** into two or more smaller files on disk. This is useful, for example, -** in order to support large, multi-gigabyte databases on older filesystems -** that limit the maximum file size to 2 GiB. -** -** USAGE: -** -** Compile this source file and link it with your application. Then -** at start-time, invoke the following procedure: -** -** int sqlite3_multiplex_initialize( -** const char *zOrigVfsName, // The underlying real VFS -** int makeDefault // True to make multiplex the default VFS -** ); -** -** The procedure call above will create and register a new VFS shim named -** "multiplex". The multiplex VFS will use the VFS named by zOrigVfsName to -** do the actual disk I/O. (The zOrigVfsName parameter may be NULL, in -** which case the default VFS at the moment sqlite3_multiplex_initialize() -** is called will be used as the underlying real VFS.) -** -** If the makeDefault parameter is TRUE then multiplex becomes the new -** default VFS. Otherwise, you can use the multiplex VFS by specifying -** "multiplex" as the 4th parameter to sqlite3_open_v2() or by employing -** URI filenames and adding "vfs=multiplex" as a parameter to the filename -** URI. -** -** The multiplex VFS allows databases up to 32 GiB in size. But it splits -** the files up into smaller pieces, so that they will work even on -** filesystems that do not support large files. The default chunk size -** is 2147418112 bytes (which is 64KiB less than 2GiB) but this can be -** changed at compile-time by defining the SQLITE_MULTIPLEX_CHUNK_SIZE -** macro. Use the "chunksize=NNNN" query parameter with a URI filename -** in order to select an alternative chunk size for individual connections -** at run-time. -*/ -#include "sqlite3.h" -#include <string.h> -#include <assert.h> -#include <stdlib.h> -#include "test_multiplex.h" - -#ifndef SQLITE_CORE - #define SQLITE_CORE 1 /* Disable the API redefinition in sqlite3ext.h */ -#endif -#include "sqlite3ext.h" - -/* -** These should be defined to be the same as the values in -** sqliteInt.h. They are defined separately here so that -** the multiplex VFS shim can be built as a loadable -** module. -*/ -#define UNUSED_PARAMETER(x) (void)(x) -#define MAX_PAGE_SIZE 0x10000 -#define DEFAULT_SECTOR_SIZE 0x1000 - -/* -** For a build without mutexes, no-op the mutex calls. -*/ -#if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE==0 -#define sqlite3_mutex_alloc(X) ((sqlite3_mutex*)8) -#define sqlite3_mutex_free(X) -#define sqlite3_mutex_enter(X) -#define sqlite3_mutex_try(X) SQLITE_OK -#define sqlite3_mutex_leave(X) -#define sqlite3_mutex_held(X) ((void)(X),1) -#define sqlite3_mutex_notheld(X) ((void)(X),1) -#endif /* SQLITE_THREADSAFE==0 */ - -/* Maximum chunk number */ -#define MX_CHUNK_NUMBER 299 - -/* First chunk for rollback journal files */ -#define SQLITE_MULTIPLEX_JOURNAL_8_3_OFFSET 400 -#define SQLITE_MULTIPLEX_WAL_8_3_OFFSET 700 - - -/************************ Shim Definitions ******************************/ - -#ifndef SQLITE_MULTIPLEX_VFS_NAME -# define SQLITE_MULTIPLEX_VFS_NAME "multiplex" -#endif - -/* This is the limit on the chunk size. It may be changed by calling -** the xFileControl() interface. It will be rounded up to a -** multiple of MAX_PAGE_SIZE. We default it here to 2GiB less 64KiB. -*/ -#ifndef SQLITE_MULTIPLEX_CHUNK_SIZE -# define SQLITE_MULTIPLEX_CHUNK_SIZE 2147418112 -#endif - -/* This used to be the default limit on number of chunks, but -** it is no longer enforced. There is currently no limit to the -** number of chunks. -** -** May be changed by calling the xFileControl() interface. -*/ -#ifndef SQLITE_MULTIPLEX_MAX_CHUNKS -# define SQLITE_MULTIPLEX_MAX_CHUNKS 12 -#endif - -/************************ Object Definitions ******************************/ - -/* Forward declaration of all object types */ -typedef struct multiplexGroup multiplexGroup; -typedef struct multiplexConn multiplexConn; - -/* -** A "multiplex group" is a collection of files that collectively -** makeup a single SQLite DB file. This allows the size of the DB -** to exceed the limits imposed by the file system. -** -** There is an instance of the following object for each defined multiplex -** group. -*/ -struct multiplexGroup { - struct multiplexReal { /* For each chunk */ - sqlite3_file *p; /* Handle for the chunk */ - char *z; /* Name of this chunk */ - } *aReal; /* list of all chunks */ - int nReal; /* Number of chunks */ - char *zName; /* Base filename of this group */ - int nName; /* Length of base filename */ - int flags; /* Flags used for original opening */ - unsigned int szChunk; /* Chunk size used for this group */ - unsigned char bEnabled; /* TRUE to use Multiplex VFS for this file */ - unsigned char bTruncate; /* TRUE to enable truncation of databases */ - multiplexGroup *pNext, *pPrev; /* Doubly linked list of all group objects */ -}; - -/* -** An instance of the following object represents each open connection -** to a file that is multiplex'ed. This object is a -** subclass of sqlite3_file. The sqlite3_file object for the underlying -** VFS is appended to this structure. -*/ -struct multiplexConn { - sqlite3_file base; /* Base class - must be first */ - multiplexGroup *pGroup; /* The underlying group of files */ -}; - -/************************* Global Variables **********************************/ -/* -** All global variables used by this file are containing within the following -** gMultiplex structure. -*/ -static struct { - /* The pOrigVfs is the real, original underlying VFS implementation. - ** Most operations pass-through to the real VFS. This value is read-only - ** during operation. It is only modified at start-time and thus does not - ** require a mutex. - */ - sqlite3_vfs *pOrigVfs; - - /* The sThisVfs is the VFS structure used by this shim. It is initialized - ** at start-time and thus does not require a mutex - */ - sqlite3_vfs sThisVfs; - - /* The sIoMethods defines the methods used by sqlite3_file objects - ** associated with this shim. It is initialized at start-time and does - ** not require a mutex. - ** - ** When the underlying VFS is called to open a file, it might return - ** either a version 1 or a version 2 sqlite3_file object. This shim - ** has to create a wrapper sqlite3_file of the same version. Hence - ** there are two I/O method structures, one for version 1 and the other - ** for version 2. - */ - sqlite3_io_methods sIoMethodsV1; - sqlite3_io_methods sIoMethodsV2; - - /* True when this shim has been initialized. - */ - int isInitialized; - - /* For run-time access any of the other global data structures in this - ** shim, the following mutex must be held. - */ - sqlite3_mutex *pMutex; - - /* List of multiplexGroup objects. - */ - multiplexGroup *pGroups; -} gMultiplex; - -/************************* Utility Routines *********************************/ -/* -** Acquire and release the mutex used to serialize access to the -** list of multiplexGroups. -*/ -static void multiplexEnter(void){ sqlite3_mutex_enter(gMultiplex.pMutex); } -static void multiplexLeave(void){ sqlite3_mutex_leave(gMultiplex.pMutex); } - -/* -** Compute a string length that is limited to what can be stored in -** lower 30 bits of a 32-bit signed integer. -** -** The value returned will never be negative. Nor will it ever be greater -** than the actual length of the string. For very long strings (greater -** than 1GiB) the value returned might be less than the true string length. -*/ -static int multiplexStrlen30(const char *z){ - const char *z2 = z; - if( z==0 ) return 0; - while( *z2 ){ z2++; } - return 0x3fffffff & (int)(z2 - z); -} - -/* -** Generate the file-name for chunk iChunk of the group with base name -** zBase. The file-name is written to buffer zOut before returning. Buffer -** zOut must be allocated by the caller so that it is at least (nBase+5) -** bytes in size, where nBase is the length of zBase, not including the -** nul-terminator. -** -** If iChunk is 0 (or 400 - the number for the first journal file chunk), -** the output is a copy of the input string. Otherwise, if -** SQLITE_ENABLE_8_3_NAMES is not defined or the input buffer does not contain -** a "." character, then the output is a copy of the input string with the -** three-digit zero-padded decimal representation if iChunk appended to it. -** For example: -** -** zBase="test.db", iChunk=4 -> zOut="test.db004" -** -** Or, if SQLITE_ENABLE_8_3_NAMES is defined and the input buffer contains -** a "." character, then everything after the "." is replaced by the -** three-digit representation of iChunk. -** -** zBase="test.db", iChunk=4 -> zOut="test.004" -** -** The output buffer string is terminated by 2 0x00 bytes. This makes it safe -** to pass to sqlite3_uri_parameter() and similar. -*/ -static void multiplexFilename( - const char *zBase, /* Filename for chunk 0 */ - int nBase, /* Size of zBase in bytes (without \0) */ - int flags, /* Flags used to open file */ - int iChunk, /* Chunk to generate filename for */ - char *zOut /* Buffer to write generated name to */ -){ - int n = nBase; - memcpy(zOut, zBase, n+1); - if( iChunk!=0 && iChunk<=MX_CHUNK_NUMBER ){ -#ifdef SQLITE_ENABLE_8_3_NAMES - int i; - for(i=n-1; i>0 && i>=n-4 && zOut[i]!='.'; i--){} - if( i>=n-4 ) n = i+1; - if( flags & SQLITE_OPEN_MAIN_JOURNAL ){ - /* The extensions on overflow files for main databases are 001, 002, - ** 003 and so forth. To avoid name collisions, add 400 to the - ** extensions of journal files so that they are 401, 402, 403, .... - */ - iChunk += SQLITE_MULTIPLEX_JOURNAL_8_3_OFFSET; - }else if( flags & SQLITE_OPEN_WAL ){ - /* To avoid name collisions, add 700 to the - ** extensions of WAL files so that they are 701, 702, 703, .... - */ - iChunk += SQLITE_MULTIPLEX_WAL_8_3_OFFSET; - } -#endif - sqlite3_snprintf(4,&zOut[n],"%03d",iChunk); - n += 3; - } - - assert( zOut[n]=='\0' ); - zOut[n+1] = '\0'; -} - -/* Compute the filename for the iChunk-th chunk -*/ -static int multiplexSubFilename(multiplexGroup *pGroup, int iChunk){ - if( iChunk>=pGroup->nReal ){ - struct multiplexReal *p; - p = sqlite3_realloc(pGroup->aReal, (iChunk+1)*sizeof(*p)); - if( p==0 ){ - return SQLITE_NOMEM; - } - memset(&p[pGroup->nReal], 0, sizeof(p[0])*(iChunk+1-pGroup->nReal)); - pGroup->aReal = p; - pGroup->nReal = iChunk+1; - } - if( pGroup->zName && pGroup->aReal[iChunk].z==0 ){ - char *z; - int n = pGroup->nName; - pGroup->aReal[iChunk].z = z = sqlite3_malloc( n+5 ); - if( z==0 ){ - return SQLITE_NOMEM; - } - multiplexFilename(pGroup->zName, pGroup->nName, pGroup->flags, iChunk, z); - } - return SQLITE_OK; -} - -/* Translate an sqlite3_file* that is really a multiplexGroup* into -** the sqlite3_file* for the underlying original VFS. -** -** For chunk 0, the pGroup->flags determines whether or not a new file -** is created if it does not already exist. For chunks 1 and higher, the -** file is created only if createFlag is 1. -*/ -static sqlite3_file *multiplexSubOpen( - multiplexGroup *pGroup, /* The multiplexor group */ - int iChunk, /* Which chunk to open. 0==original file */ - int *rc, /* Result code in and out */ - int *pOutFlags, /* Output flags */ - int createFlag /* True to create if iChunk>0 */ -){ - sqlite3_file *pSubOpen = 0; - sqlite3_vfs *pOrigVfs = gMultiplex.pOrigVfs; /* Real VFS */ - -#ifdef SQLITE_ENABLE_8_3_NAMES - /* If JOURNAL_8_3_OFFSET is set to (say) 400, then any overflow files are - ** part of a database journal are named db.401, db.402, and so on. A - ** database may therefore not grow to larger than 400 chunks. Attempting - ** to open chunk 401 indicates the database is full. */ - if( iChunk>=SQLITE_MULTIPLEX_JOURNAL_8_3_OFFSET ){ - sqlite3_log(SQLITE_FULL, "multiplexed chunk overflow: %s", pGroup->zName); - *rc = SQLITE_FULL; - return 0; - } -#endif - - *rc = multiplexSubFilename(pGroup, iChunk); - if( (*rc)==SQLITE_OK && (pSubOpen = pGroup->aReal[iChunk].p)==0 ){ - int flags, bExists; - flags = pGroup->flags; - if( createFlag ){ - flags |= SQLITE_OPEN_CREATE; - }else if( iChunk==0 ){ - /* Fall through */ - }else if( pGroup->aReal[iChunk].z==0 ){ - return 0; - }else{ - *rc = pOrigVfs->xAccess(pOrigVfs, pGroup->aReal[iChunk].z, - SQLITE_ACCESS_EXISTS, &bExists); - if( *rc || !bExists ){ - if( *rc ){ - sqlite3_log(*rc, "multiplexor.xAccess failure on %s", - pGroup->aReal[iChunk].z); - } - return 0; - } - flags &= ~SQLITE_OPEN_CREATE; - } - pSubOpen = sqlite3_malloc( pOrigVfs->szOsFile ); - if( pSubOpen==0 ){ - *rc = SQLITE_IOERR_NOMEM; - return 0; - } - pGroup->aReal[iChunk].p = pSubOpen; - *rc = pOrigVfs->xOpen(pOrigVfs, pGroup->aReal[iChunk].z, pSubOpen, - flags, pOutFlags); - if( (*rc)!=SQLITE_OK ){ - sqlite3_log(*rc, "multiplexor.xOpen failure on %s", - pGroup->aReal[iChunk].z); - sqlite3_free(pSubOpen); - pGroup->aReal[iChunk].p = 0; - return 0; - } - } - return pSubOpen; -} - -/* -** Return the size, in bytes, of chunk number iChunk. If that chunk -** does not exist, then return 0. This function does not distingish between -** non-existant files and zero-length files. -*/ -static sqlite3_int64 multiplexSubSize( - multiplexGroup *pGroup, /* The multiplexor group */ - int iChunk, /* Which chunk to open. 0==original file */ - int *rc /* Result code in and out */ -){ - sqlite3_file *pSub; - sqlite3_int64 sz = 0; - - if( *rc ) return 0; - pSub = multiplexSubOpen(pGroup, iChunk, rc, NULL, 0); - if( pSub==0 ) return 0; - *rc = pSub->pMethods->xFileSize(pSub, &sz); - return sz; -} - -/* -** This is the implementation of the multiplex_control() SQL function. -*/ -static void multiplexControlFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - int rc = SQLITE_OK; - sqlite3 *db = sqlite3_context_db_handle(context); - int op; - int iVal; - - if( !db || argc!=2 ){ - rc = SQLITE_ERROR; - }else{ - /* extract params */ - op = sqlite3_value_int(argv[0]); - iVal = sqlite3_value_int(argv[1]); - /* map function op to file_control op */ - switch( op ){ - case 1: - op = MULTIPLEX_CTRL_ENABLE; - break; - case 2: - op = MULTIPLEX_CTRL_SET_CHUNK_SIZE; - break; - case 3: - op = MULTIPLEX_CTRL_SET_MAX_CHUNKS; - break; - default: - rc = SQLITE_NOTFOUND; - break; - } - } - if( rc==SQLITE_OK ){ - rc = sqlite3_file_control(db, 0, op, &iVal); - } - sqlite3_result_error_code(context, rc); -} - -/* -** This is the entry point to register the auto-extension for the -** multiplex_control() function. -*/ -static int multiplexFuncInit( - sqlite3 *db, - char **pzErrMsg, - const sqlite3_api_routines *pApi -){ - int rc; - rc = sqlite3_create_function(db, "multiplex_control", 2, SQLITE_ANY, - 0, multiplexControlFunc, 0, 0); - return rc; -} - -/* -** Close a single sub-file in the connection group. -*/ -static void multiplexSubClose( - multiplexGroup *pGroup, - int iChunk, - sqlite3_vfs *pOrigVfs -){ - sqlite3_file *pSubOpen = pGroup->aReal[iChunk].p; - if( pSubOpen ){ - pSubOpen->pMethods->xClose(pSubOpen); - if( pOrigVfs && pGroup->aReal[iChunk].z ){ - pOrigVfs->xDelete(pOrigVfs, pGroup->aReal[iChunk].z, 0); - } - sqlite3_free(pGroup->aReal[iChunk].p); - } - sqlite3_free(pGroup->aReal[iChunk].z); - memset(&pGroup->aReal[iChunk], 0, sizeof(pGroup->aReal[iChunk])); -} - -/* -** Deallocate memory held by a multiplexGroup -*/ -static void multiplexFreeComponents(multiplexGroup *pGroup){ - int i; - for(i=0; i<pGroup->nReal; i++){ multiplexSubClose(pGroup, i, 0); } - sqlite3_free(pGroup->aReal); - pGroup->aReal = 0; - pGroup->nReal = 0; -} - - -/************************* VFS Method Wrappers *****************************/ - -/* -** This is the xOpen method used for the "multiplex" VFS. -** -** Most of the work is done by the underlying original VFS. This method -** simply links the new file into the appropriate multiplex group if it is a -** file that needs to be tracked. -*/ -static int multiplexOpen( - sqlite3_vfs *pVfs, /* The multiplex VFS */ - const char *zName, /* Name of file to be opened */ - sqlite3_file *pConn, /* Fill in this file descriptor */ - int flags, /* Flags to control the opening */ - int *pOutFlags /* Flags showing results of opening */ -){ - int rc = SQLITE_OK; /* Result code */ - multiplexConn *pMultiplexOpen; /* The new multiplex file descriptor */ - multiplexGroup *pGroup = 0; /* Corresponding multiplexGroup object */ - sqlite3_file *pSubOpen = 0; /* Real file descriptor */ - sqlite3_vfs *pOrigVfs = gMultiplex.pOrigVfs; /* Real VFS */ - int nName = 0; - int sz = 0; - char *zToFree = 0; - - UNUSED_PARAMETER(pVfs); - memset(pConn, 0, pVfs->szOsFile); - assert( zName || (flags & SQLITE_OPEN_DELETEONCLOSE) ); - - /* We need to create a group structure and manage - ** access to this group of files. - */ - multiplexEnter(); - pMultiplexOpen = (multiplexConn*)pConn; - - if( rc==SQLITE_OK ){ - /* allocate space for group */ - nName = zName ? multiplexStrlen30(zName) : 0; - sz = sizeof(multiplexGroup) /* multiplexGroup */ - + nName + 1; /* zName */ - pGroup = sqlite3_malloc( sz ); - if( pGroup==0 ){ - rc = SQLITE_NOMEM; - } - } - - if( rc==SQLITE_OK ){ - const char *zUri = (flags & SQLITE_OPEN_URI) ? zName : 0; - /* assign pointers to extra space allocated */ - memset(pGroup, 0, sz); - pMultiplexOpen->pGroup = pGroup; - pGroup->bEnabled = -1; - pGroup->bTruncate = sqlite3_uri_boolean(zUri, "truncate", - (flags & SQLITE_OPEN_MAIN_DB)==0); - pGroup->szChunk = (int)sqlite3_uri_int64(zUri, "chunksize", - SQLITE_MULTIPLEX_CHUNK_SIZE); - pGroup->szChunk = (pGroup->szChunk+0xffff)&~0xffff; - if( zName ){ - char *p = (char *)&pGroup[1]; - pGroup->zName = p; - memcpy(pGroup->zName, zName, nName+1); - pGroup->nName = nName; - } - if( pGroup->bEnabled ){ - /* Make sure that the chunksize is such that the pending byte does not - ** falls at the end of a chunk. A region of up to 64K following - ** the pending byte is never written, so if the pending byte occurs - ** near the end of a chunk, that chunk will be too small. */ -#ifndef SQLITE_OMIT_WSD - extern int sqlite3PendingByte; -#else - int sqlite3PendingByte = 0x40000000; -#endif - while( (sqlite3PendingByte % pGroup->szChunk)>=(pGroup->szChunk-65536) ){ - pGroup->szChunk += 65536; - } - } - pGroup->flags = flags; - rc = multiplexSubFilename(pGroup, 1); - if( rc==SQLITE_OK ){ - pSubOpen = multiplexSubOpen(pGroup, 0, &rc, pOutFlags, 0); - if( pSubOpen==0 && rc==SQLITE_OK ) rc = SQLITE_CANTOPEN; - } - if( rc==SQLITE_OK ){ - sqlite3_int64 sz; - - rc = pSubOpen->pMethods->xFileSize(pSubOpen, &sz); - if( rc==SQLITE_OK && zName ){ - int bExists; - if( sz==0 ){ - if( flags & SQLITE_OPEN_MAIN_JOURNAL ){ - /* If opening a main journal file and the first chunk is zero - ** bytes in size, delete any subsequent chunks from the - ** file-system. */ - int iChunk = 1; - do { - rc = pOrigVfs->xAccess(pOrigVfs, - pGroup->aReal[iChunk].z, SQLITE_ACCESS_EXISTS, &bExists - ); - if( rc==SQLITE_OK && bExists ){ - rc = pOrigVfs->xDelete(pOrigVfs, pGroup->aReal[iChunk].z, 0); - if( rc==SQLITE_OK ){ - rc = multiplexSubFilename(pGroup, ++iChunk); - } - } - }while( rc==SQLITE_OK && bExists ); - } - }else{ - /* If the first overflow file exists and if the size of the main file - ** is different from the chunk size, that means the chunk size is set - ** set incorrectly. So fix it. - ** - ** Or, if the first overflow file does not exist and the main file is - ** larger than the chunk size, that means the chunk size is too small. - ** But we have no way of determining the intended chunk size, so - ** just disable the multiplexor all togethre. - */ - rc = pOrigVfs->xAccess(pOrigVfs, pGroup->aReal[1].z, - SQLITE_ACCESS_EXISTS, &bExists); - bExists = multiplexSubSize(pGroup, 1, &rc)>0; - if( rc==SQLITE_OK && bExists && sz==(sz&0xffff0000) && sz>0 - && sz!=pGroup->szChunk ){ - pGroup->szChunk = (int)sz; - }else if( rc==SQLITE_OK && !bExists && sz>pGroup->szChunk ){ - pGroup->bEnabled = 0; - } - } - } - } - - if( rc==SQLITE_OK ){ - if( pSubOpen->pMethods->iVersion==1 ){ - pMultiplexOpen->base.pMethods = &gMultiplex.sIoMethodsV1; - }else{ - pMultiplexOpen->base.pMethods = &gMultiplex.sIoMethodsV2; - } - /* place this group at the head of our list */ - pGroup->pNext = gMultiplex.pGroups; - if( gMultiplex.pGroups ) gMultiplex.pGroups->pPrev = pGroup; - gMultiplex.pGroups = pGroup; - }else{ - multiplexFreeComponents(pGroup); - sqlite3_free(pGroup); - } - } - multiplexLeave(); - sqlite3_free(zToFree); - return rc; -} - -/* -** This is the xDelete method used for the "multiplex" VFS. -** It attempts to delete the filename specified. -*/ -static int multiplexDelete( - sqlite3_vfs *pVfs, /* The multiplex VFS */ - const char *zName, /* Name of file to delete */ - int syncDir -){ - int rc; - sqlite3_vfs *pOrigVfs = gMultiplex.pOrigVfs; /* Real VFS */ - rc = pOrigVfs->xDelete(pOrigVfs, zName, syncDir); - if( rc==SQLITE_OK ){ - /* If the main chunk was deleted successfully, also delete any subsequent - ** chunks - starting with the last (highest numbered). - */ - int nName = (int)strlen(zName); - char *z; - z = sqlite3_malloc(nName + 5); - if( z==0 ){ - rc = SQLITE_IOERR_NOMEM; - }else{ - int iChunk = 0; - int bExists; - do{ - multiplexFilename(zName, nName, SQLITE_OPEN_MAIN_JOURNAL, ++iChunk, z); - rc = pOrigVfs->xAccess(pOrigVfs, z, SQLITE_ACCESS_EXISTS, &bExists); - }while( rc==SQLITE_OK && bExists ); - while( rc==SQLITE_OK && iChunk>1 ){ - multiplexFilename(zName, nName, SQLITE_OPEN_MAIN_JOURNAL, --iChunk, z); - rc = pOrigVfs->xDelete(pOrigVfs, z, syncDir); - } - if( rc==SQLITE_OK ){ - iChunk = 0; - do{ - multiplexFilename(zName, nName, SQLITE_OPEN_WAL, ++iChunk, z); - rc = pOrigVfs->xAccess(pOrigVfs, z, SQLITE_ACCESS_EXISTS, &bExists); - }while( rc==SQLITE_OK && bExists ); - while( rc==SQLITE_OK && iChunk>1 ){ - multiplexFilename(zName, nName, SQLITE_OPEN_WAL, --iChunk, z); - rc = pOrigVfs->xDelete(pOrigVfs, z, syncDir); - } - } - } - sqlite3_free(z); - } - return rc; -} - -static int multiplexAccess(sqlite3_vfs *a, const char *b, int c, int *d){ - return gMultiplex.pOrigVfs->xAccess(gMultiplex.pOrigVfs, b, c, d); -} -static int multiplexFullPathname(sqlite3_vfs *a, const char *b, int c, char *d){ - return gMultiplex.pOrigVfs->xFullPathname(gMultiplex.pOrigVfs, b, c, d); -} -static void *multiplexDlOpen(sqlite3_vfs *a, const char *b){ - return gMultiplex.pOrigVfs->xDlOpen(gMultiplex.pOrigVfs, b); -} -static void multiplexDlError(sqlite3_vfs *a, int b, char *c){ - gMultiplex.pOrigVfs->xDlError(gMultiplex.pOrigVfs, b, c); -} -static void (*multiplexDlSym(sqlite3_vfs *a, void *b, const char *c))(void){ - return gMultiplex.pOrigVfs->xDlSym(gMultiplex.pOrigVfs, b, c); -} -static void multiplexDlClose(sqlite3_vfs *a, void *b){ - gMultiplex.pOrigVfs->xDlClose(gMultiplex.pOrigVfs, b); -} -static int multiplexRandomness(sqlite3_vfs *a, int b, char *c){ - return gMultiplex.pOrigVfs->xRandomness(gMultiplex.pOrigVfs, b, c); -} -static int multiplexSleep(sqlite3_vfs *a, int b){ - return gMultiplex.pOrigVfs->xSleep(gMultiplex.pOrigVfs, b); -} -static int multiplexCurrentTime(sqlite3_vfs *a, double *b){ - return gMultiplex.pOrigVfs->xCurrentTime(gMultiplex.pOrigVfs, b); -} -static int multiplexGetLastError(sqlite3_vfs *a, int b, char *c){ - return gMultiplex.pOrigVfs->xGetLastError(gMultiplex.pOrigVfs, b, c); -} -static int multiplexCurrentTimeInt64(sqlite3_vfs *a, sqlite3_int64 *b){ - return gMultiplex.pOrigVfs->xCurrentTimeInt64(gMultiplex.pOrigVfs, b); -} - -/************************ I/O Method Wrappers *******************************/ - -/* xClose requests get passed through to the original VFS. -** We loop over all open chunk handles and close them. -** The group structure for this file is unlinked from -** our list of groups and freed. -*/ -static int multiplexClose(sqlite3_file *pConn){ - multiplexConn *p = (multiplexConn*)pConn; - multiplexGroup *pGroup = p->pGroup; - int rc = SQLITE_OK; - multiplexEnter(); - multiplexFreeComponents(pGroup); - /* remove from linked list */ - if( pGroup->pNext ) pGroup->pNext->pPrev = pGroup->pPrev; - if( pGroup->pPrev ){ - pGroup->pPrev->pNext = pGroup->pNext; - }else{ - gMultiplex.pGroups = pGroup->pNext; - } - sqlite3_free(pGroup); - multiplexLeave(); - return rc; -} - -/* Pass xRead requests thru to the original VFS after -** determining the correct chunk to operate on. -** Break up reads across chunk boundaries. -*/ -static int multiplexRead( - sqlite3_file *pConn, - void *pBuf, - int iAmt, - sqlite3_int64 iOfst -){ - multiplexConn *p = (multiplexConn*)pConn; - multiplexGroup *pGroup = p->pGroup; - int rc = SQLITE_OK; - multiplexEnter(); - if( !pGroup->bEnabled ){ - sqlite3_file *pSubOpen = multiplexSubOpen(pGroup, 0, &rc, NULL, 0); - if( pSubOpen==0 ){ - rc = SQLITE_IOERR_READ; - }else{ - rc = pSubOpen->pMethods->xRead(pSubOpen, pBuf, iAmt, iOfst); - } - }else{ - while( iAmt > 0 ){ - int i = (int)(iOfst / pGroup->szChunk); - sqlite3_file *pSubOpen = multiplexSubOpen(pGroup, i, &rc, NULL, 1); - if( pSubOpen ){ - int extra = ((int)(iOfst % pGroup->szChunk) + iAmt) - pGroup->szChunk; - if( extra<0 ) extra = 0; - iAmt -= extra; - rc = pSubOpen->pMethods->xRead(pSubOpen, pBuf, iAmt, - iOfst % pGroup->szChunk); - if( rc!=SQLITE_OK ) break; - pBuf = (char *)pBuf + iAmt; - iOfst += iAmt; - iAmt = extra; - }else{ - rc = SQLITE_IOERR_READ; - break; - } - } - } - multiplexLeave(); - return rc; -} - -/* Pass xWrite requests thru to the original VFS after -** determining the correct chunk to operate on. -** Break up writes across chunk boundaries. -*/ -static int multiplexWrite( - sqlite3_file *pConn, - const void *pBuf, - int iAmt, - sqlite3_int64 iOfst -){ - multiplexConn *p = (multiplexConn*)pConn; - multiplexGroup *pGroup = p->pGroup; - int rc = SQLITE_OK; - multiplexEnter(); - if( !pGroup->bEnabled ){ - sqlite3_file *pSubOpen = multiplexSubOpen(pGroup, 0, &rc, NULL, 0); - if( pSubOpen==0 ){ - rc = SQLITE_IOERR_WRITE; - }else{ - rc = pSubOpen->pMethods->xWrite(pSubOpen, pBuf, iAmt, iOfst); - } - }else{ - while( rc==SQLITE_OK && iAmt>0 ){ - int i = (int)(iOfst / pGroup->szChunk); - sqlite3_file *pSubOpen = multiplexSubOpen(pGroup, i, &rc, NULL, 1); - if( pSubOpen ){ - int extra = ((int)(iOfst % pGroup->szChunk) + iAmt) - - pGroup->szChunk; - if( extra<0 ) extra = 0; - iAmt -= extra; - rc = pSubOpen->pMethods->xWrite(pSubOpen, pBuf, iAmt, - iOfst % pGroup->szChunk); - pBuf = (char *)pBuf + iAmt; - iOfst += iAmt; - iAmt = extra; - } - } - } - multiplexLeave(); - return rc; -} - -/* Pass xTruncate requests thru to the original VFS after -** determining the correct chunk to operate on. Delete any -** chunks above the truncate mark. -*/ -static int multiplexTruncate(sqlite3_file *pConn, sqlite3_int64 size){ - multiplexConn *p = (multiplexConn*)pConn; - multiplexGroup *pGroup = p->pGroup; - int rc = SQLITE_OK; - multiplexEnter(); - if( !pGroup->bEnabled ){ - sqlite3_file *pSubOpen = multiplexSubOpen(pGroup, 0, &rc, NULL, 0); - if( pSubOpen==0 ){ - rc = SQLITE_IOERR_TRUNCATE; - }else{ - rc = pSubOpen->pMethods->xTruncate(pSubOpen, size); - } - }else{ - int i; - int iBaseGroup = (int)(size / pGroup->szChunk); - sqlite3_file *pSubOpen; - sqlite3_vfs *pOrigVfs = gMultiplex.pOrigVfs; /* Real VFS */ - /* delete the chunks above the truncate limit */ - for(i = pGroup->nReal-1; i>iBaseGroup && rc==SQLITE_OK; i--){ - if( pGroup->bTruncate ){ - multiplexSubClose(pGroup, i, pOrigVfs); - }else{ - pSubOpen = multiplexSubOpen(pGroup, i, &rc, 0, 0); - if( pSubOpen ){ - rc = pSubOpen->pMethods->xTruncate(pSubOpen, 0); - } - } - } - if( rc==SQLITE_OK ){ - pSubOpen = multiplexSubOpen(pGroup, iBaseGroup, &rc, 0, 0); - if( pSubOpen ){ - rc = pSubOpen->pMethods->xTruncate(pSubOpen, size % pGroup->szChunk); - } - } - if( rc ) rc = SQLITE_IOERR_TRUNCATE; - } - multiplexLeave(); - return rc; -} - -/* Pass xSync requests through to the original VFS without change -*/ -static int multiplexSync(sqlite3_file *pConn, int flags){ - multiplexConn *p = (multiplexConn*)pConn; - multiplexGroup *pGroup = p->pGroup; - int rc = SQLITE_OK; - int i; - multiplexEnter(); - for(i=0; i<pGroup->nReal; i++){ - sqlite3_file *pSubOpen = pGroup->aReal[i].p; - if( pSubOpen ){ - int rc2 = pSubOpen->pMethods->xSync(pSubOpen, flags); - if( rc2!=SQLITE_OK ) rc = rc2; - } - } - multiplexLeave(); - return rc; -} - -/* Pass xFileSize requests through to the original VFS. -** Aggregate the size of all the chunks before returning. -*/ -static int multiplexFileSize(sqlite3_file *pConn, sqlite3_int64 *pSize){ - multiplexConn *p = (multiplexConn*)pConn; - multiplexGroup *pGroup = p->pGroup; - int rc = SQLITE_OK; - int i; - multiplexEnter(); - if( !pGroup->bEnabled ){ - sqlite3_file *pSubOpen = multiplexSubOpen(pGroup, 0, &rc, NULL, 0); - if( pSubOpen==0 ){ - rc = SQLITE_IOERR_FSTAT; - }else{ - rc = pSubOpen->pMethods->xFileSize(pSubOpen, pSize); - } - }else{ - *pSize = 0; - for(i=0; rc==SQLITE_OK; i++){ - sqlite3_int64 sz = multiplexSubSize(pGroup, i, &rc); - if( sz==0 ) break; - *pSize = i*(sqlite3_int64)pGroup->szChunk + sz; - } - } - multiplexLeave(); - return rc; -} - -/* Pass xLock requests through to the original VFS unchanged. -*/ -static int multiplexLock(sqlite3_file *pConn, int lock){ - multiplexConn *p = (multiplexConn*)pConn; - int rc; - sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL, 0); - if( pSubOpen ){ - return pSubOpen->pMethods->xLock(pSubOpen, lock); - } - return SQLITE_BUSY; -} - -/* Pass xUnlock requests through to the original VFS unchanged. -*/ -static int multiplexUnlock(sqlite3_file *pConn, int lock){ - multiplexConn *p = (multiplexConn*)pConn; - int rc; - sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL, 0); - if( pSubOpen ){ - return pSubOpen->pMethods->xUnlock(pSubOpen, lock); - } - return SQLITE_IOERR_UNLOCK; -} - -/* Pass xCheckReservedLock requests through to the original VFS unchanged. -*/ -static int multiplexCheckReservedLock(sqlite3_file *pConn, int *pResOut){ - multiplexConn *p = (multiplexConn*)pConn; - int rc; - sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL, 0); - if( pSubOpen ){ - return pSubOpen->pMethods->xCheckReservedLock(pSubOpen, pResOut); - } - return SQLITE_IOERR_CHECKRESERVEDLOCK; -} - -/* Pass xFileControl requests through to the original VFS unchanged, -** except for any MULTIPLEX_CTRL_* requests here. -*/ -static int multiplexFileControl(sqlite3_file *pConn, int op, void *pArg){ - multiplexConn *p = (multiplexConn*)pConn; - multiplexGroup *pGroup = p->pGroup; - int rc = SQLITE_ERROR; - sqlite3_file *pSubOpen; - - if( !gMultiplex.isInitialized ) return SQLITE_MISUSE; - switch( op ){ - case MULTIPLEX_CTRL_ENABLE: - if( pArg ) { - int bEnabled = *(int *)pArg; - pGroup->bEnabled = bEnabled; - rc = SQLITE_OK; - } - break; - case MULTIPLEX_CTRL_SET_CHUNK_SIZE: - if( pArg ) { - unsigned int szChunk = *(unsigned*)pArg; - if( szChunk<1 ){ - rc = SQLITE_MISUSE; - }else{ - /* Round up to nearest multiple of MAX_PAGE_SIZE. */ - szChunk = (szChunk + (MAX_PAGE_SIZE-1)); - szChunk &= ~(MAX_PAGE_SIZE-1); - pGroup->szChunk = szChunk; - rc = SQLITE_OK; - } - } - break; - case MULTIPLEX_CTRL_SET_MAX_CHUNKS: - rc = SQLITE_OK; - break; - case SQLITE_FCNTL_SIZE_HINT: - case SQLITE_FCNTL_CHUNK_SIZE: - /* no-op these */ - rc = SQLITE_OK; - break; - default: - pSubOpen = multiplexSubOpen(pGroup, 0, &rc, NULL, 0); - if( pSubOpen ){ - rc = pSubOpen->pMethods->xFileControl(pSubOpen, op, pArg); - if( op==SQLITE_FCNTL_VFSNAME && rc==SQLITE_OK ){ - *(char**)pArg = sqlite3_mprintf("multiplex/%z", *(char**)pArg); - } - } - break; - } - return rc; -} - -/* Pass xSectorSize requests through to the original VFS unchanged. -*/ -static int multiplexSectorSize(sqlite3_file *pConn){ - multiplexConn *p = (multiplexConn*)pConn; - int rc; - sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL, 0); - if( pSubOpen && pSubOpen->pMethods->xSectorSize ){ - return pSubOpen->pMethods->xSectorSize(pSubOpen); - } - return DEFAULT_SECTOR_SIZE; -} - -/* Pass xDeviceCharacteristics requests through to the original VFS unchanged. -*/ -static int multiplexDeviceCharacteristics(sqlite3_file *pConn){ - multiplexConn *p = (multiplexConn*)pConn; - int rc; - sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL, 0); - if( pSubOpen ){ - return pSubOpen->pMethods->xDeviceCharacteristics(pSubOpen); - } - return 0; -} - -/* Pass xShmMap requests through to the original VFS unchanged. -*/ -static int multiplexShmMap( - sqlite3_file *pConn, /* Handle open on database file */ - int iRegion, /* Region to retrieve */ - int szRegion, /* Size of regions */ - int bExtend, /* True to extend file if necessary */ - void volatile **pp /* OUT: Mapped memory */ -){ - multiplexConn *p = (multiplexConn*)pConn; - int rc; - sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL, 0); - if( pSubOpen ){ - return pSubOpen->pMethods->xShmMap(pSubOpen, iRegion, szRegion, bExtend,pp); - } - return SQLITE_IOERR; -} - -/* Pass xShmLock requests through to the original VFS unchanged. -*/ -static int multiplexShmLock( - sqlite3_file *pConn, /* Database file holding the shared memory */ - int ofst, /* First lock to acquire or release */ - int n, /* Number of locks to acquire or release */ - int flags /* What to do with the lock */ -){ - multiplexConn *p = (multiplexConn*)pConn; - int rc; - sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL, 0); - if( pSubOpen ){ - return pSubOpen->pMethods->xShmLock(pSubOpen, ofst, n, flags); - } - return SQLITE_BUSY; -} - -/* Pass xShmBarrier requests through to the original VFS unchanged. -*/ -static void multiplexShmBarrier(sqlite3_file *pConn){ - multiplexConn *p = (multiplexConn*)pConn; - int rc; - sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL, 0); - if( pSubOpen ){ - pSubOpen->pMethods->xShmBarrier(pSubOpen); - } -} - -/* Pass xShmUnmap requests through to the original VFS unchanged. -*/ -static int multiplexShmUnmap(sqlite3_file *pConn, int deleteFlag){ - multiplexConn *p = (multiplexConn*)pConn; - int rc; - sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL, 0); - if( pSubOpen ){ - return pSubOpen->pMethods->xShmUnmap(pSubOpen, deleteFlag); - } - return SQLITE_OK; -} - -/************************** Public Interfaces *****************************/ -/* -** CAPI: Initialize the multiplex VFS shim - sqlite3_multiplex_initialize() -** -** Use the VFS named zOrigVfsName as the VFS that does the actual work. -** Use the default if zOrigVfsName==NULL. -** -** The multiplex VFS shim is named "multiplex". It will become the default -** VFS if makeDefault is non-zero. -** -** THIS ROUTINE IS NOT THREADSAFE. Call this routine exactly once -** during start-up. -*/ -int sqlite3_multiplex_initialize(const char *zOrigVfsName, int makeDefault){ - sqlite3_vfs *pOrigVfs; - if( gMultiplex.isInitialized ) return SQLITE_MISUSE; - pOrigVfs = sqlite3_vfs_find(zOrigVfsName); - if( pOrigVfs==0 ) return SQLITE_ERROR; - assert( pOrigVfs!=&gMultiplex.sThisVfs ); - gMultiplex.pMutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST); - if( !gMultiplex.pMutex ){ - return SQLITE_NOMEM; - } - gMultiplex.pGroups = NULL; - gMultiplex.isInitialized = 1; - gMultiplex.pOrigVfs = pOrigVfs; - gMultiplex.sThisVfs = *pOrigVfs; - gMultiplex.sThisVfs.szOsFile += sizeof(multiplexConn); - gMultiplex.sThisVfs.zName = SQLITE_MULTIPLEX_VFS_NAME; - gMultiplex.sThisVfs.xOpen = multiplexOpen; - gMultiplex.sThisVfs.xDelete = multiplexDelete; - gMultiplex.sThisVfs.xAccess = multiplexAccess; - gMultiplex.sThisVfs.xFullPathname = multiplexFullPathname; - gMultiplex.sThisVfs.xDlOpen = multiplexDlOpen; - gMultiplex.sThisVfs.xDlError = multiplexDlError; - gMultiplex.sThisVfs.xDlSym = multiplexDlSym; - gMultiplex.sThisVfs.xDlClose = multiplexDlClose; - gMultiplex.sThisVfs.xRandomness = multiplexRandomness; - gMultiplex.sThisVfs.xSleep = multiplexSleep; - gMultiplex.sThisVfs.xCurrentTime = multiplexCurrentTime; - gMultiplex.sThisVfs.xGetLastError = multiplexGetLastError; - gMultiplex.sThisVfs.xCurrentTimeInt64 = multiplexCurrentTimeInt64; - - gMultiplex.sIoMethodsV1.iVersion = 1; - gMultiplex.sIoMethodsV1.xClose = multiplexClose; - gMultiplex.sIoMethodsV1.xRead = multiplexRead; - gMultiplex.sIoMethodsV1.xWrite = multiplexWrite; - gMultiplex.sIoMethodsV1.xTruncate = multiplexTruncate; - gMultiplex.sIoMethodsV1.xSync = multiplexSync; - gMultiplex.sIoMethodsV1.xFileSize = multiplexFileSize; - gMultiplex.sIoMethodsV1.xLock = multiplexLock; - gMultiplex.sIoMethodsV1.xUnlock = multiplexUnlock; - gMultiplex.sIoMethodsV1.xCheckReservedLock = multiplexCheckReservedLock; - gMultiplex.sIoMethodsV1.xFileControl = multiplexFileControl; - gMultiplex.sIoMethodsV1.xSectorSize = multiplexSectorSize; - gMultiplex.sIoMethodsV1.xDeviceCharacteristics = - multiplexDeviceCharacteristics; - gMultiplex.sIoMethodsV2 = gMultiplex.sIoMethodsV1; - gMultiplex.sIoMethodsV2.iVersion = 2; - gMultiplex.sIoMethodsV2.xShmMap = multiplexShmMap; - gMultiplex.sIoMethodsV2.xShmLock = multiplexShmLock; - gMultiplex.sIoMethodsV2.xShmBarrier = multiplexShmBarrier; - gMultiplex.sIoMethodsV2.xShmUnmap = multiplexShmUnmap; - sqlite3_vfs_register(&gMultiplex.sThisVfs, makeDefault); - - sqlite3_auto_extension((void*)multiplexFuncInit); - - return SQLITE_OK; -} - -/* -** CAPI: Shutdown the multiplex system - sqlite3_multiplex_shutdown() -** -** All SQLite database connections must be closed before calling this -** routine. -** -** THIS ROUTINE IS NOT THREADSAFE. Call this routine exactly once while -** shutting down in order to free all remaining multiplex groups. -*/ -int sqlite3_multiplex_shutdown(void){ - if( gMultiplex.isInitialized==0 ) return SQLITE_MISUSE; - if( gMultiplex.pGroups ) return SQLITE_MISUSE; - gMultiplex.isInitialized = 0; - sqlite3_mutex_free(gMultiplex.pMutex); - sqlite3_vfs_unregister(&gMultiplex.sThisVfs); - memset(&gMultiplex, 0, sizeof(gMultiplex)); - return SQLITE_OK; -} - -/***************************** Test Code ***********************************/ -#ifdef SQLITE_TEST -#include <tcl.h> -extern const char *sqlite3ErrName(int); - - -/* -** tclcmd: sqlite3_multiplex_initialize NAME MAKEDEFAULT -*/ -static int test_multiplex_initialize( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - const char *zName; /* Name of new multiplex VFS */ - int makeDefault; /* True to make the new VFS the default */ - int rc; /* Value returned by multiplex_initialize() */ - - UNUSED_PARAMETER(clientData); - - /* Process arguments */ - if( objc!=3 ){ - Tcl_WrongNumArgs(interp, 1, objv, "NAME MAKEDEFAULT"); - return TCL_ERROR; - } - zName = Tcl_GetString(objv[1]); - if( Tcl_GetBooleanFromObj(interp, objv[2], &makeDefault) ) return TCL_ERROR; - if( zName[0]=='\0' ) zName = 0; - - /* Call sqlite3_multiplex_initialize() */ - rc = sqlite3_multiplex_initialize(zName, makeDefault); - Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_STATIC); - - return TCL_OK; -} - -/* -** tclcmd: sqlite3_multiplex_shutdown -*/ -static int test_multiplex_shutdown( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - int rc; /* Value returned by multiplex_shutdown() */ - - UNUSED_PARAMETER(clientData); - - if( objc!=1 ){ - Tcl_WrongNumArgs(interp, 1, objv, ""); - return TCL_ERROR; - } - - /* Call sqlite3_multiplex_shutdown() */ - rc = sqlite3_multiplex_shutdown(); - Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_STATIC); - - return TCL_OK; -} - -/* -** tclcmd: sqlite3_multiplex_dump -*/ -static int test_multiplex_dump( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - Tcl_Obj *pResult; - Tcl_Obj *pGroupTerm; - multiplexGroup *pGroup; - int i; - int nChunks = 0; - - UNUSED_PARAMETER(clientData); - UNUSED_PARAMETER(objc); - UNUSED_PARAMETER(objv); - - pResult = Tcl_NewObj(); - multiplexEnter(); - for(pGroup=gMultiplex.pGroups; pGroup; pGroup=pGroup->pNext){ - pGroupTerm = Tcl_NewObj(); - - if( pGroup->zName ){ - pGroup->zName[pGroup->nName] = '\0'; - Tcl_ListObjAppendElement(interp, pGroupTerm, - Tcl_NewStringObj(pGroup->zName, -1)); - }else{ - Tcl_ListObjAppendElement(interp, pGroupTerm, Tcl_NewObj()); - } - Tcl_ListObjAppendElement(interp, pGroupTerm, - Tcl_NewIntObj(pGroup->nName)); - Tcl_ListObjAppendElement(interp, pGroupTerm, - Tcl_NewIntObj(pGroup->flags)); - - /* count number of chunks with open handles */ - for(i=0; i<pGroup->nReal; i++){ - if( pGroup->aReal[i].p!=0 ) nChunks++; - } - Tcl_ListObjAppendElement(interp, pGroupTerm, - Tcl_NewIntObj(nChunks)); - - Tcl_ListObjAppendElement(interp, pGroupTerm, - Tcl_NewIntObj(pGroup->szChunk)); - Tcl_ListObjAppendElement(interp, pGroupTerm, - Tcl_NewIntObj(pGroup->nReal)); - - Tcl_ListObjAppendElement(interp, pResult, pGroupTerm); - } - multiplexLeave(); - Tcl_SetObjResult(interp, pResult); - return TCL_OK; -} - -/* -** Tclcmd: test_multiplex_control HANDLE DBNAME SUB-COMMAND ?INT-VALUE? -*/ -static int test_multiplex_control( - ClientData cd, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - int rc; /* Return code from file_control() */ - int idx; /* Index in aSub[] */ - Tcl_CmdInfo cmdInfo; /* Command info structure for HANDLE */ - sqlite3 *db; /* Underlying db handle for HANDLE */ - int iValue = 0; - void *pArg = 0; - - struct SubCommand { - const char *zName; - int op; - int argtype; - } aSub[] = { - { "enable", MULTIPLEX_CTRL_ENABLE, 1 }, - { "chunk_size", MULTIPLEX_CTRL_SET_CHUNK_SIZE, 1 }, - { "max_chunks", MULTIPLEX_CTRL_SET_MAX_CHUNKS, 1 }, - { 0, 0, 0 } - }; - - if( objc!=5 ){ - Tcl_WrongNumArgs(interp, 1, objv, "HANDLE DBNAME SUB-COMMAND INT-VALUE"); - return TCL_ERROR; - } - - if( 0==Tcl_GetCommandInfo(interp, Tcl_GetString(objv[1]), &cmdInfo) ){ - Tcl_AppendResult(interp, "expected database handle, got \"", 0); - Tcl_AppendResult(interp, Tcl_GetString(objv[1]), "\"", 0); - return TCL_ERROR; - }else{ - db = *(sqlite3 **)cmdInfo.objClientData; - } - - rc = Tcl_GetIndexFromObjStruct( - interp, objv[3], aSub, sizeof(aSub[0]), "sub-command", 0, &idx - ); - if( rc!=TCL_OK ) return rc; - - switch( aSub[idx].argtype ){ - case 1: - if( Tcl_GetIntFromObj(interp, objv[4], &iValue) ){ - return TCL_ERROR; - } - pArg = (void *)&iValue; - break; - default: - Tcl_WrongNumArgs(interp, 4, objv, "SUB-COMMAND"); - return TCL_ERROR; - } - - rc = sqlite3_file_control(db, Tcl_GetString(objv[2]), aSub[idx].op, pArg); - Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_STATIC); - return (rc==SQLITE_OK) ? TCL_OK : TCL_ERROR; -} - -/* -** This routine registers the custom TCL commands defined in this -** module. This should be the only procedure visible from outside -** of this module. -*/ -int Sqlitemultiplex_Init(Tcl_Interp *interp){ - static struct { - char *zName; - Tcl_ObjCmdProc *xProc; - } aCmd[] = { - { "sqlite3_multiplex_initialize", test_multiplex_initialize }, - { "sqlite3_multiplex_shutdown", test_multiplex_shutdown }, - { "sqlite3_multiplex_dump", test_multiplex_dump }, - { "sqlite3_multiplex_control", test_multiplex_control }, - }; - int i; - - for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){ - Tcl_CreateObjCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0); - } - - return TCL_OK; -} -#endif diff --git a/components/external/SQLite-3.8.1/SQLiteLib/test/test_multiplex.h b/components/external/SQLite-3.8.1/SQLiteLib/test/test_multiplex.h deleted file mode 100644 index 9fe2f0f2b2..0000000000 --- a/components/external/SQLite-3.8.1/SQLiteLib/test/test_multiplex.h +++ /dev/null @@ -1,99 +0,0 @@ -/* -** 2011 March 18 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** -** This file contains a VFS "shim" - a layer that sits in between the -** pager and the real VFS. -** -** This particular shim enforces a multiplex system on DB files. -** This shim shards/partitions a single DB file into smaller -** "chunks" such that the total DB file size may exceed the maximum -** file size of the underlying file system. -** -*/ - -#ifndef _TEST_MULTIPLEX_H -#define _TEST_MULTIPLEX_H - -/* -** CAPI: File-control Operations Supported by Multiplex VFS -** -** Values interpreted by the xFileControl method of a Multiplex VFS db file-handle. -** -** MULTIPLEX_CTRL_ENABLE: -** This file control is used to enable or disable the multiplex -** shim. -** -** MULTIPLEX_CTRL_SET_CHUNK_SIZE: -** This file control is used to set the maximum allowed chunk -** size for a multiplex file set. The chunk size should be -** a multiple of SQLITE_MAX_PAGE_SIZE, and will be rounded up -** if not. -** -** MULTIPLEX_CTRL_SET_MAX_CHUNKS: -** This file control is used to set the maximum number of chunks -** allowed to be used for a mutliplex file set. -*/ -#define MULTIPLEX_CTRL_ENABLE 214014 -#define MULTIPLEX_CTRL_SET_CHUNK_SIZE 214015 -#define MULTIPLEX_CTRL_SET_MAX_CHUNKS 214016 - -#ifdef __cplusplus -extern "C" { -#endif - -/* -** CAPI: Initialize the multiplex VFS shim - sqlite3_multiplex_initialize() -** -** Use the VFS named zOrigVfsName as the VFS that does the actual work. -** Use the default if zOrigVfsName==NULL. -** -** The multiplex VFS shim is named "multiplex". It will become the default -** VFS if makeDefault is non-zero. -** -** An auto-extension is registered which will make the function -** multiplex_control() available to database connections. This -** function gives access to the xFileControl interface of the -** multiplex VFS shim. -** -** SELECT multiplex_control(<op>,<val>); -** -** <op>=1 MULTIPLEX_CTRL_ENABLE -** <val>=0 disable -** <val>=1 enable -** -** <op>=2 MULTIPLEX_CTRL_SET_CHUNK_SIZE -** <val> int, chunk size -** -** <op>=3 MULTIPLEX_CTRL_SET_MAX_CHUNKS -** <val> int, max chunks -** -** THIS ROUTINE IS NOT THREADSAFE. Call this routine exactly once -** during start-up. -*/ -extern int sqlite3_multiplex_initialize(const char *zOrigVfsName, int makeDefault); - -/* -** CAPI: Shutdown the multiplex system - sqlite3_multiplex_shutdown() -** -** All SQLite database connections must be closed before calling this -** routine. -** -** THIS ROUTINE IS NOT THREADSAFE. Call this routine exactly once while -** shutting down in order to free all remaining multiplex groups. -*/ -extern int sqlite3_multiplex_shutdown(void); - -#ifdef __cplusplus -} /* End of the 'extern "C"' block */ -#endif - -#endif /* _TEST_MULTIPLEX_H */ diff --git a/components/external/SQLite-3.8.1/SQLiteLib/test/test_mutex.c b/components/external/SQLite-3.8.1/SQLiteLib/test/test_mutex.c deleted file mode 100644 index c9b4a29ab7..0000000000 --- a/components/external/SQLite-3.8.1/SQLiteLib/test/test_mutex.c +++ /dev/null @@ -1,439 +0,0 @@ -/* -** 2008 June 18 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This file contains test logic for the sqlite3_mutex interfaces. -*/ - -#include "tcl.h" -#include "sqlite3.h" -#include "sqliteInt.h" -#include <stdlib.h> -#include <assert.h> -#include <string.h> - -/* defined in main.c */ -extern const char *sqlite3ErrName(int); - -/* A countable mutex */ -struct sqlite3_mutex { - sqlite3_mutex *pReal; - int eType; -}; - -/* State variables */ -static struct test_mutex_globals { - int isInstalled; /* True if installed */ - int disableInit; /* True to cause sqlite3_initalize() to fail */ - int disableTry; /* True to force sqlite3_mutex_try() to fail */ - int isInit; /* True if initialized */ - sqlite3_mutex_methods m; /* Interface to "real" mutex system */ - int aCounter[8]; /* Number of grabs of each type of mutex */ - sqlite3_mutex aStatic[6]; /* The six static mutexes */ -} g = {0}; - -/* Return true if the countable mutex is currently held */ -static int counterMutexHeld(sqlite3_mutex *p){ - return g.m.xMutexHeld(p->pReal); -} - -/* Return true if the countable mutex is not currently held */ -static int counterMutexNotheld(sqlite3_mutex *p){ - return g.m.xMutexNotheld(p->pReal); -} - -/* Initialize the countable mutex interface -** Or, if g.disableInit is non-zero, then do not initialize but instead -** return the value of g.disableInit as the result code. This can be used -** to simulate an initialization failure. -*/ -static int counterMutexInit(void){ - int rc; - if( g.disableInit ) return g.disableInit; - rc = g.m.xMutexInit(); - g.isInit = 1; - return rc; -} - -/* -** Uninitialize the mutex subsystem -*/ -static int counterMutexEnd(void){ - g.isInit = 0; - return g.m.xMutexEnd(); -} - -/* -** Allocate a countable mutex -*/ -static sqlite3_mutex *counterMutexAlloc(int eType){ - sqlite3_mutex *pReal; - sqlite3_mutex *pRet = 0; - - assert( g.isInit ); - assert(eType<8 && eType>=0); - - pReal = g.m.xMutexAlloc(eType); - if( !pReal ) return 0; - - if( eType==SQLITE_MUTEX_FAST || eType==SQLITE_MUTEX_RECURSIVE ){ - pRet = (sqlite3_mutex *)malloc(sizeof(sqlite3_mutex)); - }else{ - pRet = &g.aStatic[eType-2]; - } - - pRet->eType = eType; - pRet->pReal = pReal; - return pRet; -} - -/* -** Free a countable mutex -*/ -static void counterMutexFree(sqlite3_mutex *p){ - assert( g.isInit ); - g.m.xMutexFree(p->pReal); - if( p->eType==SQLITE_MUTEX_FAST || p->eType==SQLITE_MUTEX_RECURSIVE ){ - free(p); - } -} - -/* -** Enter a countable mutex. Block until entry is safe. -*/ -static void counterMutexEnter(sqlite3_mutex *p){ - assert( g.isInit ); - g.aCounter[p->eType]++; - g.m.xMutexEnter(p->pReal); -} - -/* -** Try to enter a mutex. Return true on success. -*/ -static int counterMutexTry(sqlite3_mutex *p){ - assert( g.isInit ); - g.aCounter[p->eType]++; - if( g.disableTry ) return SQLITE_BUSY; - return g.m.xMutexTry(p->pReal); -} - -/* Leave a mutex -*/ -static void counterMutexLeave(sqlite3_mutex *p){ - assert( g.isInit ); - g.m.xMutexLeave(p->pReal); -} - -/* -** sqlite3_shutdown -*/ -static int test_shutdown( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - int rc; - - if( objc!=1 ){ - Tcl_WrongNumArgs(interp, 1, objv, ""); - return TCL_ERROR; - } - - rc = sqlite3_shutdown(); - Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE); - return TCL_OK; -} - -/* -** sqlite3_initialize -*/ -static int test_initialize( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - int rc; - - if( objc!=1 ){ - Tcl_WrongNumArgs(interp, 1, objv, ""); - return TCL_ERROR; - } - - rc = sqlite3_initialize(); - Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE); - return TCL_OK; -} - -/* -** install_mutex_counters BOOLEAN -*/ -static int test_install_mutex_counters( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - int rc = SQLITE_OK; - int isInstall; - - sqlite3_mutex_methods counter_methods = { - counterMutexInit, - counterMutexEnd, - counterMutexAlloc, - counterMutexFree, - counterMutexEnter, - counterMutexTry, - counterMutexLeave, - counterMutexHeld, - counterMutexNotheld - }; - - if( objc!=2 ){ - Tcl_WrongNumArgs(interp, 1, objv, "BOOLEAN"); - return TCL_ERROR; - } - if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[1], &isInstall) ){ - return TCL_ERROR; - } - - assert(isInstall==0 || isInstall==1); - assert(g.isInstalled==0 || g.isInstalled==1); - if( isInstall==g.isInstalled ){ - Tcl_AppendResult(interp, "mutex counters are ", 0); - Tcl_AppendResult(interp, isInstall?"already installed":"not installed", 0); - return TCL_ERROR; - } - - if( isInstall ){ - assert( g.m.xMutexAlloc==0 ); - rc = sqlite3_config(SQLITE_CONFIG_GETMUTEX, &g.m); - if( rc==SQLITE_OK ){ - sqlite3_config(SQLITE_CONFIG_MUTEX, &counter_methods); - } - g.disableTry = 0; - }else{ - assert( g.m.xMutexAlloc ); - rc = sqlite3_config(SQLITE_CONFIG_MUTEX, &g.m); - memset(&g.m, 0, sizeof(sqlite3_mutex_methods)); - } - - if( rc==SQLITE_OK ){ - g.isInstalled = isInstall; - } - - Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE); - return TCL_OK; -} - -/* -** read_mutex_counters -*/ -static int test_read_mutex_counters( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - Tcl_Obj *pRet; - int ii; - char *aName[8] = { - "fast", "recursive", "static_master", "static_mem", - "static_open", "static_prng", "static_lru", "static_pmem" - }; - - if( objc!=1 ){ - Tcl_WrongNumArgs(interp, 1, objv, ""); - return TCL_ERROR; - } - - pRet = Tcl_NewObj(); - Tcl_IncrRefCount(pRet); - for(ii=0; ii<8; ii++){ - Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj(aName[ii], -1)); - Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(g.aCounter[ii])); - } - Tcl_SetObjResult(interp, pRet); - Tcl_DecrRefCount(pRet); - - return TCL_OK; -} - -/* -** clear_mutex_counters -*/ -static int test_clear_mutex_counters( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - int ii; - - if( objc!=1 ){ - Tcl_WrongNumArgs(interp, 1, objv, ""); - return TCL_ERROR; - } - - for(ii=0; ii<8; ii++){ - g.aCounter[ii] = 0; - } - return TCL_OK; -} - -/* -** Create and free a mutex. Return the mutex pointer. The pointer -** will be invalid since the mutex has already been freed. The -** return pointer just checks to see if the mutex really was allocated. -*/ -static int test_alloc_mutex( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ -#if SQLITE_THREADSAFE - sqlite3_mutex *p = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST); - char zBuf[100]; - sqlite3_mutex_free(p); - sqlite3_snprintf(sizeof(zBuf), zBuf, "%p", p); - Tcl_AppendResult(interp, zBuf, (char*)0); -#endif - return TCL_OK; -} - -/* -** sqlite3_config OPTION -** -** OPTION can be either one of the keywords: -** -** SQLITE_CONFIG_SINGLETHREAD -** SQLITE_CONFIG_MULTITHREAD -** SQLITE_CONFIG_SERIALIZED -** -** Or OPTION can be an raw integer. -*/ -static int test_config( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - struct ConfigOption { - const char *zName; - int iValue; - } aOpt[] = { - {"singlethread", SQLITE_CONFIG_SINGLETHREAD}, - {"multithread", SQLITE_CONFIG_MULTITHREAD}, - {"serialized", SQLITE_CONFIG_SERIALIZED}, - {0, 0} - }; - int s = sizeof(struct ConfigOption); - int i; - int rc; - - if( objc!=2 ){ - Tcl_WrongNumArgs(interp, 1, objv, ""); - return TCL_ERROR; - } - - if( Tcl_GetIndexFromObjStruct(interp, objv[1], aOpt, s, "flag", 0, &i) ){ - if( Tcl_GetIntFromObj(interp, objv[1], &i) ){ - return TCL_ERROR; - } - }else{ - i = aOpt[i].iValue; - } - - rc = sqlite3_config(i); - Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE); - return TCL_OK; -} - -static sqlite3 *getDbPointer(Tcl_Interp *pInterp, Tcl_Obj *pObj){ - sqlite3 *db; - Tcl_CmdInfo info; - char *zCmd = Tcl_GetString(pObj); - if( Tcl_GetCommandInfo(pInterp, zCmd, &info) ){ - db = *((sqlite3 **)info.objClientData); - }else{ - db = (sqlite3*)sqlite3TestTextToPtr(zCmd); - } - assert( db ); - return db; -} - -static int test_enter_db_mutex( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - sqlite3 *db; - if( objc!=2 ){ - Tcl_WrongNumArgs(interp, 1, objv, "DB"); - return TCL_ERROR; - } - db = getDbPointer(interp, objv[1]); - if( !db ){ - return TCL_ERROR; - } - sqlite3_mutex_enter(sqlite3_db_mutex(db)); - return TCL_OK; -} - -static int test_leave_db_mutex( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - sqlite3 *db; - if( objc!=2 ){ - Tcl_WrongNumArgs(interp, 1, objv, "DB"); - return TCL_ERROR; - } - db = getDbPointer(interp, objv[1]); - if( !db ){ - return TCL_ERROR; - } - sqlite3_mutex_leave(sqlite3_db_mutex(db)); - return TCL_OK; -} - -int Sqlitetest_mutex_Init(Tcl_Interp *interp){ - static struct { - char *zName; - Tcl_ObjCmdProc *xProc; - } aCmd[] = { - { "sqlite3_shutdown", (Tcl_ObjCmdProc*)test_shutdown }, - { "sqlite3_initialize", (Tcl_ObjCmdProc*)test_initialize }, - { "sqlite3_config", (Tcl_ObjCmdProc*)test_config }, - - { "enter_db_mutex", (Tcl_ObjCmdProc*)test_enter_db_mutex }, - { "leave_db_mutex", (Tcl_ObjCmdProc*)test_leave_db_mutex }, - - { "alloc_dealloc_mutex", (Tcl_ObjCmdProc*)test_alloc_mutex }, - { "install_mutex_counters", (Tcl_ObjCmdProc*)test_install_mutex_counters }, - { "read_mutex_counters", (Tcl_ObjCmdProc*)test_read_mutex_counters }, - { "clear_mutex_counters", (Tcl_ObjCmdProc*)test_clear_mutex_counters }, - }; - int i; - for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){ - Tcl_CreateObjCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0); - } - - Tcl_LinkVar(interp, "disable_mutex_init", - (char*)&g.disableInit, TCL_LINK_INT); - Tcl_LinkVar(interp, "disable_mutex_try", - (char*)&g.disableTry, TCL_LINK_INT); - return SQLITE_OK; -} diff --git a/components/external/SQLite-3.8.1/SQLiteLib/test/test_onefile.c b/components/external/SQLite-3.8.1/SQLiteLib/test/test_onefile.c deleted file mode 100644 index 69867441b8..0000000000 --- a/components/external/SQLite-3.8.1/SQLiteLib/test/test_onefile.c +++ /dev/null @@ -1,830 +0,0 @@ -/* -** 2007 September 14 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** -** OVERVIEW: -** -** This file contains some example code demonstrating how the SQLite -** vfs feature can be used to have SQLite operate directly on an -** embedded media, without using an intermediate file system. -** -** Because this is only a demo designed to run on a workstation, the -** underlying media is simulated using a regular file-system file. The -** size of the file is fixed when it is first created (default size 10 MB). -** From SQLite's point of view, this space is used to store a single -** database file and the journal file. -** -** Any statement journal created is stored in volatile memory obtained -** from sqlite3_malloc(). Any attempt to create a temporary database file -** will fail (SQLITE_IOERR). To prevent SQLite from attempting this, -** it should be configured to store all temporary database files in -** main memory (see pragma "temp_store" or the SQLITE_TEMP_STORE compile -** time option). -** -** ASSUMPTIONS: -** -** After it has been created, the blob file is accessed using the -** following three functions only: -** -** mediaRead(); - Read a 512 byte block from the file. -** mediaWrite(); - Write a 512 byte block to the file. -** mediaSync(); - Tell the media hardware to sync. -** -** It is assumed that these can be easily implemented by any "real" -** media vfs driver adapting this code. -** -** FILE FORMAT: -** -** The basic principle is that the "database file" is stored at the -** beginning of the 10 MB blob and grows in a forward direction. The -** "journal file" is stored at the end of the 10MB blob and grows -** in the reverse direction. If, during a transaction, insufficient -** space is available to expand either the journal or database file, -** an SQLITE_FULL error is returned. The database file is never allowed -** to consume more than 90% of the blob space. If SQLite tries to -** create a file larger than this, SQLITE_FULL is returned. -** -** No allowance is made for "wear-leveling", as is required by. -** embedded devices in the absence of equivalent hardware features. -** -** The first 512 block byte of the file is reserved for storing the -** size of the "database file". It is updated as part of the sync() -** operation. On startup, it can only be trusted if no journal file -** exists. If a journal-file does exist, then it stores the real size -** of the database region. The second and subsequent blocks store the -** actual database content. -** -** The size of the "journal file" is not stored persistently in the -** file. When the system is running, the size of the journal file is -** stored in volatile memory. When recovering from a crash, this vfs -** reports a very large size for the journal file. The normal journal -** header and checksum mechanisms serve to prevent SQLite from -** processing any data that lies past the logical end of the journal. -** -** When SQLite calls OsDelete() to delete the journal file, the final -** 512 bytes of the blob (the area containing the first journal header) -** are zeroed. -** -** LOCKING: -** -** File locking is a no-op. Only one connection may be open at any one -** time using this demo vfs. -*/ - -#include "sqlite3.h" -#include <assert.h> -#include <string.h> - -/* -** Maximum pathname length supported by the fs backend. -*/ -#define BLOCKSIZE 512 -#define BLOBSIZE 10485760 - -/* -** Name used to identify this VFS. -*/ -#define FS_VFS_NAME "fs" - -typedef struct fs_real_file fs_real_file; -struct fs_real_file { - sqlite3_file *pFile; - const char *zName; - int nDatabase; /* Current size of database region */ - int nJournal; /* Current size of journal region */ - int nBlob; /* Total size of allocated blob */ - int nRef; /* Number of pointers to this structure */ - fs_real_file *pNext; - fs_real_file **ppThis; -}; - -typedef struct fs_file fs_file; -struct fs_file { - sqlite3_file base; - int eType; - fs_real_file *pReal; -}; - -typedef struct tmp_file tmp_file; -struct tmp_file { - sqlite3_file base; - int nSize; - int nAlloc; - char *zAlloc; -}; - -/* Values for fs_file.eType. */ -#define DATABASE_FILE 1 -#define JOURNAL_FILE 2 - -/* -** Method declarations for fs_file. -*/ -static int fsClose(sqlite3_file*); -static int fsRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst); -static int fsWrite(sqlite3_file*, const void*, int iAmt, sqlite3_int64 iOfst); -static int fsTruncate(sqlite3_file*, sqlite3_int64 size); -static int fsSync(sqlite3_file*, int flags); -static int fsFileSize(sqlite3_file*, sqlite3_int64 *pSize); -static int fsLock(sqlite3_file*, int); -static int fsUnlock(sqlite3_file*, int); -static int fsCheckReservedLock(sqlite3_file*, int *pResOut); -static int fsFileControl(sqlite3_file*, int op, void *pArg); -static int fsSectorSize(sqlite3_file*); -static int fsDeviceCharacteristics(sqlite3_file*); - -/* -** Method declarations for tmp_file. -*/ -static int tmpClose(sqlite3_file*); -static int tmpRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst); -static int tmpWrite(sqlite3_file*, const void*, int iAmt, sqlite3_int64 iOfst); -static int tmpTruncate(sqlite3_file*, sqlite3_int64 size); -static int tmpSync(sqlite3_file*, int flags); -static int tmpFileSize(sqlite3_file*, sqlite3_int64 *pSize); -static int tmpLock(sqlite3_file*, int); -static int tmpUnlock(sqlite3_file*, int); -static int tmpCheckReservedLock(sqlite3_file*, int *pResOut); -static int tmpFileControl(sqlite3_file*, int op, void *pArg); -static int tmpSectorSize(sqlite3_file*); -static int tmpDeviceCharacteristics(sqlite3_file*); - -/* -** Method declarations for fs_vfs. -*/ -static int fsOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *); -static int fsDelete(sqlite3_vfs*, const char *zName, int syncDir); -static int fsAccess(sqlite3_vfs*, const char *zName, int flags, int *); -static int fsFullPathname(sqlite3_vfs*, const char *zName, int nOut,char *zOut); -static void *fsDlOpen(sqlite3_vfs*, const char *zFilename); -static void fsDlError(sqlite3_vfs*, int nByte, char *zErrMsg); -static void (*fsDlSym(sqlite3_vfs*,void*, const char *zSymbol))(void); -static void fsDlClose(sqlite3_vfs*, void*); -static int fsRandomness(sqlite3_vfs*, int nByte, char *zOut); -static int fsSleep(sqlite3_vfs*, int microseconds); -static int fsCurrentTime(sqlite3_vfs*, double*); - - -typedef struct fs_vfs_t fs_vfs_t; -struct fs_vfs_t { - sqlite3_vfs base; - fs_real_file *pFileList; - sqlite3_vfs *pParent; -}; - -static fs_vfs_t fs_vfs = { - { - 1, /* iVersion */ - 0, /* szOsFile */ - 0, /* mxPathname */ - 0, /* pNext */ - FS_VFS_NAME, /* zName */ - 0, /* pAppData */ - fsOpen, /* xOpen */ - fsDelete, /* xDelete */ - fsAccess, /* xAccess */ - fsFullPathname, /* xFullPathname */ - fsDlOpen, /* xDlOpen */ - fsDlError, /* xDlError */ - fsDlSym, /* xDlSym */ - fsDlClose, /* xDlClose */ - fsRandomness, /* xRandomness */ - fsSleep, /* xSleep */ - fsCurrentTime, /* xCurrentTime */ - 0 /* xCurrentTimeInt64 */ - }, - 0, /* pFileList */ - 0 /* pParent */ -}; - -static sqlite3_io_methods fs_io_methods = { - 1, /* iVersion */ - fsClose, /* xClose */ - fsRead, /* xRead */ - fsWrite, /* xWrite */ - fsTruncate, /* xTruncate */ - fsSync, /* xSync */ - fsFileSize, /* xFileSize */ - fsLock, /* xLock */ - fsUnlock, /* xUnlock */ - fsCheckReservedLock, /* xCheckReservedLock */ - fsFileControl, /* xFileControl */ - fsSectorSize, /* xSectorSize */ - fsDeviceCharacteristics, /* xDeviceCharacteristics */ - 0, /* xShmMap */ - 0, /* xShmLock */ - 0, /* xShmBarrier */ - 0 /* xShmUnmap */ -}; - - -static sqlite3_io_methods tmp_io_methods = { - 1, /* iVersion */ - tmpClose, /* xClose */ - tmpRead, /* xRead */ - tmpWrite, /* xWrite */ - tmpTruncate, /* xTruncate */ - tmpSync, /* xSync */ - tmpFileSize, /* xFileSize */ - tmpLock, /* xLock */ - tmpUnlock, /* xUnlock */ - tmpCheckReservedLock, /* xCheckReservedLock */ - tmpFileControl, /* xFileControl */ - tmpSectorSize, /* xSectorSize */ - tmpDeviceCharacteristics, /* xDeviceCharacteristics */ - 0, /* xShmMap */ - 0, /* xShmLock */ - 0, /* xShmBarrier */ - 0 /* xShmUnmap */ -}; - -/* Useful macros used in several places */ -#define MIN(x,y) ((x)<(y)?(x):(y)) -#define MAX(x,y) ((x)>(y)?(x):(y)) - - -/* -** Close a tmp-file. -*/ -static int tmpClose(sqlite3_file *pFile){ - tmp_file *pTmp = (tmp_file *)pFile; - sqlite3_free(pTmp->zAlloc); - return SQLITE_OK; -} - -/* -** Read data from a tmp-file. -*/ -static int tmpRead( - sqlite3_file *pFile, - void *zBuf, - int iAmt, - sqlite_int64 iOfst -){ - tmp_file *pTmp = (tmp_file *)pFile; - if( (iAmt+iOfst)>pTmp->nSize ){ - return SQLITE_IOERR_SHORT_READ; - } - memcpy(zBuf, &pTmp->zAlloc[iOfst], iAmt); - return SQLITE_OK; -} - -/* -** Write data to a tmp-file. -*/ -static int tmpWrite( - sqlite3_file *pFile, - const void *zBuf, - int iAmt, - sqlite_int64 iOfst -){ - tmp_file *pTmp = (tmp_file *)pFile; - if( (iAmt+iOfst)>pTmp->nAlloc ){ - int nNew = (int)(2*(iAmt+iOfst+pTmp->nAlloc)); - char *zNew = sqlite3_realloc(pTmp->zAlloc, nNew); - if( !zNew ){ - return SQLITE_NOMEM; - } - pTmp->zAlloc = zNew; - pTmp->nAlloc = nNew; - } - memcpy(&pTmp->zAlloc[iOfst], zBuf, iAmt); - pTmp->nSize = (int)MAX(pTmp->nSize, iOfst+iAmt); - return SQLITE_OK; -} - -/* -** Truncate a tmp-file. -*/ -static int tmpTruncate(sqlite3_file *pFile, sqlite_int64 size){ - tmp_file *pTmp = (tmp_file *)pFile; - pTmp->nSize = (int)MIN(pTmp->nSize, size); - return SQLITE_OK; -} - -/* -** Sync a tmp-file. -*/ -static int tmpSync(sqlite3_file *pFile, int flags){ - return SQLITE_OK; -} - -/* -** Return the current file-size of a tmp-file. -*/ -static int tmpFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){ - tmp_file *pTmp = (tmp_file *)pFile; - *pSize = pTmp->nSize; - return SQLITE_OK; -} - -/* -** Lock a tmp-file. -*/ -static int tmpLock(sqlite3_file *pFile, int eLock){ - return SQLITE_OK; -} - -/* -** Unlock a tmp-file. -*/ -static int tmpUnlock(sqlite3_file *pFile, int eLock){ - return SQLITE_OK; -} - -/* -** Check if another file-handle holds a RESERVED lock on a tmp-file. -*/ -static int tmpCheckReservedLock(sqlite3_file *pFile, int *pResOut){ - *pResOut = 0; - return SQLITE_OK; -} - -/* -** File control method. For custom operations on a tmp-file. -*/ -static int tmpFileControl(sqlite3_file *pFile, int op, void *pArg){ - return SQLITE_OK; -} - -/* -** Return the sector-size in bytes for a tmp-file. -*/ -static int tmpSectorSize(sqlite3_file *pFile){ - return 0; -} - -/* -** Return the device characteristic flags supported by a tmp-file. -*/ -static int tmpDeviceCharacteristics(sqlite3_file *pFile){ - return 0; -} - -/* -** Close an fs-file. -*/ -static int fsClose(sqlite3_file *pFile){ - int rc = SQLITE_OK; - fs_file *p = (fs_file *)pFile; - fs_real_file *pReal = p->pReal; - - /* Decrement the real_file ref-count. */ - pReal->nRef--; - assert(pReal->nRef>=0); - - /* When the ref-count reaches 0, destroy the structure */ - if( pReal->nRef==0 ){ - *pReal->ppThis = pReal->pNext; - if( pReal->pNext ){ - pReal->pNext->ppThis = pReal->ppThis; - } - rc = pReal->pFile->pMethods->xClose(pReal->pFile); - sqlite3_free(pReal); - } - - return rc; -} - -/* -** Read data from an fs-file. -*/ -static int fsRead( - sqlite3_file *pFile, - void *zBuf, - int iAmt, - sqlite_int64 iOfst -){ - int rc = SQLITE_OK; - fs_file *p = (fs_file *)pFile; - fs_real_file *pReal = p->pReal; - sqlite3_file *pF = pReal->pFile; - - if( (p->eType==DATABASE_FILE && (iAmt+iOfst)>pReal->nDatabase) - || (p->eType==JOURNAL_FILE && (iAmt+iOfst)>pReal->nJournal) - ){ - rc = SQLITE_IOERR_SHORT_READ; - }else if( p->eType==DATABASE_FILE ){ - rc = pF->pMethods->xRead(pF, zBuf, iAmt, iOfst+BLOCKSIZE); - }else{ - /* Journal file. */ - int iRem = iAmt; - int iBuf = 0; - int ii = (int)iOfst; - while( iRem>0 && rc==SQLITE_OK ){ - int iRealOff = pReal->nBlob - BLOCKSIZE*((ii/BLOCKSIZE)+1) + ii%BLOCKSIZE; - int iRealAmt = MIN(iRem, BLOCKSIZE - (iRealOff%BLOCKSIZE)); - - rc = pF->pMethods->xRead(pF, &((char *)zBuf)[iBuf], iRealAmt, iRealOff); - ii += iRealAmt; - iBuf += iRealAmt; - iRem -= iRealAmt; - } - } - - return rc; -} - -/* -** Write data to an fs-file. -*/ -static int fsWrite( - sqlite3_file *pFile, - const void *zBuf, - int iAmt, - sqlite_int64 iOfst -){ - int rc = SQLITE_OK; - fs_file *p = (fs_file *)pFile; - fs_real_file *pReal = p->pReal; - sqlite3_file *pF = pReal->pFile; - - if( p->eType==DATABASE_FILE ){ - if( (iAmt+iOfst+BLOCKSIZE)>(pReal->nBlob-pReal->nJournal) ){ - rc = SQLITE_FULL; - }else{ - rc = pF->pMethods->xWrite(pF, zBuf, iAmt, iOfst+BLOCKSIZE); - if( rc==SQLITE_OK ){ - pReal->nDatabase = (int)MAX(pReal->nDatabase, iAmt+iOfst); - } - } - }else{ - /* Journal file. */ - int iRem = iAmt; - int iBuf = 0; - int ii = (int)iOfst; - while( iRem>0 && rc==SQLITE_OK ){ - int iRealOff = pReal->nBlob - BLOCKSIZE*((ii/BLOCKSIZE)+1) + ii%BLOCKSIZE; - int iRealAmt = MIN(iRem, BLOCKSIZE - (iRealOff%BLOCKSIZE)); - - if( iRealOff<(pReal->nDatabase+BLOCKSIZE) ){ - rc = SQLITE_FULL; - }else{ - rc = pF->pMethods->xWrite(pF, &((char *)zBuf)[iBuf], iRealAmt,iRealOff); - ii += iRealAmt; - iBuf += iRealAmt; - iRem -= iRealAmt; - } - } - if( rc==SQLITE_OK ){ - pReal->nJournal = (int)MAX(pReal->nJournal, iAmt+iOfst); - } - } - - return rc; -} - -/* -** Truncate an fs-file. -*/ -static int fsTruncate(sqlite3_file *pFile, sqlite_int64 size){ - fs_file *p = (fs_file *)pFile; - fs_real_file *pReal = p->pReal; - if( p->eType==DATABASE_FILE ){ - pReal->nDatabase = (int)MIN(pReal->nDatabase, size); - }else{ - pReal->nJournal = (int)MIN(pReal->nJournal, size); - } - return SQLITE_OK; -} - -/* -** Sync an fs-file. -*/ -static int fsSync(sqlite3_file *pFile, int flags){ - fs_file *p = (fs_file *)pFile; - fs_real_file *pReal = p->pReal; - sqlite3_file *pRealFile = pReal->pFile; - int rc = SQLITE_OK; - - if( p->eType==DATABASE_FILE ){ - unsigned char zSize[4]; - zSize[0] = (pReal->nDatabase&0xFF000000)>>24; - zSize[1] = (pReal->nDatabase&0x00FF0000)>>16; - zSize[2] = (pReal->nDatabase&0x0000FF00)>>8; - zSize[3] = (pReal->nDatabase&0x000000FF); - rc = pRealFile->pMethods->xWrite(pRealFile, zSize, 4, 0); - } - if( rc==SQLITE_OK ){ - rc = pRealFile->pMethods->xSync(pRealFile, flags&(~SQLITE_SYNC_DATAONLY)); - } - - return rc; -} - -/* -** Return the current file-size of an fs-file. -*/ -static int fsFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){ - fs_file *p = (fs_file *)pFile; - fs_real_file *pReal = p->pReal; - if( p->eType==DATABASE_FILE ){ - *pSize = pReal->nDatabase; - }else{ - *pSize = pReal->nJournal; - } - return SQLITE_OK; -} - -/* -** Lock an fs-file. -*/ -static int fsLock(sqlite3_file *pFile, int eLock){ - return SQLITE_OK; -} - -/* -** Unlock an fs-file. -*/ -static int fsUnlock(sqlite3_file *pFile, int eLock){ - return SQLITE_OK; -} - -/* -** Check if another file-handle holds a RESERVED lock on an fs-file. -*/ -static int fsCheckReservedLock(sqlite3_file *pFile, int *pResOut){ - *pResOut = 0; - return SQLITE_OK; -} - -/* -** File control method. For custom operations on an fs-file. -*/ -static int fsFileControl(sqlite3_file *pFile, int op, void *pArg){ - return SQLITE_OK; -} - -/* -** Return the sector-size in bytes for an fs-file. -*/ -static int fsSectorSize(sqlite3_file *pFile){ - return BLOCKSIZE; -} - -/* -** Return the device characteristic flags supported by an fs-file. -*/ -static int fsDeviceCharacteristics(sqlite3_file *pFile){ - return 0; -} - -/* -** Open an fs file handle. -*/ -static int fsOpen( - sqlite3_vfs *pVfs, - const char *zName, - sqlite3_file *pFile, - int flags, - int *pOutFlags -){ - fs_vfs_t *pFsVfs = (fs_vfs_t *)pVfs; - fs_file *p = (fs_file *)pFile; - fs_real_file *pReal = 0; - int eType; - int nName; - int rc = SQLITE_OK; - - if( 0==(flags&(SQLITE_OPEN_MAIN_DB|SQLITE_OPEN_MAIN_JOURNAL)) ){ - tmp_file *p = (tmp_file *)pFile; - memset(p, 0, sizeof(*p)); - p->base.pMethods = &tmp_io_methods; - return SQLITE_OK; - } - - eType = ((flags&(SQLITE_OPEN_MAIN_DB))?DATABASE_FILE:JOURNAL_FILE); - p->base.pMethods = &fs_io_methods; - p->eType = eType; - - assert(strlen("-journal")==8); - nName = (int)strlen(zName)-((eType==JOURNAL_FILE)?8:0); - pReal=pFsVfs->pFileList; - for(; pReal && strncmp(pReal->zName, zName, nName); pReal=pReal->pNext); - - if( !pReal ){ - int real_flags = (flags&~(SQLITE_OPEN_MAIN_DB))|SQLITE_OPEN_TEMP_DB; - sqlite3_int64 size; - sqlite3_file *pRealFile; - sqlite3_vfs *pParent = pFsVfs->pParent; - assert(eType==DATABASE_FILE); - - pReal = (fs_real_file *)sqlite3_malloc(sizeof(*pReal)+pParent->szOsFile); - if( !pReal ){ - rc = SQLITE_NOMEM; - goto open_out; - } - memset(pReal, 0, sizeof(*pReal)+pParent->szOsFile); - pReal->zName = zName; - pReal->pFile = (sqlite3_file *)(&pReal[1]); - - rc = pParent->xOpen(pParent, zName, pReal->pFile, real_flags, pOutFlags); - if( rc!=SQLITE_OK ){ - goto open_out; - } - pRealFile = pReal->pFile; - - rc = pRealFile->pMethods->xFileSize(pRealFile, &size); - if( rc!=SQLITE_OK ){ - goto open_out; - } - if( size==0 ){ - rc = pRealFile->pMethods->xWrite(pRealFile, "\0", 1, BLOBSIZE-1); - pReal->nBlob = BLOBSIZE; - }else{ - unsigned char zS[4]; - pReal->nBlob = (int)size; - rc = pRealFile->pMethods->xRead(pRealFile, zS, 4, 0); - pReal->nDatabase = (zS[0]<<24)+(zS[1]<<16)+(zS[2]<<8)+zS[3]; - if( rc==SQLITE_OK ){ - rc = pRealFile->pMethods->xRead(pRealFile, zS, 4, pReal->nBlob-4); - if( zS[0] || zS[1] || zS[2] || zS[3] ){ - pReal->nJournal = pReal->nBlob; - } - } - } - - if( rc==SQLITE_OK ){ - pReal->pNext = pFsVfs->pFileList; - if( pReal->pNext ){ - pReal->pNext->ppThis = &pReal->pNext; - } - pReal->ppThis = &pFsVfs->pFileList; - pFsVfs->pFileList = pReal; - } - } - -open_out: - if( pReal ){ - if( rc==SQLITE_OK ){ - p->pReal = pReal; - pReal->nRef++; - }else{ - if( pReal->pFile->pMethods ){ - pReal->pFile->pMethods->xClose(pReal->pFile); - } - sqlite3_free(pReal); - } - } - return rc; -} - -/* -** Delete the file located at zPath. If the dirSync argument is true, -** ensure the file-system modifications are synced to disk before -** returning. -*/ -static int fsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){ - int rc = SQLITE_OK; - fs_vfs_t *pFsVfs = (fs_vfs_t *)pVfs; - fs_real_file *pReal; - sqlite3_file *pF; - int nName = (int)strlen(zPath) - 8; - - assert(strlen("-journal")==8); - assert(strcmp("-journal", &zPath[nName])==0); - - pReal = pFsVfs->pFileList; - for(; pReal && strncmp(pReal->zName, zPath, nName); pReal=pReal->pNext); - if( pReal ){ - pF = pReal->pFile; - rc = pF->pMethods->xWrite(pF, "\0\0\0\0", 4, pReal->nBlob-BLOCKSIZE); - if( rc==SQLITE_OK ){ - pReal->nJournal = 0; - } - } - return rc; -} - -/* -** Test for access permissions. Return true if the requested permission -** is available, or false otherwise. -*/ -static int fsAccess( - sqlite3_vfs *pVfs, - const char *zPath, - int flags, - int *pResOut -){ - fs_vfs_t *pFsVfs = (fs_vfs_t *)pVfs; - fs_real_file *pReal; - int isJournal = 0; - int nName = (int)strlen(zPath); - - if( flags!=SQLITE_ACCESS_EXISTS ){ - sqlite3_vfs *pParent = ((fs_vfs_t *)pVfs)->pParent; - return pParent->xAccess(pParent, zPath, flags, pResOut); - } - - assert(strlen("-journal")==8); - if( nName>8 && strcmp("-journal", &zPath[nName-8])==0 ){ - nName -= 8; - isJournal = 1; - } - - pReal = pFsVfs->pFileList; - for(; pReal && strncmp(pReal->zName, zPath, nName); pReal=pReal->pNext); - - *pResOut = (pReal && (!isJournal || pReal->nJournal>0)); - return SQLITE_OK; -} - -/* -** Populate buffer zOut with the full canonical pathname corresponding -** to the pathname in zPath. zOut is guaranteed to point to a buffer -** of at least (FS_MAX_PATHNAME+1) bytes. -*/ -static int fsFullPathname( - sqlite3_vfs *pVfs, /* Pointer to vfs object */ - const char *zPath, /* Possibly relative input path */ - int nOut, /* Size of output buffer in bytes */ - char *zOut /* Output buffer */ -){ - sqlite3_vfs *pParent = ((fs_vfs_t *)pVfs)->pParent; - return pParent->xFullPathname(pParent, zPath, nOut, zOut); -} - -/* -** Open the dynamic library located at zPath and return a handle. -*/ -static void *fsDlOpen(sqlite3_vfs *pVfs, const char *zPath){ - sqlite3_vfs *pParent = ((fs_vfs_t *)pVfs)->pParent; - return pParent->xDlOpen(pParent, zPath); -} - -/* -** Populate the buffer zErrMsg (size nByte bytes) with a human readable -** utf-8 string describing the most recent error encountered associated -** with dynamic libraries. -*/ -static void fsDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){ - sqlite3_vfs *pParent = ((fs_vfs_t *)pVfs)->pParent; - pParent->xDlError(pParent, nByte, zErrMsg); -} - -/* -** Return a pointer to the symbol zSymbol in the dynamic library pHandle. -*/ -static void (*fsDlSym(sqlite3_vfs *pVfs, void *pH, const char *zSym))(void){ - sqlite3_vfs *pParent = ((fs_vfs_t *)pVfs)->pParent; - return pParent->xDlSym(pParent, pH, zSym); -} - -/* -** Close the dynamic library handle pHandle. -*/ -static void fsDlClose(sqlite3_vfs *pVfs, void *pHandle){ - sqlite3_vfs *pParent = ((fs_vfs_t *)pVfs)->pParent; - pParent->xDlClose(pParent, pHandle); -} - -/* -** Populate the buffer pointed to by zBufOut with nByte bytes of -** random data. -*/ -static int fsRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){ - sqlite3_vfs *pParent = ((fs_vfs_t *)pVfs)->pParent; - return pParent->xRandomness(pParent, nByte, zBufOut); -} - -/* -** Sleep for nMicro microseconds. Return the number of microseconds -** actually slept. -*/ -static int fsSleep(sqlite3_vfs *pVfs, int nMicro){ - sqlite3_vfs *pParent = ((fs_vfs_t *)pVfs)->pParent; - return pParent->xSleep(pParent, nMicro); -} - -/* -** Return the current time as a Julian Day number in *pTimeOut. -*/ -static int fsCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){ - sqlite3_vfs *pParent = ((fs_vfs_t *)pVfs)->pParent; - return pParent->xCurrentTime(pParent, pTimeOut); -} - -/* -** This procedure registers the fs vfs with SQLite. If the argument is -** true, the fs vfs becomes the new default vfs. It is the only publicly -** available function in this file. -*/ -int fs_register(void){ - if( fs_vfs.pParent ) return SQLITE_OK; - fs_vfs.pParent = sqlite3_vfs_find(0); - fs_vfs.base.mxPathname = fs_vfs.pParent->mxPathname; - fs_vfs.base.szOsFile = MAX(sizeof(tmp_file), sizeof(fs_file)); - return sqlite3_vfs_register(&fs_vfs.base, 0); -} - -#ifdef SQLITE_TEST - int SqlitetestOnefile_Init() {return fs_register();} -#endif diff --git a/components/external/SQLite-3.8.1/SQLiteLib/test/test_osinst.c b/components/external/SQLite-3.8.1/SQLiteLib/test/test_osinst.c deleted file mode 100644 index 531433313e..0000000000 --- a/components/external/SQLite-3.8.1/SQLiteLib/test/test_osinst.c +++ /dev/null @@ -1,1215 +0,0 @@ -/* -** 2008 April 10 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -****************************************************************************** -** -** This file contains the implementation of an SQLite vfs wrapper that -** adds instrumentation to all vfs and file methods. C and Tcl interfaces -** are provided to control the instrumentation. -*/ - -/* -** This module contains code for a wrapper VFS that causes a log of -** most VFS calls to be written into a nominated file on disk. The log -** is stored in a compressed binary format to reduce the amount of IO -** overhead introduced into the application by logging. -** -** All calls on sqlite3_file objects except xFileControl() are logged. -** Additionally, calls to the xAccess(), xOpen(), and xDelete() -** methods are logged. The other sqlite3_vfs object methods (xDlXXX, -** xRandomness, xSleep, xCurrentTime, xGetLastError and xCurrentTimeInt64) -** are not logged. -** -** The binary log files are read using a virtual table implementation -** also contained in this file. -** -** CREATING LOG FILES: -** -** int sqlite3_vfslog_new( -** const char *zVfs, // Name of new VFS -** const char *zParentVfs, // Name of parent VFS (or NULL) -** const char *zLog // Name of log file to write to -** ); -** -** int sqlite3_vfslog_finalize(const char *zVfs); -** -** ANNOTATING LOG FILES: -** -** To write an arbitrary message into a log file: -** -** int sqlite3_vfslog_annotate(const char *zVfs, const char *zMsg); -** -** READING LOG FILES: -** -** Log files are read using the "vfslog" virtual table implementation -** in this file. To register the virtual table with SQLite, use: -** -** int sqlite3_vfslog_register(sqlite3 *db); -** -** Then, if the log file is named "vfs.log", the following SQL command: -** -** CREATE VIRTUAL TABLE v USING vfslog('vfs.log'); -** -** creates a virtual table with 6 columns, as follows: -** -** CREATE TABLE v( -** event TEXT, // "xOpen", "xRead" etc. -** file TEXT, // Name of file this call applies to -** clicks INTEGER, // Time spent in call -** rc INTEGER, // Return value -** size INTEGER, // Bytes read or written -** offset INTEGER // File offset read or written -** ); -*/ - -#include "sqlite3.h" -#include <string.h> -#include <assert.h> - - -/* -** Maximum pathname length supported by the vfslog backend. -*/ -#define INST_MAX_PATHNAME 512 - -#define OS_ACCESS 1 -#define OS_CHECKRESERVEDLOCK 2 -#define OS_CLOSE 3 -#define OS_CURRENTTIME 4 -#define OS_DELETE 5 -#define OS_DEVCHAR 6 -#define OS_FILECONTROL 7 -#define OS_FILESIZE 8 -#define OS_FULLPATHNAME 9 -#define OS_LOCK 11 -#define OS_OPEN 12 -#define OS_RANDOMNESS 13 -#define OS_READ 14 -#define OS_SECTORSIZE 15 -#define OS_SLEEP 16 -#define OS_SYNC 17 -#define OS_TRUNCATE 18 -#define OS_UNLOCK 19 -#define OS_WRITE 20 -#define OS_SHMUNMAP 22 -#define OS_SHMMAP 23 -#define OS_SHMLOCK 25 -#define OS_SHMBARRIER 26 -#define OS_ANNOTATE 28 - -#define OS_NUMEVENTS 29 - -#define VFSLOG_BUFFERSIZE 8192 - -typedef struct VfslogVfs VfslogVfs; -typedef struct VfslogFile VfslogFile; - -struct VfslogVfs { - sqlite3_vfs base; /* VFS methods */ - sqlite3_vfs *pVfs; /* Parent VFS */ - int iNextFileId; /* Next file id */ - sqlite3_file *pLog; /* Log file handle */ - sqlite3_int64 iOffset; /* Log file offset of start of write buffer */ - int nBuf; /* Number of valid bytes in aBuf[] */ - char aBuf[VFSLOG_BUFFERSIZE]; /* Write buffer */ -}; - -struct VfslogFile { - sqlite3_file base; /* IO methods */ - sqlite3_file *pReal; /* Underlying file handle */ - sqlite3_vfs *pVfslog; /* Associated VsflogVfs object */ - int iFileId; /* File id number */ -}; - -#define REALVFS(p) (((VfslogVfs *)(p))->pVfs) - - - -/* -** Method declarations for vfslog_file. -*/ -static int vfslogClose(sqlite3_file*); -static int vfslogRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst); -static int vfslogWrite(sqlite3_file*,const void*,int iAmt, sqlite3_int64 iOfst); -static int vfslogTruncate(sqlite3_file*, sqlite3_int64 size); -static int vfslogSync(sqlite3_file*, int flags); -static int vfslogFileSize(sqlite3_file*, sqlite3_int64 *pSize); -static int vfslogLock(sqlite3_file*, int); -static int vfslogUnlock(sqlite3_file*, int); -static int vfslogCheckReservedLock(sqlite3_file*, int *pResOut); -static int vfslogFileControl(sqlite3_file*, int op, void *pArg); -static int vfslogSectorSize(sqlite3_file*); -static int vfslogDeviceCharacteristics(sqlite3_file*); - -static int vfslogShmLock(sqlite3_file *pFile, int ofst, int n, int flags); -static int vfslogShmMap(sqlite3_file *pFile,int,int,int,volatile void **); -static void vfslogShmBarrier(sqlite3_file*); -static int vfslogShmUnmap(sqlite3_file *pFile, int deleteFlag); - -/* -** Method declarations for vfslog_vfs. -*/ -static int vfslogOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *); -static int vfslogDelete(sqlite3_vfs*, const char *zName, int syncDir); -static int vfslogAccess(sqlite3_vfs*, const char *zName, int flags, int *); -static int vfslogFullPathname(sqlite3_vfs*, const char *zName, int, char *zOut); -static void *vfslogDlOpen(sqlite3_vfs*, const char *zFilename); -static void vfslogDlError(sqlite3_vfs*, int nByte, char *zErrMsg); -static void (*vfslogDlSym(sqlite3_vfs *pVfs, void *p, const char*zSym))(void); -static void vfslogDlClose(sqlite3_vfs*, void*); -static int vfslogRandomness(sqlite3_vfs*, int nByte, char *zOut); -static int vfslogSleep(sqlite3_vfs*, int microseconds); -static int vfslogCurrentTime(sqlite3_vfs*, double*); - -static int vfslogGetLastError(sqlite3_vfs*, int, char *); -static int vfslogCurrentTimeInt64(sqlite3_vfs*, sqlite3_int64*); - -static sqlite3_vfs vfslog_vfs = { - 1, /* iVersion */ - sizeof(VfslogFile), /* szOsFile */ - INST_MAX_PATHNAME, /* mxPathname */ - 0, /* pNext */ - 0, /* zName */ - 0, /* pAppData */ - vfslogOpen, /* xOpen */ - vfslogDelete, /* xDelete */ - vfslogAccess, /* xAccess */ - vfslogFullPathname, /* xFullPathname */ - vfslogDlOpen, /* xDlOpen */ - vfslogDlError, /* xDlError */ - vfslogDlSym, /* xDlSym */ - vfslogDlClose, /* xDlClose */ - vfslogRandomness, /* xRandomness */ - vfslogSleep, /* xSleep */ - vfslogCurrentTime, /* xCurrentTime */ - vfslogGetLastError, /* xGetLastError */ - vfslogCurrentTimeInt64 /* xCurrentTime */ -}; - -static sqlite3_io_methods vfslog_io_methods = { - 2, /* iVersion */ - vfslogClose, /* xClose */ - vfslogRead, /* xRead */ - vfslogWrite, /* xWrite */ - vfslogTruncate, /* xTruncate */ - vfslogSync, /* xSync */ - vfslogFileSize, /* xFileSize */ - vfslogLock, /* xLock */ - vfslogUnlock, /* xUnlock */ - vfslogCheckReservedLock, /* xCheckReservedLock */ - vfslogFileControl, /* xFileControl */ - vfslogSectorSize, /* xSectorSize */ - vfslogDeviceCharacteristics, /* xDeviceCharacteristics */ - vfslogShmMap, /* xShmMap */ - vfslogShmLock, /* xShmLock */ - vfslogShmBarrier, /* xShmBarrier */ - vfslogShmUnmap /* xShmUnmap */ -}; - -#if SQLITE_OS_UNIX && !defined(NO_GETTOD) -#include <sys/time.h> -static sqlite3_uint64 vfslog_time(){ - struct timeval sTime; - gettimeofday(&sTime, 0); - return sTime.tv_usec + (sqlite3_uint64)sTime.tv_sec * 1000000; -} -#elif SQLITE_OS_WIN -#include <windows.h> -#include <time.h> -static sqlite3_uint64 vfslog_time(){ - FILETIME ft; - sqlite3_uint64 u64time = 0; - - GetSystemTimeAsFileTime(&ft); - - u64time |= ft.dwHighDateTime; - u64time <<= 32; - u64time |= ft.dwLowDateTime; - - /* ft is 100-nanosecond intervals, we want microseconds */ - return u64time /(sqlite3_uint64)10; -} -#else -static sqlite3_uint64 vfslog_time(){ - return 0; -} -#endif - -static void vfslog_call(sqlite3_vfs *, int, int, sqlite3_int64, int, int, int); -static void vfslog_string(sqlite3_vfs *, const char *); - -/* -** Close an vfslog-file. -*/ -static int vfslogClose(sqlite3_file *pFile){ - sqlite3_uint64 t; - int rc = SQLITE_OK; - VfslogFile *p = (VfslogFile *)pFile; - - t = vfslog_time(); - if( p->pReal->pMethods ){ - rc = p->pReal->pMethods->xClose(p->pReal); - } - t = vfslog_time() - t; - vfslog_call(p->pVfslog, OS_CLOSE, p->iFileId, t, rc, 0, 0); - return rc; -} - -/* -** Read data from an vfslog-file. -*/ -static int vfslogRead( - sqlite3_file *pFile, - void *zBuf, - int iAmt, - sqlite_int64 iOfst -){ - int rc; - sqlite3_uint64 t; - VfslogFile *p = (VfslogFile *)pFile; - t = vfslog_time(); - rc = p->pReal->pMethods->xRead(p->pReal, zBuf, iAmt, iOfst); - t = vfslog_time() - t; - vfslog_call(p->pVfslog, OS_READ, p->iFileId, t, rc, iAmt, (int)iOfst); - return rc; -} - -/* -** Write data to an vfslog-file. -*/ -static int vfslogWrite( - sqlite3_file *pFile, - const void *z, - int iAmt, - sqlite_int64 iOfst -){ - int rc; - sqlite3_uint64 t; - VfslogFile *p = (VfslogFile *)pFile; - t = vfslog_time(); - rc = p->pReal->pMethods->xWrite(p->pReal, z, iAmt, iOfst); - t = vfslog_time() - t; - vfslog_call(p->pVfslog, OS_WRITE, p->iFileId, t, rc, iAmt, (int)iOfst); - return rc; -} - -/* -** Truncate an vfslog-file. -*/ -static int vfslogTruncate(sqlite3_file *pFile, sqlite_int64 size){ - int rc; - sqlite3_uint64 t; - VfslogFile *p = (VfslogFile *)pFile; - t = vfslog_time(); - rc = p->pReal->pMethods->xTruncate(p->pReal, size); - t = vfslog_time() - t; - vfslog_call(p->pVfslog, OS_TRUNCATE, p->iFileId, t, rc, 0, (int)size); - return rc; -} - -/* -** Sync an vfslog-file. -*/ -static int vfslogSync(sqlite3_file *pFile, int flags){ - int rc; - sqlite3_uint64 t; - VfslogFile *p = (VfslogFile *)pFile; - t = vfslog_time(); - rc = p->pReal->pMethods->xSync(p->pReal, flags); - t = vfslog_time() - t; - vfslog_call(p->pVfslog, OS_SYNC, p->iFileId, t, rc, flags, 0); - return rc; -} - -/* -** Return the current file-size of an vfslog-file. -*/ -static int vfslogFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){ - int rc; - sqlite3_uint64 t; - VfslogFile *p = (VfslogFile *)pFile; - t = vfslog_time(); - rc = p->pReal->pMethods->xFileSize(p->pReal, pSize); - t = vfslog_time() - t; - vfslog_call(p->pVfslog, OS_FILESIZE, p->iFileId, t, rc, 0, (int)*pSize); - return rc; -} - -/* -** Lock an vfslog-file. -*/ -static int vfslogLock(sqlite3_file *pFile, int eLock){ - int rc; - sqlite3_uint64 t; - VfslogFile *p = (VfslogFile *)pFile; - t = vfslog_time(); - rc = p->pReal->pMethods->xLock(p->pReal, eLock); - t = vfslog_time() - t; - vfslog_call(p->pVfslog, OS_LOCK, p->iFileId, t, rc, eLock, 0); - return rc; -} - -/* -** Unlock an vfslog-file. -*/ -static int vfslogUnlock(sqlite3_file *pFile, int eLock){ - int rc; - sqlite3_uint64 t; - VfslogFile *p = (VfslogFile *)pFile; - t = vfslog_time(); - rc = p->pReal->pMethods->xUnlock(p->pReal, eLock); - t = vfslog_time() - t; - vfslog_call(p->pVfslog, OS_UNLOCK, p->iFileId, t, rc, eLock, 0); - return rc; -} - -/* -** Check if another file-handle holds a RESERVED lock on an vfslog-file. -*/ -static int vfslogCheckReservedLock(sqlite3_file *pFile, int *pResOut){ - int rc; - sqlite3_uint64 t; - VfslogFile *p = (VfslogFile *)pFile; - t = vfslog_time(); - rc = p->pReal->pMethods->xCheckReservedLock(p->pReal, pResOut); - t = vfslog_time() - t; - vfslog_call(p->pVfslog, OS_CHECKRESERVEDLOCK, p->iFileId, t, rc, *pResOut, 0); - return rc; -} - -/* -** File control method. For custom operations on an vfslog-file. -*/ -static int vfslogFileControl(sqlite3_file *pFile, int op, void *pArg){ - VfslogFile *p = (VfslogFile *)pFile; - int rc = p->pReal->pMethods->xFileControl(p->pReal, op, pArg); - if( op==SQLITE_FCNTL_VFSNAME && rc==SQLITE_OK ){ - *(char**)pArg = sqlite3_mprintf("vfslog/%z", *(char**)pArg); - } - return rc; -} - -/* -** Return the sector-size in bytes for an vfslog-file. -*/ -static int vfslogSectorSize(sqlite3_file *pFile){ - int rc; - sqlite3_uint64 t; - VfslogFile *p = (VfslogFile *)pFile; - t = vfslog_time(); - rc = p->pReal->pMethods->xSectorSize(p->pReal); - t = vfslog_time() - t; - vfslog_call(p->pVfslog, OS_SECTORSIZE, p->iFileId, t, rc, 0, 0); - return rc; -} - -/* -** Return the device characteristic flags supported by an vfslog-file. -*/ -static int vfslogDeviceCharacteristics(sqlite3_file *pFile){ - int rc; - sqlite3_uint64 t; - VfslogFile *p = (VfslogFile *)pFile; - t = vfslog_time(); - rc = p->pReal->pMethods->xDeviceCharacteristics(p->pReal); - t = vfslog_time() - t; - vfslog_call(p->pVfslog, OS_DEVCHAR, p->iFileId, t, rc, 0, 0); - return rc; -} - -static int vfslogShmLock(sqlite3_file *pFile, int ofst, int n, int flags){ - int rc; - sqlite3_uint64 t; - VfslogFile *p = (VfslogFile *)pFile; - t = vfslog_time(); - rc = p->pReal->pMethods->xShmLock(p->pReal, ofst, n, flags); - t = vfslog_time() - t; - vfslog_call(p->pVfslog, OS_SHMLOCK, p->iFileId, t, rc, 0, 0); - return rc; -} -static int vfslogShmMap( - sqlite3_file *pFile, - int iRegion, - int szRegion, - int isWrite, - volatile void **pp -){ - int rc; - sqlite3_uint64 t; - VfslogFile *p = (VfslogFile *)pFile; - t = vfslog_time(); - rc = p->pReal->pMethods->xShmMap(p->pReal, iRegion, szRegion, isWrite, pp); - t = vfslog_time() - t; - vfslog_call(p->pVfslog, OS_SHMMAP, p->iFileId, t, rc, 0, 0); - return rc; -} -static void vfslogShmBarrier(sqlite3_file *pFile){ - sqlite3_uint64 t; - VfslogFile *p = (VfslogFile *)pFile; - t = vfslog_time(); - p->pReal->pMethods->xShmBarrier(p->pReal); - t = vfslog_time() - t; - vfslog_call(p->pVfslog, OS_SHMBARRIER, p->iFileId, t, SQLITE_OK, 0, 0); -} -static int vfslogShmUnmap(sqlite3_file *pFile, int deleteFlag){ - int rc; - sqlite3_uint64 t; - VfslogFile *p = (VfslogFile *)pFile; - t = vfslog_time(); - rc = p->pReal->pMethods->xShmUnmap(p->pReal, deleteFlag); - t = vfslog_time() - t; - vfslog_call(p->pVfslog, OS_SHMUNMAP, p->iFileId, t, rc, 0, 0); - return rc; -} - - -/* -** Open an vfslog file handle. -*/ -static int vfslogOpen( - sqlite3_vfs *pVfs, - const char *zName, - sqlite3_file *pFile, - int flags, - int *pOutFlags -){ - int rc; - sqlite3_uint64 t; - VfslogFile *p = (VfslogFile *)pFile; - VfslogVfs *pLog = (VfslogVfs *)pVfs; - - pFile->pMethods = &vfslog_io_methods; - p->pReal = (sqlite3_file *)&p[1]; - p->pVfslog = pVfs; - p->iFileId = ++pLog->iNextFileId; - - t = vfslog_time(); - rc = REALVFS(pVfs)->xOpen(REALVFS(pVfs), zName, p->pReal, flags, pOutFlags); - t = vfslog_time() - t; - - vfslog_call(pVfs, OS_OPEN, p->iFileId, t, rc, 0, 0); - vfslog_string(pVfs, zName); - return rc; -} - -/* -** Delete the file located at zPath. If the dirSync argument is true, -** ensure the file-system modifications are synced to disk before -** returning. -*/ -static int vfslogDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){ - int rc; - sqlite3_uint64 t; - t = vfslog_time(); - rc = REALVFS(pVfs)->xDelete(REALVFS(pVfs), zPath, dirSync); - t = vfslog_time() - t; - vfslog_call(pVfs, OS_DELETE, 0, t, rc, dirSync, 0); - vfslog_string(pVfs, zPath); - return rc; -} - -/* -** Test for access permissions. Return true if the requested permission -** is available, or false otherwise. -*/ -static int vfslogAccess( - sqlite3_vfs *pVfs, - const char *zPath, - int flags, - int *pResOut -){ - int rc; - sqlite3_uint64 t; - t = vfslog_time(); - rc = REALVFS(pVfs)->xAccess(REALVFS(pVfs), zPath, flags, pResOut); - t = vfslog_time() - t; - vfslog_call(pVfs, OS_ACCESS, 0, t, rc, flags, *pResOut); - vfslog_string(pVfs, zPath); - return rc; -} - -/* -** Populate buffer zOut with the full canonical pathname corresponding -** to the pathname in zPath. zOut is guaranteed to point to a buffer -** of at least (INST_MAX_PATHNAME+1) bytes. -*/ -static int vfslogFullPathname( - sqlite3_vfs *pVfs, - const char *zPath, - int nOut, - char *zOut -){ - return REALVFS(pVfs)->xFullPathname(REALVFS(pVfs), zPath, nOut, zOut); -} - -/* -** Open the dynamic library located at zPath and return a handle. -*/ -static void *vfslogDlOpen(sqlite3_vfs *pVfs, const char *zPath){ - return REALVFS(pVfs)->xDlOpen(REALVFS(pVfs), zPath); -} - -/* -** Populate the buffer zErrMsg (size nByte bytes) with a human readable -** utf-8 string describing the most recent error encountered associated -** with dynamic libraries. -*/ -static void vfslogDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){ - REALVFS(pVfs)->xDlError(REALVFS(pVfs), nByte, zErrMsg); -} - -/* -** Return a pointer to the symbol zSymbol in the dynamic library pHandle. -*/ -static void (*vfslogDlSym(sqlite3_vfs *pVfs, void *p, const char *zSym))(void){ - return REALVFS(pVfs)->xDlSym(REALVFS(pVfs), p, zSym); -} - -/* -** Close the dynamic library handle pHandle. -*/ -static void vfslogDlClose(sqlite3_vfs *pVfs, void *pHandle){ - REALVFS(pVfs)->xDlClose(REALVFS(pVfs), pHandle); -} - -/* -** Populate the buffer pointed to by zBufOut with nByte bytes of -** random data. -*/ -static int vfslogRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){ - return REALVFS(pVfs)->xRandomness(REALVFS(pVfs), nByte, zBufOut); -} - -/* -** Sleep for nMicro microseconds. Return the number of microseconds -** actually slept. -*/ -static int vfslogSleep(sqlite3_vfs *pVfs, int nMicro){ - return REALVFS(pVfs)->xSleep(REALVFS(pVfs), nMicro); -} - -/* -** Return the current time as a Julian Day number in *pTimeOut. -*/ -static int vfslogCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){ - return REALVFS(pVfs)->xCurrentTime(REALVFS(pVfs), pTimeOut); -} - -static int vfslogGetLastError(sqlite3_vfs *pVfs, int a, char *b){ - return REALVFS(pVfs)->xGetLastError(REALVFS(pVfs), a, b); -} -static int vfslogCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *p){ - return REALVFS(pVfs)->xCurrentTimeInt64(REALVFS(pVfs), p); -} - -static void vfslog_flush(VfslogVfs *p){ -#ifdef SQLITE_TEST - extern int sqlite3_io_error_pending; - extern int sqlite3_io_error_persist; - extern int sqlite3_diskfull_pending; - - int pending = sqlite3_io_error_pending; - int persist = sqlite3_io_error_persist; - int diskfull = sqlite3_diskfull_pending; - - sqlite3_io_error_pending = 0; - sqlite3_io_error_persist = 0; - sqlite3_diskfull_pending = 0; -#endif - - if( p->nBuf ){ - p->pLog->pMethods->xWrite(p->pLog, p->aBuf, p->nBuf, p->iOffset); - p->iOffset += p->nBuf; - p->nBuf = 0; - } - -#ifdef SQLITE_TEST - sqlite3_io_error_pending = pending; - sqlite3_io_error_persist = persist; - sqlite3_diskfull_pending = diskfull; -#endif -} - -static void put32bits(unsigned char *p, unsigned int v){ - p[0] = v>>24; - p[1] = v>>16; - p[2] = v>>8; - p[3] = v; -} - -static void vfslog_call( - sqlite3_vfs *pVfs, - int eEvent, - int iFileid, - sqlite3_int64 nClick, - int return_code, - int size, - int offset -){ - VfslogVfs *p = (VfslogVfs *)pVfs; - unsigned char *zRec; - if( (24+p->nBuf)>sizeof(p->aBuf) ){ - vfslog_flush(p); - } - zRec = (unsigned char *)&p->aBuf[p->nBuf]; - put32bits(&zRec[0], eEvent); - put32bits(&zRec[4], iFileid); - put32bits(&zRec[8], (unsigned int)(nClick&0xffff)); - put32bits(&zRec[12], return_code); - put32bits(&zRec[16], size); - put32bits(&zRec[20], offset); - p->nBuf += 24; -} - -static void vfslog_string(sqlite3_vfs *pVfs, const char *zStr){ - VfslogVfs *p = (VfslogVfs *)pVfs; - unsigned char *zRec; - int nStr = zStr ? (int)strlen(zStr) : 0; - if( (4+nStr+p->nBuf)>sizeof(p->aBuf) ){ - vfslog_flush(p); - } - zRec = (unsigned char *)&p->aBuf[p->nBuf]; - put32bits(&zRec[0], nStr); - if( zStr ){ - memcpy(&zRec[4], zStr, nStr); - } - p->nBuf += (4 + nStr); -} - -static void vfslog_finalize(VfslogVfs *p){ - if( p->pLog->pMethods ){ - vfslog_flush(p); - p->pLog->pMethods->xClose(p->pLog); - } - sqlite3_free(p); -} - -int sqlite3_vfslog_finalize(const char *zVfs){ - sqlite3_vfs *pVfs; - pVfs = sqlite3_vfs_find(zVfs); - if( !pVfs || pVfs->xOpen!=vfslogOpen ){ - return SQLITE_ERROR; - } - sqlite3_vfs_unregister(pVfs); - vfslog_finalize((VfslogVfs *)pVfs); - return SQLITE_OK; -} - -int sqlite3_vfslog_new( - const char *zVfs, /* New VFS name */ - const char *zParentVfs, /* Parent VFS name (or NULL) */ - const char *zLog /* Log file name */ -){ - VfslogVfs *p; - sqlite3_vfs *pParent; - int nByte; - int flags; - int rc; - char *zFile; - int nVfs; - - pParent = sqlite3_vfs_find(zParentVfs); - if( !pParent ){ - return SQLITE_ERROR; - } - - nVfs = (int)strlen(zVfs); - nByte = sizeof(VfslogVfs) + pParent->szOsFile + nVfs+1+pParent->mxPathname+1; - p = (VfslogVfs *)sqlite3_malloc(nByte); - memset(p, 0, nByte); - - p->pVfs = pParent; - p->pLog = (sqlite3_file *)&p[1]; - memcpy(&p->base, &vfslog_vfs, sizeof(sqlite3_vfs)); - p->base.zName = &((char *)p->pLog)[pParent->szOsFile]; - p->base.szOsFile += pParent->szOsFile; - memcpy((char *)p->base.zName, zVfs, nVfs); - - zFile = (char *)&p->base.zName[nVfs+1]; - pParent->xFullPathname(pParent, zLog, pParent->mxPathname, zFile); - - flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_MASTER_JOURNAL; - pParent->xDelete(pParent, zFile, 0); - rc = pParent->xOpen(pParent, zFile, p->pLog, flags, &flags); - if( rc==SQLITE_OK ){ - memcpy(p->aBuf, "sqlite_ostrace1.....", 20); - p->iOffset = 0; - p->nBuf = 20; - rc = sqlite3_vfs_register((sqlite3_vfs *)p, 1); - } - if( rc ){ - vfslog_finalize(p); - } - return rc; -} - -int sqlite3_vfslog_annotate(const char *zVfs, const char *zMsg){ - sqlite3_vfs *pVfs; - pVfs = sqlite3_vfs_find(zVfs); - if( !pVfs || pVfs->xOpen!=vfslogOpen ){ - return SQLITE_ERROR; - } - vfslog_call(pVfs, OS_ANNOTATE, 0, 0, 0, 0, 0); - vfslog_string(pVfs, zMsg); - return SQLITE_OK; -} - -static const char *vfslog_eventname(int eEvent){ - const char *zEvent = 0; - - switch( eEvent ){ - case OS_CLOSE: zEvent = "xClose"; break; - case OS_READ: zEvent = "xRead"; break; - case OS_WRITE: zEvent = "xWrite"; break; - case OS_TRUNCATE: zEvent = "xTruncate"; break; - case OS_SYNC: zEvent = "xSync"; break; - case OS_FILESIZE: zEvent = "xFilesize"; break; - case OS_LOCK: zEvent = "xLock"; break; - case OS_UNLOCK: zEvent = "xUnlock"; break; - case OS_CHECKRESERVEDLOCK: zEvent = "xCheckResLock"; break; - case OS_FILECONTROL: zEvent = "xFileControl"; break; - case OS_SECTORSIZE: zEvent = "xSectorSize"; break; - case OS_DEVCHAR: zEvent = "xDeviceChar"; break; - case OS_OPEN: zEvent = "xOpen"; break; - case OS_DELETE: zEvent = "xDelete"; break; - case OS_ACCESS: zEvent = "xAccess"; break; - case OS_FULLPATHNAME: zEvent = "xFullPathname"; break; - case OS_RANDOMNESS: zEvent = "xRandomness"; break; - case OS_SLEEP: zEvent = "xSleep"; break; - case OS_CURRENTTIME: zEvent = "xCurrentTime"; break; - - case OS_SHMUNMAP: zEvent = "xShmUnmap"; break; - case OS_SHMLOCK: zEvent = "xShmLock"; break; - case OS_SHMBARRIER: zEvent = "xShmBarrier"; break; - case OS_SHMMAP: zEvent = "xShmMap"; break; - - case OS_ANNOTATE: zEvent = "annotation"; break; - } - - return zEvent; -} - -typedef struct VfslogVtab VfslogVtab; -typedef struct VfslogCsr VfslogCsr; - -/* -** Virtual table type for the vfslog reader module. -*/ -struct VfslogVtab { - sqlite3_vtab base; /* Base class */ - sqlite3_file *pFd; /* File descriptor open on vfslog file */ - sqlite3_int64 nByte; /* Size of file in bytes */ - char *zFile; /* File name for pFd */ -}; - -/* -** Virtual table cursor type for the vfslog reader module. -*/ -struct VfslogCsr { - sqlite3_vtab_cursor base; /* Base class */ - sqlite3_int64 iRowid; /* Current rowid. */ - sqlite3_int64 iOffset; /* Offset of next record in file */ - char *zTransient; /* Transient 'file' string */ - int nFile; /* Size of array azFile[] */ - char **azFile; /* File strings */ - unsigned char aBuf[1024]; /* Current vfs log entry (read from file) */ -}; - -static unsigned int get32bits(unsigned char *p){ - return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; -} - -/* -** The argument must point to a buffer containing a nul-terminated string. -** If the string begins with an SQL quote character it is overwritten by -** the dequoted version. Otherwise the buffer is left unmodified. -*/ -static void dequote(char *z){ - char quote; /* Quote character (if any ) */ - quote = z[0]; - if( quote=='[' || quote=='\'' || quote=='"' || quote=='`' ){ - int iIn = 1; /* Index of next byte to read from input */ - int iOut = 0; /* Index of next byte to write to output */ - if( quote=='[' ) quote = ']'; - while( z[iIn] ){ - if( z[iIn]==quote ){ - if( z[iIn+1]!=quote ) break; - z[iOut++] = quote; - iIn += 2; - }else{ - z[iOut++] = z[iIn++]; - } - } - z[iOut] = '\0'; - } -} - -#ifndef SQLITE_OMIT_VIRTUALTABLE -/* -** Connect to or create a vfslog virtual table. -*/ -static int vlogConnect( - sqlite3 *db, - void *pAux, - int argc, const char *const*argv, - sqlite3_vtab **ppVtab, - char **pzErr -){ - sqlite3_vfs *pVfs; /* VFS used to read log file */ - int flags; /* flags passed to pVfs->xOpen() */ - VfslogVtab *p; - int rc; - int nByte; - char *zFile; - - *ppVtab = 0; - pVfs = sqlite3_vfs_find(0); - nByte = sizeof(VfslogVtab) + pVfs->szOsFile + pVfs->mxPathname; - p = sqlite3_malloc(nByte); - if( p==0 ) return SQLITE_NOMEM; - memset(p, 0, nByte); - - p->pFd = (sqlite3_file *)&p[1]; - p->zFile = &((char *)p->pFd)[pVfs->szOsFile]; - - zFile = sqlite3_mprintf("%s", argv[3]); - if( !zFile ){ - sqlite3_free(p); - return SQLITE_NOMEM; - } - dequote(zFile); - pVfs->xFullPathname(pVfs, zFile, pVfs->mxPathname, p->zFile); - sqlite3_free(zFile); - - flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_MASTER_JOURNAL; - rc = pVfs->xOpen(pVfs, p->zFile, p->pFd, flags, &flags); - - if( rc==SQLITE_OK ){ - p->pFd->pMethods->xFileSize(p->pFd, &p->nByte); - sqlite3_declare_vtab(db, - "CREATE TABLE xxx(event, file, click, rc, size, offset)" - ); - *ppVtab = &p->base; - }else{ - sqlite3_free(p); - } - - return rc; -} - -/* -** There is no "best-index". This virtual table always does a linear -** scan of the binary VFS log file. -*/ -static int vlogBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ - pIdxInfo->estimatedCost = 10.0; - return SQLITE_OK; -} - -/* -** Disconnect from or destroy a vfslog virtual table. -*/ -static int vlogDisconnect(sqlite3_vtab *pVtab){ - VfslogVtab *p = (VfslogVtab *)pVtab; - if( p->pFd->pMethods ){ - p->pFd->pMethods->xClose(p->pFd); - p->pFd->pMethods = 0; - } - sqlite3_free(p); - return SQLITE_OK; -} - -/* -** Open a new vfslog cursor. -*/ -static int vlogOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){ - VfslogCsr *pCsr; /* Newly allocated cursor object */ - - pCsr = sqlite3_malloc(sizeof(VfslogCsr)); - if( !pCsr ) return SQLITE_NOMEM; - memset(pCsr, 0, sizeof(VfslogCsr)); - *ppCursor = &pCsr->base; - return SQLITE_OK; -} - -/* -** Close a vfslog cursor. -*/ -static int vlogClose(sqlite3_vtab_cursor *pCursor){ - VfslogCsr *p = (VfslogCsr *)pCursor; - int i; - for(i=0; i<p->nFile; i++){ - sqlite3_free(p->azFile[i]); - } - sqlite3_free(p->azFile); - sqlite3_free(p->zTransient); - sqlite3_free(p); - return SQLITE_OK; -} - -/* -** Move a vfslog cursor to the next entry in the file. -*/ -static int vlogNext(sqlite3_vtab_cursor *pCursor){ - VfslogCsr *pCsr = (VfslogCsr *)pCursor; - VfslogVtab *p = (VfslogVtab *)pCursor->pVtab; - int rc = SQLITE_OK; - int nRead; - - sqlite3_free(pCsr->zTransient); - pCsr->zTransient = 0; - - nRead = 24; - if( pCsr->iOffset+nRead<=p->nByte ){ - int eEvent; - rc = p->pFd->pMethods->xRead(p->pFd, pCsr->aBuf, nRead, pCsr->iOffset); - - eEvent = get32bits(pCsr->aBuf); - if( (rc==SQLITE_OK) - && (eEvent==OS_OPEN || eEvent==OS_DELETE || eEvent==OS_ACCESS) - ){ - char buf[4]; - rc = p->pFd->pMethods->xRead(p->pFd, buf, 4, pCsr->iOffset+nRead); - nRead += 4; - if( rc==SQLITE_OK ){ - int nStr = get32bits((unsigned char *)buf); - char *zStr = sqlite3_malloc(nStr+1); - rc = p->pFd->pMethods->xRead(p->pFd, zStr, nStr, pCsr->iOffset+nRead); - zStr[nStr] = '\0'; - nRead += nStr; - - if( eEvent==OS_OPEN ){ - int iFileid = get32bits(&pCsr->aBuf[4]); - if( iFileid>=pCsr->nFile ){ - int nNew = sizeof(pCsr->azFile[0])*(iFileid+1); - pCsr->azFile = (char **)sqlite3_realloc(pCsr->azFile, nNew); - nNew -= sizeof(pCsr->azFile[0])*pCsr->nFile; - memset(&pCsr->azFile[pCsr->nFile], 0, nNew); - pCsr->nFile = iFileid+1; - } - sqlite3_free(pCsr->azFile[iFileid]); - pCsr->azFile[iFileid] = zStr; - }else{ - pCsr->zTransient = zStr; - } - } - } - } - - pCsr->iRowid += 1; - pCsr->iOffset += nRead; - return rc; -} - -static int vlogEof(sqlite3_vtab_cursor *pCursor){ - VfslogCsr *pCsr = (VfslogCsr *)pCursor; - VfslogVtab *p = (VfslogVtab *)pCursor->pVtab; - return (pCsr->iOffset>=p->nByte); -} - -static int vlogFilter( - sqlite3_vtab_cursor *pCursor, - int idxNum, const char *idxStr, - int argc, sqlite3_value **argv -){ - VfslogCsr *pCsr = (VfslogCsr *)pCursor; - pCsr->iRowid = 0; - pCsr->iOffset = 20; - return vlogNext(pCursor); -} - -static int vlogColumn( - sqlite3_vtab_cursor *pCursor, - sqlite3_context *ctx, - int i -){ - unsigned int val; - VfslogCsr *pCsr = (VfslogCsr *)pCursor; - - assert( i<7 ); - val = get32bits(&pCsr->aBuf[4*i]); - - switch( i ){ - case 0: { - sqlite3_result_text(ctx, vfslog_eventname(val), -1, SQLITE_STATIC); - break; - } - case 1: { - char *zStr = pCsr->zTransient; - if( val!=0 && val<(unsigned)pCsr->nFile ){ - zStr = pCsr->azFile[val]; - } - sqlite3_result_text(ctx, zStr, -1, SQLITE_TRANSIENT); - break; - } - default: - sqlite3_result_int(ctx, val); - break; - } - - return SQLITE_OK; -} - -static int vlogRowid(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){ - VfslogCsr *pCsr = (VfslogCsr *)pCursor; - *pRowid = pCsr->iRowid; - return SQLITE_OK; -} - -int sqlite3_vfslog_register(sqlite3 *db){ - static sqlite3_module vfslog_module = { - 0, /* iVersion */ - vlogConnect, /* xCreate */ - vlogConnect, /* xConnect */ - vlogBestIndex, /* xBestIndex */ - vlogDisconnect, /* xDisconnect */ - vlogDisconnect, /* xDestroy */ - vlogOpen, /* xOpen - open a cursor */ - vlogClose, /* xClose - close a cursor */ - vlogFilter, /* xFilter - configure scan constraints */ - vlogNext, /* xNext - advance a cursor */ - vlogEof, /* xEof - check for end of scan */ - vlogColumn, /* xColumn - read data */ - vlogRowid, /* xRowid - read data */ - 0, /* xUpdate */ - 0, /* xBegin */ - 0, /* xSync */ - 0, /* xCommit */ - 0, /* xRollback */ - 0, /* xFindMethod */ - 0, /* xRename */ - }; - - sqlite3_create_module(db, "vfslog", &vfslog_module, 0); - return SQLITE_OK; -} -#endif /* SQLITE_OMIT_VIRTUALTABLE */ - -/************************************************************************** -*************************************************************************** -** Tcl interface starts here. -*/ - -#if defined(SQLITE_TEST) || defined(TCLSH) - -#include <tcl.h> - -static int test_vfslog( - void *clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - struct SqliteDb { sqlite3 *db; }; - sqlite3 *db; - Tcl_CmdInfo cmdInfo; - int rc = SQLITE_ERROR; - - static const char *strs[] = { "annotate", "finalize", "new", "register", 0 }; - enum VL_enum { VL_ANNOTATE, VL_FINALIZE, VL_NEW, VL_REGISTER }; - int iSub; - - if( objc<2 ){ - Tcl_WrongNumArgs(interp, 1, objv, "SUB-COMMAND ..."); - return TCL_ERROR; - } - if( Tcl_GetIndexFromObj(interp, objv[1], strs, "sub-command", 0, &iSub) ){ - return TCL_ERROR; - } - - switch( (enum VL_enum)iSub ){ - case VL_ANNOTATE: { - int rc; - char *zVfs; - char *zMsg; - if( objc!=4 ){ - Tcl_WrongNumArgs(interp, 3, objv, "VFS"); - return TCL_ERROR; - } - zVfs = Tcl_GetString(objv[2]); - zMsg = Tcl_GetString(objv[3]); - rc = sqlite3_vfslog_annotate(zVfs, zMsg); - if( rc!=SQLITE_OK ){ - Tcl_AppendResult(interp, "failed", 0); - return TCL_ERROR; - } - break; - } - case VL_FINALIZE: { - int rc; - char *zVfs; - if( objc!=3 ){ - Tcl_WrongNumArgs(interp, 2, objv, "VFS"); - return TCL_ERROR; - } - zVfs = Tcl_GetString(objv[2]); - rc = sqlite3_vfslog_finalize(zVfs); - if( rc!=SQLITE_OK ){ - Tcl_AppendResult(interp, "failed", 0); - return TCL_ERROR; - } - break; - }; - - case VL_NEW: { - int rc; - char *zVfs; - char *zParent; - char *zLog; - if( objc!=5 ){ - Tcl_WrongNumArgs(interp, 2, objv, "VFS PARENT LOGFILE"); - return TCL_ERROR; - } - zVfs = Tcl_GetString(objv[2]); - zParent = Tcl_GetString(objv[3]); - zLog = Tcl_GetString(objv[4]); - if( *zParent=='\0' ) zParent = 0; - rc = sqlite3_vfslog_new(zVfs, zParent, zLog); - if( rc!=SQLITE_OK ){ - Tcl_AppendResult(interp, "failed", 0); - return TCL_ERROR; - } - break; - }; - - case VL_REGISTER: { - char *zDb; - if( objc!=3 ){ - Tcl_WrongNumArgs(interp, 2, objv, "DB"); - return TCL_ERROR; - } -#ifdef SQLITE_OMIT_VIRTUALTABLE - Tcl_AppendResult(interp, "vfslog not available because of " - "SQLITE_OMIT_VIRTUALTABLE", (void*)0); - return TCL_ERROR; -#else - zDb = Tcl_GetString(objv[2]); - if( Tcl_GetCommandInfo(interp, zDb, &cmdInfo) ){ - db = ((struct SqliteDb*)cmdInfo.objClientData)->db; - rc = sqlite3_vfslog_register(db); - } - if( rc!=SQLITE_OK ){ - Tcl_AppendResult(interp, "bad sqlite3 handle: ", zDb, (void*)0); - return TCL_ERROR; - } - break; -#endif - } - } - - return TCL_OK; -} - -int SqlitetestOsinst_Init(Tcl_Interp *interp){ - Tcl_CreateObjCommand(interp, "vfslog", test_vfslog, 0, 0); - return TCL_OK; -} - -#endif /* SQLITE_TEST */ diff --git a/components/external/SQLite-3.8.1/SQLiteLib/test/test_pcache.c b/components/external/SQLite-3.8.1/SQLiteLib/test/test_pcache.c deleted file mode 100644 index 8fcfe7e26e..0000000000 --- a/components/external/SQLite-3.8.1/SQLiteLib/test/test_pcache.c +++ /dev/null @@ -1,467 +0,0 @@ -/* -** 2008 November 18 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** -** This file contains code used for testing the SQLite system. -** None of the code in this file goes into a deliverable build. -** -** This file contains an application-defined pager cache -** implementation that can be plugged in in place of the -** default pcache. This alternative pager cache will throw -** some errors that the default cache does not. -** -** This pagecache implementation is designed for simplicity -** not speed. -*/ -#include "sqlite3.h" -#include <string.h> -#include <assert.h> - -/* -** Global data used by this test implementation. There is no -** mutexing, which means this page cache will not work in a -** multi-threaded test. -*/ -typedef struct testpcacheGlobalType testpcacheGlobalType; -struct testpcacheGlobalType { - void *pDummy; /* Dummy allocation to simulate failures */ - int nInstance; /* Number of current instances */ - unsigned discardChance; /* Chance of discarding on an unpin (0-100) */ - unsigned prngSeed; /* Seed for the PRNG */ - unsigned highStress; /* Call xStress agressively */ -}; -static testpcacheGlobalType testpcacheGlobal; - -/* -** Initializer. -** -** Verify that the initializer is only called when the system is -** uninitialized. Allocate some memory and report SQLITE_NOMEM if -** the allocation fails. This provides a means to test the recovery -** from a failed initialization attempt. It also verifies that the -** the destructor always gets call - otherwise there would be a -** memory leak. -*/ -static int testpcacheInit(void *pArg){ - assert( pArg==(void*)&testpcacheGlobal ); - assert( testpcacheGlobal.pDummy==0 ); - assert( testpcacheGlobal.nInstance==0 ); - testpcacheGlobal.pDummy = sqlite3_malloc(10); - return testpcacheGlobal.pDummy==0 ? SQLITE_NOMEM : SQLITE_OK; -} - -/* -** Destructor -** -** Verify that this is only called after initialization. -** Free the memory allocated by the initializer. -*/ -static void testpcacheShutdown(void *pArg){ - assert( pArg==(void*)&testpcacheGlobal ); - assert( testpcacheGlobal.pDummy!=0 ); - assert( testpcacheGlobal.nInstance==0 ); - sqlite3_free( testpcacheGlobal.pDummy ); - testpcacheGlobal.pDummy = 0; -} - -/* -** Number of pages in a cache. -** -** The number of pages is a hard upper bound in this test module. -** If more pages are requested, sqlite3PcacheFetch() returns NULL. -** -** If testing with in-memory temp tables, provide a larger pcache. -** Some of the test cases need this. -*/ -#if defined(SQLITE_TEMP_STORE) && SQLITE_TEMP_STORE>=2 -# define TESTPCACHE_NPAGE 499 -#else -# define TESTPCACHE_NPAGE 217 -#endif -#define TESTPCACHE_RESERVE 17 - -/* -** Magic numbers used to determine validity of the page cache. -*/ -#define TESTPCACHE_VALID 0x364585fd -#define TESTPCACHE_CLEAR 0xd42670d4 - -/* -** Private implementation of a page cache. -*/ -typedef struct testpcache testpcache; -struct testpcache { - int szPage; /* Size of each page. Multiple of 8. */ - int szExtra; /* Size of extra data that accompanies each page */ - int bPurgeable; /* True if the page cache is purgeable */ - int nFree; /* Number of unused slots in a[] */ - int nPinned; /* Number of pinned slots in a[] */ - unsigned iRand; /* State of the PRNG */ - unsigned iMagic; /* Magic number for sanity checking */ - struct testpcachePage { - sqlite3_pcache_page page; /* Base class */ - unsigned key; /* The key for this page. 0 means unallocated */ - int isPinned; /* True if the page is pinned */ - } a[TESTPCACHE_NPAGE]; /* All pages in the cache */ -}; - -/* -** Get a random number using the PRNG in the given page cache. -*/ -static unsigned testpcacheRandom(testpcache *p){ - unsigned x = 0; - int i; - for(i=0; i<4; i++){ - p->iRand = (p->iRand*69069 + 5); - x = (x<<8) | ((p->iRand>>16)&0xff); - } - return x; -} - - -/* -** Allocate a new page cache instance. -*/ -static sqlite3_pcache *testpcacheCreate( - int szPage, - int szExtra, - int bPurgeable -){ - int nMem; - char *x; - testpcache *p; - int i; - assert( testpcacheGlobal.pDummy!=0 ); - szPage = (szPage+7)&~7; - nMem = sizeof(testpcache) + TESTPCACHE_NPAGE*(szPage+szExtra); - p = sqlite3_malloc( nMem ); - if( p==0 ) return 0; - x = (char*)&p[1]; - p->szPage = szPage; - p->szExtra = szExtra; - p->nFree = TESTPCACHE_NPAGE; - p->nPinned = 0; - p->iRand = testpcacheGlobal.prngSeed; - p->bPurgeable = bPurgeable; - p->iMagic = TESTPCACHE_VALID; - for(i=0; i<TESTPCACHE_NPAGE; i++, x += (szPage+szExtra)){ - p->a[i].key = 0; - p->a[i].isPinned = 0; - p->a[i].page.pBuf = (void*)x; - p->a[i].page.pExtra = (void*)&x[szPage]; - } - testpcacheGlobal.nInstance++; - return (sqlite3_pcache*)p; -} - -/* -** Set the cache size -*/ -static void testpcacheCachesize(sqlite3_pcache *pCache, int newSize){ - testpcache *p = (testpcache*)pCache; - assert( p->iMagic==TESTPCACHE_VALID ); - assert( testpcacheGlobal.pDummy!=0 ); - assert( testpcacheGlobal.nInstance>0 ); -} - -/* -** Return the number of pages in the cache that are being used. -** This includes both pinned and unpinned pages. -*/ -static int testpcachePagecount(sqlite3_pcache *pCache){ - testpcache *p = (testpcache*)pCache; - assert( p->iMagic==TESTPCACHE_VALID ); - assert( testpcacheGlobal.pDummy!=0 ); - assert( testpcacheGlobal.nInstance>0 ); - return TESTPCACHE_NPAGE - p->nFree; -} - -/* -** Fetch a page. -*/ -static sqlite3_pcache_page *testpcacheFetch( - sqlite3_pcache *pCache, - unsigned key, - int createFlag -){ - testpcache *p = (testpcache*)pCache; - int i, j; - assert( p->iMagic==TESTPCACHE_VALID ); - assert( testpcacheGlobal.pDummy!=0 ); - assert( testpcacheGlobal.nInstance>0 ); - - /* See if the page is already in cache. Return immediately if it is */ - for(i=0; i<TESTPCACHE_NPAGE; i++){ - if( p->a[i].key==key ){ - if( !p->a[i].isPinned ){ - p->nPinned++; - assert( p->nPinned <= TESTPCACHE_NPAGE - p->nFree ); - p->a[i].isPinned = 1; - } - return &p->a[i].page; - } - } - - /* If createFlag is 0, never allocate a new page */ - if( createFlag==0 ){ - return 0; - } - - /* If no pages are available, always fail */ - if( p->nPinned==TESTPCACHE_NPAGE ){ - return 0; - } - - /* Do not allocate the last TESTPCACHE_RESERVE pages unless createFlag is 2 */ - if( p->nPinned>=TESTPCACHE_NPAGE-TESTPCACHE_RESERVE && createFlag<2 ){ - return 0; - } - - /* Do not allocate if highStress is enabled and createFlag is not 2. - ** - ** The highStress setting causes pagerStress() to be called much more - ** often, which exercises the pager logic more intensely. - */ - if( testpcacheGlobal.highStress && createFlag<2 ){ - return 0; - } - - /* Find a free page to allocate if there are any free pages. - ** Withhold TESTPCACHE_RESERVE free pages until createFlag is 2. - */ - if( p->nFree>TESTPCACHE_RESERVE || (createFlag==2 && p->nFree>0) ){ - j = testpcacheRandom(p) % TESTPCACHE_NPAGE; - for(i=0; i<TESTPCACHE_NPAGE; i++, j = (j+1)%TESTPCACHE_NPAGE){ - if( p->a[j].key==0 ){ - p->a[j].key = key; - p->a[j].isPinned = 1; - memset(p->a[j].page.pBuf, 0, p->szPage); - memset(p->a[j].page.pExtra, 0, p->szExtra); - p->nPinned++; - p->nFree--; - assert( p->nPinned <= TESTPCACHE_NPAGE - p->nFree ); - return &p->a[j].page; - } - } - - /* The prior loop always finds a freepage to allocate */ - assert( 0 ); - } - - /* If this cache is not purgeable then we have to fail. - */ - if( p->bPurgeable==0 ){ - return 0; - } - - /* If there are no free pages, recycle a page. The page to - ** recycle is selected at random from all unpinned pages. - */ - j = testpcacheRandom(p) % TESTPCACHE_NPAGE; - for(i=0; i<TESTPCACHE_NPAGE; i++, j = (j+1)%TESTPCACHE_NPAGE){ - if( p->a[j].key>0 && p->a[j].isPinned==0 ){ - p->a[j].key = key; - p->a[j].isPinned = 1; - memset(p->a[j].page.pBuf, 0, p->szPage); - memset(p->a[j].page.pExtra, 0, p->szExtra); - p->nPinned++; - assert( p->nPinned <= TESTPCACHE_NPAGE - p->nFree ); - return &p->a[j].page; - } - } - - /* The previous loop always finds a page to recycle. */ - assert(0); - return 0; -} - -/* -** Unpin a page. -*/ -static void testpcacheUnpin( - sqlite3_pcache *pCache, - sqlite3_pcache_page *pOldPage, - int discard -){ - testpcache *p = (testpcache*)pCache; - int i; - assert( p->iMagic==TESTPCACHE_VALID ); - assert( testpcacheGlobal.pDummy!=0 ); - assert( testpcacheGlobal.nInstance>0 ); - - /* Randomly discard pages as they are unpinned according to the - ** discardChance setting. If discardChance is 0, the random discard - ** never happens. If discardChance is 100, it always happens. - */ - if( p->bPurgeable - && (100-testpcacheGlobal.discardChance) <= (testpcacheRandom(p)%100) - ){ - discard = 1; - } - - for(i=0; i<TESTPCACHE_NPAGE; i++){ - if( &p->a[i].page==pOldPage ){ - /* The pOldPage pointer always points to a pinned page */ - assert( p->a[i].isPinned ); - p->a[i].isPinned = 0; - p->nPinned--; - assert( p->nPinned>=0 ); - if( discard ){ - p->a[i].key = 0; - p->nFree++; - assert( p->nFree<=TESTPCACHE_NPAGE ); - } - return; - } - } - - /* The pOldPage pointer always points to a valid page */ - assert( 0 ); -} - - -/* -** Rekey a single page. -*/ -static void testpcacheRekey( - sqlite3_pcache *pCache, - sqlite3_pcache_page *pOldPage, - unsigned oldKey, - unsigned newKey -){ - testpcache *p = (testpcache*)pCache; - int i; - assert( p->iMagic==TESTPCACHE_VALID ); - assert( testpcacheGlobal.pDummy!=0 ); - assert( testpcacheGlobal.nInstance>0 ); - - /* If there already exists another page at newKey, verify that - ** the other page is unpinned and discard it. - */ - for(i=0; i<TESTPCACHE_NPAGE; i++){ - if( p->a[i].key==newKey ){ - /* The new key is never a page that is already pinned */ - assert( p->a[i].isPinned==0 ); - p->a[i].key = 0; - p->nFree++; - assert( p->nFree<=TESTPCACHE_NPAGE ); - break; - } - } - - /* Find the page to be rekeyed and rekey it. - */ - for(i=0; i<TESTPCACHE_NPAGE; i++){ - if( p->a[i].key==oldKey ){ - /* The oldKey and pOldPage parameters match */ - assert( &p->a[i].page==pOldPage ); - /* Page to be rekeyed must be pinned */ - assert( p->a[i].isPinned ); - p->a[i].key = newKey; - return; - } - } - - /* Rekey is always given a valid page to work with */ - assert( 0 ); -} - - -/* -** Truncate the page cache. Every page with a key of iLimit or larger -** is discarded. -*/ -static void testpcacheTruncate(sqlite3_pcache *pCache, unsigned iLimit){ - testpcache *p = (testpcache*)pCache; - unsigned int i; - assert( p->iMagic==TESTPCACHE_VALID ); - assert( testpcacheGlobal.pDummy!=0 ); - assert( testpcacheGlobal.nInstance>0 ); - for(i=0; i<TESTPCACHE_NPAGE; i++){ - if( p->a[i].key>=iLimit ){ - p->a[i].key = 0; - if( p->a[i].isPinned ){ - p->nPinned--; - assert( p->nPinned>=0 ); - } - p->nFree++; - assert( p->nFree<=TESTPCACHE_NPAGE ); - } - } -} - -/* -** Destroy a page cache. -*/ -static void testpcacheDestroy(sqlite3_pcache *pCache){ - testpcache *p = (testpcache*)pCache; - assert( p->iMagic==TESTPCACHE_VALID ); - assert( testpcacheGlobal.pDummy!=0 ); - assert( testpcacheGlobal.nInstance>0 ); - p->iMagic = TESTPCACHE_CLEAR; - sqlite3_free(p); - testpcacheGlobal.nInstance--; -} - - -/* -** Invoke this routine to register or unregister the testing pager cache -** implemented by this file. -** -** Install the test pager cache if installFlag is 1 and uninstall it if -** installFlag is 0. -** -** When installing, discardChance is a number between 0 and 100 that -** indicates the probability of discarding a page when unpinning the -** page. 0 means never discard (unless the discard flag is set). -** 100 means always discard. -*/ -void installTestPCache( - int installFlag, /* True to install. False to uninstall. */ - unsigned discardChance, /* 0-100. Chance to discard on unpin */ - unsigned prngSeed, /* Seed for the PRNG */ - unsigned highStress /* Call xStress agressively */ -){ - static const sqlite3_pcache_methods2 testPcache = { - 1, - (void*)&testpcacheGlobal, - testpcacheInit, - testpcacheShutdown, - testpcacheCreate, - testpcacheCachesize, - testpcachePagecount, - testpcacheFetch, - testpcacheUnpin, - testpcacheRekey, - testpcacheTruncate, - testpcacheDestroy, - }; - static sqlite3_pcache_methods2 defaultPcache; - static int isInstalled = 0; - - assert( testpcacheGlobal.nInstance==0 ); - assert( testpcacheGlobal.pDummy==0 ); - assert( discardChance<=100 ); - testpcacheGlobal.discardChance = discardChance; - testpcacheGlobal.prngSeed = prngSeed ^ (prngSeed<<16); - testpcacheGlobal.highStress = highStress; - if( installFlag!=isInstalled ){ - if( installFlag ){ - sqlite3_config(SQLITE_CONFIG_GETPCACHE2, &defaultPcache); - assert( defaultPcache.xCreate!=testpcacheCreate ); - sqlite3_config(SQLITE_CONFIG_PCACHE2, &testPcache); - }else{ - assert( defaultPcache.xCreate!=0 ); - sqlite3_config(SQLITE_CONFIG_PCACHE2, &defaultPcache); - } - isInstalled = installFlag; - } -} diff --git a/components/external/SQLite-3.8.1/SQLiteLib/test/test_quota.c b/components/external/SQLite-3.8.1/SQLiteLib/test/test_quota.c deleted file mode 100644 index e590996ca4..0000000000 --- a/components/external/SQLite-3.8.1/SQLiteLib/test/test_quota.c +++ /dev/null @@ -1,2008 +0,0 @@ -/* -** 2010 September 31 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** -** This file contains a VFS "shim" - a layer that sits in between the -** pager and the real VFS. -** -** This particular shim enforces a quota system on files. One or more -** database files are in a "quota group" that is defined by a GLOB -** pattern. A quota is set for the combined size of all files in the -** the group. A quota of zero means "no limit". If the total size -** of all files in the quota group is greater than the limit, then -** write requests that attempt to enlarge a file fail with SQLITE_FULL. -** -** However, before returning SQLITE_FULL, the write requests invoke -** a callback function that is configurable for each quota group. -** This callback has the opportunity to enlarge the quota. If the -** callback does enlarge the quota such that the total size of all -** files within the group is less than the new quota, then the write -** continues as if nothing had happened. -*/ -#include "test_quota.h" -#include <string.h> -#include <assert.h> - -/* -** For an build without mutexes, no-op the mutex calls. -*/ -#if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE==0 -#define sqlite3_mutex_alloc(X) ((sqlite3_mutex*)8) -#define sqlite3_mutex_free(X) -#define sqlite3_mutex_enter(X) -#define sqlite3_mutex_try(X) SQLITE_OK -#define sqlite3_mutex_leave(X) -#define sqlite3_mutex_held(X) ((void)(X),1) -#define sqlite3_mutex_notheld(X) ((void)(X),1) -#endif /* SQLITE_THREADSAFE==0 */ - - -/* -** Figure out if we are dealing with Unix, Windows, or some other -** operating system. After the following block of preprocess macros, -** all of SQLITE_OS_UNIX, SQLITE_OS_WIN, and SQLITE_OS_OTHER -** will defined to either 1 or 0. One of the four will be 1. The other -** three will be 0. -*/ -#if defined(SQLITE_OS_OTHER) -# if SQLITE_OS_OTHER==1 -# undef SQLITE_OS_UNIX -# define SQLITE_OS_UNIX 0 -# undef SQLITE_OS_WIN -# define SQLITE_OS_WIN 0 -# else -# undef SQLITE_OS_OTHER -# endif -#endif -#if !defined(SQLITE_OS_UNIX) && !defined(SQLITE_OS_OTHER) -# define SQLITE_OS_OTHER 0 -# ifndef SQLITE_OS_WIN -# if defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) \ - || defined(__MINGW32__) || defined(__BORLANDC__) -# define SQLITE_OS_WIN 1 -# define SQLITE_OS_UNIX 0 -# else -# define SQLITE_OS_WIN 0 -# define SQLITE_OS_UNIX 1 -# endif -# else -# define SQLITE_OS_UNIX 0 -# endif -#else -# ifndef SQLITE_OS_WIN -# define SQLITE_OS_WIN 0 -# endif -#endif - -#if SQLITE_OS_UNIX -# include <unistd.h> -#endif -#if SQLITE_OS_WIN -# include <windows.h> -# include <io.h> -#endif - - -/************************ Object Definitions ******************************/ - -/* Forward declaration of all object types */ -typedef struct quotaGroup quotaGroup; -typedef struct quotaConn quotaConn; -typedef struct quotaFile quotaFile; - -/* -** A "quota group" is a collection of files whose collective size we want -** to limit. Each quota group is defined by a GLOB pattern. -** -** There is an instance of the following object for each defined quota -** group. This object records the GLOB pattern that defines which files -** belong to the quota group. The object also remembers the size limit -** for the group (the quota) and the callback to be invoked when the -** sum of the sizes of the files within the group goes over the limit. -** -** A quota group must be established (using sqlite3_quota_set(...)) -** prior to opening any of the database connections that access files -** within the quota group. -*/ -struct quotaGroup { - const char *zPattern; /* Filename pattern to be quotaed */ - sqlite3_int64 iLimit; /* Upper bound on total file size */ - sqlite3_int64 iSize; /* Current size of all files */ - void (*xCallback)( /* Callback invoked when going over quota */ - const char *zFilename, /* Name of file whose size increases */ - sqlite3_int64 *piLimit, /* IN/OUT: The current limit */ - sqlite3_int64 iSize, /* Total size of all files in the group */ - void *pArg /* Client data */ - ); - void *pArg; /* Third argument to the xCallback() */ - void (*xDestroy)(void*); /* Optional destructor for pArg */ - quotaGroup *pNext, **ppPrev; /* Doubly linked list of all quota objects */ - quotaFile *pFiles; /* Files within this group */ -}; - -/* -** An instance of this structure represents a single file that is part -** of a quota group. A single file can be opened multiple times. In -** order keep multiple openings of the same file from causing the size -** of the file to count against the quota multiple times, each file -** has a unique instance of this object and multiple open connections -** to the same file each point to a single instance of this object. -*/ -struct quotaFile { - char *zFilename; /* Name of this file */ - quotaGroup *pGroup; /* Quota group to which this file belongs */ - sqlite3_int64 iSize; /* Current size of this file */ - int nRef; /* Number of times this file is open */ - int deleteOnClose; /* True to delete this file when it closes */ - quotaFile *pNext, **ppPrev; /* Linked list of files in the same group */ -}; - -/* -** An instance of the following object represents each open connection -** to a file that participates in quota tracking. This object is a -** subclass of sqlite3_file. The sqlite3_file object for the underlying -** VFS is appended to this structure. -*/ -struct quotaConn { - sqlite3_file base; /* Base class - must be first */ - quotaFile *pFile; /* The underlying file */ - /* The underlying VFS sqlite3_file is appended to this object */ -}; - -/* -** An instance of the following object records the state of an -** open file. This object is opaque to all users - the internal -** structure is only visible to the functions below. -*/ -struct quota_FILE { - FILE *f; /* Open stdio file pointer */ - sqlite3_int64 iOfst; /* Current offset into the file */ - quotaFile *pFile; /* The file record in the quota system */ -#if SQLITE_OS_WIN - char *zMbcsName; /* Full MBCS pathname of the file */ -#endif -}; - - -/************************* Global Variables **********************************/ -/* -** All global variables used by this file are containing within the following -** gQuota structure. -*/ -static struct { - /* The pOrigVfs is the real, original underlying VFS implementation. - ** Most operations pass-through to the real VFS. This value is read-only - ** during operation. It is only modified at start-time and thus does not - ** require a mutex. - */ - sqlite3_vfs *pOrigVfs; - - /* The sThisVfs is the VFS structure used by this shim. It is initialized - ** at start-time and thus does not require a mutex - */ - sqlite3_vfs sThisVfs; - - /* The sIoMethods defines the methods used by sqlite3_file objects - ** associated with this shim. It is initialized at start-time and does - ** not require a mutex. - ** - ** When the underlying VFS is called to open a file, it might return - ** either a version 1 or a version 2 sqlite3_file object. This shim - ** has to create a wrapper sqlite3_file of the same version. Hence - ** there are two I/O method structures, one for version 1 and the other - ** for version 2. - */ - sqlite3_io_methods sIoMethodsV1; - sqlite3_io_methods sIoMethodsV2; - - /* True when this shim as been initialized. - */ - int isInitialized; - - /* For run-time access any of the other global data structures in this - ** shim, the following mutex must be held. - */ - sqlite3_mutex *pMutex; - - /* List of quotaGroup objects. - */ - quotaGroup *pGroup; - -} gQuota; - -/************************* Utility Routines *********************************/ -/* -** Acquire and release the mutex used to serialize access to the -** list of quotaGroups. -*/ -static void quotaEnter(void){ sqlite3_mutex_enter(gQuota.pMutex); } -static void quotaLeave(void){ sqlite3_mutex_leave(gQuota.pMutex); } - -/* Count the number of open files in a quotaGroup -*/ -static int quotaGroupOpenFileCount(quotaGroup *pGroup){ - int N = 0; - quotaFile *pFile = pGroup->pFiles; - while( pFile ){ - if( pFile->nRef ) N++; - pFile = pFile->pNext; - } - return N; -} - -/* Remove a file from a quota group. -*/ -static void quotaRemoveFile(quotaFile *pFile){ - quotaGroup *pGroup = pFile->pGroup; - pGroup->iSize -= pFile->iSize; - *pFile->ppPrev = pFile->pNext; - if( pFile->pNext ) pFile->pNext->ppPrev = pFile->ppPrev; - sqlite3_free(pFile); -} - -/* Remove all files from a quota group. It is always the case that -** all files will be closed when this routine is called. -*/ -static void quotaRemoveAllFiles(quotaGroup *pGroup){ - while( pGroup->pFiles ){ - assert( pGroup->pFiles->nRef==0 ); - quotaRemoveFile(pGroup->pFiles); - } -} - - -/* If the reference count and threshold for a quotaGroup are both -** zero, then destroy the quotaGroup. -*/ -static void quotaGroupDeref(quotaGroup *pGroup){ - if( pGroup->iLimit==0 && quotaGroupOpenFileCount(pGroup)==0 ){ - quotaRemoveAllFiles(pGroup); - *pGroup->ppPrev = pGroup->pNext; - if( pGroup->pNext ) pGroup->pNext->ppPrev = pGroup->ppPrev; - if( pGroup->xDestroy ) pGroup->xDestroy(pGroup->pArg); - sqlite3_free(pGroup); - } -} - -/* -** Return TRUE if string z matches glob pattern zGlob. -** -** Globbing rules: -** -** '*' Matches any sequence of zero or more characters. -** -** '?' Matches exactly one character. -** -** [...] Matches one character from the enclosed list of -** characters. -** -** [^...] Matches one character not in the enclosed list. -** -** / Matches "/" or "\\" -** -*/ -static int quotaStrglob(const char *zGlob, const char *z){ - int c, c2, cx; - int invert; - int seen; - - while( (c = (*(zGlob++)))!=0 ){ - if( c=='*' ){ - while( (c=(*(zGlob++))) == '*' || c=='?' ){ - if( c=='?' && (*(z++))==0 ) return 0; - } - if( c==0 ){ - return 1; - }else if( c=='[' ){ - while( *z && quotaStrglob(zGlob-1,z)==0 ){ - z++; - } - return (*z)!=0; - } - cx = (c=='/') ? '\\' : c; - while( (c2 = (*(z++)))!=0 ){ - while( c2!=c && c2!=cx ){ - c2 = *(z++); - if( c2==0 ) return 0; - } - if( quotaStrglob(zGlob,z) ) return 1; - } - return 0; - }else if( c=='?' ){ - if( (*(z++))==0 ) return 0; - }else if( c=='[' ){ - int prior_c = 0; - seen = 0; - invert = 0; - c = *(z++); - if( c==0 ) return 0; - c2 = *(zGlob++); - if( c2=='^' ){ - invert = 1; - c2 = *(zGlob++); - } - if( c2==']' ){ - if( c==']' ) seen = 1; - c2 = *(zGlob++); - } - while( c2 && c2!=']' ){ - if( c2=='-' && zGlob[0]!=']' && zGlob[0]!=0 && prior_c>0 ){ - c2 = *(zGlob++); - if( c>=prior_c && c<=c2 ) seen = 1; - prior_c = 0; - }else{ - if( c==c2 ){ - seen = 1; - } - prior_c = c2; - } - c2 = *(zGlob++); - } - if( c2==0 || (seen ^ invert)==0 ) return 0; - }else if( c=='/' ){ - if( z[0]!='/' && z[0]!='\\' ) return 0; - z++; - }else{ - if( c!=(*(z++)) ) return 0; - } - } - return *z==0; -} - - -/* Find a quotaGroup given the filename. -** -** Return a pointer to the quotaGroup object. Return NULL if not found. -*/ -static quotaGroup *quotaGroupFind(const char *zFilename){ - quotaGroup *p; - for(p=gQuota.pGroup; p && quotaStrglob(p->zPattern, zFilename)==0; - p=p->pNext){} - return p; -} - -/* Translate an sqlite3_file* that is really a quotaConn* into -** the sqlite3_file* for the underlying original VFS. -*/ -static sqlite3_file *quotaSubOpen(sqlite3_file *pConn){ - quotaConn *p = (quotaConn*)pConn; - return (sqlite3_file*)&p[1]; -} - -/* Find a file in a quota group and return a pointer to that file. -** Return NULL if the file is not in the group. -*/ -static quotaFile *quotaFindFile( - quotaGroup *pGroup, /* Group in which to look for the file */ - const char *zName, /* Full pathname of the file */ - int createFlag /* Try to create the file if not found */ -){ - quotaFile *pFile = pGroup->pFiles; - while( pFile && strcmp(pFile->zFilename, zName)!=0 ){ - pFile = pFile->pNext; - } - if( pFile==0 && createFlag ){ - int nName = (int)(strlen(zName) & 0x3fffffff); - pFile = (quotaFile *)sqlite3_malloc( sizeof(*pFile) + nName + 1 ); - if( pFile ){ - memset(pFile, 0, sizeof(*pFile)); - pFile->zFilename = (char*)&pFile[1]; - memcpy(pFile->zFilename, zName, nName+1); - pFile->pNext = pGroup->pFiles; - if( pGroup->pFiles ) pGroup->pFiles->ppPrev = &pFile->pNext; - pFile->ppPrev = &pGroup->pFiles; - pGroup->pFiles = pFile; - pFile->pGroup = pGroup; - } - } - return pFile; -} -/* -** Translate UTF8 to MBCS for use in fopen() calls. Return a pointer to the -** translated text.. Call quota_mbcs_free() to deallocate any memory -** used to store the returned pointer when done. -*/ -static char *quota_utf8_to_mbcs(const char *zUtf8){ -#if SQLITE_OS_WIN - size_t n; /* Bytes in zUtf8 */ - int nWide; /* number of UTF-16 characters */ - int nMbcs; /* Bytes of MBCS */ - LPWSTR zTmpWide; /* The UTF16 text */ - char *zMbcs; /* The MBCS text */ - int codepage; /* Code page used by fopen() */ - - n = strlen(zUtf8); - nWide = MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, NULL, 0); - if( nWide==0 ) return 0; - zTmpWide = (LPWSTR)sqlite3_malloc( (nWide+1)*sizeof(zTmpWide[0]) ); - if( zTmpWide==0 ) return 0; - MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, zTmpWide, nWide); - codepage = AreFileApisANSI() ? CP_ACP : CP_OEMCP; - nMbcs = WideCharToMultiByte(codepage, 0, zTmpWide, nWide, 0, 0, 0, 0); - zMbcs = nMbcs ? (char*)sqlite3_malloc( nMbcs+1 ) : 0; - if( zMbcs ){ - WideCharToMultiByte(codepage, 0, zTmpWide, nWide, zMbcs, nMbcs, 0, 0); - } - sqlite3_free(zTmpWide); - return zMbcs; -#else - return (char*)zUtf8; /* No-op on unix */ -#endif -} - -/* -** Deallocate any memory allocated by quota_utf8_to_mbcs(). -*/ -static void quota_mbcs_free(char *zOld){ -#if SQLITE_OS_WIN - sqlite3_free(zOld); -#else - /* No-op on unix */ -#endif -} - -/************************* VFS Method Wrappers *****************************/ -/* -** This is the xOpen method used for the "quota" VFS. -** -** Most of the work is done by the underlying original VFS. This method -** simply links the new file into the appropriate quota group if it is a -** file that needs to be tracked. -*/ -static int quotaOpen( - sqlite3_vfs *pVfs, /* The quota VFS */ - const char *zName, /* Name of file to be opened */ - sqlite3_file *pConn, /* Fill in this file descriptor */ - int flags, /* Flags to control the opening */ - int *pOutFlags /* Flags showing results of opening */ -){ - int rc; /* Result code */ - quotaConn *pQuotaOpen; /* The new quota file descriptor */ - quotaFile *pFile; /* Corresponding quotaFile obj */ - quotaGroup *pGroup; /* The group file belongs to */ - sqlite3_file *pSubOpen; /* Real file descriptor */ - sqlite3_vfs *pOrigVfs = gQuota.pOrigVfs; /* Real VFS */ - - /* If the file is not a main database file or a WAL, then use the - ** normal xOpen method. - */ - if( (flags & (SQLITE_OPEN_MAIN_DB|SQLITE_OPEN_WAL))==0 ){ - return pOrigVfs->xOpen(pOrigVfs, zName, pConn, flags, pOutFlags); - } - - /* If the name of the file does not match any quota group, then - ** use the normal xOpen method. - */ - quotaEnter(); - pGroup = quotaGroupFind(zName); - if( pGroup==0 ){ - rc = pOrigVfs->xOpen(pOrigVfs, zName, pConn, flags, pOutFlags); - }else{ - /* If we get to this point, it means the file needs to be quota tracked. - */ - pQuotaOpen = (quotaConn*)pConn; - pSubOpen = quotaSubOpen(pConn); - rc = pOrigVfs->xOpen(pOrigVfs, zName, pSubOpen, flags, pOutFlags); - if( rc==SQLITE_OK ){ - pFile = quotaFindFile(pGroup, zName, 1); - if( pFile==0 ){ - quotaLeave(); - pSubOpen->pMethods->xClose(pSubOpen); - return SQLITE_NOMEM; - } - pFile->deleteOnClose = (flags & SQLITE_OPEN_DELETEONCLOSE)!=0; - pFile->nRef++; - pQuotaOpen->pFile = pFile; - if( pSubOpen->pMethods->iVersion==1 ){ - pQuotaOpen->base.pMethods = &gQuota.sIoMethodsV1; - }else{ - pQuotaOpen->base.pMethods = &gQuota.sIoMethodsV2; - } - } - } - quotaLeave(); - return rc; -} - -/* -** This is the xDelete method used for the "quota" VFS. -** -** If the file being deleted is part of the quota group, then reduce -** the size of the quota group accordingly. And remove the file from -** the set of files in the quota group. -*/ -static int quotaDelete( - sqlite3_vfs *pVfs, /* The quota VFS */ - const char *zName, /* Name of file to be deleted */ - int syncDir /* Do a directory sync after deleting */ -){ - int rc; /* Result code */ - quotaFile *pFile; /* Files in the quota */ - quotaGroup *pGroup; /* The group file belongs to */ - sqlite3_vfs *pOrigVfs = gQuota.pOrigVfs; /* Real VFS */ - - /* Do the actual file delete */ - rc = pOrigVfs->xDelete(pOrigVfs, zName, syncDir); - - /* If the file just deleted is a member of a quota group, then remove - ** it from that quota group. - */ - if( rc==SQLITE_OK ){ - quotaEnter(); - pGroup = quotaGroupFind(zName); - if( pGroup ){ - pFile = quotaFindFile(pGroup, zName, 0); - if( pFile ){ - if( pFile->nRef ){ - pFile->deleteOnClose = 1; - }else{ - quotaRemoveFile(pFile); - quotaGroupDeref(pGroup); - } - } - } - quotaLeave(); - } - return rc; -} - - -/************************ I/O Method Wrappers *******************************/ - -/* xClose requests get passed through to the original VFS. But we -** also have to unlink the quotaConn from the quotaFile and quotaGroup. -** The quotaFile and/or quotaGroup are freed if they are no longer in use. -*/ -static int quotaClose(sqlite3_file *pConn){ - quotaConn *p = (quotaConn*)pConn; - quotaFile *pFile = p->pFile; - sqlite3_file *pSubOpen = quotaSubOpen(pConn); - int rc; - rc = pSubOpen->pMethods->xClose(pSubOpen); - quotaEnter(); - pFile->nRef--; - if( pFile->nRef==0 ){ - quotaGroup *pGroup = pFile->pGroup; - if( pFile->deleteOnClose ){ - gQuota.pOrigVfs->xDelete(gQuota.pOrigVfs, pFile->zFilename, 0); - quotaRemoveFile(pFile); - } - quotaGroupDeref(pGroup); - } - quotaLeave(); - return rc; -} - -/* Pass xRead requests directory thru to the original VFS without -** further processing. -*/ -static int quotaRead( - sqlite3_file *pConn, - void *pBuf, - int iAmt, - sqlite3_int64 iOfst -){ - sqlite3_file *pSubOpen = quotaSubOpen(pConn); - return pSubOpen->pMethods->xRead(pSubOpen, pBuf, iAmt, iOfst); -} - -/* Check xWrite requests to see if they expand the file. If they do, -** the perform a quota check before passing them through to the -** original VFS. -*/ -static int quotaWrite( - sqlite3_file *pConn, - const void *pBuf, - int iAmt, - sqlite3_int64 iOfst -){ - quotaConn *p = (quotaConn*)pConn; - sqlite3_file *pSubOpen = quotaSubOpen(pConn); - sqlite3_int64 iEnd = iOfst+iAmt; - quotaGroup *pGroup; - quotaFile *pFile = p->pFile; - sqlite3_int64 szNew; - - if( pFile->iSize<iEnd ){ - pGroup = pFile->pGroup; - quotaEnter(); - szNew = pGroup->iSize - pFile->iSize + iEnd; - if( szNew>pGroup->iLimit && pGroup->iLimit>0 ){ - if( pGroup->xCallback ){ - pGroup->xCallback(pFile->zFilename, &pGroup->iLimit, szNew, - pGroup->pArg); - } - if( szNew>pGroup->iLimit && pGroup->iLimit>0 ){ - quotaLeave(); - return SQLITE_FULL; - } - } - pGroup->iSize = szNew; - pFile->iSize = iEnd; - quotaLeave(); - } - return pSubOpen->pMethods->xWrite(pSubOpen, pBuf, iAmt, iOfst); -} - -/* Pass xTruncate requests thru to the original VFS. If the -** success, update the file size. -*/ -static int quotaTruncate(sqlite3_file *pConn, sqlite3_int64 size){ - quotaConn *p = (quotaConn*)pConn; - sqlite3_file *pSubOpen = quotaSubOpen(pConn); - int rc = pSubOpen->pMethods->xTruncate(pSubOpen, size); - quotaFile *pFile = p->pFile; - quotaGroup *pGroup; - if( rc==SQLITE_OK ){ - quotaEnter(); - pGroup = pFile->pGroup; - pGroup->iSize -= pFile->iSize; - pFile->iSize = size; - pGroup->iSize += size; - quotaLeave(); - } - return rc; -} - -/* Pass xSync requests through to the original VFS without change -*/ -static int quotaSync(sqlite3_file *pConn, int flags){ - sqlite3_file *pSubOpen = quotaSubOpen(pConn); - return pSubOpen->pMethods->xSync(pSubOpen, flags); -} - -/* Pass xFileSize requests through to the original VFS but then -** update the quotaGroup with the new size before returning. -*/ -static int quotaFileSize(sqlite3_file *pConn, sqlite3_int64 *pSize){ - quotaConn *p = (quotaConn*)pConn; - sqlite3_file *pSubOpen = quotaSubOpen(pConn); - quotaFile *pFile = p->pFile; - quotaGroup *pGroup; - sqlite3_int64 sz; - int rc; - - rc = pSubOpen->pMethods->xFileSize(pSubOpen, &sz); - if( rc==SQLITE_OK ){ - quotaEnter(); - pGroup = pFile->pGroup; - pGroup->iSize -= pFile->iSize; - pFile->iSize = sz; - pGroup->iSize += sz; - quotaLeave(); - *pSize = sz; - } - return rc; -} - -/* Pass xLock requests through to the original VFS unchanged. -*/ -static int quotaLock(sqlite3_file *pConn, int lock){ - sqlite3_file *pSubOpen = quotaSubOpen(pConn); - return pSubOpen->pMethods->xLock(pSubOpen, lock); -} - -/* Pass xUnlock requests through to the original VFS unchanged. -*/ -static int quotaUnlock(sqlite3_file *pConn, int lock){ - sqlite3_file *pSubOpen = quotaSubOpen(pConn); - return pSubOpen->pMethods->xUnlock(pSubOpen, lock); -} - -/* Pass xCheckReservedLock requests through to the original VFS unchanged. -*/ -static int quotaCheckReservedLock(sqlite3_file *pConn, int *pResOut){ - sqlite3_file *pSubOpen = quotaSubOpen(pConn); - return pSubOpen->pMethods->xCheckReservedLock(pSubOpen, pResOut); -} - -/* Pass xFileControl requests through to the original VFS unchanged. -*/ -static int quotaFileControl(sqlite3_file *pConn, int op, void *pArg){ - sqlite3_file *pSubOpen = quotaSubOpen(pConn); - int rc = pSubOpen->pMethods->xFileControl(pSubOpen, op, pArg); -#if defined(SQLITE_FCNTL_VFSNAME) - if( op==SQLITE_FCNTL_VFSNAME && rc==SQLITE_OK ){ - *(char**)pArg = sqlite3_mprintf("quota/%z", *(char**)pArg); - } -#endif - return rc; -} - -/* Pass xSectorSize requests through to the original VFS unchanged. -*/ -static int quotaSectorSize(sqlite3_file *pConn){ - sqlite3_file *pSubOpen = quotaSubOpen(pConn); - return pSubOpen->pMethods->xSectorSize(pSubOpen); -} - -/* Pass xDeviceCharacteristics requests through to the original VFS unchanged. -*/ -static int quotaDeviceCharacteristics(sqlite3_file *pConn){ - sqlite3_file *pSubOpen = quotaSubOpen(pConn); - return pSubOpen->pMethods->xDeviceCharacteristics(pSubOpen); -} - -/* Pass xShmMap requests through to the original VFS unchanged. -*/ -static int quotaShmMap( - sqlite3_file *pConn, /* Handle open on database file */ - int iRegion, /* Region to retrieve */ - int szRegion, /* Size of regions */ - int bExtend, /* True to extend file if necessary */ - void volatile **pp /* OUT: Mapped memory */ -){ - sqlite3_file *pSubOpen = quotaSubOpen(pConn); - return pSubOpen->pMethods->xShmMap(pSubOpen, iRegion, szRegion, bExtend, pp); -} - -/* Pass xShmLock requests through to the original VFS unchanged. -*/ -static int quotaShmLock( - sqlite3_file *pConn, /* Database file holding the shared memory */ - int ofst, /* First lock to acquire or release */ - int n, /* Number of locks to acquire or release */ - int flags /* What to do with the lock */ -){ - sqlite3_file *pSubOpen = quotaSubOpen(pConn); - return pSubOpen->pMethods->xShmLock(pSubOpen, ofst, n, flags); -} - -/* Pass xShmBarrier requests through to the original VFS unchanged. -*/ -static void quotaShmBarrier(sqlite3_file *pConn){ - sqlite3_file *pSubOpen = quotaSubOpen(pConn); - pSubOpen->pMethods->xShmBarrier(pSubOpen); -} - -/* Pass xShmUnmap requests through to the original VFS unchanged. -*/ -static int quotaShmUnmap(sqlite3_file *pConn, int deleteFlag){ - sqlite3_file *pSubOpen = quotaSubOpen(pConn); - return pSubOpen->pMethods->xShmUnmap(pSubOpen, deleteFlag); -} - -/************************** Public Interfaces *****************************/ -/* -** Initialize the quota VFS shim. Use the VFS named zOrigVfsName -** as the VFS that does the actual work. Use the default if -** zOrigVfsName==NULL. -** -** The quota VFS shim is named "quota". It will become the default -** VFS if makeDefault is non-zero. -** -** THIS ROUTINE IS NOT THREADSAFE. Call this routine exactly once -** during start-up. -*/ -int sqlite3_quota_initialize(const char *zOrigVfsName, int makeDefault){ - sqlite3_vfs *pOrigVfs; - if( gQuota.isInitialized ) return SQLITE_MISUSE; - pOrigVfs = sqlite3_vfs_find(zOrigVfsName); - if( pOrigVfs==0 ) return SQLITE_ERROR; - assert( pOrigVfs!=&gQuota.sThisVfs ); - gQuota.pMutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST); - if( !gQuota.pMutex ){ - return SQLITE_NOMEM; - } - gQuota.isInitialized = 1; - gQuota.pOrigVfs = pOrigVfs; - gQuota.sThisVfs = *pOrigVfs; - gQuota.sThisVfs.xOpen = quotaOpen; - gQuota.sThisVfs.xDelete = quotaDelete; - gQuota.sThisVfs.szOsFile += sizeof(quotaConn); - gQuota.sThisVfs.zName = "quota"; - gQuota.sIoMethodsV1.iVersion = 1; - gQuota.sIoMethodsV1.xClose = quotaClose; - gQuota.sIoMethodsV1.xRead = quotaRead; - gQuota.sIoMethodsV1.xWrite = quotaWrite; - gQuota.sIoMethodsV1.xTruncate = quotaTruncate; - gQuota.sIoMethodsV1.xSync = quotaSync; - gQuota.sIoMethodsV1.xFileSize = quotaFileSize; - gQuota.sIoMethodsV1.xLock = quotaLock; - gQuota.sIoMethodsV1.xUnlock = quotaUnlock; - gQuota.sIoMethodsV1.xCheckReservedLock = quotaCheckReservedLock; - gQuota.sIoMethodsV1.xFileControl = quotaFileControl; - gQuota.sIoMethodsV1.xSectorSize = quotaSectorSize; - gQuota.sIoMethodsV1.xDeviceCharacteristics = quotaDeviceCharacteristics; - gQuota.sIoMethodsV2 = gQuota.sIoMethodsV1; - gQuota.sIoMethodsV2.iVersion = 2; - gQuota.sIoMethodsV2.xShmMap = quotaShmMap; - gQuota.sIoMethodsV2.xShmLock = quotaShmLock; - gQuota.sIoMethodsV2.xShmBarrier = quotaShmBarrier; - gQuota.sIoMethodsV2.xShmUnmap = quotaShmUnmap; - sqlite3_vfs_register(&gQuota.sThisVfs, makeDefault); - return SQLITE_OK; -} - -/* -** Shutdown the quota system. -** -** All SQLite database connections must be closed before calling this -** routine. -** -** THIS ROUTINE IS NOT THREADSAFE. Call this routine exactly once while -** shutting down in order to free all remaining quota groups. -*/ -int sqlite3_quota_shutdown(void){ - quotaGroup *pGroup; - if( gQuota.isInitialized==0 ) return SQLITE_MISUSE; - for(pGroup=gQuota.pGroup; pGroup; pGroup=pGroup->pNext){ - if( quotaGroupOpenFileCount(pGroup)>0 ) return SQLITE_MISUSE; - } - while( gQuota.pGroup ){ - pGroup = gQuota.pGroup; - gQuota.pGroup = pGroup->pNext; - pGroup->iLimit = 0; - assert( quotaGroupOpenFileCount(pGroup)==0 ); - quotaGroupDeref(pGroup); - } - gQuota.isInitialized = 0; - sqlite3_mutex_free(gQuota.pMutex); - sqlite3_vfs_unregister(&gQuota.sThisVfs); - memset(&gQuota, 0, sizeof(gQuota)); - return SQLITE_OK; -} - -/* -** Create or destroy a quota group. -** -** The quota group is defined by the zPattern. When calling this routine -** with a zPattern for a quota group that already exists, this routine -** merely updates the iLimit, xCallback, and pArg values for that quota -** group. If zPattern is new, then a new quota group is created. -** -** If the iLimit for a quota group is set to zero, then the quota group -** is disabled and will be deleted when the last database connection using -** the quota group is closed. -** -** Calling this routine on a zPattern that does not exist and with a -** zero iLimit is a no-op. -** -** A quota group must exist with a non-zero iLimit prior to opening -** database connections if those connections are to participate in the -** quota group. Creating a quota group does not affect database connections -** that are already open. -*/ -int sqlite3_quota_set( - const char *zPattern, /* The filename pattern */ - sqlite3_int64 iLimit, /* New quota to set for this quota group */ - void (*xCallback)( /* Callback invoked when going over quota */ - const char *zFilename, /* Name of file whose size increases */ - sqlite3_int64 *piLimit, /* IN/OUT: The current limit */ - sqlite3_int64 iSize, /* Total size of all files in the group */ - void *pArg /* Client data */ - ), - void *pArg, /* client data passed thru to callback */ - void (*xDestroy)(void*) /* Optional destructor for pArg */ -){ - quotaGroup *pGroup; - quotaEnter(); - pGroup = gQuota.pGroup; - while( pGroup && strcmp(pGroup->zPattern, zPattern)!=0 ){ - pGroup = pGroup->pNext; - } - if( pGroup==0 ){ - int nPattern = (int)(strlen(zPattern) & 0x3fffffff); - if( iLimit<=0 ){ - quotaLeave(); - return SQLITE_OK; - } - pGroup = (quotaGroup *)sqlite3_malloc( sizeof(*pGroup) + nPattern + 1 ); - if( pGroup==0 ){ - quotaLeave(); - return SQLITE_NOMEM; - } - memset(pGroup, 0, sizeof(*pGroup)); - pGroup->zPattern = (char*)&pGroup[1]; - memcpy((char *)pGroup->zPattern, zPattern, nPattern+1); - if( gQuota.pGroup ) gQuota.pGroup->ppPrev = &pGroup->pNext; - pGroup->pNext = gQuota.pGroup; - pGroup->ppPrev = &gQuota.pGroup; - gQuota.pGroup = pGroup; - } - pGroup->iLimit = iLimit; - pGroup->xCallback = xCallback; - if( pGroup->xDestroy && pGroup->pArg!=pArg ){ - pGroup->xDestroy(pGroup->pArg); - } - pGroup->pArg = pArg; - pGroup->xDestroy = xDestroy; - quotaGroupDeref(pGroup); - quotaLeave(); - return SQLITE_OK; -} - -/* -** Bring the named file under quota management. Or if it is already under -** management, update its size. -*/ -int sqlite3_quota_file(const char *zFilename){ - char *zFull; - sqlite3_file *fd; - int rc; - int outFlags = 0; - sqlite3_int64 iSize; - int nAlloc = gQuota.sThisVfs.szOsFile + gQuota.sThisVfs.mxPathname+2; - - /* Allocate space for a file-handle and the full path for file zFilename */ - fd = (sqlite3_file *)sqlite3_malloc(nAlloc); - if( fd==0 ){ - rc = SQLITE_NOMEM; - }else{ - zFull = &((char *)fd)[gQuota.sThisVfs.szOsFile]; - rc = gQuota.pOrigVfs->xFullPathname(gQuota.pOrigVfs, zFilename, - gQuota.sThisVfs.mxPathname+1, zFull); - } - - if( rc==SQLITE_OK ){ - zFull[strlen(zFull)+1] = '\0'; - rc = quotaOpen(&gQuota.sThisVfs, zFull, fd, - SQLITE_OPEN_READONLY | SQLITE_OPEN_MAIN_DB, &outFlags); - if( rc==SQLITE_OK ){ - fd->pMethods->xFileSize(fd, &iSize); - fd->pMethods->xClose(fd); - }else if( rc==SQLITE_CANTOPEN ){ - quotaGroup *pGroup; - quotaFile *pFile; - quotaEnter(); - pGroup = quotaGroupFind(zFull); - if( pGroup ){ - pFile = quotaFindFile(pGroup, zFull, 0); - if( pFile ) quotaRemoveFile(pFile); - } - quotaLeave(); - } - } - - sqlite3_free(fd); - return rc; -} - -/* -** Open a potentially quotaed file for I/O. -*/ -quota_FILE *sqlite3_quota_fopen(const char *zFilename, const char *zMode){ - quota_FILE *p = 0; - char *zFull = 0; - char *zFullTranslated = 0; - int rc; - quotaGroup *pGroup; - quotaFile *pFile; - - zFull = (char*)sqlite3_malloc(gQuota.sThisVfs.mxPathname + 1); - if( zFull==0 ) return 0; - rc = gQuota.pOrigVfs->xFullPathname(gQuota.pOrigVfs, zFilename, - gQuota.sThisVfs.mxPathname+1, zFull); - if( rc ) goto quota_fopen_error; - p = (quota_FILE*)sqlite3_malloc(sizeof(*p)); - if( p==0 ) goto quota_fopen_error; - memset(p, 0, sizeof(*p)); - zFullTranslated = quota_utf8_to_mbcs(zFull); - if( zFullTranslated==0 ) goto quota_fopen_error; - p->f = fopen(zFullTranslated, zMode); - if( p->f==0 ) goto quota_fopen_error; - quotaEnter(); - pGroup = quotaGroupFind(zFull); - if( pGroup ){ - pFile = quotaFindFile(pGroup, zFull, 1); - if( pFile==0 ){ - quotaLeave(); - goto quota_fopen_error; - } - pFile->nRef++; - p->pFile = pFile; - } - quotaLeave(); - sqlite3_free(zFull); -#if SQLITE_OS_WIN - p->zMbcsName = zFullTranslated; -#endif - return p; - -quota_fopen_error: - quota_mbcs_free(zFullTranslated); - sqlite3_free(zFull); - if( p && p->f ) fclose(p->f); - sqlite3_free(p); - return 0; -} - -/* -** Read content from a quota_FILE -*/ -size_t sqlite3_quota_fread( - void *pBuf, /* Store the content here */ - size_t size, /* Size of each element */ - size_t nmemb, /* Number of elements to read */ - quota_FILE *p /* Read from this quota_FILE object */ -){ - return fread(pBuf, size, nmemb, p->f); -} - -/* -** Write content into a quota_FILE. Invoke the quota callback and block -** the write if we exceed quota. -*/ -size_t sqlite3_quota_fwrite( - const void *pBuf, /* Take content to write from here */ - size_t size, /* Size of each element */ - size_t nmemb, /* Number of elements */ - quota_FILE *p /* Write to this quota_FILE objecct */ -){ - sqlite3_int64 iOfst; - sqlite3_int64 iEnd; - sqlite3_int64 szNew; - quotaFile *pFile; - size_t rc; - - iOfst = ftell(p->f); - iEnd = iOfst + size*nmemb; - pFile = p->pFile; - if( pFile && pFile->iSize<iEnd ){ - quotaGroup *pGroup = pFile->pGroup; - quotaEnter(); - szNew = pGroup->iSize - pFile->iSize + iEnd; - if( szNew>pGroup->iLimit && pGroup->iLimit>0 ){ - if( pGroup->xCallback ){ - pGroup->xCallback(pFile->zFilename, &pGroup->iLimit, szNew, - pGroup->pArg); - } - if( szNew>pGroup->iLimit && pGroup->iLimit>0 ){ - iEnd = pGroup->iLimit - pGroup->iSize + pFile->iSize; - nmemb = (size_t)((iEnd - iOfst)/size); - iEnd = iOfst + size*nmemb; - szNew = pGroup->iSize - pFile->iSize + iEnd; - } - } - pGroup->iSize = szNew; - pFile->iSize = iEnd; - quotaLeave(); - }else{ - pFile = 0; - } - rc = fwrite(pBuf, size, nmemb, p->f); - - /* If the write was incomplete, adjust the file size and group size - ** downward */ - if( rc<nmemb && pFile ){ - size_t nWritten = rc; - sqlite3_int64 iNewEnd = iOfst + size*nWritten; - if( iNewEnd<iEnd ) iNewEnd = iEnd; - quotaEnter(); - pFile->pGroup->iSize += iNewEnd - pFile->iSize; - pFile->iSize = iNewEnd; - quotaLeave(); - } - return rc; -} - -/* -** Close an open quota_FILE stream. -*/ -int sqlite3_quota_fclose(quota_FILE *p){ - int rc; - quotaFile *pFile; - rc = fclose(p->f); - pFile = p->pFile; - if( pFile ){ - quotaEnter(); - pFile->nRef--; - if( pFile->nRef==0 ){ - quotaGroup *pGroup = pFile->pGroup; - if( pFile->deleteOnClose ){ - gQuota.pOrigVfs->xDelete(gQuota.pOrigVfs, pFile->zFilename, 0); - quotaRemoveFile(pFile); - } - quotaGroupDeref(pGroup); - } - quotaLeave(); - } -#if SQLITE_OS_WIN - quota_mbcs_free(p->zMbcsName); -#endif - sqlite3_free(p); - return rc; -} - -/* -** Flush memory buffers for a quota_FILE to disk. -*/ -int sqlite3_quota_fflush(quota_FILE *p, int doFsync){ - int rc; - rc = fflush(p->f); - if( rc==0 && doFsync ){ -#if SQLITE_OS_UNIX - rc = fsync(fileno(p->f)); -#endif -#if SQLITE_OS_WIN - rc = _commit(_fileno(p->f)); -#endif - } - return rc!=0; -} - -/* -** Seek on a quota_FILE stream. -*/ -int sqlite3_quota_fseek(quota_FILE *p, long offset, int whence){ - return fseek(p->f, offset, whence); -} - -/* -** rewind a quota_FILE stream. -*/ -void sqlite3_quota_rewind(quota_FILE *p){ - rewind(p->f); -} - -/* -** Tell the current location of a quota_FILE stream. -*/ -long sqlite3_quota_ftell(quota_FILE *p){ - return ftell(p->f); -} - -/* -** Test the error indicator for the given file. -*/ -int sqlite3_quota_ferror(quota_FILE *p){ - return ferror(p->f); -} - -/* -** Truncate a file to szNew bytes. -*/ -int sqlite3_quota_ftruncate(quota_FILE *p, sqlite3_int64 szNew){ - quotaFile *pFile = p->pFile; - int rc; - if( (pFile = p->pFile)!=0 && pFile->iSize<szNew ){ - quotaGroup *pGroup; - if( pFile->iSize<szNew ){ - /* This routine cannot be used to extend a file that is under - ** quota management. Only true truncation is allowed. */ - return -1; - } - pGroup = pFile->pGroup; - quotaEnter(); - pGroup->iSize += szNew - pFile->iSize; - quotaLeave(); - } -#if SQLITE_OS_UNIX - rc = ftruncate(fileno(p->f), szNew); -#endif -#if SQLITE_OS_WIN -# if defined(__MINGW32__) && defined(SQLITE_TEST) - /* _chsize_s() is missing from MingW (as of 2012-11-06). Use - ** _chsize() as a work-around for testing purposes. */ - rc = _chsize(_fileno(p->f), (long)szNew); -# else - rc = _chsize_s(_fileno(p->f), szNew); -# endif -#endif - if( pFile && rc==0 ){ - quotaGroup *pGroup = pFile->pGroup; - quotaEnter(); - pGroup->iSize += szNew - pFile->iSize; - pFile->iSize = szNew; - quotaLeave(); - } - return rc; -} - -/* -** Determine the time that the given file was last modified, in -** seconds size 1970. Write the result into *pTime. Return 0 on -** success and non-zero on any kind of error. -*/ -int sqlite3_quota_file_mtime(quota_FILE *p, time_t *pTime){ - int rc; -#if SQLITE_OS_UNIX - struct stat buf; - rc = fstat(fileno(p->f), &buf); -#endif -#if SQLITE_OS_WIN - struct _stati64 buf; - rc = _stati64(p->zMbcsName, &buf); -#endif - if( rc==0 ) *pTime = buf.st_mtime; - return rc; -} - -/* -** Return the true size of the file, as reported by the operating -** system. -*/ -sqlite3_int64 sqlite3_quota_file_truesize(quota_FILE *p){ - int rc; -#if SQLITE_OS_UNIX - struct stat buf; - rc = fstat(fileno(p->f), &buf); -#endif -#if SQLITE_OS_WIN - struct _stati64 buf; - rc = _stati64(p->zMbcsName, &buf); -#endif - return rc==0 ? buf.st_size : -1; -} - -/* -** Return the size of the file, as it is known to the quota subsystem. -*/ -sqlite3_int64 sqlite3_quota_file_size(quota_FILE *p){ - return p->pFile ? p->pFile->iSize : -1; -} - -/* -** Determine the amount of data in bytes available for reading -** in the given file. -*/ -long sqlite3_quota_file_available(quota_FILE *p){ - FILE* f = p->f; - long pos1, pos2; - int rc; - pos1 = ftell(f); - if ( pos1 < 0 ) return -1; - rc = fseek(f, 0, SEEK_END); - if ( rc != 0 ) return -1; - pos2 = ftell(f); - if ( pos2 < 0 ) return -1; - rc = fseek(f, pos1, SEEK_SET); - if ( rc != 0 ) return -1; - return pos2 - pos1; -} - -/* -** Remove a managed file. Update quotas accordingly. -*/ -int sqlite3_quota_remove(const char *zFilename){ - char *zFull; /* Full pathname for zFilename */ - size_t nFull; /* Number of bytes in zFilename */ - int rc; /* Result code */ - quotaGroup *pGroup; /* Group containing zFilename */ - quotaFile *pFile; /* A file in the group */ - quotaFile *pNextFile; /* next file in the group */ - int diff; /* Difference between filenames */ - char c; /* First character past end of pattern */ - - zFull = (char*)sqlite3_malloc(gQuota.sThisVfs.mxPathname + 1); - if( zFull==0 ) return SQLITE_NOMEM; - rc = gQuota.pOrigVfs->xFullPathname(gQuota.pOrigVfs, zFilename, - gQuota.sThisVfs.mxPathname+1, zFull); - if( rc ){ - sqlite3_free(zFull); - return rc; - } - - /* Figure out the length of the full pathname. If the name ends with - ** / (or \ on windows) then remove the trailing /. - */ - nFull = strlen(zFull); - if( nFull>0 && (zFull[nFull-1]=='/' || zFull[nFull-1]=='\\') ){ - nFull--; - zFull[nFull] = 0; - } - - quotaEnter(); - pGroup = quotaGroupFind(zFull); - if( pGroup ){ - for(pFile=pGroup->pFiles; pFile && rc==SQLITE_OK; pFile=pNextFile){ - pNextFile = pFile->pNext; - diff = strncmp(zFull, pFile->zFilename, nFull); - if( diff==0 && ((c = pFile->zFilename[nFull])==0 || c=='/' || c=='\\') ){ - if( pFile->nRef ){ - pFile->deleteOnClose = 1; - }else{ - rc = gQuota.pOrigVfs->xDelete(gQuota.pOrigVfs, pFile->zFilename, 0); - quotaRemoveFile(pFile); - quotaGroupDeref(pGroup); - } - } - } - } - quotaLeave(); - sqlite3_free(zFull); - return rc; -} - -/***************************** Test Code ***********************************/ -#ifdef SQLITE_TEST -#include <tcl.h> - -/* -** Argument passed to a TCL quota-over-limit callback. -*/ -typedef struct TclQuotaCallback TclQuotaCallback; -struct TclQuotaCallback { - Tcl_Interp *interp; /* Interpreter in which to run the script */ - Tcl_Obj *pScript; /* Script to be run */ -}; - -extern const char *sqlite3ErrName(int); - - -/* -** This is the callback from a quota-over-limit. -*/ -static void tclQuotaCallback( - const char *zFilename, /* Name of file whose size increases */ - sqlite3_int64 *piLimit, /* IN/OUT: The current limit */ - sqlite3_int64 iSize, /* Total size of all files in the group */ - void *pArg /* Client data */ -){ - TclQuotaCallback *p; /* Callback script object */ - Tcl_Obj *pEval; /* Script to evaluate */ - Tcl_Obj *pVarname; /* Name of variable to pass as 2nd arg */ - unsigned int rnd; /* Random part of pVarname */ - int rc; /* Tcl error code */ - - p = (TclQuotaCallback *)pArg; - if( p==0 ) return; - - pVarname = Tcl_NewStringObj("::piLimit_", -1); - Tcl_IncrRefCount(pVarname); - sqlite3_randomness(sizeof(rnd), (void *)&rnd); - Tcl_AppendObjToObj(pVarname, Tcl_NewIntObj((int)(rnd&0x7FFFFFFF))); - Tcl_ObjSetVar2(p->interp, pVarname, 0, Tcl_NewWideIntObj(*piLimit), 0); - - pEval = Tcl_DuplicateObj(p->pScript); - Tcl_IncrRefCount(pEval); - Tcl_ListObjAppendElement(0, pEval, Tcl_NewStringObj(zFilename, -1)); - Tcl_ListObjAppendElement(0, pEval, pVarname); - Tcl_ListObjAppendElement(0, pEval, Tcl_NewWideIntObj(iSize)); - rc = Tcl_EvalObjEx(p->interp, pEval, TCL_EVAL_GLOBAL); - - if( rc==TCL_OK ){ - Tcl_WideInt x; - Tcl_Obj *pLimit = Tcl_ObjGetVar2(p->interp, pVarname, 0, 0); - rc = Tcl_GetWideIntFromObj(p->interp, pLimit, &x); - *piLimit = x; - Tcl_UnsetVar(p->interp, Tcl_GetString(pVarname), 0); - } - - Tcl_DecrRefCount(pEval); - Tcl_DecrRefCount(pVarname); - if( rc!=TCL_OK ) Tcl_BackgroundError(p->interp); -} - -/* -** Destructor for a TCL quota-over-limit callback. -*/ -static void tclCallbackDestructor(void *pObj){ - TclQuotaCallback *p = (TclQuotaCallback*)pObj; - if( p ){ - Tcl_DecrRefCount(p->pScript); - sqlite3_free((char *)p); - } -} - -/* -** tclcmd: sqlite3_quota_initialize NAME MAKEDEFAULT -*/ -static int test_quota_initialize( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - const char *zName; /* Name of new quota VFS */ - int makeDefault; /* True to make the new VFS the default */ - int rc; /* Value returned by quota_initialize() */ - - /* Process arguments */ - if( objc!=3 ){ - Tcl_WrongNumArgs(interp, 1, objv, "NAME MAKEDEFAULT"); - return TCL_ERROR; - } - zName = Tcl_GetString(objv[1]); - if( Tcl_GetBooleanFromObj(interp, objv[2], &makeDefault) ) return TCL_ERROR; - if( zName[0]=='\0' ) zName = 0; - - /* Call sqlite3_quota_initialize() */ - rc = sqlite3_quota_initialize(zName, makeDefault); - Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_STATIC); - - return TCL_OK; -} - -/* -** tclcmd: sqlite3_quota_shutdown -*/ -static int test_quota_shutdown( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - int rc; /* Value returned by quota_shutdown() */ - - if( objc!=1 ){ - Tcl_WrongNumArgs(interp, 1, objv, ""); - return TCL_ERROR; - } - - /* Call sqlite3_quota_shutdown() */ - rc = sqlite3_quota_shutdown(); - Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_STATIC); - - return TCL_OK; -} - -/* -** tclcmd: sqlite3_quota_set PATTERN LIMIT SCRIPT -*/ -static int test_quota_set( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - const char *zPattern; /* File pattern to configure */ - Tcl_WideInt iLimit; /* Initial quota in bytes */ - Tcl_Obj *pScript; /* Tcl script to invoke to increase quota */ - int rc; /* Value returned by quota_set() */ - TclQuotaCallback *p; /* Callback object */ - int nScript; /* Length of callback script */ - void (*xDestroy)(void*); /* Optional destructor for pArg */ - void (*xCallback)(const char *, sqlite3_int64 *, sqlite3_int64, void *); - - /* Process arguments */ - if( objc!=4 ){ - Tcl_WrongNumArgs(interp, 1, objv, "PATTERN LIMIT SCRIPT"); - return TCL_ERROR; - } - zPattern = Tcl_GetString(objv[1]); - if( Tcl_GetWideIntFromObj(interp, objv[2], &iLimit) ) return TCL_ERROR; - pScript = objv[3]; - Tcl_GetStringFromObj(pScript, &nScript); - - if( nScript>0 ){ - /* Allocate a TclQuotaCallback object */ - p = (TclQuotaCallback *)sqlite3_malloc(sizeof(TclQuotaCallback)); - if( !p ){ - Tcl_SetResult(interp, (char *)"SQLITE_NOMEM", TCL_STATIC); - return TCL_OK; - } - memset(p, 0, sizeof(TclQuotaCallback)); - p->interp = interp; - Tcl_IncrRefCount(pScript); - p->pScript = pScript; - xDestroy = tclCallbackDestructor; - xCallback = tclQuotaCallback; - }else{ - p = 0; - xDestroy = 0; - xCallback = 0; - } - - /* Invoke sqlite3_quota_set() */ - rc = sqlite3_quota_set(zPattern, iLimit, xCallback, (void*)p, xDestroy); - - Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_STATIC); - return TCL_OK; -} - -/* -** tclcmd: sqlite3_quota_file FILENAME -*/ -static int test_quota_file( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - const char *zFilename; /* File pattern to configure */ - int rc; /* Value returned by quota_file() */ - - /* Process arguments */ - if( objc!=2 ){ - Tcl_WrongNumArgs(interp, 1, objv, "FILENAME"); - return TCL_ERROR; - } - zFilename = Tcl_GetString(objv[1]); - - /* Invoke sqlite3_quota_file() */ - rc = sqlite3_quota_file(zFilename); - - Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_STATIC); - return TCL_OK; -} - -/* -** tclcmd: sqlite3_quota_dump -*/ -static int test_quota_dump( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - Tcl_Obj *pResult; - Tcl_Obj *pGroupTerm; - Tcl_Obj *pFileTerm; - quotaGroup *pGroup; - quotaFile *pFile; - - pResult = Tcl_NewObj(); - quotaEnter(); - for(pGroup=gQuota.pGroup; pGroup; pGroup=pGroup->pNext){ - pGroupTerm = Tcl_NewObj(); - Tcl_ListObjAppendElement(interp, pGroupTerm, - Tcl_NewStringObj(pGroup->zPattern, -1)); - Tcl_ListObjAppendElement(interp, pGroupTerm, - Tcl_NewWideIntObj(pGroup->iLimit)); - Tcl_ListObjAppendElement(interp, pGroupTerm, - Tcl_NewWideIntObj(pGroup->iSize)); - for(pFile=pGroup->pFiles; pFile; pFile=pFile->pNext){ - int i; - char zTemp[1000]; - pFileTerm = Tcl_NewObj(); - sqlite3_snprintf(sizeof(zTemp), zTemp, "%s", pFile->zFilename); - for(i=0; zTemp[i]; i++){ if( zTemp[i]=='\\' ) zTemp[i] = '/'; } - Tcl_ListObjAppendElement(interp, pFileTerm, - Tcl_NewStringObj(zTemp, -1)); - Tcl_ListObjAppendElement(interp, pFileTerm, - Tcl_NewWideIntObj(pFile->iSize)); - Tcl_ListObjAppendElement(interp, pFileTerm, - Tcl_NewWideIntObj(pFile->nRef)); - Tcl_ListObjAppendElement(interp, pFileTerm, - Tcl_NewWideIntObj(pFile->deleteOnClose)); - Tcl_ListObjAppendElement(interp, pGroupTerm, pFileTerm); - } - Tcl_ListObjAppendElement(interp, pResult, pGroupTerm); - } - quotaLeave(); - Tcl_SetObjResult(interp, pResult); - return TCL_OK; -} - -/* -** tclcmd: sqlite3_quota_fopen FILENAME MODE -*/ -static int test_quota_fopen( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - const char *zFilename; /* File pattern to configure */ - const char *zMode; /* Mode string */ - quota_FILE *p; /* Open string object */ - char zReturn[50]; /* Name of pointer to return */ - - /* Process arguments */ - if( objc!=3 ){ - Tcl_WrongNumArgs(interp, 1, objv, "FILENAME MODE"); - return TCL_ERROR; - } - zFilename = Tcl_GetString(objv[1]); - zMode = Tcl_GetString(objv[2]); - p = sqlite3_quota_fopen(zFilename, zMode); - sqlite3_snprintf(sizeof(zReturn), zReturn, "%p", p); - Tcl_SetResult(interp, zReturn, TCL_VOLATILE); - return TCL_OK; -} - -/* Defined in test1.c */ -extern void *sqlite3TestTextToPtr(const char*); - -/* -** tclcmd: sqlite3_quota_fread HANDLE SIZE NELEM -*/ -static int test_quota_fread( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - quota_FILE *p; - char *zBuf; - int sz; - int nElem; - size_t got; - - if( objc!=4 ){ - Tcl_WrongNumArgs(interp, 1, objv, "HANDLE SIZE NELEM"); - return TCL_ERROR; - } - p = sqlite3TestTextToPtr(Tcl_GetString(objv[1])); - if( Tcl_GetIntFromObj(interp, objv[2], &sz) ) return TCL_ERROR; - if( Tcl_GetIntFromObj(interp, objv[3], &nElem) ) return TCL_ERROR; - zBuf = (char*)sqlite3_malloc( sz*nElem + 1 ); - if( zBuf==0 ){ - Tcl_SetResult(interp, "out of memory", TCL_STATIC); - return TCL_ERROR; - } - got = sqlite3_quota_fread(zBuf, sz, nElem, p); - zBuf[got*sz] = 0; - Tcl_SetResult(interp, zBuf, TCL_VOLATILE); - sqlite3_free(zBuf); - return TCL_OK; -} - -/* -** tclcmd: sqlite3_quota_fwrite HANDLE SIZE NELEM CONTENT -*/ -static int test_quota_fwrite( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - quota_FILE *p; - char *zBuf; - int sz; - int nElem; - size_t got; - - if( objc!=5 ){ - Tcl_WrongNumArgs(interp, 1, objv, "HANDLE SIZE NELEM CONTENT"); - return TCL_ERROR; - } - p = sqlite3TestTextToPtr(Tcl_GetString(objv[1])); - if( Tcl_GetIntFromObj(interp, objv[2], &sz) ) return TCL_ERROR; - if( Tcl_GetIntFromObj(interp, objv[3], &nElem) ) return TCL_ERROR; - zBuf = Tcl_GetString(objv[4]); - got = sqlite3_quota_fwrite(zBuf, sz, nElem, p); - Tcl_SetObjResult(interp, Tcl_NewWideIntObj(got)); - return TCL_OK; -} - -/* -** tclcmd: sqlite3_quota_fclose HANDLE -*/ -static int test_quota_fclose( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - quota_FILE *p; - int rc; - - if( objc!=2 ){ - Tcl_WrongNumArgs(interp, 1, objv, "HANDLE"); - return TCL_ERROR; - } - p = sqlite3TestTextToPtr(Tcl_GetString(objv[1])); - rc = sqlite3_quota_fclose(p); - Tcl_SetObjResult(interp, Tcl_NewIntObj(rc)); - return TCL_OK; -} - -/* -** tclcmd: sqlite3_quota_fflush HANDLE ?HARDSYNC? -*/ -static int test_quota_fflush( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - quota_FILE *p; - int rc; - int doSync = 0; - - if( objc!=2 && objc!=3 ){ - Tcl_WrongNumArgs(interp, 1, objv, "HANDLE ?HARDSYNC?"); - return TCL_ERROR; - } - p = sqlite3TestTextToPtr(Tcl_GetString(objv[1])); - if( objc==3 ){ - if( Tcl_GetBooleanFromObj(interp, objv[2], &doSync) ) return TCL_ERROR; - } - rc = sqlite3_quota_fflush(p, doSync); - Tcl_SetObjResult(interp, Tcl_NewIntObj(rc)); - return TCL_OK; -} - -/* -** tclcmd: sqlite3_quota_fseek HANDLE OFFSET WHENCE -*/ -static int test_quota_fseek( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - quota_FILE *p; - int ofst; - const char *zWhence; - int whence; - int rc; - - if( objc!=4 ){ - Tcl_WrongNumArgs(interp, 1, objv, "HANDLE OFFSET WHENCE"); - return TCL_ERROR; - } - p = sqlite3TestTextToPtr(Tcl_GetString(objv[1])); - if( Tcl_GetIntFromObj(interp, objv[2], &ofst) ) return TCL_ERROR; - zWhence = Tcl_GetString(objv[3]); - if( strcmp(zWhence, "SEEK_SET")==0 ){ - whence = SEEK_SET; - }else if( strcmp(zWhence, "SEEK_CUR")==0 ){ - whence = SEEK_CUR; - }else if( strcmp(zWhence, "SEEK_END")==0 ){ - whence = SEEK_END; - }else{ - Tcl_AppendResult(interp, - "WHENCE should be SEEK_SET, SEEK_CUR, or SEEK_END", (char*)0); - return TCL_ERROR; - } - rc = sqlite3_quota_fseek(p, ofst, whence); - Tcl_SetObjResult(interp, Tcl_NewIntObj(rc)); - return TCL_OK; -} - -/* -** tclcmd: sqlite3_quota_rewind HANDLE -*/ -static int test_quota_rewind( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - quota_FILE *p; - if( objc!=2 ){ - Tcl_WrongNumArgs(interp, 1, objv, "HANDLE"); - return TCL_ERROR; - } - p = sqlite3TestTextToPtr(Tcl_GetString(objv[1])); - sqlite3_quota_rewind(p); - return TCL_OK; -} - -/* -** tclcmd: sqlite3_quota_ftell HANDLE -*/ -static int test_quota_ftell( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - quota_FILE *p; - sqlite3_int64 x; - if( objc!=2 ){ - Tcl_WrongNumArgs(interp, 1, objv, "HANDLE"); - return TCL_ERROR; - } - p = sqlite3TestTextToPtr(Tcl_GetString(objv[1])); - x = sqlite3_quota_ftell(p); - Tcl_SetObjResult(interp, Tcl_NewWideIntObj(x)); - return TCL_OK; -} - -/* -** tclcmd: sqlite3_quota_ftruncate HANDLE SIZE -*/ -static int test_quota_ftruncate( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - quota_FILE *p; - sqlite3_int64 x; - Tcl_WideInt w; - int rc; - if( objc!=3 ){ - Tcl_WrongNumArgs(interp, 1, objv, "HANDLE SIZE"); - return TCL_ERROR; - } - p = sqlite3TestTextToPtr(Tcl_GetString(objv[1])); - if( Tcl_GetWideIntFromObj(interp, objv[2], &w) ) return TCL_ERROR; - x = (sqlite3_int64)w; - rc = sqlite3_quota_ftruncate(p, x); - Tcl_SetObjResult(interp, Tcl_NewIntObj(rc)); - return TCL_OK; -} - -/* -** tclcmd: sqlite3_quota_file_size HANDLE -*/ -static int test_quota_file_size( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - quota_FILE *p; - sqlite3_int64 x; - if( objc!=2 ){ - Tcl_WrongNumArgs(interp, 1, objv, "HANDLE"); - return TCL_ERROR; - } - p = sqlite3TestTextToPtr(Tcl_GetString(objv[1])); - x = sqlite3_quota_file_size(p); - Tcl_SetObjResult(interp, Tcl_NewWideIntObj(x)); - return TCL_OK; -} - -/* -** tclcmd: sqlite3_quota_file_truesize HANDLE -*/ -static int test_quota_file_truesize( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - quota_FILE *p; - sqlite3_int64 x; - if( objc!=2 ){ - Tcl_WrongNumArgs(interp, 1, objv, "HANDLE"); - return TCL_ERROR; - } - p = sqlite3TestTextToPtr(Tcl_GetString(objv[1])); - x = sqlite3_quota_file_truesize(p); - Tcl_SetObjResult(interp, Tcl_NewWideIntObj(x)); - return TCL_OK; -} - -/* -** tclcmd: sqlite3_quota_file_mtime HANDLE -*/ -static int test_quota_file_mtime( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - quota_FILE *p; - time_t t; - if( objc!=2 ){ - Tcl_WrongNumArgs(interp, 1, objv, "HANDLE"); - return TCL_ERROR; - } - p = sqlite3TestTextToPtr(Tcl_GetString(objv[1])); - t = 0; - sqlite3_quota_file_mtime(p, &t); - Tcl_SetObjResult(interp, Tcl_NewWideIntObj(t)); - return TCL_OK; -} - - -/* -** tclcmd: sqlite3_quota_remove FILENAME -*/ -static int test_quota_remove( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - const char *zFilename; /* File pattern to configure */ - int rc; - if( objc!=2 ){ - Tcl_WrongNumArgs(interp, 1, objv, "FILENAME"); - return TCL_ERROR; - } - zFilename = Tcl_GetString(objv[1]); - rc = sqlite3_quota_remove(zFilename); - Tcl_SetObjResult(interp, Tcl_NewIntObj(rc)); - return TCL_OK; -} - -/* -** tclcmd: sqlite3_quota_glob PATTERN TEXT -** -** Test the glob pattern matching. Return 1 if TEXT matches PATTERN -** and return 0 if it does not. -*/ -static int test_quota_glob( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - const char *zPattern; /* The glob pattern */ - const char *zText; /* Text to compare agains the pattern */ - int rc; - if( objc!=3 ){ - Tcl_WrongNumArgs(interp, 1, objv, "PATTERN TEXT"); - return TCL_ERROR; - } - zPattern = Tcl_GetString(objv[1]); - zText = Tcl_GetString(objv[2]); - rc = quotaStrglob(zPattern, zText); - Tcl_SetObjResult(interp, Tcl_NewIntObj(rc)); - return TCL_OK; -} - -/* -** tclcmd: sqlite3_quota_file_available HANDLE -** -** Return the number of bytes from the current file point to the end of -** the file. -*/ -static int test_quota_file_available( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - quota_FILE *p; - sqlite3_int64 x; - if( objc!=2 ){ - Tcl_WrongNumArgs(interp, 1, objv, "HANDLE"); - return TCL_ERROR; - } - p = sqlite3TestTextToPtr(Tcl_GetString(objv[1])); - x = sqlite3_quota_file_available(p); - Tcl_SetObjResult(interp, Tcl_NewWideIntObj(x)); - return TCL_OK; -} - -/* -** tclcmd: sqlite3_quota_ferror HANDLE -** -** Return true if the file handle is in the error state. -*/ -static int test_quota_ferror( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - quota_FILE *p; - int x; - if( objc!=2 ){ - Tcl_WrongNumArgs(interp, 1, objv, "HANDLE"); - return TCL_ERROR; - } - p = sqlite3TestTextToPtr(Tcl_GetString(objv[1])); - x = sqlite3_quota_ferror(p); - Tcl_SetObjResult(interp, Tcl_NewIntObj(x)); - return TCL_OK; -} - -/* -** This routine registers the custom TCL commands defined in this -** module. This should be the only procedure visible from outside -** of this module. -*/ -int Sqlitequota_Init(Tcl_Interp *interp){ - static struct { - char *zName; - Tcl_ObjCmdProc *xProc; - } aCmd[] = { - { "sqlite3_quota_initialize", test_quota_initialize }, - { "sqlite3_quota_shutdown", test_quota_shutdown }, - { "sqlite3_quota_set", test_quota_set }, - { "sqlite3_quota_file", test_quota_file }, - { "sqlite3_quota_dump", test_quota_dump }, - { "sqlite3_quota_fopen", test_quota_fopen }, - { "sqlite3_quota_fread", test_quota_fread }, - { "sqlite3_quota_fwrite", test_quota_fwrite }, - { "sqlite3_quota_fclose", test_quota_fclose }, - { "sqlite3_quota_fflush", test_quota_fflush }, - { "sqlite3_quota_fseek", test_quota_fseek }, - { "sqlite3_quota_rewind", test_quota_rewind }, - { "sqlite3_quota_ftell", test_quota_ftell }, - { "sqlite3_quota_ftruncate", test_quota_ftruncate }, - { "sqlite3_quota_file_size", test_quota_file_size }, - { "sqlite3_quota_file_truesize", test_quota_file_truesize }, - { "sqlite3_quota_file_mtime", test_quota_file_mtime }, - { "sqlite3_quota_remove", test_quota_remove }, - { "sqlite3_quota_glob", test_quota_glob }, - { "sqlite3_quota_file_available",test_quota_file_available }, - { "sqlite3_quota_ferror", test_quota_ferror }, - }; - int i; - - for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){ - Tcl_CreateObjCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0); - } - - return TCL_OK; -} -#endif diff --git a/components/external/SQLite-3.8.1/SQLiteLib/test/test_quota.h b/components/external/SQLite-3.8.1/SQLiteLib/test/test_quota.h deleted file mode 100644 index 2d0767a19a..0000000000 --- a/components/external/SQLite-3.8.1/SQLiteLib/test/test_quota.h +++ /dev/null @@ -1,274 +0,0 @@ -/* -** 2011 December 1 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** -** This file contains the interface definition for the quota a VFS shim. -** -** This particular shim enforces a quota system on files. One or more -** database files are in a "quota group" that is defined by a GLOB -** pattern. A quota is set for the combined size of all files in the -** the group. A quota of zero means "no limit". If the total size -** of all files in the quota group is greater than the limit, then -** write requests that attempt to enlarge a file fail with SQLITE_FULL. -** -** However, before returning SQLITE_FULL, the write requests invoke -** a callback function that is configurable for each quota group. -** This callback has the opportunity to enlarge the quota. If the -** callback does enlarge the quota such that the total size of all -** files within the group is less than the new quota, then the write -** continues as if nothing had happened. -*/ -#ifndef _QUOTA_H_ -#include "sqlite3.h" -#include <stdio.h> -#include <sys/types.h> -#include <sys/stat.h> -#if SQLITE_OS_UNIX -# include <unistd.h> -#endif -#if SQLITE_OS_WIN -# include <windows.h> -#endif - -/* Make this callable from C++ */ -#ifdef __cplusplus -extern "C" { -#endif - -/* -** Initialize the quota VFS shim. Use the VFS named zOrigVfsName -** as the VFS that does the actual work. Use the default if -** zOrigVfsName==NULL. -** -** The quota VFS shim is named "quota". It will become the default -** VFS if makeDefault is non-zero. -** -** THIS ROUTINE IS NOT THREADSAFE. Call this routine exactly once -** during start-up. -*/ -int sqlite3_quota_initialize(const char *zOrigVfsName, int makeDefault); - -/* -** Shutdown the quota system. -** -** All SQLite database connections must be closed before calling this -** routine. -** -** THIS ROUTINE IS NOT THREADSAFE. Call this routine exactly once while -** shutting down in order to free all remaining quota groups. -*/ -int sqlite3_quota_shutdown(void); - -/* -** Create or destroy a quota group. -** -** The quota group is defined by the zPattern. When calling this routine -** with a zPattern for a quota group that already exists, this routine -** merely updates the iLimit, xCallback, and pArg values for that quota -** group. If zPattern is new, then a new quota group is created. -** -** The zPattern is always compared against the full pathname of the file. -** Even if APIs are called with relative pathnames, SQLite converts the -** name to a full pathname before comparing it against zPattern. zPattern -** is a glob pattern with the following matching rules: -** -** '*' Matches any sequence of zero or more characters. -** -** '?' Matches exactly one character. -** -** [...] Matches one character from the enclosed list of -** characters. "]" can be part of the list if it is -** the first character. Within the list "X-Y" matches -** characters X or Y or any character in between the -** two. Ex: "[0-9]" matches any digit. -** -** [^...] Matches one character not in the enclosed list. -** -** / Matches either / or \. This allows glob patterns -** containing / to work on both unix and windows. -** -** Note that, unlike unix shell globbing, the directory separator "/" -** can match a wildcard. So, for example, the pattern "/abc/xyz/" "*" -** matches any files anywhere in the directory hierarchy beneath -** /abc/xyz. -** -** The glob algorithm works on bytes. Multi-byte UTF8 characters are -** matched as if each byte were a separate character. -** -** If the iLimit for a quota group is set to zero, then the quota group -** is disabled and will be deleted when the last database connection using -** the quota group is closed. -** -** Calling this routine on a zPattern that does not exist and with a -** zero iLimit is a no-op. -** -** A quota group must exist with a non-zero iLimit prior to opening -** database connections if those connections are to participate in the -** quota group. Creating a quota group does not affect database connections -** that are already open. -** -** The patterns that define the various quota groups should be distinct. -** If the same filename matches more than one quota group pattern, then -** the behavior of this package is undefined. -*/ -int sqlite3_quota_set( - const char *zPattern, /* The filename pattern */ - sqlite3_int64 iLimit, /* New quota to set for this quota group */ - void (*xCallback)( /* Callback invoked when going over quota */ - const char *zFilename, /* Name of file whose size increases */ - sqlite3_int64 *piLimit, /* IN/OUT: The current limit */ - sqlite3_int64 iSize, /* Total size of all files in the group */ - void *pArg /* Client data */ - ), - void *pArg, /* client data passed thru to callback */ - void (*xDestroy)(void*) /* Optional destructor for pArg */ -); - -/* -** Bring the named file under quota management, assuming its name matches -** the glob pattern of some quota group. Or if it is already under -** management, update its size. If zFilename does not match the glob -** pattern of any quota group, this routine is a no-op. -*/ -int sqlite3_quota_file(const char *zFilename); - -/* -** The following object serves the same role as FILE in the standard C -** library. It represents an open connection to a file on disk for I/O. -** -** A single quota_FILE should not be used by two or more threads at the -** same time. Multiple threads can be using different quota_FILE objects -** simultaneously, but not the same quota_FILE object. -*/ -typedef struct quota_FILE quota_FILE; - -/* -** Create a new quota_FILE object used to read and/or write to the -** file zFilename. The zMode parameter is as with standard library zMode. -*/ -quota_FILE *sqlite3_quota_fopen(const char *zFilename, const char *zMode); - -/* -** Perform I/O against a quota_FILE object. When doing writes, the -** quota mechanism may result in a short write, in order to prevent -** the sum of sizes of all files from going over quota. -*/ -size_t sqlite3_quota_fread(void*, size_t, size_t, quota_FILE*); -size_t sqlite3_quota_fwrite(const void*, size_t, size_t, quota_FILE*); - -/* -** Flush all written content held in memory buffers out to disk. -** This is the equivalent of fflush() in the standard library. -** -** If the hardSync parameter is true (non-zero) then this routine -** also forces OS buffers to disk - the equivalent of fsync(). -** -** This routine return zero on success and non-zero if something goes -** wrong. -*/ -int sqlite3_quota_fflush(quota_FILE*, int hardSync); - -/* -** Close a quota_FILE object and free all associated resources. The -** file remains under quota management. -*/ -int sqlite3_quota_fclose(quota_FILE*); - -/* -** Move the read/write pointer for a quota_FILE object. Or tell the -** current location of the read/write pointer. -*/ -int sqlite3_quota_fseek(quota_FILE*, long, int); -void sqlite3_quota_rewind(quota_FILE*); -long sqlite3_quota_ftell(quota_FILE*); - -/* -** Test the error indicator for the given file. -** -** Return non-zero if the error indicator is set. -*/ -int sqlite3_quota_ferror(quota_FILE*); - -/* -** Truncate a file previously opened by sqlite3_quota_fopen(). Return -** zero on success and non-zero on any kind of failure. -** -** The newSize argument must be less than or equal to the current file size. -** Any attempt to "truncate" a file to a larger size results in -** undefined behavior. -*/ -int sqlite3_quota_ftruncate(quota_FILE*, sqlite3_int64 newSize); - -/* -** Return the last modification time of the opened file, in seconds -** since 1970. -*/ -int sqlite3_quota_file_mtime(quota_FILE*, time_t *pTime); - -/* -** Return the size of the file as it is known to the quota system. -** -** This size might be different from the true size of the file on -** disk if some outside process has modified the file without using the -** quota mechanism, or if calls to sqlite3_quota_fwrite() have occurred -** which have increased the file size, but those writes have not yet been -** forced to disk using sqlite3_quota_fflush(). -** -** Return -1 if the file is not participating in quota management. -*/ -sqlite3_int64 sqlite3_quota_file_size(quota_FILE*); - -/* -** Return the true size of the file. -** -** The true size should be the same as the size of the file as known -** to the quota system, however the sizes might be different if the -** file has been extended or truncated via some outside process or if -** pending writes have not yet been flushed to disk. -** -** Return -1 if the file does not exist or if the size of the file -** cannot be determined for some reason. -*/ -sqlite3_int64 sqlite3_quota_file_truesize(quota_FILE*); - -/* -** Determine the amount of data in bytes available for reading -** in the given file. -** -** Return -1 if the amount cannot be determined for some reason. -*/ -long sqlite3_quota_file_available(quota_FILE*); - -/* -** Delete a file from the disk, if that file is under quota management. -** Adjust quotas accordingly. -** -** If zFilename is the name of a directory that matches one of the -** quota glob patterns, then all files under quota management that -** are contained within that directory are deleted. -** -** A standard SQLite result code is returned (SQLITE_OK, SQLITE_NOMEM, etc.) -** When deleting a directory of files, if the deletion of any one -** file fails (for example due to an I/O error), then this routine -** returns immediately, with the error code, and does not try to -** delete any of the other files in the specified directory. -** -** All files are removed from quota management and deleted from disk. -** However, no attempt is made to remove empty directories. -** -** This routine is a no-op for files that are not under quota management. -*/ -int sqlite3_quota_remove(const char *zFilename); - -#ifdef __cplusplus -} /* end of the 'extern "C"' block */ -#endif -#endif /* _QUOTA_H_ */ diff --git a/components/external/SQLite-3.8.1/SQLiteLib/test/test_rtree.c b/components/external/SQLite-3.8.1/SQLiteLib/test/test_rtree.c deleted file mode 100644 index e1966c2437..0000000000 --- a/components/external/SQLite-3.8.1/SQLiteLib/test/test_rtree.c +++ /dev/null @@ -1,305 +0,0 @@ -/* -** 2010 August 28 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** Code for testing all sorts of SQLite interfaces. This code -** is not included in the SQLite library. -*/ - -#include <sqlite3.h> -#include <tcl.h> - -/* Solely for the UNUSED_PARAMETER() macro. */ -#include "sqliteInt.h" - -#ifdef SQLITE_ENABLE_RTREE -/* -** Type used to cache parameter information for the "circle" r-tree geometry -** callback. -*/ -typedef struct Circle Circle; -struct Circle { - struct Box { - double xmin; - double xmax; - double ymin; - double ymax; - } aBox[2]; - double centerx; - double centery; - double radius; -}; - -/* -** Destructor function for Circle objects allocated by circle_geom(). -*/ -static void circle_del(void *p){ - sqlite3_free(p); -} - -/* -** Implementation of "circle" r-tree geometry callback. -*/ -static int circle_geom( - sqlite3_rtree_geometry *p, - int nCoord, -#ifdef SQLITE_RTREE_INT_ONLY - sqlite3_int64 *aCoord, -#else - double *aCoord, -#endif - int *pRes -){ - int i; /* Iterator variable */ - Circle *pCircle; /* Structure defining circular region */ - double xmin, xmax; /* X dimensions of box being tested */ - double ymin, ymax; /* X dimensions of box being tested */ - - if( p->pUser==0 ){ - /* If pUser is still 0, then the parameter values have not been tested - ** for correctness or stored into a Circle structure yet. Do this now. */ - - /* This geometry callback is for use with a 2-dimensional r-tree table. - ** Return an error if the table does not have exactly 2 dimensions. */ - if( nCoord!=4 ) return SQLITE_ERROR; - - /* Test that the correct number of parameters (3) have been supplied, - ** and that the parameters are in range (that the radius of the circle - ** radius is greater than zero). */ - if( p->nParam!=3 || p->aParam[2]<0.0 ) return SQLITE_ERROR; - - /* Allocate a structure to cache parameter data in. Return SQLITE_NOMEM - ** if the allocation fails. */ - pCircle = (Circle *)(p->pUser = sqlite3_malloc(sizeof(Circle))); - if( !pCircle ) return SQLITE_NOMEM; - p->xDelUser = circle_del; - - /* Record the center and radius of the circular region. One way that - ** tested bounding boxes that intersect the circular region are detected - ** is by testing if each corner of the bounding box lies within radius - ** units of the center of the circle. */ - pCircle->centerx = p->aParam[0]; - pCircle->centery = p->aParam[1]; - pCircle->radius = p->aParam[2]; - - /* Define two bounding box regions. The first, aBox[0], extends to - ** infinity in the X dimension. It covers the same range of the Y dimension - ** as the circular region. The second, aBox[1], extends to infinity in - ** the Y dimension and is constrained to the range of the circle in the - ** X dimension. - ** - ** Then imagine each box is split in half along its short axis by a line - ** that intersects the center of the circular region. A bounding box - ** being tested can be said to intersect the circular region if it contains - ** points from each half of either of the two infinite bounding boxes. - */ - pCircle->aBox[0].xmin = pCircle->centerx; - pCircle->aBox[0].xmax = pCircle->centerx; - pCircle->aBox[0].ymin = pCircle->centery + pCircle->radius; - pCircle->aBox[0].ymax = pCircle->centery - pCircle->radius; - pCircle->aBox[1].xmin = pCircle->centerx + pCircle->radius; - pCircle->aBox[1].xmax = pCircle->centerx - pCircle->radius; - pCircle->aBox[1].ymin = pCircle->centery; - pCircle->aBox[1].ymax = pCircle->centery; - } - - pCircle = (Circle *)p->pUser; - xmin = aCoord[0]; - xmax = aCoord[1]; - ymin = aCoord[2]; - ymax = aCoord[3]; - - /* Check if any of the 4 corners of the bounding-box being tested lie - ** inside the circular region. If they do, then the bounding-box does - ** intersect the region of interest. Set the output variable to true and - ** return SQLITE_OK in this case. */ - for(i=0; i<4; i++){ - double x = (i&0x01) ? xmax : xmin; - double y = (i&0x02) ? ymax : ymin; - double d2; - - d2 = (x-pCircle->centerx)*(x-pCircle->centerx); - d2 += (y-pCircle->centery)*(y-pCircle->centery); - if( d2<(pCircle->radius*pCircle->radius) ){ - *pRes = 1; - return SQLITE_OK; - } - } - - /* Check if the bounding box covers any other part of the circular region. - ** See comments above for a description of how this test works. If it does - ** cover part of the circular region, set the output variable to true - ** and return SQLITE_OK. */ - for(i=0; i<2; i++){ - if( xmin<=pCircle->aBox[i].xmin - && xmax>=pCircle->aBox[i].xmax - && ymin<=pCircle->aBox[i].ymin - && ymax>=pCircle->aBox[i].ymax - ){ - *pRes = 1; - return SQLITE_OK; - } - } - - /* The specified bounding box does not intersect the circular region. Set - ** the output variable to zero and return SQLITE_OK. */ - *pRes = 0; - return SQLITE_OK; -} - -/* END of implementation of "circle" geometry callback. -************************************************************************** -*************************************************************************/ - -#include <assert.h> -#include "tcl.h" - -typedef struct Cube Cube; -struct Cube { - double x; - double y; - double z; - double width; - double height; - double depth; -}; - -static void cube_context_free(void *p){ - sqlite3_free(p); -} - -/* -** The context pointer registered along with the 'cube' callback is -** always ((void *)&gHere). This is just to facilitate testing, it is not -** actually used for anything. -*/ -static int gHere = 42; - -/* -** Implementation of a simple r-tree geom callback to test for intersection -** of r-tree rows with a "cube" shape. Cubes are defined by six scalar -** coordinates as follows: -** -** cube(x, y, z, width, height, depth) -** -** The width, height and depth parameters must all be greater than zero. -*/ -static int cube_geom( - sqlite3_rtree_geometry *p, - int nCoord, -#ifdef SQLITE_RTREE_INT_ONLY - sqlite3_int64 *aCoord, -#else - double *aCoord, -#endif - int *piRes -){ - Cube *pCube = (Cube *)p->pUser; - - assert( p->pContext==(void *)&gHere ); - - if( pCube==0 ){ - if( p->nParam!=6 || nCoord!=6 - || p->aParam[3]<=0.0 || p->aParam[4]<=0.0 || p->aParam[5]<=0.0 - ){ - return SQLITE_ERROR; - } - pCube = (Cube *)sqlite3_malloc(sizeof(Cube)); - if( !pCube ){ - return SQLITE_NOMEM; - } - pCube->x = p->aParam[0]; - pCube->y = p->aParam[1]; - pCube->z = p->aParam[2]; - pCube->width = p->aParam[3]; - pCube->height = p->aParam[4]; - pCube->depth = p->aParam[5]; - - p->pUser = (void *)pCube; - p->xDelUser = cube_context_free; - } - - assert( nCoord==6 ); - *piRes = 0; - if( aCoord[0]<=(pCube->x+pCube->width) - && aCoord[1]>=pCube->x - && aCoord[2]<=(pCube->y+pCube->height) - && aCoord[3]>=pCube->y - && aCoord[4]<=(pCube->z+pCube->depth) - && aCoord[5]>=pCube->z - ){ - *piRes = 1; - } - - return SQLITE_OK; -} -#endif /* SQLITE_ENABLE_RTREE */ - -static int register_cube_geom( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ -#ifndef SQLITE_ENABLE_RTREE - UNUSED_PARAMETER(clientData); - UNUSED_PARAMETER(interp); - UNUSED_PARAMETER(objc); - UNUSED_PARAMETER(objv); -#else - extern int getDbPointer(Tcl_Interp*, const char*, sqlite3**); - extern const char *sqlite3ErrName(int); - 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_rtree_geometry_callback(db, "cube", cube_geom, (void *)&gHere); - Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_STATIC); -#endif - return TCL_OK; -} - -static int register_circle_geom( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ -#ifndef SQLITE_ENABLE_RTREE - UNUSED_PARAMETER(clientData); - UNUSED_PARAMETER(interp); - UNUSED_PARAMETER(objc); - UNUSED_PARAMETER(objv); -#else - extern int getDbPointer(Tcl_Interp*, const char*, sqlite3**); - extern const char *sqlite3ErrName(int); - 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_rtree_geometry_callback(db, "circle", circle_geom, 0); - Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_STATIC); -#endif - return TCL_OK; -} - -int Sqlitetestrtree_Init(Tcl_Interp *interp){ - Tcl_CreateObjCommand(interp, "register_cube_geom", register_cube_geom, 0, 0); - Tcl_CreateObjCommand(interp, "register_circle_geom",register_circle_geom,0,0); - return TCL_OK; -} diff --git a/components/external/SQLite-3.8.1/SQLiteLib/test/test_schema.c b/components/external/SQLite-3.8.1/SQLiteLib/test/test_schema.c deleted file mode 100644 index 00a9f4dd90..0000000000 --- a/components/external/SQLite-3.8.1/SQLiteLib/test/test_schema.c +++ /dev/null @@ -1,362 +0,0 @@ -/* -** 2006 June 10 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** Code for testing the virtual table interfaces. This code -** is not included in the SQLite library. It is used for automated -** testing of the SQLite library. -*/ - -/* The code in this file defines a sqlite3 virtual-table module that -** provides a read-only view of the current database schema. There is one -** row in the schema table for each column in the database schema. -*/ -#define SCHEMA \ -"CREATE TABLE x(" \ - "database," /* Name of database (i.e. main, temp etc.) */ \ - "tablename," /* Name of table */ \ - "cid," /* Column number (from left-to-right, 0 upward) */ \ - "name," /* Column name */ \ - "type," /* Specified type (i.e. VARCHAR(32)) */ \ - "not_null," /* Boolean. True if NOT NULL was specified */ \ - "dflt_value," /* Default value for this column */ \ - "pk" /* True if this column is part of the primary key */ \ -")" - -/* If SQLITE_TEST is defined this code is preprocessed for use as part -** of the sqlite test binary "testfixture". Otherwise it is preprocessed -** to be compiled into an sqlite dynamic extension. -*/ -#ifdef SQLITE_TEST - #include "sqliteInt.h" - #include "tcl.h" -#else - #include "sqlite3ext.h" - SQLITE_EXTENSION_INIT1 -#endif - -#include <stdlib.h> -#include <string.h> -#include <assert.h> - -typedef struct schema_vtab schema_vtab; -typedef struct schema_cursor schema_cursor; - -/* A schema table object */ -struct schema_vtab { - sqlite3_vtab base; - sqlite3 *db; -}; - -/* A schema table cursor object */ -struct schema_cursor { - sqlite3_vtab_cursor base; - sqlite3_stmt *pDbList; - sqlite3_stmt *pTableList; - sqlite3_stmt *pColumnList; - int rowid; -}; - -/* -** None of this works unless we have virtual tables. -*/ -#ifndef SQLITE_OMIT_VIRTUALTABLE - -/* -** Table destructor for the schema module. -*/ -static int schemaDestroy(sqlite3_vtab *pVtab){ - sqlite3_free(pVtab); - return 0; -} - -/* -** Table constructor for the schema module. -*/ -static int schemaCreate( - sqlite3 *db, - void *pAux, - int argc, const char *const*argv, - sqlite3_vtab **ppVtab, - char **pzErr -){ - int rc = SQLITE_NOMEM; - schema_vtab *pVtab = sqlite3_malloc(sizeof(schema_vtab)); - if( pVtab ){ - memset(pVtab, 0, sizeof(schema_vtab)); - pVtab->db = db; -#ifndef SQLITE_OMIT_VIRTUALTABLE - rc = sqlite3_declare_vtab(db, SCHEMA); -#endif - } - *ppVtab = (sqlite3_vtab *)pVtab; - return rc; -} - -/* -** Open a new cursor on the schema table. -*/ -static int schemaOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){ - int rc = SQLITE_NOMEM; - schema_cursor *pCur; - pCur = sqlite3_malloc(sizeof(schema_cursor)); - if( pCur ){ - memset(pCur, 0, sizeof(schema_cursor)); - *ppCursor = (sqlite3_vtab_cursor *)pCur; - rc = SQLITE_OK; - } - return rc; -} - -/* -** Close a schema table cursor. -*/ -static int schemaClose(sqlite3_vtab_cursor *cur){ - schema_cursor *pCur = (schema_cursor *)cur; - sqlite3_finalize(pCur->pDbList); - sqlite3_finalize(pCur->pTableList); - sqlite3_finalize(pCur->pColumnList); - sqlite3_free(pCur); - return SQLITE_OK; -} - -/* -** Retrieve a column of data. -*/ -static int schemaColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){ - schema_cursor *pCur = (schema_cursor *)cur; - switch( i ){ - case 0: - sqlite3_result_value(ctx, sqlite3_column_value(pCur->pDbList, 1)); - break; - case 1: - sqlite3_result_value(ctx, sqlite3_column_value(pCur->pTableList, 0)); - break; - default: - sqlite3_result_value(ctx, sqlite3_column_value(pCur->pColumnList, i-2)); - break; - } - return SQLITE_OK; -} - -/* -** Retrieve the current rowid. -*/ -static int schemaRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){ - schema_cursor *pCur = (schema_cursor *)cur; - *pRowid = pCur->rowid; - return SQLITE_OK; -} - -static int finalize(sqlite3_stmt **ppStmt){ - int rc = sqlite3_finalize(*ppStmt); - *ppStmt = 0; - return rc; -} - -static int schemaEof(sqlite3_vtab_cursor *cur){ - schema_cursor *pCur = (schema_cursor *)cur; - return (pCur->pDbList ? 0 : 1); -} - -/* -** Advance the cursor to the next row. -*/ -static int schemaNext(sqlite3_vtab_cursor *cur){ - int rc = SQLITE_OK; - schema_cursor *pCur = (schema_cursor *)cur; - schema_vtab *pVtab = (schema_vtab *)(cur->pVtab); - char *zSql = 0; - - while( !pCur->pColumnList || SQLITE_ROW!=sqlite3_step(pCur->pColumnList) ){ - if( SQLITE_OK!=(rc = finalize(&pCur->pColumnList)) ) goto next_exit; - - while( !pCur->pTableList || SQLITE_ROW!=sqlite3_step(pCur->pTableList) ){ - if( SQLITE_OK!=(rc = finalize(&pCur->pTableList)) ) goto next_exit; - - assert(pCur->pDbList); - while( SQLITE_ROW!=sqlite3_step(pCur->pDbList) ){ - rc = finalize(&pCur->pDbList); - goto next_exit; - } - - /* Set zSql to the SQL to pull the list of tables from the - ** sqlite_master (or sqlite_temp_master) table of the database - ** identfied by the row pointed to by the SQL statement pCur->pDbList - ** (iterating through a "PRAGMA database_list;" statement). - */ - if( sqlite3_column_int(pCur->pDbList, 0)==1 ){ - zSql = sqlite3_mprintf( - "SELECT name FROM sqlite_temp_master WHERE type='table'" - ); - }else{ - sqlite3_stmt *pDbList = pCur->pDbList; - zSql = sqlite3_mprintf( - "SELECT name FROM %Q.sqlite_master WHERE type='table'", - sqlite3_column_text(pDbList, 1) - ); - } - if( !zSql ){ - rc = SQLITE_NOMEM; - goto next_exit; - } - - rc = sqlite3_prepare(pVtab->db, zSql, -1, &pCur->pTableList, 0); - sqlite3_free(zSql); - if( rc!=SQLITE_OK ) goto next_exit; - } - - /* Set zSql to the SQL to the table_info pragma for the table currently - ** identified by the rows pointed to by statements pCur->pDbList and - ** pCur->pTableList. - */ - zSql = sqlite3_mprintf("PRAGMA %Q.table_info(%Q)", - sqlite3_column_text(pCur->pDbList, 1), - sqlite3_column_text(pCur->pTableList, 0) - ); - - if( !zSql ){ - rc = SQLITE_NOMEM; - goto next_exit; - } - rc = sqlite3_prepare(pVtab->db, zSql, -1, &pCur->pColumnList, 0); - sqlite3_free(zSql); - if( rc!=SQLITE_OK ) goto next_exit; - } - pCur->rowid++; - -next_exit: - /* TODO: Handle rc */ - return rc; -} - -/* -** Reset a schema table cursor. -*/ -static int schemaFilter( - sqlite3_vtab_cursor *pVtabCursor, - int idxNum, const char *idxStr, - int argc, sqlite3_value **argv -){ - int rc; - schema_vtab *pVtab = (schema_vtab *)(pVtabCursor->pVtab); - schema_cursor *pCur = (schema_cursor *)pVtabCursor; - pCur->rowid = 0; - finalize(&pCur->pTableList); - finalize(&pCur->pColumnList); - finalize(&pCur->pDbList); - rc = sqlite3_prepare(pVtab->db,"PRAGMA database_list", -1, &pCur->pDbList, 0); - return (rc==SQLITE_OK ? schemaNext(pVtabCursor) : rc); -} - -/* -** Analyse the WHERE condition. -*/ -static int schemaBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ - return SQLITE_OK; -} - -/* -** A virtual table module that merely echos method calls into TCL -** variables. -*/ -static sqlite3_module schemaModule = { - 0, /* iVersion */ - schemaCreate, - schemaCreate, - schemaBestIndex, - schemaDestroy, - schemaDestroy, - schemaOpen, /* xOpen - open a cursor */ - schemaClose, /* xClose - close a cursor */ - schemaFilter, /* xFilter - configure scan constraints */ - schemaNext, /* xNext - advance a cursor */ - schemaEof, /* xEof */ - schemaColumn, /* xColumn - read data */ - schemaRowid, /* xRowid - read data */ - 0, /* xUpdate */ - 0, /* xBegin */ - 0, /* xSync */ - 0, /* xCommit */ - 0, /* xRollback */ - 0, /* xFindMethod */ - 0, /* xRename */ -}; - -#endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) */ - -#ifdef SQLITE_TEST - -/* -** Decode a pointer to an sqlite3 object. -*/ -extern int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb); - -/* -** Register the schema virtual table module. -*/ -static int register_schema_module( - 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 */ -){ - sqlite3 *db; - if( objc!=2 ){ - Tcl_WrongNumArgs(interp, 1, objv, "DB"); - return TCL_ERROR; - } - if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; -#ifndef SQLITE_OMIT_VIRTUALTABLE - sqlite3_create_module(db, "schema", &schemaModule, 0); -#endif - return TCL_OK; -} - -/* -** Register commands with the TCL interpreter. -*/ -int Sqlitetestschema_Init(Tcl_Interp *interp){ - static struct { - char *zName; - Tcl_ObjCmdProc *xProc; - void *clientData; - } aObjCmd[] = { - { "register_schema_module", register_schema_module, 0 }, - }; - int i; - for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){ - Tcl_CreateObjCommand(interp, aObjCmd[i].zName, - aObjCmd[i].xProc, aObjCmd[i].clientData, 0); - } - return TCL_OK; -} - -#else - -/* -** Extension load function. -*/ -#ifdef _WIN32 -__declspec(dllexport) -#endif -int sqlite3_schema_init( - sqlite3 *db, - char **pzErrMsg, - const sqlite3_api_routines *pApi -){ - SQLITE_EXTENSION_INIT2(pApi); -#ifndef SQLITE_OMIT_VIRTUALTABLE - sqlite3_create_module(db, "schema", &schemaModule, 0); -#endif - return 0; -} - -#endif diff --git a/components/external/SQLite-3.8.1/SQLiteLib/test/test_server.c b/components/external/SQLite-3.8.1/SQLiteLib/test/test_server.c deleted file mode 100644 index 4eb1cf1966..0000000000 --- a/components/external/SQLite-3.8.1/SQLiteLib/test/test_server.c +++ /dev/null @@ -1,516 +0,0 @@ -/* -** 2006 January 07 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -****************************************************************************** -** -** This file contains demonstration code. Nothing in this file gets compiled -** or linked into the SQLite library unless you use a non-standard option: -** -** -DSQLITE_SERVER=1 -** -** The configure script will never generate a Makefile with the option -** above. You will need to manually modify the Makefile if you want to -** include any of the code from this file in your project. Or, at your -** option, you may copy and paste the code from this file and -** thereby avoiding a recompile of SQLite. -** -** -** This source file demonstrates how to use SQLite to create an SQL database -** server thread in a multiple-threaded program. One or more client threads -** send messages to the server thread and the server thread processes those -** messages in the order received and returns the results to the client. -** -** One might ask: "Why bother? Why not just let each thread connect -** to the database directly?" There are a several of reasons to -** prefer the client/server approach. -** -** (1) Some systems (ex: Redhat9) have broken threading implementations -** that prevent SQLite database connections from being used in -** a thread different from the one where they were created. With -** the client/server approach, all database connections are created -** and used within the server thread. Client calls to the database -** can be made from multiple threads (though not at the same time!) -** -** (2) Beginning with SQLite version 3.3.0, when two or more -** connections to the same database occur within the same thread, -** they can optionally share their database cache. This reduces -** I/O and memory requirements. Cache shared is controlled using -** the sqlite3_enable_shared_cache() API. -** -** (3) Database connections on a shared cache use table-level locking -** instead of file-level locking for improved concurrency. -** -** (4) Database connections on a shared cache can by optionally -** set to READ UNCOMMITTED isolation. (The default isolation for -** SQLite is SERIALIZABLE.) When this occurs, readers will -** never be blocked by a writer and writers will not be -** blocked by readers. There can still only be a single writer -** at a time, but multiple readers can simultaneously exist with -** that writer. This is a huge increase in concurrency. -** -** To summarize the rational for using a client/server approach: prior -** to SQLite version 3.3.0 it probably was not worth the trouble. But -** with SQLite version 3.3.0 and beyond you can get significant performance -** and concurrency improvements and memory usage reductions by going -** client/server. -** -** Note: The extra features of version 3.3.0 described by points (2) -** through (4) above are only available if you compile without the -** option -DSQLITE_OMIT_SHARED_CACHE. -** -** Here is how the client/server approach works: The database server -** thread is started on this procedure: -** -** void *sqlite3_server(void *NotUsed); -** -** The sqlite_server procedure runs as long as the g.serverHalt variable -** is false. A mutex is used to make sure no more than one server runs -** at a time. The server waits for messages to arrive on a message -** queue and processes the messages in order. -** -** Two convenience routines are provided for starting and stopping the -** server thread: -** -** void sqlite3_server_start(void); -** void sqlite3_server_stop(void); -** -** Both of the convenience routines return immediately. Neither will -** ever give an error. If a server is already started or already halted, -** then the routines are effectively no-ops. -** -** Clients use the following interfaces: -** -** sqlite3_client_open -** sqlite3_client_prepare -** sqlite3_client_step -** sqlite3_client_reset -** sqlite3_client_finalize -** sqlite3_client_close -** -** These interfaces work exactly like the standard core SQLite interfaces -** having the same names without the "_client_" infix. Many other SQLite -** interfaces can be used directly without having to send messages to the -** server as long as SQLITE_ENABLE_MEMORY_MANAGEMENT is not defined. -** The following interfaces fall into this second category: -** -** sqlite3_bind_* -** sqlite3_changes -** sqlite3_clear_bindings -** sqlite3_column_* -** sqlite3_complete -** sqlite3_create_collation -** sqlite3_create_function -** sqlite3_data_count -** sqlite3_db_handle -** sqlite3_errcode -** sqlite3_errmsg -** sqlite3_last_insert_rowid -** sqlite3_total_changes -** sqlite3_transfer_bindings -** -** A single SQLite connection (an sqlite3* object) or an SQLite statement -** (an sqlite3_stmt* object) should only be passed to a single interface -** function at a time. The connections and statements can be passed from -** any thread to any of the functions listed in the second group above as -** long as the same connection is not in use by two threads at once and -** as long as SQLITE_ENABLE_MEMORY_MANAGEMENT is not defined. Additional -** information about the SQLITE_ENABLE_MEMORY_MANAGEMENT constraint is -** below. -** -** The busy handler for all database connections should remain turned -** off. That means that any lock contention will cause the associated -** sqlite3_client_step() call to return immediately with an SQLITE_BUSY -** error code. If a busy handler is enabled and lock contention occurs, -** then the entire server thread will block. This will cause not only -** the requesting client to block but every other database client as -** well. It is possible to enhance the code below so that lock -** contention will cause the message to be placed back on the top of -** the queue to be tried again later. But such enhanced processing is -** not included here, in order to keep the example simple. -** -** This example code assumes the use of pthreads. Pthreads -** implementations are available for windows. (See, for example -** http://sourceware.org/pthreads-win32/announcement.html.) Or, you -** can translate the locking and thread synchronization code to use -** windows primitives easily enough. The details are left as an -** exercise to the reader. -** -**** Restrictions Associated With SQLITE_ENABLE_MEMORY_MANAGEMENT **** -** -** If you compile with SQLITE_ENABLE_MEMORY_MANAGEMENT defined, then -** SQLite includes code that tracks how much memory is being used by -** each thread. These memory counts can become confused if memory -** is allocated by one thread and then freed by another. For that -** reason, when SQLITE_ENABLE_MEMORY_MANAGEMENT is used, all operations -** that might allocate or free memory should be performanced in the same -** thread that originally created the database connection. In that case, -** many of the operations that are listed above as safe to be performed -** in separate threads would need to be sent over to the server to be -** done there. If SQLITE_ENABLE_MEMORY_MANAGEMENT is defined, then -** the following functions can be used safely from different threads -** without messing up the allocation counts: -** -** sqlite3_bind_parameter_name -** sqlite3_bind_parameter_index -** sqlite3_changes -** sqlite3_column_blob -** sqlite3_column_count -** sqlite3_complete -** sqlite3_data_count -** sqlite3_db_handle -** sqlite3_errcode -** sqlite3_errmsg -** sqlite3_last_insert_rowid -** sqlite3_total_changes -** -** The remaining functions are not thread-safe when memory management -** is enabled. So one would have to define some new interface routines -** along the following lines: -** -** sqlite3_client_bind_* -** sqlite3_client_clear_bindings -** sqlite3_client_column_* -** sqlite3_client_create_collation -** sqlite3_client_create_function -** sqlite3_client_transfer_bindings -** -** The example code in this file is intended for use with memory -** management turned off. So the implementation of these additional -** client interfaces is left as an exercise to the reader. -** -** It may seem surprising to the reader that the list of safe functions -** above does not include things like sqlite3_bind_int() or -** sqlite3_column_int(). But those routines might, in fact, allocate -** or deallocate memory. In the case of sqlite3_bind_int(), if the -** parameter was previously bound to a string that string might need -** to be deallocated before the new integer value is inserted. In -** the case of sqlite3_column_int(), the value of the column might be -** a UTF-16 string which will need to be converted to UTF-8 then into -** an integer. -*/ - -/* Include this to get the definition of SQLITE_THREADSAFE, in the -** case that default values are used. -*/ -#include "sqliteInt.h" - -/* -** Only compile the code in this file on UNIX with a SQLITE_THREADSAFE build -** and only if the SQLITE_SERVER macro is defined. -*/ -#if defined(SQLITE_SERVER) && !defined(SQLITE_OMIT_SHARED_CACHE) -#if SQLITE_OS_UNIX && SQLITE_THREADSAFE - -/* -** We require only pthreads and the public interface of SQLite. -*/ -#include <pthread.h> -#include "sqlite3.h" - -/* -** Messages are passed from client to server and back again as -** instances of the following structure. -*/ -typedef struct SqlMessage SqlMessage; -struct SqlMessage { - int op; /* Opcode for the message */ - sqlite3 *pDb; /* The SQLite connection */ - sqlite3_stmt *pStmt; /* A specific statement */ - int errCode; /* Error code returned */ - const char *zIn; /* Input filename or SQL statement */ - int nByte; /* Size of the zIn parameter for prepare() */ - const char *zOut; /* Tail of the SQL statement */ - SqlMessage *pNext; /* Next message in the queue */ - SqlMessage *pPrev; /* Previous message in the queue */ - pthread_mutex_t clientMutex; /* Hold this mutex to access the message */ - pthread_cond_t clientWakeup; /* Signal to wake up the client */ -}; - -/* -** Legal values for SqlMessage.op -*/ -#define MSG_Open 1 /* sqlite3_open(zIn, &pDb) */ -#define MSG_Prepare 2 /* sqlite3_prepare(pDb, zIn, nByte, &pStmt, &zOut) */ -#define MSG_Step 3 /* sqlite3_step(pStmt) */ -#define MSG_Reset 4 /* sqlite3_reset(pStmt) */ -#define MSG_Finalize 5 /* sqlite3_finalize(pStmt) */ -#define MSG_Close 6 /* sqlite3_close(pDb) */ -#define MSG_Done 7 /* Server has finished with this message */ - - -/* -** State information about the server is stored in a static variable -** named "g" as follows: -*/ -static struct ServerState { - pthread_mutex_t queueMutex; /* Hold this mutex to access the msg queue */ - pthread_mutex_t serverMutex; /* Held by the server while it is running */ - pthread_cond_t serverWakeup; /* Signal this condvar to wake up the server */ - volatile int serverHalt; /* Server halts itself when true */ - SqlMessage *pQueueHead; /* Head of the message queue */ - SqlMessage *pQueueTail; /* Tail of the message queue */ -} g = { - PTHREAD_MUTEX_INITIALIZER, - PTHREAD_MUTEX_INITIALIZER, - PTHREAD_COND_INITIALIZER, -}; - -/* -** Send a message to the server. Block until we get a reply. -** -** The mutex and condition variable in the message are uninitialized -** when this routine is called. This routine takes care of -** initializing them and destroying them when it has finished. -*/ -static void sendToServer(SqlMessage *pMsg){ - /* Initialize the mutex and condition variable on the message - */ - pthread_mutex_init(&pMsg->clientMutex, 0); - pthread_cond_init(&pMsg->clientWakeup, 0); - - /* Add the message to the head of the server's message queue. - */ - pthread_mutex_lock(&g.queueMutex); - pMsg->pNext = g.pQueueHead; - if( g.pQueueHead==0 ){ - g.pQueueTail = pMsg; - }else{ - g.pQueueHead->pPrev = pMsg; - } - pMsg->pPrev = 0; - g.pQueueHead = pMsg; - pthread_mutex_unlock(&g.queueMutex); - - /* Signal the server that the new message has be queued, then - ** block waiting for the server to process the message. - */ - pthread_mutex_lock(&pMsg->clientMutex); - pthread_cond_signal(&g.serverWakeup); - while( pMsg->op!=MSG_Done ){ - pthread_cond_wait(&pMsg->clientWakeup, &pMsg->clientMutex); - } - pthread_mutex_unlock(&pMsg->clientMutex); - - /* Destroy the mutex and condition variable of the message. - */ - pthread_mutex_destroy(&pMsg->clientMutex); - pthread_cond_destroy(&pMsg->clientWakeup); -} - -/* -** The following 6 routines are client-side implementations of the -** core SQLite interfaces: -** -** sqlite3_open -** sqlite3_prepare -** sqlite3_step -** sqlite3_reset -** sqlite3_finalize -** sqlite3_close -** -** Clients should use the following client-side routines instead of -** the core routines above. -** -** sqlite3_client_open -** sqlite3_client_prepare -** sqlite3_client_step -** sqlite3_client_reset -** sqlite3_client_finalize -** sqlite3_client_close -** -** Each of these routines creates a message for the desired operation, -** sends that message to the server, waits for the server to process -** then message and return a response. -*/ -int sqlite3_client_open(const char *zDatabaseName, sqlite3 **ppDb){ - SqlMessage msg; - msg.op = MSG_Open; - msg.zIn = zDatabaseName; - sendToServer(&msg); - *ppDb = msg.pDb; - return msg.errCode; -} -int sqlite3_client_prepare( - sqlite3 *pDb, - const char *zSql, - int nByte, - sqlite3_stmt **ppStmt, - const char **pzTail -){ - SqlMessage msg; - msg.op = MSG_Prepare; - msg.pDb = pDb; - msg.zIn = zSql; - msg.nByte = nByte; - sendToServer(&msg); - *ppStmt = msg.pStmt; - if( pzTail ) *pzTail = msg.zOut; - return msg.errCode; -} -int sqlite3_client_step(sqlite3_stmt *pStmt){ - SqlMessage msg; - msg.op = MSG_Step; - msg.pStmt = pStmt; - sendToServer(&msg); - return msg.errCode; -} -int sqlite3_client_reset(sqlite3_stmt *pStmt){ - SqlMessage msg; - msg.op = MSG_Reset; - msg.pStmt = pStmt; - sendToServer(&msg); - return msg.errCode; -} -int sqlite3_client_finalize(sqlite3_stmt *pStmt){ - SqlMessage msg; - msg.op = MSG_Finalize; - msg.pStmt = pStmt; - sendToServer(&msg); - return msg.errCode; -} -int sqlite3_client_close(sqlite3 *pDb){ - SqlMessage msg; - msg.op = MSG_Close; - msg.pDb = pDb; - sendToServer(&msg); - return msg.errCode; -} - -/* -** This routine implements the server. To start the server, first -** make sure g.serverHalt is false, then create a new detached thread -** on this procedure. See the sqlite3_server_start() routine below -** for an example. This procedure loops until g.serverHalt becomes -** true. -*/ -void *sqlite3_server(void *NotUsed){ - if( pthread_mutex_trylock(&g.serverMutex) ){ - return 0; /* Another server is already running */ - } - sqlite3_enable_shared_cache(1); - while( !g.serverHalt ){ - SqlMessage *pMsg; - - /* Remove the last message from the message queue. - */ - pthread_mutex_lock(&g.queueMutex); - while( g.pQueueTail==0 && g.serverHalt==0 ){ - pthread_cond_wait(&g.serverWakeup, &g.queueMutex); - } - pMsg = g.pQueueTail; - if( pMsg ){ - if( pMsg->pPrev ){ - pMsg->pPrev->pNext = 0; - }else{ - g.pQueueHead = 0; - } - g.pQueueTail = pMsg->pPrev; - } - pthread_mutex_unlock(&g.queueMutex); - if( pMsg==0 ) break; - - /* Process the message just removed - */ - pthread_mutex_lock(&pMsg->clientMutex); - switch( pMsg->op ){ - case MSG_Open: { - pMsg->errCode = sqlite3_open(pMsg->zIn, &pMsg->pDb); - break; - } - case MSG_Prepare: { - pMsg->errCode = sqlite3_prepare(pMsg->pDb, pMsg->zIn, pMsg->nByte, - &pMsg->pStmt, &pMsg->zOut); - break; - } - case MSG_Step: { - pMsg->errCode = sqlite3_step(pMsg->pStmt); - break; - } - case MSG_Reset: { - pMsg->errCode = sqlite3_reset(pMsg->pStmt); - break; - } - case MSG_Finalize: { - pMsg->errCode = sqlite3_finalize(pMsg->pStmt); - break; - } - case MSG_Close: { - pMsg->errCode = sqlite3_close(pMsg->pDb); - break; - } - } - - /* Signal the client that the message has been processed. - */ - pMsg->op = MSG_Done; - pthread_mutex_unlock(&pMsg->clientMutex); - pthread_cond_signal(&pMsg->clientWakeup); - } - pthread_mutex_unlock(&g.serverMutex); - return 0; -} - -/* -** Start a server thread if one is not already running. If there -** is aleady a server thread running, the new thread will quickly -** die and this routine is effectively a no-op. -*/ -void sqlite3_server_start(void){ - pthread_t x; - int rc; - g.serverHalt = 0; - rc = pthread_create(&x, 0, sqlite3_server, 0); - if( rc==0 ){ - pthread_detach(x); - } -} - -/* -** A wrapper around sqlite3_server() that decrements the int variable -** pointed to by the first argument after the sqlite3_server() call -** returns. -*/ -static void *serverWrapper(void *pnDecr){ - void *p = sqlite3_server(0); - (*(int*)pnDecr)--; - return p; -} - -/* -** This function is the similar to sqlite3_server_start(), except that -** the integer pointed to by the first argument is decremented when -** the server thread exits. -*/ -void sqlite3_server_start2(int *pnDecr){ - pthread_t x; - int rc; - g.serverHalt = 0; - rc = pthread_create(&x, 0, serverWrapper, (void*)pnDecr); - if( rc==0 ){ - pthread_detach(x); - } -} - -/* -** If a server thread is running, then stop it. If no server is -** running, this routine is effectively a no-op. -** -** This routine waits until the server has actually stopped before -** returning. -*/ -void sqlite3_server_stop(void){ - g.serverHalt = 1; - pthread_cond_broadcast(&g.serverWakeup); - pthread_mutex_lock(&g.serverMutex); - pthread_mutex_unlock(&g.serverMutex); -} - -#endif /* SQLITE_OS_UNIX && SQLITE_THREADSAFE */ -#endif /* defined(SQLITE_SERVER) */ diff --git a/components/external/SQLite-3.8.1/SQLiteLib/test/test_sqllog.c b/components/external/SQLite-3.8.1/SQLiteLib/test/test_sqllog.c deleted file mode 100644 index 4aa68b7c42..0000000000 --- a/components/external/SQLite-3.8.1/SQLiteLib/test/test_sqllog.c +++ /dev/null @@ -1,507 +0,0 @@ -/* -** 2012 November 26 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** -** OVERVIEW -** -** This file contains experimental code used to record data from live -** SQLite applications that may be useful for offline analysis. -** Specifically, this module can be used to capture the following -** information: -** -** 1) The initial contents of all database files opened by the -** application, and -** -** 2) All SQL statements executed by the application. -** -** The captured information can then be used to run (for example) -** performance analysis looking for slow queries or to look for -** optimization opportunities in either the application or in SQLite -** itself. -** -** USAGE -** -** To use this module, SQLite must be compiled with the SQLITE_ENABLE_SQLLOG -** pre-processor symbol defined and this file linked into the application. -** One way to link this file into the application is to append the content -** of this file onto the end of the "sqlite3.c" amalgamation and then -** recompile the application as normal except with the addition of the -** -DSQLITE_ENABLE_SQLLOG option. -** -** At runtime, logging is enabled by setting environment variable -** SQLITE_SQLLOG_DIR to the name of a directory in which to store logged -** data. The logging directory must already exist. -** -** Usually, if the application opens the same database file more than once -** (either by attaching it or by using more than one database handle), only -** a single copy is made. This behavior may be overridden (so that a -** separate copy is taken each time the database file is opened or attached) -** by setting the environment variable SQLITE_SQLLOG_REUSE_FILES to 0. -** -** OUTPUT: -** -** The SQLITE_SQLLOG_DIR is populated with three types of files: -** -** sqllog_N.db - Copies of database files. N may be any integer. -** -** sqllog_N.sql - A list of SQL statements executed by a single -** connection. N may be any integer. -** -** sqllog.idx - An index mapping from integer N to a database -** file name - indicating the full path of the -** database from which sqllog_N.db was copied. -** -** ERROR HANDLING: -** -** This module attempts to make a best effort to continue logging if an -** IO or other error is encountered. For example, if a log file cannot -** be opened logs are not collected for that connection, but other -** logging proceeds as expected. Errors are logged by calling sqlite3_log(). -*/ - -#ifndef _SQLITE3_H_ -#include "sqlite3.h" -#endif -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <assert.h> - -#include <sys/types.h> -#include <unistd.h> -static int getProcessId(void){ -#if SQLITE_OS_WIN - return (int)_getpid(); -#else - return (int)getpid(); -#endif -} - -/* Names of environment variables to be used */ -#define ENVIRONMENT_VARIABLE1_NAME "SQLITE_SQLLOG_DIR" -#define ENVIRONMENT_VARIABLE2_NAME "SQLITE_SQLLOG_REUSE_FILES" - -/* Assume that all database and database file names are shorted than this. */ -#define SQLLOG_NAMESZ 512 - -/* Maximum number of simultaneous database connections the process may -** open (if any more are opened an error is logged using sqlite3_log() -** and processing is halted). -*/ -#define MAX_CONNECTIONS 256 - -/* There is one instance of this object for each SQLite database connection -** that is being logged. -*/ -struct SLConn { - int isErr; /* True if an error has occurred */ - sqlite3 *db; /* Connection handle */ - int iLog; /* First integer value used in file names */ - FILE *fd; /* File descriptor for log file */ -}; - -/* This object is a singleton that keeps track of all data loggers. -*/ -static struct SLGlobal { - /* Protected by MUTEX_STATIC_MASTER */ - sqlite3_mutex *mutex; /* Recursive mutex */ - int nConn; /* Size of aConn[] array */ - - /* Protected by SLGlobal.mutex */ - int bReuse; /* True to avoid extra copies of db files */ - char zPrefix[SQLLOG_NAMESZ]; /* Prefix for all created files */ - char zIdx[SQLLOG_NAMESZ]; /* Full path to *.idx file */ - int iNextLog; /* Used to allocate file names */ - int iNextDb; /* Used to allocate database file names */ - int bRec; /* True if testSqllog() is called rec. */ - int iClock; /* Clock value */ - struct SLConn aConn[MAX_CONNECTIONS]; -} sqllogglobal; - -/* -** Return true if c is an ASCII whitespace character. -*/ -static int sqllog_isspace(char c){ - return (c==' ' || c=='\t' || c=='\n' || c=='\v' || c=='\f' || c=='\r'); -} - -/* -** The first argument points to a nul-terminated string containing an SQL -** command. Before returning, this function sets *pz to point to the start -** of the first token in this command, and *pn to the number of bytes in -** the token. This is used to check if the SQL command is an "ATTACH" or -** not. -*/ -static void sqllogTokenize(const char *z, const char **pz, int *pn){ - const char *p = z; - int n; - - /* Skip past any whitespace */ - while( sqllog_isspace(*p) ){ - p++; - } - - /* Figure out how long the first token is */ - *pz = p; - n = 0; - while( (p[n]>='a' && p[n]<='z') || (p[n]>='A' && p[n]<='Z') ) n++; - *pn = n; -} - -/* -** Check if the logs directory already contains a copy of database file -** zFile. If so, return a pointer to the full path of the copy. Otherwise, -** return NULL. -** -** If a non-NULL value is returned, then the caller must arrange to -** eventually free it using sqlite3_free(). -*/ -static char *sqllogFindFile(const char *zFile){ - char *zRet = 0; - FILE *fd = 0; - - /* Open the index file for reading */ - fd = fopen(sqllogglobal.zIdx, "r"); - if( fd==0 ){ - sqlite3_log(SQLITE_IOERR, "sqllogFindFile(): error in fopen()"); - return 0; - } - - /* Loop through each entry in the index file. If zFile is not NULL and the - ** entry is a match, then set zRet to point to the filename of the existing - ** copy and break out of the loop. */ - while( feof(fd)==0 ){ - char zLine[SQLLOG_NAMESZ*2+5]; - if( fgets(zLine, sizeof(zLine), fd) ){ - int n; - char *z; - - zLine[sizeof(zLine)-1] = '\0'; - z = zLine; - while( *z>='0' && *z<='9' ) z++; - while( *z==' ' ) z++; - - n = strlen(z); - while( n>0 && sqllog_isspace(z[n-1]) ) n--; - - if( n==strlen(zFile) && 0==memcmp(zFile, z, n) ){ - char zBuf[16]; - memset(zBuf, 0, sizeof(zBuf)); - z = zLine; - while( *z>='0' && *z<='9' ){ - zBuf[z-zLine] = *z; - z++; - } - zRet = sqlite3_mprintf("%s_%s.db", sqllogglobal.zPrefix, zBuf); - break; - } - } - } - - if( ferror(fd) ){ - sqlite3_log(SQLITE_IOERR, "sqllogFindFile(): error reading index file"); - } - - fclose(fd); - return zRet; -} - -static int sqllogFindAttached( - struct SLConn *p, /* Database connection */ - const char *zSearch, /* Name to search for (or NULL) */ - char *zName, /* OUT: Name of attached database */ - char *zFile /* OUT: Name of attached file */ -){ - sqlite3_stmt *pStmt; - int rc; - - /* The "PRAGMA database_list" command returns a list of databases in the - ** order that they were attached. So a newly attached database is - ** described by the last row returned. */ - assert( sqllogglobal.bRec==0 ); - sqllogglobal.bRec = 1; - rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0); - if( rc==SQLITE_OK ){ - while( SQLITE_ROW==sqlite3_step(pStmt) ){ - const char *zVal1; int nVal1; - const char *zVal2; int nVal2; - - zVal1 = (const char*)sqlite3_column_text(pStmt, 1); - nVal1 = sqlite3_column_bytes(pStmt, 1); - memcpy(zName, zVal1, nVal1+1); - - zVal2 = (const char*)sqlite3_column_text(pStmt, 2); - nVal2 = sqlite3_column_bytes(pStmt, 2); - memcpy(zFile, zVal2, nVal2+1); - - if( zSearch && strlen(zSearch)==nVal1 - && 0==sqlite3_strnicmp(zSearch, zVal1, nVal1) - ){ - break; - } - } - rc = sqlite3_finalize(pStmt); - } - sqllogglobal.bRec = 0; - - if( rc!=SQLITE_OK ){ - sqlite3_log(rc, "sqllogFindAttached(): error in \"PRAGMA database_list\""); - } - return rc; -} - - -/* -** Parameter zSearch is the name of a database attached to the database -** connection associated with the first argument. This function creates -** a backup of this database in the logs directory. -** -** The name used for the backup file is automatically generated. Call -** it zFile. -** -** If the bLog parameter is true, then a statement of the following form -** is written to the log file associated with *p: -** -** ATTACH 'zFile' AS 'zName'; -** -** Otherwise, if bLog is false, a comment is added to the log file: -** -** -- Main database file is 'zFile' -** -** The SLGlobal.mutex mutex is always held when this function is called. -*/ -static void sqllogCopydb(struct SLConn *p, const char *zSearch, int bLog){ - char zName[SQLLOG_NAMESZ]; /* Attached database name */ - char zFile[SQLLOG_NAMESZ]; /* Database file name */ - char *zFree; - char *zInit = 0; - int rc; - - rc = sqllogFindAttached(p, zSearch, zName, zFile); - if( rc!=SQLITE_OK ) return; - - if( zFile[0]=='\0' ){ - zInit = sqlite3_mprintf(""); - }else{ - if( sqllogglobal.bReuse ){ - zInit = sqllogFindFile(zFile); - }else{ - zInit = 0; - } - if( zInit==0 ){ - int rc; - sqlite3 *copy = 0; - int iDb; - - /* Generate a file-name to use for the copy of this database */ - iDb = sqllogglobal.iNextDb++; - zInit = sqlite3_mprintf("%s_%d.db", sqllogglobal.zPrefix, iDb); - - /* Create the backup */ - assert( sqllogglobal.bRec==0 ); - sqllogglobal.bRec = 1; - rc = sqlite3_open(zInit, ©); - if( rc==SQLITE_OK ){ - sqlite3_backup *pBak; - sqlite3_exec(copy, "PRAGMA synchronous = 0", 0, 0, 0); - pBak = sqlite3_backup_init(copy, "main", p->db, zName); - if( pBak ){ - sqlite3_backup_step(pBak, -1); - rc = sqlite3_backup_finish(pBak); - }else{ - rc = sqlite3_errcode(copy); - } - sqlite3_close(copy); - } - sqllogglobal.bRec = 0; - - if( rc==SQLITE_OK ){ - /* Write an entry into the database index file */ - FILE *fd = fopen(sqllogglobal.zIdx, "a"); - if( fd ){ - fprintf(fd, "%d %s\n", iDb, zFile); - fclose(fd); - } - }else{ - sqlite3_log(rc, "sqllogCopydb(): error backing up database"); - } - } - } - - if( bLog ){ - zFree = sqlite3_mprintf("ATTACH '%q' AS '%q'; -- clock=%d\n", - zInit, zName, sqllogglobal.iClock++ - ); - }else{ - zFree = sqlite3_mprintf("-- Main database is '%q'\n", zInit); - } - fprintf(p->fd, "%s", zFree); - sqlite3_free(zFree); - - sqlite3_free(zInit); -} - -/* -** If it is not already open, open the log file for connection *p. -** -** The SLGlobal.mutex mutex is always held when this function is called. -*/ -static void sqllogOpenlog(struct SLConn *p){ - /* If the log file has not yet been opened, open it now. */ - if( p->fd==0 ){ - char *zLog; - - /* If it is still NULL, have global.zPrefix point to a copy of - ** environment variable $ENVIRONMENT_VARIABLE1_NAME. */ - if( sqllogglobal.zPrefix[0]==0 ){ - FILE *fd; - char *zVar = getenv(ENVIRONMENT_VARIABLE1_NAME); - if( zVar==0 || strlen(zVar)+10>=(sizeof(sqllogglobal.zPrefix)) ) return; - sprintf(sqllogglobal.zPrefix, "%s/sqllog_%d", zVar, getProcessId()); - sprintf(sqllogglobal.zIdx, "%s.idx", sqllogglobal.zPrefix); - if( getenv(ENVIRONMENT_VARIABLE2_NAME) ){ - sqllogglobal.bReuse = atoi(getenv(ENVIRONMENT_VARIABLE2_NAME)); - } - fd = fopen(sqllogglobal.zIdx, "w"); - if( fd ) fclose(fd); - } - - /* Open the log file */ - zLog = sqlite3_mprintf("%s_%d.sql", sqllogglobal.zPrefix, p->iLog); - p->fd = fopen(zLog, "w"); - sqlite3_free(zLog); - if( p->fd==0 ){ - sqlite3_log(SQLITE_IOERR, "sqllogOpenlog(): Failed to open log file"); - } - } -} - -/* -** This function is called if the SQLLOG callback is invoked to report -** execution of an SQL statement. Parameter p is the connection the statement -** was executed by and parameter zSql is the text of the statement itself. -*/ -static void testSqllogStmt(struct SLConn *p, const char *zSql){ - const char *zFirst; /* Pointer to first token in zSql */ - int nFirst; /* Size of token zFirst in bytes */ - - sqllogTokenize(zSql, &zFirst, &nFirst); - if( nFirst!=6 || 0!=sqlite3_strnicmp("ATTACH", zFirst, 6) ){ - /* Not an ATTACH statement. Write this directly to the log. */ - fprintf(p->fd, "%s; -- clock=%d\n", zSql, sqllogglobal.iClock++); - }else{ - /* This is an ATTACH statement. Copy the database. */ - sqllogCopydb(p, 0, 1); - } -} - -/* -** The SQLITE_CONFIG_SQLLOG callback registered by sqlite3_init_sqllog(). -** -** The eType parameter has the following values: -** -** 0: Opening a new database connection. zSql is the name of the -** file being opened. db is a pointer to the newly created database -** connection. -** -** 1: An SQL statement has run to completion. zSql is the text of the -** SQL statement with all parameters expanded to their actual values. -** -** 2: Closing a database connection. zSql is NULL. The db pointer to -** the database connection being closed has already been shut down -** and cannot be used for any further SQL. -** -** The pCtx parameter is a copy of the pointer that was originally passed -** into the sqlite3_config(SQLITE_CONFIG_SQLLOG) statement. In this -** particular implementation, pCtx is always a pointer to the -** sqllogglobal global variable define above. -*/ -static void testSqllog(void *pCtx, sqlite3 *db, const char *zSql, int eType){ - struct SLConn *p = 0; - sqlite3_mutex *master = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER); - - assert( eType==0 || eType==1 || eType==2 ); - assert( (eType==2)==(zSql==0) ); - - /* This is a database open command. */ - if( eType==0 ){ - sqlite3_mutex_enter(master); - if( sqllogglobal.mutex==0 ){ - sqllogglobal.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_RECURSIVE); - } - p = &sqllogglobal.aConn[sqllogglobal.nConn++]; - p->fd = 0; - p->db = db; - p->iLog = sqllogglobal.iNextLog++; - sqlite3_mutex_leave(master); - - /* Open the log and take a copy of the main database file */ - sqlite3_mutex_enter(sqllogglobal.mutex); - if( sqllogglobal.bRec==0 ){ - sqllogOpenlog(p); - if( p->fd ) sqllogCopydb(p, "main", 0); - } - sqlite3_mutex_leave(sqllogglobal.mutex); - } - - else{ - - int i; - for(i=0; i<sqllogglobal.nConn; i++){ - p = &sqllogglobal.aConn[i]; - if( p->db==db ) break; - } - if( i==sqllogglobal.nConn ) return; - - /* A database handle close command */ - if( eType==2 ){ - sqlite3_mutex_enter(master); - if( p->fd ) fclose(p->fd); - p->db = 0; - p->fd = 0; - - sqllogglobal.nConn--; - if( sqllogglobal.nConn==0 ){ - sqlite3_mutex_free(sqllogglobal.mutex); - sqllogglobal.mutex = 0; - }else{ - int nShift = &sqllogglobal.aConn[sqllogglobal.nConn] - p; - if( nShift>0 ){ - memmove(p, &p[1], nShift*sizeof(struct SLConn)); - } - } - sqlite3_mutex_leave(master); - - /* An ordinary SQL command. */ - }else if( p->fd ){ - sqlite3_mutex_enter(sqllogglobal.mutex); - if( sqllogglobal.bRec==0 ){ - testSqllogStmt(p, zSql); - } - sqlite3_mutex_leave(sqllogglobal.mutex); - } - } -} - -/* -** This function is called either before sqlite3_initialized() or by it. -** It checks if the SQLITE_SQLLOG_DIR variable is defined, and if so -** registers an SQLITE_CONFIG_SQLLOG callback to record the applications -** database activity. -*/ -void sqlite3_init_sqllog(void){ - if( getenv(ENVIRONMENT_VARIABLE1_NAME) ){ - if( SQLITE_OK==sqlite3_config(SQLITE_CONFIG_SQLLOG, testSqllog, 0) ){ - memset(&sqllogglobal, 0, sizeof(sqllogglobal)); - sqllogglobal.bReuse = 1; - } - } -} diff --git a/components/external/SQLite-3.8.1/SQLiteLib/test/test_stat.c b/components/external/SQLite-3.8.1/SQLiteLib/test/test_stat.c deleted file mode 100644 index d4c902b5ea..0000000000 --- a/components/external/SQLite-3.8.1/SQLiteLib/test/test_stat.c +++ /dev/null @@ -1,639 +0,0 @@ -/* -** 2010 July 12 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -****************************************************************************** -** -** This file contains an implementation of the "dbstat" virtual table. -** -** The dbstat virtual table is used to extract low-level formatting -** information from an SQLite database in order to implement the -** "sqlite3_analyzer" utility. See the ../tool/spaceanal.tcl script -** for an example implementation. -*/ - -#ifndef SQLITE_AMALGAMATION -# include "sqliteInt.h" -#endif - -#ifndef SQLITE_OMIT_VIRTUALTABLE - -/* -** Page paths: -** -** The value of the 'path' column describes the path taken from the -** root-node of the b-tree structure to each page. The value of the -** root-node path is '/'. -** -** The value of the path for the left-most child page of the root of -** a b-tree is '/000/'. (Btrees store content ordered from left to right -** so the pages to the left have smaller keys than the pages to the right.) -** The next to left-most child of the root page is -** '/001', and so on, each sibling page identified by a 3-digit hex -** value. The children of the 451st left-most sibling have paths such -** as '/1c2/000/, '/1c2/001/' etc. -** -** Overflow pages are specified by appending a '+' character and a -** six-digit hexadecimal value to the path to the cell they are linked -** from. For example, the three overflow pages in a chain linked from -** the left-most cell of the 450th child of the root page are identified -** by the paths: -** -** '/1c2/000+000000' // First page in overflow chain -** '/1c2/000+000001' // Second page in overflow chain -** '/1c2/000+000002' // Third page in overflow chain -** -** If the paths are sorted using the BINARY collation sequence, then -** the overflow pages associated with a cell will appear earlier in the -** sort-order than its child page: -** -** '/1c2/000/' // Left-most child of 451st child of root -*/ -#define VTAB_SCHEMA \ - "CREATE TABLE xx( " \ - " name STRING, /* Name of table or index */" \ - " path INTEGER, /* Path to page from root */" \ - " pageno INTEGER, /* Page number */" \ - " pagetype STRING, /* 'internal', 'leaf' or 'overflow' */" \ - " ncell INTEGER, /* Cells on page (0 for overflow) */" \ - " payload INTEGER, /* Bytes of payload on this page */" \ - " unused INTEGER, /* Bytes of unused space on this page */" \ - " mx_payload INTEGER, /* Largest payload size of all cells */" \ - " pgoffset INTEGER, /* Offset of page in file */" \ - " pgsize INTEGER /* Size of the page */" \ - ");" - - -typedef struct StatTable StatTable; -typedef struct StatCursor StatCursor; -typedef struct StatPage StatPage; -typedef struct StatCell StatCell; - -struct StatCell { - int nLocal; /* Bytes of local payload */ - u32 iChildPg; /* Child node (or 0 if this is a leaf) */ - int nOvfl; /* Entries in aOvfl[] */ - u32 *aOvfl; /* Array of overflow page numbers */ - int nLastOvfl; /* Bytes of payload on final overflow page */ - int iOvfl; /* Iterates through aOvfl[] */ -}; - -struct StatPage { - u32 iPgno; - DbPage *pPg; - int iCell; - - char *zPath; /* Path to this page */ - - /* Variables populated by statDecodePage(): */ - u8 flags; /* Copy of flags byte */ - int nCell; /* Number of cells on page */ - int nUnused; /* Number of unused bytes on page */ - StatCell *aCell; /* Array of parsed cells */ - u32 iRightChildPg; /* Right-child page number (or 0) */ - int nMxPayload; /* Largest payload of any cell on this page */ -}; - -struct StatCursor { - sqlite3_vtab_cursor base; - sqlite3_stmt *pStmt; /* Iterates through set of root pages */ - int isEof; /* After pStmt has returned SQLITE_DONE */ - - StatPage aPage[32]; - int iPage; /* Current entry in aPage[] */ - - /* Values to return. */ - char *zName; /* Value of 'name' column */ - char *zPath; /* Value of 'path' column */ - u32 iPageno; /* Value of 'pageno' column */ - char *zPagetype; /* Value of 'pagetype' column */ - int nCell; /* Value of 'ncell' column */ - int nPayload; /* Value of 'payload' column */ - int nUnused; /* Value of 'unused' column */ - int nMxPayload; /* Value of 'mx_payload' column */ - i64 iOffset; /* Value of 'pgOffset' column */ - int szPage; /* Value of 'pgSize' column */ -}; - -struct StatTable { - sqlite3_vtab base; - sqlite3 *db; -}; - -#ifndef get2byte -# define get2byte(x) ((x)[0]<<8 | (x)[1]) -#endif - -/* -** Connect to or create a statvfs virtual table. -*/ -static int statConnect( - sqlite3 *db, - void *pAux, - int argc, const char *const*argv, - sqlite3_vtab **ppVtab, - char **pzErr -){ - StatTable *pTab; - - pTab = (StatTable *)sqlite3_malloc(sizeof(StatTable)); - memset(pTab, 0, sizeof(StatTable)); - pTab->db = db; - - sqlite3_declare_vtab(db, VTAB_SCHEMA); - *ppVtab = &pTab->base; - return SQLITE_OK; -} - -/* -** Disconnect from or destroy a statvfs virtual table. -*/ -static int statDisconnect(sqlite3_vtab *pVtab){ - sqlite3_free(pVtab); - return SQLITE_OK; -} - -/* -** There is no "best-index". This virtual table always does a linear -** scan of the binary VFS log file. -*/ -static int statBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ - - /* Records are always returned in ascending order of (name, path). - ** If this will satisfy the client, set the orderByConsumed flag so that - ** SQLite does not do an external sort. - */ - if( ( pIdxInfo->nOrderBy==1 - && pIdxInfo->aOrderBy[0].iColumn==0 - && pIdxInfo->aOrderBy[0].desc==0 - ) || - ( pIdxInfo->nOrderBy==2 - && pIdxInfo->aOrderBy[0].iColumn==0 - && pIdxInfo->aOrderBy[0].desc==0 - && pIdxInfo->aOrderBy[1].iColumn==1 - && pIdxInfo->aOrderBy[1].desc==0 - ) - ){ - pIdxInfo->orderByConsumed = 1; - } - - pIdxInfo->estimatedCost = 10.0; - return SQLITE_OK; -} - -/* -** Open a new statvfs cursor. -*/ -static int statOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){ - StatTable *pTab = (StatTable *)pVTab; - StatCursor *pCsr; - int rc; - - pCsr = (StatCursor *)sqlite3_malloc(sizeof(StatCursor)); - memset(pCsr, 0, sizeof(StatCursor)); - pCsr->base.pVtab = pVTab; - - rc = sqlite3_prepare_v2(pTab->db, - "SELECT 'sqlite_master' AS name, 1 AS rootpage, 'table' AS type" - " UNION ALL " - "SELECT name, rootpage, type FROM sqlite_master WHERE rootpage!=0" - " ORDER BY name", -1, - &pCsr->pStmt, 0 - ); - if( rc!=SQLITE_OK ){ - sqlite3_free(pCsr); - return rc; - } - - *ppCursor = (sqlite3_vtab_cursor *)pCsr; - return SQLITE_OK; -} - -static void statClearPage(StatPage *p){ - int i; - for(i=0; i<p->nCell; i++){ - sqlite3_free(p->aCell[i].aOvfl); - } - sqlite3PagerUnref(p->pPg); - sqlite3_free(p->aCell); - sqlite3_free(p->zPath); - memset(p, 0, sizeof(StatPage)); -} - -static void statResetCsr(StatCursor *pCsr){ - int i; - sqlite3_reset(pCsr->pStmt); - for(i=0; i<ArraySize(pCsr->aPage); i++){ - statClearPage(&pCsr->aPage[i]); - } - pCsr->iPage = 0; - sqlite3_free(pCsr->zPath); - pCsr->zPath = 0; -} - -/* -** Close a statvfs cursor. -*/ -static int statClose(sqlite3_vtab_cursor *pCursor){ - StatCursor *pCsr = (StatCursor *)pCursor; - statResetCsr(pCsr); - sqlite3_finalize(pCsr->pStmt); - sqlite3_free(pCsr); - return SQLITE_OK; -} - -static void getLocalPayload( - int nUsable, /* Usable bytes per page */ - u8 flags, /* Page flags */ - int nTotal, /* Total record (payload) size */ - int *pnLocal /* OUT: Bytes stored locally */ -){ - int nLocal; - int nMinLocal; - int nMaxLocal; - - if( flags==0x0D ){ /* Table leaf node */ - nMinLocal = (nUsable - 12) * 32 / 255 - 23; - nMaxLocal = nUsable - 35; - }else{ /* Index interior and leaf nodes */ - nMinLocal = (nUsable - 12) * 32 / 255 - 23; - nMaxLocal = (nUsable - 12) * 64 / 255 - 23; - } - - nLocal = nMinLocal + (nTotal - nMinLocal) % (nUsable - 4); - if( nLocal>nMaxLocal ) nLocal = nMinLocal; - *pnLocal = nLocal; -} - -static int statDecodePage(Btree *pBt, StatPage *p){ - int nUnused; - int iOff; - int nHdr; - int isLeaf; - int szPage; - - u8 *aData = sqlite3PagerGetData(p->pPg); - u8 *aHdr = &aData[p->iPgno==1 ? 100 : 0]; - - p->flags = aHdr[0]; - p->nCell = get2byte(&aHdr[3]); - p->nMxPayload = 0; - - isLeaf = (p->flags==0x0A || p->flags==0x0D); - nHdr = 12 - isLeaf*4 + (p->iPgno==1)*100; - - nUnused = get2byte(&aHdr[5]) - nHdr - 2*p->nCell; - nUnused += (int)aHdr[7]; - iOff = get2byte(&aHdr[1]); - while( iOff ){ - nUnused += get2byte(&aData[iOff+2]); - iOff = get2byte(&aData[iOff]); - } - p->nUnused = nUnused; - p->iRightChildPg = isLeaf ? 0 : sqlite3Get4byte(&aHdr[8]); - szPage = sqlite3BtreeGetPageSize(pBt); - - if( p->nCell ){ - int i; /* Used to iterate through cells */ - int nUsable = szPage - sqlite3BtreeGetReserve(pBt); - - p->aCell = sqlite3_malloc((p->nCell+1) * sizeof(StatCell)); - memset(p->aCell, 0, (p->nCell+1) * sizeof(StatCell)); - - for(i=0; i<p->nCell; i++){ - StatCell *pCell = &p->aCell[i]; - - iOff = get2byte(&aData[nHdr+i*2]); - if( !isLeaf ){ - pCell->iChildPg = sqlite3Get4byte(&aData[iOff]); - iOff += 4; - } - if( p->flags==0x05 ){ - /* A table interior node. nPayload==0. */ - }else{ - u32 nPayload; /* Bytes of payload total (local+overflow) */ - int nLocal; /* Bytes of payload stored locally */ - iOff += getVarint32(&aData[iOff], nPayload); - if( p->flags==0x0D ){ - u64 dummy; - iOff += sqlite3GetVarint(&aData[iOff], &dummy); - } - if( nPayload>(u32)p->nMxPayload ) p->nMxPayload = nPayload; - getLocalPayload(nUsable, p->flags, nPayload, &nLocal); - pCell->nLocal = nLocal; - assert( nLocal>=0 ); - assert( nPayload>=(u32)nLocal ); - assert( nLocal<=(nUsable-35) ); - if( nPayload>(u32)nLocal ){ - int j; - int nOvfl = ((nPayload - nLocal) + nUsable-4 - 1) / (nUsable - 4); - pCell->nLastOvfl = (nPayload-nLocal) - (nOvfl-1) * (nUsable-4); - pCell->nOvfl = nOvfl; - pCell->aOvfl = sqlite3_malloc(sizeof(u32)*nOvfl); - pCell->aOvfl[0] = sqlite3Get4byte(&aData[iOff+nLocal]); - for(j=1; j<nOvfl; j++){ - int rc; - u32 iPrev = pCell->aOvfl[j-1]; - DbPage *pPg = 0; - rc = sqlite3PagerGet(sqlite3BtreePager(pBt), iPrev, &pPg); - if( rc!=SQLITE_OK ){ - assert( pPg==0 ); - return rc; - } - pCell->aOvfl[j] = sqlite3Get4byte(sqlite3PagerGetData(pPg)); - sqlite3PagerUnref(pPg); - } - } - } - } - } - - return SQLITE_OK; -} - -/* -** Populate the pCsr->iOffset and pCsr->szPage member variables. Based on -** the current value of pCsr->iPageno. -*/ -static void statSizeAndOffset(StatCursor *pCsr){ - StatTable *pTab = (StatTable *)((sqlite3_vtab_cursor *)pCsr)->pVtab; - Btree *pBt = pTab->db->aDb[0].pBt; - Pager *pPager = sqlite3BtreePager(pBt); - sqlite3_file *fd; - sqlite3_int64 x[2]; - - /* The default page size and offset */ - pCsr->szPage = sqlite3BtreeGetPageSize(pBt); - pCsr->iOffset = (i64)pCsr->szPage * (pCsr->iPageno - 1); - - /* If connected to a ZIPVFS backend, override the page size and - ** offset with actual values obtained from ZIPVFS. - */ - fd = sqlite3PagerFile(pPager); - x[0] = pCsr->iPageno; - if( sqlite3OsFileControl(fd, 230440, &x)==SQLITE_OK ){ - pCsr->iOffset = x[0]; - pCsr->szPage = (int)x[1]; - } -} - -/* -** Move a statvfs cursor to the next entry in the file. -*/ -static int statNext(sqlite3_vtab_cursor *pCursor){ - int rc; - int nPayload; - StatCursor *pCsr = (StatCursor *)pCursor; - StatTable *pTab = (StatTable *)pCursor->pVtab; - Btree *pBt = pTab->db->aDb[0].pBt; - Pager *pPager = sqlite3BtreePager(pBt); - - sqlite3_free(pCsr->zPath); - pCsr->zPath = 0; - - if( pCsr->aPage[0].pPg==0 ){ - rc = sqlite3_step(pCsr->pStmt); - if( rc==SQLITE_ROW ){ - int nPage; - u32 iRoot = (u32)sqlite3_column_int64(pCsr->pStmt, 1); - sqlite3PagerPagecount(pPager, &nPage); - if( nPage==0 ){ - pCsr->isEof = 1; - return sqlite3_reset(pCsr->pStmt); - } - rc = sqlite3PagerGet(pPager, iRoot, &pCsr->aPage[0].pPg); - pCsr->aPage[0].iPgno = iRoot; - pCsr->aPage[0].iCell = 0; - pCsr->aPage[0].zPath = sqlite3_mprintf("/"); - pCsr->iPage = 0; - }else{ - pCsr->isEof = 1; - return sqlite3_reset(pCsr->pStmt); - } - }else{ - - /* Page p itself has already been visited. */ - StatPage *p = &pCsr->aPage[pCsr->iPage]; - - while( p->iCell<p->nCell ){ - StatCell *pCell = &p->aCell[p->iCell]; - if( pCell->iOvfl<pCell->nOvfl ){ - int nUsable = sqlite3BtreeGetPageSize(pBt)-sqlite3BtreeGetReserve(pBt); - pCsr->zName = (char *)sqlite3_column_text(pCsr->pStmt, 0); - pCsr->iPageno = pCell->aOvfl[pCell->iOvfl]; - pCsr->zPagetype = "overflow"; - pCsr->nCell = 0; - pCsr->nMxPayload = 0; - pCsr->zPath = sqlite3_mprintf( - "%s%.3x+%.6x", p->zPath, p->iCell, pCell->iOvfl - ); - if( pCell->iOvfl<pCell->nOvfl-1 ){ - pCsr->nUnused = 0; - pCsr->nPayload = nUsable - 4; - }else{ - pCsr->nPayload = pCell->nLastOvfl; - pCsr->nUnused = nUsable - 4 - pCsr->nPayload; - } - pCell->iOvfl++; - statSizeAndOffset(pCsr); - return SQLITE_OK; - } - if( p->iRightChildPg ) break; - p->iCell++; - } - - while( !p->iRightChildPg || p->iCell>p->nCell ){ - statClearPage(p); - if( pCsr->iPage==0 ) return statNext(pCursor); - pCsr->iPage--; - p = &pCsr->aPage[pCsr->iPage]; - } - pCsr->iPage++; - assert( p==&pCsr->aPage[pCsr->iPage-1] ); - - if( p->iCell==p->nCell ){ - p[1].iPgno = p->iRightChildPg; - }else{ - p[1].iPgno = p->aCell[p->iCell].iChildPg; - } - rc = sqlite3PagerGet(pPager, p[1].iPgno, &p[1].pPg); - p[1].iCell = 0; - p[1].zPath = sqlite3_mprintf("%s%.3x/", p->zPath, p->iCell); - p->iCell++; - } - - - /* Populate the StatCursor fields with the values to be returned - ** by the xColumn() and xRowid() methods. - */ - if( rc==SQLITE_OK ){ - int i; - StatPage *p = &pCsr->aPage[pCsr->iPage]; - pCsr->zName = (char *)sqlite3_column_text(pCsr->pStmt, 0); - pCsr->iPageno = p->iPgno; - - statDecodePage(pBt, p); - statSizeAndOffset(pCsr); - - switch( p->flags ){ - case 0x05: /* table internal */ - case 0x02: /* index internal */ - pCsr->zPagetype = "internal"; - break; - case 0x0D: /* table leaf */ - case 0x0A: /* index leaf */ - pCsr->zPagetype = "leaf"; - break; - default: - pCsr->zPagetype = "corrupted"; - break; - } - pCsr->nCell = p->nCell; - pCsr->nUnused = p->nUnused; - pCsr->nMxPayload = p->nMxPayload; - pCsr->zPath = sqlite3_mprintf("%s", p->zPath); - nPayload = 0; - for(i=0; i<p->nCell; i++){ - nPayload += p->aCell[i].nLocal; - } - pCsr->nPayload = nPayload; - } - - return rc; -} - -static int statEof(sqlite3_vtab_cursor *pCursor){ - StatCursor *pCsr = (StatCursor *)pCursor; - return pCsr->isEof; -} - -static int statFilter( - sqlite3_vtab_cursor *pCursor, - int idxNum, const char *idxStr, - int argc, sqlite3_value **argv -){ - StatCursor *pCsr = (StatCursor *)pCursor; - - statResetCsr(pCsr); - return statNext(pCursor); -} - -static int statColumn( - sqlite3_vtab_cursor *pCursor, - sqlite3_context *ctx, - int i -){ - StatCursor *pCsr = (StatCursor *)pCursor; - switch( i ){ - case 0: /* name */ - sqlite3_result_text(ctx, pCsr->zName, -1, SQLITE_STATIC); - break; - case 1: /* path */ - sqlite3_result_text(ctx, pCsr->zPath, -1, SQLITE_TRANSIENT); - break; - case 2: /* pageno */ - sqlite3_result_int64(ctx, pCsr->iPageno); - break; - case 3: /* pagetype */ - sqlite3_result_text(ctx, pCsr->zPagetype, -1, SQLITE_STATIC); - break; - case 4: /* ncell */ - sqlite3_result_int(ctx, pCsr->nCell); - break; - case 5: /* payload */ - sqlite3_result_int(ctx, pCsr->nPayload); - break; - case 6: /* unused */ - sqlite3_result_int(ctx, pCsr->nUnused); - break; - case 7: /* mx_payload */ - sqlite3_result_int(ctx, pCsr->nMxPayload); - break; - case 8: /* pgoffset */ - sqlite3_result_int64(ctx, pCsr->iOffset); - break; - case 9: /* pgsize */ - sqlite3_result_int(ctx, pCsr->szPage); - break; - } - return SQLITE_OK; -} - -static int statRowid(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){ - StatCursor *pCsr = (StatCursor *)pCursor; - *pRowid = pCsr->iPageno; - return SQLITE_OK; -} - -int sqlite3_dbstat_register(sqlite3 *db){ - static sqlite3_module dbstat_module = { - 0, /* iVersion */ - statConnect, /* xCreate */ - statConnect, /* xConnect */ - statBestIndex, /* xBestIndex */ - statDisconnect, /* xDisconnect */ - statDisconnect, /* xDestroy */ - statOpen, /* xOpen - open a cursor */ - statClose, /* xClose - close a cursor */ - statFilter, /* xFilter - configure scan constraints */ - statNext, /* xNext - advance a cursor */ - statEof, /* xEof - check for end of scan */ - statColumn, /* xColumn - read data */ - statRowid, /* xRowid - read data */ - 0, /* xUpdate */ - 0, /* xBegin */ - 0, /* xSync */ - 0, /* xCommit */ - 0, /* xRollback */ - 0, /* xFindMethod */ - 0, /* xRename */ - }; - sqlite3_create_module(db, "dbstat", &dbstat_module, 0); - return SQLITE_OK; -} - -#endif - -#if defined(SQLITE_TEST) || TCLSH==2 -#include <tcl.h> - -static int test_dbstat( - void *clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ -#ifdef SQLITE_OMIT_VIRTUALTABLE - Tcl_AppendResult(interp, "dbstat not available because of " - "SQLITE_OMIT_VIRTUALTABLE", (void*)0); - return TCL_ERROR; -#else - struct SqliteDb { sqlite3 *db; }; - char *zDb; - Tcl_CmdInfo cmdInfo; - - if( objc!=2 ){ - Tcl_WrongNumArgs(interp, 1, objv, "DB"); - return TCL_ERROR; - } - - zDb = Tcl_GetString(objv[1]); - if( Tcl_GetCommandInfo(interp, zDb, &cmdInfo) ){ - sqlite3* db = ((struct SqliteDb*)cmdInfo.objClientData)->db; - sqlite3_dbstat_register(db); - } - return TCL_OK; -#endif -} - -int SqlitetestStat_Init(Tcl_Interp *interp){ - Tcl_CreateObjCommand(interp, "register_dbstat_vtab", test_dbstat, 0, 0); - return TCL_OK; -} -#endif /* if defined(SQLITE_TEST) || TCLSH==2 */ diff --git a/components/external/SQLite-3.8.1/SQLiteLib/test/test_superlock.c b/components/external/SQLite-3.8.1/SQLiteLib/test/test_superlock.c deleted file mode 100644 index 936fcad0c5..0000000000 --- a/components/external/SQLite-3.8.1/SQLiteLib/test/test_superlock.c +++ /dev/null @@ -1,356 +0,0 @@ -/* -** 2010 November 19 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** Example code for obtaining an exclusive lock on an SQLite database -** file. This method is complicated, but works for both WAL and rollback -** mode database files. The interface to the example code in this file -** consists of the following two functions: -** -** sqlite3demo_superlock() -** sqlite3demo_superunlock() -*/ - -#include <sqlite3.h> -#include <string.h> /* memset(), strlen() */ -#include <assert.h> /* assert() */ - -/* -** A structure to collect a busy-handler callback and argument and a count -** of the number of times it has been invoked. -*/ -struct SuperlockBusy { - int (*xBusy)(void*,int); /* Pointer to busy-handler function */ - void *pBusyArg; /* First arg to pass to xBusy */ - int nBusy; /* Number of times xBusy has been invoked */ -}; -typedef struct SuperlockBusy SuperlockBusy; - -/* -** An instance of the following structure is allocated for each active -** superlock. The opaque handle returned by sqlite3demo_superlock() is -** actually a pointer to an instance of this structure. -*/ -struct Superlock { - sqlite3 *db; /* Database handle used to lock db */ - int bWal; /* True if db is a WAL database */ -}; -typedef struct Superlock Superlock; - -/* -** The pCtx pointer passed to this function is actually a pointer to a -** SuperlockBusy structure. Invoke the busy-handler function encapsulated -** by the structure and return the result. -*/ -static int superlockBusyHandler(void *pCtx, int UNUSED){ - SuperlockBusy *pBusy = (SuperlockBusy *)pCtx; - if( pBusy->xBusy==0 ) return 0; - return pBusy->xBusy(pBusy->pBusyArg, pBusy->nBusy++); -} - -/* -** This function is used to determine if the main database file for -** connection db is open in WAL mode or not. If no error occurs and the -** database file is in WAL mode, set *pbWal to true and return SQLITE_OK. -** If it is not in WAL mode, set *pbWal to false. -** -** If an error occurs, return an SQLite error code. The value of *pbWal -** is undefined in this case. -*/ -static int superlockIsWal(Superlock *pLock){ - int rc; /* Return Code */ - sqlite3_stmt *pStmt; /* Compiled PRAGMA journal_mode statement */ - - rc = sqlite3_prepare(pLock->db, "PRAGMA main.journal_mode", -1, &pStmt, 0); - if( rc!=SQLITE_OK ) return rc; - - pLock->bWal = 0; - if( SQLITE_ROW==sqlite3_step(pStmt) ){ - const char *zMode = (const char *)sqlite3_column_text(pStmt, 0); - if( zMode && strlen(zMode)==3 && sqlite3_strnicmp("wal", zMode, 3)==0 ){ - pLock->bWal = 1; - } - } - - return sqlite3_finalize(pStmt); -} - -/* -** Obtain an exclusive shm-lock on nByte bytes starting at offset idx -** of the file fd. If the lock cannot be obtained immediately, invoke -** the busy-handler until either it is obtained or the busy-handler -** callback returns 0. -*/ -static int superlockShmLock( - sqlite3_file *fd, /* Database file handle */ - int idx, /* Offset of shm-lock to obtain */ - int nByte, /* Number of consective bytes to lock */ - SuperlockBusy *pBusy /* Busy-handler wrapper object */ -){ - int rc; - int (*xShmLock)(sqlite3_file*, int, int, int) = fd->pMethods->xShmLock; - do { - rc = xShmLock(fd, idx, nByte, SQLITE_SHM_LOCK|SQLITE_SHM_EXCLUSIVE); - }while( rc==SQLITE_BUSY && superlockBusyHandler((void *)pBusy, 0) ); - return rc; -} - -/* -** Obtain the extra locks on the database file required for WAL databases. -** Invoke the supplied busy-handler as required. -*/ -static int superlockWalLock( - sqlite3 *db, /* Database handle open on WAL database */ - SuperlockBusy *pBusy /* Busy handler wrapper object */ -){ - int rc; /* Return code */ - sqlite3_file *fd = 0; /* Main database file handle */ - void volatile *p = 0; /* Pointer to first page of shared memory */ - - /* Obtain a pointer to the sqlite3_file object open on the main db file. */ - rc = sqlite3_file_control(db, "main", SQLITE_FCNTL_FILE_POINTER, (void *)&fd); - if( rc!=SQLITE_OK ) return rc; - - /* Obtain the "recovery" lock. Normally, this lock is only obtained by - ** clients running database recovery. - */ - rc = superlockShmLock(fd, 2, 1, pBusy); - if( rc!=SQLITE_OK ) return rc; - - /* Zero the start of the first shared-memory page. This means that any - ** clients that open read or write transactions from this point on will - ** have to run recovery before proceeding. Since they need the "recovery" - ** lock that this process is holding to do that, no new read or write - ** transactions may now be opened. Nor can a checkpoint be run, for the - ** same reason. - */ - rc = fd->pMethods->xShmMap(fd, 0, 32*1024, 1, &p); - if( rc!=SQLITE_OK ) return rc; - memset((void *)p, 0, 32); - - /* Obtain exclusive locks on all the "read-lock" slots. Once these locks - ** are held, it is guaranteed that there are no active reader, writer or - ** checkpointer clients. - */ - rc = superlockShmLock(fd, 3, SQLITE_SHM_NLOCK-3, pBusy); - return rc; -} - -/* -** Release a superlock held on a database file. The argument passed to -** this function must have been obtained from a successful call to -** sqlite3demo_superlock(). -*/ -void sqlite3demo_superunlock(void *pLock){ - Superlock *p = (Superlock *)pLock; - if( p->bWal ){ - int rc; /* Return code */ - int flags = SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE; - sqlite3_file *fd = 0; - rc = sqlite3_file_control(p->db, "main", SQLITE_FCNTL_FILE_POINTER, (void *)&fd); - if( rc==SQLITE_OK ){ - fd->pMethods->xShmLock(fd, 2, 1, flags); - fd->pMethods->xShmLock(fd, 3, SQLITE_SHM_NLOCK-3, flags); - } - } - sqlite3_close(p->db); - sqlite3_free(p); -} - -/* -** Obtain a superlock on the database file identified by zPath, using the -** locking primitives provided by VFS zVfs. If successful, SQLITE_OK is -** returned and output variable *ppLock is populated with an opaque handle -** that may be used with sqlite3demo_superunlock() to release the lock. -** -** If an error occurs, *ppLock is set to 0 and an SQLite error code -** (e.g. SQLITE_BUSY) is returned. -** -** If a required lock cannot be obtained immediately and the xBusy parameter -** to this function is not NULL, then xBusy is invoked in the same way -** as a busy-handler registered with SQLite (using sqlite3_busy_handler()) -** until either the lock can be obtained or the busy-handler function returns -** 0 (indicating "give up"). -*/ -int sqlite3demo_superlock( - const char *zPath, /* Path to database file to lock */ - const char *zVfs, /* VFS to use to access database file */ - int (*xBusy)(void*,int), /* Busy handler callback */ - void *pBusyArg, /* Context arg for busy handler */ - void **ppLock /* OUT: Context to pass to superunlock() */ -){ - SuperlockBusy busy = {0, 0, 0}; /* Busy handler wrapper object */ - int rc; /* Return code */ - Superlock *pLock; - - pLock = sqlite3_malloc(sizeof(Superlock)); - if( !pLock ) return SQLITE_NOMEM; - memset(pLock, 0, sizeof(Superlock)); - - /* Open a database handle on the file to superlock. */ - rc = sqlite3_open_v2( - zPath, &pLock->db, SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, zVfs - ); - - /* Install a busy-handler and execute a BEGIN EXCLUSIVE. If this is not - ** a WAL database, this is all we need to do. - ** - ** A wrapper function is used to invoke the busy-handler instead of - ** registering the busy-handler function supplied by the user directly - ** with SQLite. This is because the same busy-handler function may be - ** invoked directly later on when attempting to obtain the extra locks - ** required in WAL mode. By using the wrapper, we are able to guarantee - ** that the "nBusy" integer parameter passed to the users busy-handler - ** represents the total number of busy-handler invocations made within - ** this call to sqlite3demo_superlock(), including any made during the - ** "BEGIN EXCLUSIVE". - */ - if( rc==SQLITE_OK ){ - busy.xBusy = xBusy; - busy.pBusyArg = pBusyArg; - sqlite3_busy_handler(pLock->db, superlockBusyHandler, (void *)&busy); - rc = sqlite3_exec(pLock->db, "BEGIN EXCLUSIVE", 0, 0, 0); - } - - /* If the BEGIN EXCLUSIVE was executed successfully and this is a WAL - ** database, call superlockWalLock() to obtain the extra locks required - ** to prevent readers, writers and/or checkpointers from accessing the - ** db while this process is holding the superlock. - ** - ** Before attempting any WAL locks, commit the transaction started above - ** to drop the WAL read and write locks currently held. Otherwise, the - ** new WAL locks may conflict with the old. - */ - if( rc==SQLITE_OK ){ - if( SQLITE_OK==(rc = superlockIsWal(pLock)) && pLock->bWal ){ - rc = sqlite3_exec(pLock->db, "COMMIT", 0, 0, 0); - if( rc==SQLITE_OK ){ - rc = superlockWalLock(pLock->db, &busy); - } - } - } - - if( rc!=SQLITE_OK ){ - sqlite3demo_superunlock(pLock); - *ppLock = 0; - }else{ - *ppLock = pLock; - } - - return rc; -} - -/* -** End of example code. Everything below here is the test harness. -************************************************************************** -************************************************************************** -*************************************************************************/ - - -#ifdef SQLITE_TEST - -#include <tcl.h> - -struct InterpAndScript { - Tcl_Interp *interp; - Tcl_Obj *pScript; -}; -typedef struct InterpAndScript InterpAndScript; - -static void superunlock_del(ClientData cd){ - sqlite3demo_superunlock((void *)cd); -} - -static int superunlock_cmd( - ClientData cd, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - if( objc!=1 ){ - Tcl_WrongNumArgs(interp, 1, objv, ""); - return TCL_ERROR; - } - Tcl_DeleteCommand(interp, Tcl_GetString(objv[0])); - return TCL_OK; -} - -static int superlock_busy(void *pCtx, int nBusy){ - InterpAndScript *p = (InterpAndScript *)pCtx; - Tcl_Obj *pEval; /* Script to evaluate */ - int iVal = 0; /* Value to return */ - - pEval = Tcl_DuplicateObj(p->pScript); - Tcl_IncrRefCount(pEval); - Tcl_ListObjAppendElement(p->interp, pEval, Tcl_NewIntObj(nBusy)); - Tcl_EvalObjEx(p->interp, pEval, TCL_EVAL_GLOBAL); - Tcl_GetIntFromObj(p->interp, Tcl_GetObjResult(p->interp), &iVal); - Tcl_DecrRefCount(pEval); - - return iVal; -} - -/* -** Tclcmd: sqlite3demo_superlock CMDNAME PATH VFS BUSY-HANDLER-SCRIPT -*/ -static int superlock_cmd( - ClientData cd, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - void *pLock; /* Lock context */ - char *zPath; - char *zVfs = 0; - InterpAndScript busy = {0, 0}; - int (*xBusy)(void*,int) = 0; /* Busy handler callback */ - int rc; /* Return code from sqlite3demo_superlock() */ - - if( objc<3 || objc>5 ){ - Tcl_WrongNumArgs( - interp, 1, objv, "CMDNAME PATH ?VFS? ?BUSY-HANDLER-SCRIPT?"); - return TCL_ERROR; - } - - zPath = Tcl_GetString(objv[2]); - - if( objc>3 ){ - zVfs = Tcl_GetString(objv[3]); - if( strlen(zVfs)==0 ) zVfs = 0; - } - if( objc>4 ){ - busy.interp = interp; - busy.pScript = objv[4]; - xBusy = superlock_busy; - } - - rc = sqlite3demo_superlock(zPath, zVfs, xBusy, &busy, &pLock); - assert( rc==SQLITE_OK || pLock==0 ); - assert( rc!=SQLITE_OK || pLock!=0 ); - - if( rc!=SQLITE_OK ){ - extern const char *sqlite3ErrStr(int); - Tcl_ResetResult(interp); - Tcl_AppendResult(interp, sqlite3ErrStr(rc), 0); - return TCL_ERROR; - } - - Tcl_CreateObjCommand( - interp, Tcl_GetString(objv[1]), superunlock_cmd, pLock, superunlock_del - ); - Tcl_SetObjResult(interp, objv[1]); - return TCL_OK; -} - -int SqliteSuperlock_Init(Tcl_Interp *interp){ - Tcl_CreateObjCommand(interp, "sqlite3demo_superlock", superlock_cmd, 0, 0); - return TCL_OK; -} -#endif diff --git a/components/external/SQLite-3.8.1/SQLiteLib/test/test_syscall.c b/components/external/SQLite-3.8.1/SQLiteLib/test/test_syscall.c deleted file mode 100644 index 7c0873c16d..0000000000 --- a/components/external/SQLite-3.8.1/SQLiteLib/test/test_syscall.c +++ /dev/null @@ -1,705 +0,0 @@ -/* -** 2011 March 28 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** -** The code in this file implements a Tcl interface used to test error -** handling in the os_unix.c module. Wrapper functions that support fault -** injection are registered as the low-level OS functions using the -** xSetSystemCall() method of the VFS. The Tcl interface is as follows: -** -** -** test_syscall install LIST -** Install wrapper functions for all system calls in argument LIST. -** LIST must be a list consisting of zero or more of the following -** literal values: -** -** open close access getcwd stat fstat -** ftruncate fcntl read pread pread64 write -** pwrite pwrite64 fchmod fallocate mmap -** -** test_syscall uninstall -** Uninstall all wrapper functions. -** -** test_syscall fault ?COUNT PERSIST? -** If [test_syscall fault] is invoked without the two arguments, fault -** injection is disabled. Otherwise, fault injection is configured to -** cause a failure on the COUNT'th next call to a system call with a -** wrapper function installed. A COUNT value of 1 means fail the next -** system call. -** -** Argument PERSIST is interpreted as a boolean. If true, the all -** system calls following the initial failure also fail. Otherwise, only -** the single transient failure is injected. -** -** test_syscall errno CALL ERRNO -** Set the value that the global "errno" is set to following a fault -** in call CALL. Argument CALL must be one of the system call names -** listed above (under [test_syscall install]). ERRNO is a symbolic -** name (i.e. "EACCES"). Not all errno codes are supported. Add extra -** to the aErrno table in function test_syscall_errno() below as -** required. -** -** test_syscall reset ?SYSTEM-CALL? -** With no argument, this is an alias for the [uninstall] command. However, -** this command uses a VFS call of the form: -** -** xSetSystemCall(pVfs, 0, 0); -** -** To restore the default system calls. The [uninstall] command restores -** each system call individually by calling (i.e.): -** -** xSetSystemCall(pVfs, "open", 0); -** -** With an argument, this command attempts to reset the system call named -** by the parameter using the same method as [uninstall]. -** -** test_syscall exists SYSTEM-CALL -** Return true if the named system call exists. Or false otherwise. -** -** test_syscall list -** Return a list of all system calls. The list is constructed using -** the xNextSystemCall() VFS method. -*/ - -#include "sqliteInt.h" -#include "sqlite3.h" -#include "tcl.h" -#include <stdlib.h> -#include <string.h> -#include <assert.h> - -#if SQLITE_OS_UNIX - -/* From main.c */ -extern const char *sqlite3ErrName(int); - -#include <sys/mman.h> -#include <sys/types.h> -#include <errno.h> - -static struct TestSyscallGlobal { - int bPersist; /* 1 for persistent errors, 0 for transient */ - int nCount; /* Fail after this many more calls */ - int nFail; /* Number of failures that have occurred */ -} gSyscall = { 0, 0 }; - -static int ts_open(const char *, int, int); -static int ts_close(int fd); -static int ts_access(const char *zPath, int mode); -static char *ts_getcwd(char *zPath, size_t nPath); -static int ts_stat(const char *zPath, struct stat *p); -static int ts_fstat(int fd, struct stat *p); -static int ts_ftruncate(int fd, off_t n); -static int ts_fcntl(int fd, int cmd, ... ); -static int ts_read(int fd, void *aBuf, size_t nBuf); -static int ts_pread(int fd, void *aBuf, size_t nBuf, off_t off); -static int ts_pread64(int fd, void *aBuf, size_t nBuf, off_t off); -static int ts_write(int fd, const void *aBuf, size_t nBuf); -static int ts_pwrite(int fd, const void *aBuf, size_t nBuf, off_t off); -static int ts_pwrite64(int fd, const void *aBuf, size_t nBuf, off_t off); -static int ts_fchmod(int fd, mode_t mode); -static int ts_fallocate(int fd, off_t off, off_t len); -static void *ts_mmap(void *, size_t, int, int, int, off_t); -static void *ts_mremap(void*, size_t, size_t, int, ...); - -struct TestSyscallArray { - const char *zName; - sqlite3_syscall_ptr xTest; - sqlite3_syscall_ptr xOrig; - int default_errno; /* Default value for errno following errors */ - int custom_errno; /* Current value for errno if error */ -} aSyscall[] = { - /* 0 */ { "open", (sqlite3_syscall_ptr)ts_open, 0, EACCES, 0 }, - /* 1 */ { "close", (sqlite3_syscall_ptr)ts_close, 0, 0, 0 }, - /* 2 */ { "access", (sqlite3_syscall_ptr)ts_access, 0, 0, 0 }, - /* 3 */ { "getcwd", (sqlite3_syscall_ptr)ts_getcwd, 0, 0, 0 }, - /* 4 */ { "stat", (sqlite3_syscall_ptr)ts_stat, 0, 0, 0 }, - /* 5 */ { "fstat", (sqlite3_syscall_ptr)ts_fstat, 0, 0, 0 }, - /* 6 */ { "ftruncate", (sqlite3_syscall_ptr)ts_ftruncate, 0, EIO, 0 }, - /* 7 */ { "fcntl", (sqlite3_syscall_ptr)ts_fcntl, 0, EACCES, 0 }, - /* 8 */ { "read", (sqlite3_syscall_ptr)ts_read, 0, 0, 0 }, - /* 9 */ { "pread", (sqlite3_syscall_ptr)ts_pread, 0, 0, 0 }, - /* 10 */ { "pread64", (sqlite3_syscall_ptr)ts_pread64, 0, 0, 0 }, - /* 11 */ { "write", (sqlite3_syscall_ptr)ts_write, 0, 0, 0 }, - /* 12 */ { "pwrite", (sqlite3_syscall_ptr)ts_pwrite, 0, 0, 0 }, - /* 13 */ { "pwrite64", (sqlite3_syscall_ptr)ts_pwrite64, 0, 0, 0 }, - /* 14 */ { "fchmod", (sqlite3_syscall_ptr)ts_fchmod, 0, 0, 0 }, - /* 15 */ { "fallocate", (sqlite3_syscall_ptr)ts_fallocate, 0, 0, 0 }, - /* 16 */ { "mmap", (sqlite3_syscall_ptr)ts_mmap, 0, 0, 0 }, - /* 17 */ { "mremap", (sqlite3_syscall_ptr)ts_mremap, 0, 0, 0 }, - { 0, 0, 0, 0, 0 } -}; - -#define orig_open ((int(*)(const char *, int, int))aSyscall[0].xOrig) -#define orig_close ((int(*)(int))aSyscall[1].xOrig) -#define orig_access ((int(*)(const char*,int))aSyscall[2].xOrig) -#define orig_getcwd ((char*(*)(char*,size_t))aSyscall[3].xOrig) -#define orig_stat ((int(*)(const char*,struct stat*))aSyscall[4].xOrig) -#define orig_fstat ((int(*)(int,struct stat*))aSyscall[5].xOrig) -#define orig_ftruncate ((int(*)(int,off_t))aSyscall[6].xOrig) -#define orig_fcntl ((int(*)(int,int,...))aSyscall[7].xOrig) -#define orig_read ((ssize_t(*)(int,void*,size_t))aSyscall[8].xOrig) -#define orig_pread ((ssize_t(*)(int,void*,size_t,off_t))aSyscall[9].xOrig) -#define orig_pread64 ((ssize_t(*)(int,void*,size_t,off_t))aSyscall[10].xOrig) -#define orig_write ((ssize_t(*)(int,const void*,size_t))aSyscall[11].xOrig) -#define orig_pwrite ((ssize_t(*)(int,const void*,size_t,off_t))\ - aSyscall[12].xOrig) -#define orig_pwrite64 ((ssize_t(*)(int,const void*,size_t,off_t))\ - aSyscall[13].xOrig) -#define orig_fchmod ((int(*)(int,mode_t))aSyscall[14].xOrig) -#define orig_fallocate ((int(*)(int,off_t,off_t))aSyscall[15].xOrig) -#define orig_mmap ((void*(*)(void*,size_t,int,int,int,off_t))aSyscall[16].xOrig) -#define orig_mremap ((void*(*)(void*,size_t,size_t,int,...))aSyscall[17].xOrig) - -/* -** This function is called exactly once from within each invocation of a -** system call wrapper in this file. It returns 1 if the function should -** fail, or 0 if it should succeed. -*/ -static int tsIsFail(void){ - gSyscall.nCount--; - if( gSyscall.nCount==0 || (gSyscall.nFail && gSyscall.bPersist) ){ - gSyscall.nFail++; - return 1; - } - return 0; -} - -/* -** Return the current error-number value for function zFunc. zFunc must be -** the name of a system call in the aSyscall[] table. -** -** Usually, the current error-number is the value that errno should be set -** to if the named system call fails. The exception is "fallocate". See -** comments above the implementation of ts_fallocate() for details. -*/ -static int tsErrno(const char *zFunc){ - int i; - int nFunc = strlen(zFunc); - for(i=0; aSyscall[i].zName; i++){ - if( strlen(aSyscall[i].zName)!=nFunc ) continue; - if( memcmp(aSyscall[i].zName, zFunc, nFunc) ) continue; - return aSyscall[i].custom_errno; - } - - assert(0); - return 0; -} - -/* -** A wrapper around tsIsFail(). If tsIsFail() returns non-zero, set the -** value of errno before returning. -*/ -static int tsIsFailErrno(const char *zFunc){ - if( tsIsFail() ){ - errno = tsErrno(zFunc); - return 1; - } - return 0; -} - -/* -** A wrapper around open(). -*/ -static int ts_open(const char *zFile, int flags, int mode){ - if( tsIsFailErrno("open") ){ - return -1; - } - return orig_open(zFile, flags, mode); -} - -/* -** A wrapper around close(). -*/ -static int ts_close(int fd){ - if( tsIsFail() ){ - /* Even if simulating an error, close the original file-descriptor. - ** This is to stop the test process from running out of file-descriptors - ** when running a long test. If a call to close() appears to fail, SQLite - ** never attempts to use the file-descriptor afterwards (or even to close - ** it a second time). */ - orig_close(fd); - return -1; - } - return orig_close(fd); -} - -/* -** A wrapper around access(). -*/ -static int ts_access(const char *zPath, int mode){ - if( tsIsFail() ){ - return -1; - } - return orig_access(zPath, mode); -} - -/* -** A wrapper around getcwd(). -*/ -static char *ts_getcwd(char *zPath, size_t nPath){ - if( tsIsFail() ){ - return NULL; - } - return orig_getcwd(zPath, nPath); -} - -/* -** A wrapper around stat(). -*/ -static int ts_stat(const char *zPath, struct stat *p){ - if( tsIsFail() ){ - return -1; - } - return orig_stat(zPath, p); -} - -/* -** A wrapper around fstat(). -*/ -static int ts_fstat(int fd, struct stat *p){ - if( tsIsFailErrno("fstat") ){ - return -1; - } - return orig_fstat(fd, p); -} - -/* -** A wrapper around ftruncate(). -*/ -static int ts_ftruncate(int fd, off_t n){ - if( tsIsFailErrno("ftruncate") ){ - return -1; - } - return orig_ftruncate(fd, n); -} - -/* -** A wrapper around fcntl(). -*/ -static int ts_fcntl(int fd, int cmd, ... ){ - va_list ap; - void *pArg; - if( tsIsFailErrno("fcntl") ){ - return -1; - } - va_start(ap, cmd); - pArg = va_arg(ap, void *); - return orig_fcntl(fd, cmd, pArg); -} - -/* -** A wrapper around read(). -*/ -static int ts_read(int fd, void *aBuf, size_t nBuf){ - if( tsIsFailErrno("read") ){ - return -1; - } - return orig_read(fd, aBuf, nBuf); -} - -/* -** A wrapper around pread(). -*/ -static int ts_pread(int fd, void *aBuf, size_t nBuf, off_t off){ - if( tsIsFailErrno("pread") ){ - return -1; - } - return orig_pread(fd, aBuf, nBuf, off); -} - -/* -** A wrapper around pread64(). -*/ -static int ts_pread64(int fd, void *aBuf, size_t nBuf, off_t off){ - if( tsIsFailErrno("pread64") ){ - return -1; - } - return orig_pread64(fd, aBuf, nBuf, off); -} - -/* -** A wrapper around write(). -*/ -static int ts_write(int fd, const void *aBuf, size_t nBuf){ - if( tsIsFailErrno("write") ){ - if( tsErrno("write")==EINTR ) orig_write(fd, aBuf, nBuf/2); - return -1; - } - return orig_write(fd, aBuf, nBuf); -} - -/* -** A wrapper around pwrite(). -*/ -static int ts_pwrite(int fd, const void *aBuf, size_t nBuf, off_t off){ - if( tsIsFailErrno("pwrite") ){ - return -1; - } - return orig_pwrite(fd, aBuf, nBuf, off); -} - -/* -** A wrapper around pwrite64(). -*/ -static int ts_pwrite64(int fd, const void *aBuf, size_t nBuf, off_t off){ - if( tsIsFailErrno("pwrite64") ){ - return -1; - } - return orig_pwrite64(fd, aBuf, nBuf, off); -} - -/* -** A wrapper around fchmod(). -*/ -static int ts_fchmod(int fd, mode_t mode){ - if( tsIsFail() ){ - return -1; - } - return orig_fchmod(fd, mode); -} - -/* -** A wrapper around fallocate(). -** -** SQLite assumes that the fallocate() function is compatible with -** posix_fallocate(). According to the Linux man page (2009-09-30): -** -** posix_fallocate() returns zero on success, or an error number on -** failure. Note that errno is not set. -*/ -static int ts_fallocate(int fd, off_t off, off_t len){ - if( tsIsFail() ){ - return tsErrno("fallocate"); - } - return orig_fallocate(fd, off, len); -} - -static void *ts_mmap( - void *pAddr, - size_t nByte, - int prot, - int flags, - int fd, - off_t iOff -){ - if( tsIsFailErrno("mmap") ){ - return MAP_FAILED; - } - return orig_mmap(pAddr, nByte, prot, flags, fd, iOff); -} - -static void *ts_mremap(void *a, size_t b, size_t c, int d, ...){ - va_list ap; - void *pArg; - if( tsIsFailErrno("mremap") ){ - return MAP_FAILED; - } - va_start(ap, d); - pArg = va_arg(ap, void *); - return orig_mremap(a, b, c, d, pArg); -} - -static int test_syscall_install( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - sqlite3_vfs *pVfs; - int nElem; - int i; - Tcl_Obj **apElem; - - if( objc!=3 ){ - Tcl_WrongNumArgs(interp, 2, objv, "SYSCALL-LIST"); - return TCL_ERROR; - } - if( Tcl_ListObjGetElements(interp, objv[2], &nElem, &apElem) ){ - return TCL_ERROR; - } - pVfs = sqlite3_vfs_find(0); - - for(i=0; i<nElem; i++){ - int iCall; - int rc = Tcl_GetIndexFromObjStruct(interp, - apElem[i], aSyscall, sizeof(aSyscall[0]), "system-call", 0, &iCall - ); - if( rc ) return rc; - if( aSyscall[iCall].xOrig==0 ){ - aSyscall[iCall].xOrig = pVfs->xGetSystemCall(pVfs, aSyscall[iCall].zName); - pVfs->xSetSystemCall(pVfs, aSyscall[iCall].zName, aSyscall[iCall].xTest); - } - aSyscall[iCall].custom_errno = aSyscall[iCall].default_errno; - } - - return TCL_OK; -} - -static int test_syscall_uninstall( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - sqlite3_vfs *pVfs; - int i; - - if( objc!=2 ){ - Tcl_WrongNumArgs(interp, 2, objv, ""); - return TCL_ERROR; - } - - pVfs = sqlite3_vfs_find(0); - for(i=0; aSyscall[i].zName; i++){ - if( aSyscall[i].xOrig ){ - pVfs->xSetSystemCall(pVfs, aSyscall[i].zName, 0); - aSyscall[i].xOrig = 0; - } - } - return TCL_OK; -} - -static int test_syscall_reset( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - sqlite3_vfs *pVfs; - int i; - int rc; - - if( objc!=2 && objc!=3 ){ - Tcl_WrongNumArgs(interp, 2, objv, ""); - return TCL_ERROR; - } - - pVfs = sqlite3_vfs_find(0); - if( objc==2 ){ - rc = pVfs->xSetSystemCall(pVfs, 0, 0); - for(i=0; aSyscall[i].zName; i++) aSyscall[i].xOrig = 0; - }else{ - int nFunc; - char *zFunc = Tcl_GetStringFromObj(objv[2], &nFunc); - rc = pVfs->xSetSystemCall(pVfs, Tcl_GetString(objv[2]), 0); - for(i=0; rc==SQLITE_OK && aSyscall[i].zName; i++){ - if( strlen(aSyscall[i].zName)!=nFunc ) continue; - if( memcmp(aSyscall[i].zName, zFunc, nFunc) ) continue; - aSyscall[i].xOrig = 0; - } - } - if( rc!=SQLITE_OK ){ - Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1)); - return TCL_ERROR; - } - - Tcl_ResetResult(interp); - return TCL_OK; -} - -static int test_syscall_exists( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - sqlite3_vfs *pVfs; - sqlite3_syscall_ptr x; - - if( objc!=3 ){ - Tcl_WrongNumArgs(interp, 2, objv, ""); - return TCL_ERROR; - } - - pVfs = sqlite3_vfs_find(0); - x = pVfs->xGetSystemCall(pVfs, Tcl_GetString(objv[2])); - - Tcl_SetObjResult(interp, Tcl_NewBooleanObj(x!=0)); - return TCL_OK; -} - -static int test_syscall_fault( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - int nCount = 0; - int bPersist = 0; - - if( objc!=2 && objc!=4 ){ - Tcl_WrongNumArgs(interp, 2, objv, "?COUNT PERSIST?"); - return TCL_ERROR; - } - - if( objc==4 ){ - if( Tcl_GetIntFromObj(interp, objv[2], &nCount) - || Tcl_GetBooleanFromObj(interp, objv[3], &bPersist) - ){ - return TCL_ERROR; - } - } - - Tcl_SetObjResult(interp, Tcl_NewIntObj(gSyscall.nFail)); - gSyscall.nCount = nCount; - gSyscall.bPersist = bPersist; - gSyscall.nFail = 0; - return TCL_OK; -} - -static int test_syscall_errno( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - int iCall; - int iErrno; - int rc; - - struct Errno { - const char *z; - int i; - } aErrno[] = { - { "EACCES", EACCES }, - { "EINTR", EINTR }, - { "EIO", EIO }, - { "EOVERFLOW", EOVERFLOW }, - { "ENOMEM", ENOMEM }, - { "EAGAIN", EAGAIN }, - { "ETIMEDOUT", ETIMEDOUT }, - { "EBUSY", EBUSY }, - { "EPERM", EPERM }, - { "EDEADLK", EDEADLK }, - { "ENOLCK", ENOLCK }, - { 0, 0 } - }; - - if( objc!=4 ){ - Tcl_WrongNumArgs(interp, 2, objv, "SYSCALL ERRNO"); - return TCL_ERROR; - } - - rc = Tcl_GetIndexFromObjStruct(interp, - objv[2], aSyscall, sizeof(aSyscall[0]), "system-call", 0, &iCall - ); - if( rc!=TCL_OK ) return rc; - rc = Tcl_GetIndexFromObjStruct(interp, - objv[3], aErrno, sizeof(aErrno[0]), "errno", 0, &iErrno - ); - if( rc!=TCL_OK ) return rc; - - aSyscall[iCall].custom_errno = aErrno[iErrno].i; - return TCL_OK; -} - -static int test_syscall_list( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - const char *zSys; - sqlite3_vfs *pVfs; - Tcl_Obj *pList; - - if( objc!=2 ){ - Tcl_WrongNumArgs(interp, 2, objv, ""); - return TCL_ERROR; - } - - pVfs = sqlite3_vfs_find(0); - pList = Tcl_NewObj(); - Tcl_IncrRefCount(pList); - for(zSys = pVfs->xNextSystemCall(pVfs, 0); - zSys!=0; - zSys = pVfs->xNextSystemCall(pVfs, zSys) - ){ - Tcl_ListObjAppendElement(interp, pList, Tcl_NewStringObj(zSys, -1)); - } - - Tcl_SetObjResult(interp, pList); - Tcl_DecrRefCount(pList); - return TCL_OK; -} - -static int test_syscall_defaultvfs( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - sqlite3_vfs *pVfs; - - if( objc!=2 ){ - Tcl_WrongNumArgs(interp, 2, objv, ""); - return TCL_ERROR; - } - - pVfs = sqlite3_vfs_find(0); - Tcl_SetObjResult(interp, Tcl_NewStringObj(pVfs->zName, -1)); - return TCL_OK; -} - -static int test_syscall( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - struct SyscallCmd { - const char *zName; - Tcl_ObjCmdProc *xCmd; - } aCmd[] = { - { "fault", test_syscall_fault }, - { "install", test_syscall_install }, - { "uninstall", test_syscall_uninstall }, - { "reset", test_syscall_reset }, - { "errno", test_syscall_errno }, - { "exists", test_syscall_exists }, - { "list", test_syscall_list }, - { "defaultvfs", test_syscall_defaultvfs }, - { 0, 0 } - }; - int iCmd; - int rc; - - if( objc<2 ){ - Tcl_WrongNumArgs(interp, 1, objv, "SUB-COMMAND ..."); - return TCL_ERROR; - } - rc = Tcl_GetIndexFromObjStruct(interp, - objv[1], aCmd, sizeof(aCmd[0]), "sub-command", 0, &iCmd - ); - if( rc!=TCL_OK ) return rc; - return aCmd[iCmd].xCmd(clientData, interp, objc, objv); -} - -int SqlitetestSyscall_Init(Tcl_Interp *interp){ - struct SyscallCmd { - const char *zName; - Tcl_ObjCmdProc *xCmd; - } aCmd[] = { - { "test_syscall", test_syscall}, - }; - int i; - - for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){ - Tcl_CreateObjCommand(interp, aCmd[i].zName, aCmd[i].xCmd, 0, 0); - } - return TCL_OK; -} -#else -int SqlitetestSyscall_Init(Tcl_Interp *interp){ - return TCL_OK; -} -#endif diff --git a/components/external/SQLite-3.8.1/SQLiteLib/test/test_tclvar.c b/components/external/SQLite-3.8.1/SQLiteLib/test/test_tclvar.c deleted file mode 100644 index 1219190c03..0000000000 --- a/components/external/SQLite-3.8.1/SQLiteLib/test/test_tclvar.c +++ /dev/null @@ -1,332 +0,0 @@ -/* -** 2006 June 13 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** Code for testing the virtual table interfaces. This code -** is not included in the SQLite library. It is used for automated -** testing of the SQLite library. -** -** The emphasis of this file is a virtual table that provides -** access to TCL variables. -*/ -#include "sqliteInt.h" -#include "tcl.h" -#include <stdlib.h> -#include <string.h> - -#ifndef SQLITE_OMIT_VIRTUALTABLE - -typedef struct tclvar_vtab tclvar_vtab; -typedef struct tclvar_cursor tclvar_cursor; - -/* -** A tclvar virtual-table object -*/ -struct tclvar_vtab { - sqlite3_vtab base; - Tcl_Interp *interp; -}; - -/* A tclvar cursor object */ -struct tclvar_cursor { - sqlite3_vtab_cursor base; - - Tcl_Obj *pList1; /* Result of [info vars ?pattern?] */ - Tcl_Obj *pList2; /* Result of [array names [lindex $pList1 $i1]] */ - int i1; /* Current item in pList1 */ - int i2; /* Current item (if any) in pList2 */ -}; - -/* Methods for the tclvar module */ -static int tclvarConnect( - sqlite3 *db, - void *pAux, - int argc, const char *const*argv, - sqlite3_vtab **ppVtab, - char **pzErr -){ - tclvar_vtab *pVtab; - static const char zSchema[] = - "CREATE TABLE whatever(name TEXT, arrayname TEXT, value TEXT)"; - pVtab = sqlite3MallocZero( sizeof(*pVtab) ); - if( pVtab==0 ) return SQLITE_NOMEM; - *ppVtab = &pVtab->base; - pVtab->interp = (Tcl_Interp *)pAux; - sqlite3_declare_vtab(db, zSchema); - return SQLITE_OK; -} -/* Note that for this virtual table, the xCreate and xConnect -** methods are identical. */ - -static int tclvarDisconnect(sqlite3_vtab *pVtab){ - sqlite3_free(pVtab); - return SQLITE_OK; -} -/* The xDisconnect and xDestroy methods are also the same */ - -/* -** Open a new tclvar cursor. -*/ -static int tclvarOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){ - tclvar_cursor *pCur; - pCur = sqlite3MallocZero(sizeof(tclvar_cursor)); - *ppCursor = &pCur->base; - return SQLITE_OK; -} - -/* -** Close a tclvar cursor. -*/ -static int tclvarClose(sqlite3_vtab_cursor *cur){ - tclvar_cursor *pCur = (tclvar_cursor *)cur; - if( pCur->pList1 ){ - Tcl_DecrRefCount(pCur->pList1); - } - if( pCur->pList2 ){ - Tcl_DecrRefCount(pCur->pList2); - } - sqlite3_free(pCur); - return SQLITE_OK; -} - -/* -** Returns 1 if data is ready, or 0 if not. -*/ -static int next2(Tcl_Interp *interp, tclvar_cursor *pCur, Tcl_Obj *pObj){ - Tcl_Obj *p; - - if( pObj ){ - if( !pCur->pList2 ){ - p = Tcl_NewStringObj("array names", -1); - Tcl_IncrRefCount(p); - Tcl_ListObjAppendElement(0, p, pObj); - Tcl_EvalObjEx(interp, p, TCL_EVAL_GLOBAL); - Tcl_DecrRefCount(p); - pCur->pList2 = Tcl_GetObjResult(interp); - Tcl_IncrRefCount(pCur->pList2); - assert( pCur->i2==0 ); - }else{ - int n = 0; - pCur->i2++; - Tcl_ListObjLength(0, pCur->pList2, &n); - if( pCur->i2>=n ){ - Tcl_DecrRefCount(pCur->pList2); - pCur->pList2 = 0; - pCur->i2 = 0; - return 0; - } - } - } - - return 1; -} - -static int tclvarNext(sqlite3_vtab_cursor *cur){ - Tcl_Obj *pObj; - int n = 0; - int ok = 0; - - tclvar_cursor *pCur = (tclvar_cursor *)cur; - Tcl_Interp *interp = ((tclvar_vtab *)(cur->pVtab))->interp; - - Tcl_ListObjLength(0, pCur->pList1, &n); - while( !ok && pCur->i1<n ){ - Tcl_ListObjIndex(0, pCur->pList1, pCur->i1, &pObj); - ok = next2(interp, pCur, pObj); - if( !ok ){ - pCur->i1++; - } - } - - return 0; -} - -static int tclvarFilter( - sqlite3_vtab_cursor *pVtabCursor, - int idxNum, const char *idxStr, - int argc, sqlite3_value **argv -){ - tclvar_cursor *pCur = (tclvar_cursor *)pVtabCursor; - Tcl_Interp *interp = ((tclvar_vtab *)(pVtabCursor->pVtab))->interp; - - Tcl_Obj *p = Tcl_NewStringObj("info vars", -1); - Tcl_IncrRefCount(p); - - assert( argc==0 || argc==1 ); - if( argc==1 ){ - Tcl_Obj *pArg = Tcl_NewStringObj((char*)sqlite3_value_text(argv[0]), -1); - Tcl_ListObjAppendElement(0, p, pArg); - } - Tcl_EvalObjEx(interp, p, TCL_EVAL_GLOBAL); - if( pCur->pList1 ){ - Tcl_DecrRefCount(pCur->pList1); - } - if( pCur->pList2 ){ - Tcl_DecrRefCount(pCur->pList2); - pCur->pList2 = 0; - } - pCur->i1 = 0; - pCur->i2 = 0; - pCur->pList1 = Tcl_GetObjResult(interp); - Tcl_IncrRefCount(pCur->pList1); - assert( pCur->i1==0 && pCur->i2==0 && pCur->pList2==0 ); - - Tcl_DecrRefCount(p); - return tclvarNext(pVtabCursor); -} - -static int tclvarColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){ - Tcl_Obj *p1; - Tcl_Obj *p2; - const char *z1; - const char *z2 = ""; - tclvar_cursor *pCur = (tclvar_cursor*)cur; - Tcl_Interp *interp = ((tclvar_vtab *)cur->pVtab)->interp; - - Tcl_ListObjIndex(interp, pCur->pList1, pCur->i1, &p1); - Tcl_ListObjIndex(interp, pCur->pList2, pCur->i2, &p2); - z1 = Tcl_GetString(p1); - if( p2 ){ - z2 = Tcl_GetString(p2); - } - switch (i) { - case 0: { - sqlite3_result_text(ctx, z1, -1, SQLITE_TRANSIENT); - break; - } - case 1: { - sqlite3_result_text(ctx, z2, -1, SQLITE_TRANSIENT); - break; - } - case 2: { - Tcl_Obj *pVal = Tcl_GetVar2Ex(interp, z1, *z2?z2:0, TCL_GLOBAL_ONLY); - sqlite3_result_text(ctx, Tcl_GetString(pVal), -1, SQLITE_TRANSIENT); - break; - } - } - return SQLITE_OK; -} - -static int tclvarRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){ - *pRowid = 0; - return SQLITE_OK; -} - -static int tclvarEof(sqlite3_vtab_cursor *cur){ - tclvar_cursor *pCur = (tclvar_cursor*)cur; - return (pCur->pList2?0:1); -} - -static int tclvarBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ - int ii; - - for(ii=0; ii<pIdxInfo->nConstraint; ii++){ - struct sqlite3_index_constraint const *pCons = &pIdxInfo->aConstraint[ii]; - if( pCons->iColumn==0 && pCons->usable - && pCons->op==SQLITE_INDEX_CONSTRAINT_EQ ){ - struct sqlite3_index_constraint_usage *pUsage; - pUsage = &pIdxInfo->aConstraintUsage[ii]; - pUsage->omit = 0; - pUsage->argvIndex = 1; - return SQLITE_OK; - } - } - - for(ii=0; ii<pIdxInfo->nConstraint; ii++){ - struct sqlite3_index_constraint const *pCons = &pIdxInfo->aConstraint[ii]; - if( pCons->iColumn==0 && pCons->usable - && pCons->op==SQLITE_INDEX_CONSTRAINT_MATCH ){ - struct sqlite3_index_constraint_usage *pUsage; - pUsage = &pIdxInfo->aConstraintUsage[ii]; - pUsage->omit = 1; - pUsage->argvIndex = 1; - return SQLITE_OK; - } - } - - return SQLITE_OK; -} - -/* -** A virtual table module that provides read-only access to a -** Tcl global variable namespace. -*/ -static sqlite3_module tclvarModule = { - 0, /* iVersion */ - tclvarConnect, - tclvarConnect, - tclvarBestIndex, - tclvarDisconnect, - tclvarDisconnect, - tclvarOpen, /* xOpen - open a cursor */ - tclvarClose, /* xClose - close a cursor */ - tclvarFilter, /* xFilter - configure scan constraints */ - tclvarNext, /* xNext - advance a cursor */ - tclvarEof, /* xEof - check for end of scan */ - tclvarColumn, /* xColumn - read data */ - tclvarRowid, /* xRowid - read data */ - 0, /* xUpdate */ - 0, /* xBegin */ - 0, /* xSync */ - 0, /* xCommit */ - 0, /* xRollback */ - 0, /* xFindMethod */ - 0, /* xRename */ -}; - -/* -** Decode a pointer to an sqlite3 object. -*/ -extern int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb); - -/* -** Register the echo virtual table module. -*/ -static int register_tclvar_module( - 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; - if( objc!=2 ){ - Tcl_WrongNumArgs(interp, 1, objv, "DB"); - return TCL_ERROR; - } - if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; -#ifndef SQLITE_OMIT_VIRTUALTABLE - sqlite3_create_module(db, "tclvar", &tclvarModule, (void *)interp); -#endif - return TCL_OK; -} - -#endif - - -/* -** Register commands with the TCL interpreter. -*/ -int Sqlitetesttclvar_Init(Tcl_Interp *interp){ -#ifndef SQLITE_OMIT_VIRTUALTABLE - static struct { - char *zName; - Tcl_ObjCmdProc *xProc; - void *clientData; - } aObjCmd[] = { - { "register_tclvar_module", register_tclvar_module, 0 }, - }; - int i; - for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){ - Tcl_CreateObjCommand(interp, aObjCmd[i].zName, - aObjCmd[i].xProc, aObjCmd[i].clientData, 0); - } -#endif - return TCL_OK; -} diff --git a/components/external/SQLite-3.8.1/SQLiteLib/test/test_thread.c b/components/external/SQLite-3.8.1/SQLiteLib/test/test_thread.c deleted file mode 100644 index 2f9363b750..0000000000 --- a/components/external/SQLite-3.8.1/SQLiteLib/test/test_thread.c +++ /dev/null @@ -1,647 +0,0 @@ -/* -** 2007 September 9 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** -** This file contains the implementation of some Tcl commands used to -** test that sqlite3 database handles may be concurrently accessed by -** multiple threads. Right now this only works on unix. -*/ - -#include "sqliteInt.h" -#include <tcl.h> - -#if SQLITE_THREADSAFE - -#include <errno.h> - -#if !defined(_MSC_VER) -#include <unistd.h> -#endif - -/* -** One of these is allocated for each thread created by [sqlthread spawn]. -*/ -typedef struct SqlThread SqlThread; -struct SqlThread { - Tcl_ThreadId parent; /* Thread id of parent thread */ - Tcl_Interp *interp; /* Parent interpreter */ - char *zScript; /* The script to execute. */ - char *zVarname; /* Varname in parent script */ -}; - -/* -** A custom Tcl_Event type used by this module. When the event is -** handled, script zScript is evaluated in interpreter interp. If -** the evaluation throws an exception (returns TCL_ERROR), then the -** error is handled by Tcl_BackgroundError(). If no error occurs, -** the result is simply discarded. -*/ -typedef struct EvalEvent EvalEvent; -struct EvalEvent { - Tcl_Event base; /* Base class of type Tcl_Event */ - char *zScript; /* The script to execute. */ - Tcl_Interp *interp; /* The interpreter to execute it in. */ -}; - -static Tcl_ObjCmdProc sqlthread_proc; -static Tcl_ObjCmdProc clock_seconds_proc; -#if SQLITE_OS_UNIX && defined(SQLITE_ENABLE_UNLOCK_NOTIFY) -static Tcl_ObjCmdProc blocking_step_proc; -static Tcl_ObjCmdProc blocking_prepare_v2_proc; -#endif -int Sqlitetest1_Init(Tcl_Interp *); -int Sqlite3_Init(Tcl_Interp *); - -/* Functions from main.c */ -extern const char *sqlite3ErrName(int); - -/* Functions from test1.c */ -extern void *sqlite3TestTextToPtr(const char *); -extern int getDbPointer(Tcl_Interp *, const char *, sqlite3 **); -extern int sqlite3TestMakePointerStr(Tcl_Interp *, char *, void *); -extern int sqlite3TestErrCode(Tcl_Interp *, sqlite3 *, int); - -/* -** Handler for events of type EvalEvent. -*/ -static int tclScriptEvent(Tcl_Event *evPtr, int flags){ - int rc; - EvalEvent *p = (EvalEvent *)evPtr; - rc = Tcl_Eval(p->interp, p->zScript); - if( rc!=TCL_OK ){ - Tcl_BackgroundError(p->interp); - } - UNUSED_PARAMETER(flags); - return 1; -} - -/* -** Register an EvalEvent to evaluate the script pScript in the -** parent interpreter/thread of SqlThread p. -*/ -static void postToParent(SqlThread *p, Tcl_Obj *pScript){ - EvalEvent *pEvent; - char *zMsg; - int nMsg; - - zMsg = Tcl_GetStringFromObj(pScript, &nMsg); - pEvent = (EvalEvent *)ckalloc(sizeof(EvalEvent)+nMsg+1); - pEvent->base.nextPtr = 0; - pEvent->base.proc = tclScriptEvent; - pEvent->zScript = (char *)&pEvent[1]; - memcpy(pEvent->zScript, zMsg, nMsg+1); - pEvent->interp = p->interp; - - Tcl_ThreadQueueEvent(p->parent, (Tcl_Event *)pEvent, TCL_QUEUE_TAIL); - Tcl_ThreadAlert(p->parent); -} - -/* -** The main function for threads created with [sqlthread spawn]. -*/ -static Tcl_ThreadCreateType tclScriptThread(ClientData pSqlThread){ - Tcl_Interp *interp; - Tcl_Obj *pRes; - Tcl_Obj *pList; - int rc; - SqlThread *p = (SqlThread *)pSqlThread; - extern int Sqlitetest_mutex_Init(Tcl_Interp*); - - interp = Tcl_CreateInterp(); - Tcl_CreateObjCommand(interp, "clock_seconds", clock_seconds_proc, 0, 0); - Tcl_CreateObjCommand(interp, "sqlthread", sqlthread_proc, pSqlThread, 0); -#if SQLITE_OS_UNIX && defined(SQLITE_ENABLE_UNLOCK_NOTIFY) - Tcl_CreateObjCommand(interp, "sqlite3_blocking_step", blocking_step_proc,0,0); - Tcl_CreateObjCommand(interp, - "sqlite3_blocking_prepare_v2", blocking_prepare_v2_proc, (void *)1, 0); - Tcl_CreateObjCommand(interp, - "sqlite3_nonblocking_prepare_v2", blocking_prepare_v2_proc, 0, 0); -#endif - Sqlitetest1_Init(interp); - Sqlitetest_mutex_Init(interp); - Sqlite3_Init(interp); - - rc = Tcl_Eval(interp, p->zScript); - pRes = Tcl_GetObjResult(interp); - pList = Tcl_NewObj(); - Tcl_IncrRefCount(pList); - Tcl_IncrRefCount(pRes); - - if( rc!=TCL_OK ){ - Tcl_ListObjAppendElement(interp, pList, Tcl_NewStringObj("error", -1)); - Tcl_ListObjAppendElement(interp, pList, pRes); - postToParent(p, pList); - Tcl_DecrRefCount(pList); - pList = Tcl_NewObj(); - } - - Tcl_ListObjAppendElement(interp, pList, Tcl_NewStringObj("set", -1)); - Tcl_ListObjAppendElement(interp, pList, Tcl_NewStringObj(p->zVarname, -1)); - Tcl_ListObjAppendElement(interp, pList, pRes); - postToParent(p, pList); - - ckfree((void *)p); - Tcl_DecrRefCount(pList); - Tcl_DecrRefCount(pRes); - Tcl_DeleteInterp(interp); - while( Tcl_DoOneEvent(TCL_ALL_EVENTS|TCL_DONT_WAIT) ); - Tcl_ExitThread(0); - TCL_THREAD_CREATE_RETURN; -} - -/* -** sqlthread spawn VARNAME SCRIPT -** -** Spawn a new thread with its own Tcl interpreter and run the -** specified SCRIPT(s) in it. The thread terminates after running -** the script. The result of the script is stored in the variable -** VARNAME. -** -** The caller can wait for the script to terminate using [vwait VARNAME]. -*/ -static int sqlthread_spawn( - ClientData clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - Tcl_ThreadId x; - SqlThread *pNew; - int rc; - - int nVarname; char *zVarname; - int nScript; char *zScript; - - /* Parameters for thread creation */ - const int nStack = TCL_THREAD_STACK_DEFAULT; - const int flags = TCL_THREAD_NOFLAGS; - - assert(objc==4); - UNUSED_PARAMETER(clientData); - UNUSED_PARAMETER(objc); - - zVarname = Tcl_GetStringFromObj(objv[2], &nVarname); - zScript = Tcl_GetStringFromObj(objv[3], &nScript); - - pNew = (SqlThread *)ckalloc(sizeof(SqlThread)+nVarname+nScript+2); - pNew->zVarname = (char *)&pNew[1]; - pNew->zScript = (char *)&pNew->zVarname[nVarname+1]; - memcpy(pNew->zVarname, zVarname, nVarname+1); - memcpy(pNew->zScript, zScript, nScript+1); - pNew->parent = Tcl_GetCurrentThread(); - pNew->interp = interp; - - rc = Tcl_CreateThread(&x, tclScriptThread, (void *)pNew, nStack, flags); - if( rc!=TCL_OK ){ - Tcl_AppendResult(interp, "Error in Tcl_CreateThread()", 0); - ckfree((char *)pNew); - return TCL_ERROR; - } - - return TCL_OK; -} - -/* -** sqlthread parent SCRIPT -** -** This can be called by spawned threads only. It sends the specified -** script back to the parent thread for execution. The result of -** evaluating the SCRIPT is returned. The parent thread must enter -** the event loop for this to work - otherwise the caller will -** block indefinitely. -** -** NOTE: At the moment, this doesn't work. FIXME. -*/ -static int sqlthread_parent( - ClientData clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - EvalEvent *pEvent; - char *zMsg; - int nMsg; - SqlThread *p = (SqlThread *)clientData; - - assert(objc==3); - UNUSED_PARAMETER(objc); - - if( p==0 ){ - Tcl_AppendResult(interp, "no parent thread", 0); - return TCL_ERROR; - } - - zMsg = Tcl_GetStringFromObj(objv[2], &nMsg); - pEvent = (EvalEvent *)ckalloc(sizeof(EvalEvent)+nMsg+1); - pEvent->base.nextPtr = 0; - pEvent->base.proc = tclScriptEvent; - pEvent->zScript = (char *)&pEvent[1]; - memcpy(pEvent->zScript, zMsg, nMsg+1); - pEvent->interp = p->interp; - Tcl_ThreadQueueEvent(p->parent, (Tcl_Event *)pEvent, TCL_QUEUE_TAIL); - Tcl_ThreadAlert(p->parent); - - return TCL_OK; -} - -static int xBusy(void *pArg, int nBusy){ - UNUSED_PARAMETER(pArg); - UNUSED_PARAMETER(nBusy); - sqlite3_sleep(50); - return 1; /* Try again... */ -} - -/* -** sqlthread open -** -** Open a database handle and return the string representation of -** the pointer value. -*/ -static int sqlthread_open( - ClientData clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - int sqlite3TestMakePointerStr(Tcl_Interp *interp, char *zPtr, void *p); - - const char *zFilename; - sqlite3 *db; - char zBuf[100]; - extern void Md5_Register(sqlite3*); - - UNUSED_PARAMETER(clientData); - UNUSED_PARAMETER(objc); - - zFilename = Tcl_GetString(objv[2]); - sqlite3_open(zFilename, &db); -#ifdef SQLITE_HAS_CODEC - if( db && objc>=4 ){ - const char *zKey; - int nKey; - int rc; - zKey = Tcl_GetStringFromObj(objv[3], &nKey); - rc = sqlite3_key(db, zKey, nKey); - if( rc!=SQLITE_OK ){ - char *zErrMsg = sqlite3_mprintf("error %d: %s", rc, sqlite3_errmsg(db)); - sqlite3_close(db); - Tcl_AppendResult(interp, zErrMsg, (char*)0); - sqlite3_free(zErrMsg); - return TCL_ERROR; - } - } -#endif - Md5_Register(db); - sqlite3_busy_handler(db, xBusy, 0); - - if( sqlite3TestMakePointerStr(interp, zBuf, db) ) return TCL_ERROR; - Tcl_AppendResult(interp, zBuf, 0); - - return TCL_OK; -} - - -/* -** sqlthread open -** -** Return the current thread-id (Tcl_GetCurrentThread()) cast to -** an integer. -*/ -static int sqlthread_id( - ClientData clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - Tcl_ThreadId id = Tcl_GetCurrentThread(); - Tcl_SetObjResult(interp, Tcl_NewIntObj(SQLITE_PTR_TO_INT(id))); - UNUSED_PARAMETER(clientData); - UNUSED_PARAMETER(objc); - UNUSED_PARAMETER(objv); - return TCL_OK; -} - - -/* -** Dispatch routine for the sub-commands of [sqlthread]. -*/ -static int sqlthread_proc( - ClientData clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - struct SubCommand { - char *zName; - Tcl_ObjCmdProc *xProc; - int nArg; - char *zUsage; - } aSub[] = { - {"parent", sqlthread_parent, 1, "SCRIPT"}, - {"spawn", sqlthread_spawn, 2, "VARNAME SCRIPT"}, - {"open", sqlthread_open, 1, "DBNAME"}, - {"id", sqlthread_id, 0, ""}, - {0, 0, 0} - }; - struct SubCommand *pSub; - int rc; - int iIndex; - - if( objc<2 ){ - Tcl_WrongNumArgs(interp, 1, objv, "SUB-COMMAND"); - return TCL_ERROR; - } - - rc = Tcl_GetIndexFromObjStruct( - interp, objv[1], aSub, sizeof(aSub[0]), "sub-command", 0, &iIndex - ); - if( rc!=TCL_OK ) return rc; - pSub = &aSub[iIndex]; - - if( objc<(pSub->nArg+2) ){ - Tcl_WrongNumArgs(interp, 2, objv, pSub->zUsage); - return TCL_ERROR; - } - - return pSub->xProc(clientData, interp, objc, objv); -} - -/* -** The [clock_seconds] command. This is more or less the same as the -** regular tcl [clock seconds], except that it is available in testfixture -** when linked against both Tcl 8.4 and 8.5. Because [clock seconds] is -** implemented as a script in Tcl 8.5, it is not usually available to -** testfixture. -*/ -static int clock_seconds_proc( - ClientData clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - Tcl_Time now; - Tcl_GetTime(&now); - Tcl_SetObjResult(interp, Tcl_NewIntObj(now.sec)); - UNUSED_PARAMETER(clientData); - UNUSED_PARAMETER(objc); - UNUSED_PARAMETER(objv); - return TCL_OK; -} - -/************************************************************************* -** This block contains the implementation of the [sqlite3_blocking_step] -** command available to threads created by [sqlthread spawn] commands. It -** is only available on UNIX for now. This is because pthread condition -** variables are used. -** -** The source code for the C functions sqlite3_blocking_step(), -** blocking_step_notify() and the structure UnlockNotification is -** automatically extracted from this file and used as part of the -** documentation for the sqlite3_unlock_notify() API function. This -** should be considered if these functions are to be extended (i.e. to -** support windows) in the future. -*/ -#if SQLITE_OS_UNIX && defined(SQLITE_ENABLE_UNLOCK_NOTIFY) - -/* BEGIN_SQLITE_BLOCKING_STEP */ -/* This example uses the pthreads API */ -#include <pthread.h> - -/* -** A pointer to an instance of this structure is passed as the user-context -** pointer when registering for an unlock-notify callback. -*/ -typedef struct UnlockNotification UnlockNotification; -struct UnlockNotification { - int fired; /* True after unlock event has occurred */ - pthread_cond_t cond; /* Condition variable to wait on */ - pthread_mutex_t mutex; /* Mutex to protect structure */ -}; - -/* -** This function is an unlock-notify callback registered with SQLite. -*/ -static void unlock_notify_cb(void **apArg, int nArg){ - int i; - for(i=0; i<nArg; i++){ - UnlockNotification *p = (UnlockNotification *)apArg[i]; - pthread_mutex_lock(&p->mutex); - p->fired = 1; - pthread_cond_signal(&p->cond); - pthread_mutex_unlock(&p->mutex); - } -} - -/* -** This function assumes that an SQLite API call (either sqlite3_prepare_v2() -** or sqlite3_step()) has just returned SQLITE_LOCKED. The argument is the -** associated database connection. -** -** This function calls sqlite3_unlock_notify() to register for an -** unlock-notify callback, then blocks until that callback is delivered -** and returns SQLITE_OK. The caller should then retry the failed operation. -** -** Or, if sqlite3_unlock_notify() indicates that to block would deadlock -** the system, then this function returns SQLITE_LOCKED immediately. In -** this case the caller should not retry the operation and should roll -** back the current transaction (if any). -*/ -static int wait_for_unlock_notify(sqlite3 *db){ - int rc; - UnlockNotification un; - - /* Initialize the UnlockNotification structure. */ - un.fired = 0; - pthread_mutex_init(&un.mutex, 0); - pthread_cond_init(&un.cond, 0); - - /* Register for an unlock-notify callback. */ - rc = sqlite3_unlock_notify(db, unlock_notify_cb, (void *)&un); - assert( rc==SQLITE_LOCKED || rc==SQLITE_OK ); - - /* The call to sqlite3_unlock_notify() always returns either SQLITE_LOCKED - ** or SQLITE_OK. - ** - ** If SQLITE_LOCKED was returned, then the system is deadlocked. In this - ** case this function needs to return SQLITE_LOCKED to the caller so - ** that the current transaction can be rolled back. Otherwise, block - ** until the unlock-notify callback is invoked, then return SQLITE_OK. - */ - if( rc==SQLITE_OK ){ - pthread_mutex_lock(&un.mutex); - if( !un.fired ){ - pthread_cond_wait(&un.cond, &un.mutex); - } - pthread_mutex_unlock(&un.mutex); - } - - /* Destroy the mutex and condition variables. */ - pthread_cond_destroy(&un.cond); - pthread_mutex_destroy(&un.mutex); - - return rc; -} - -/* -** This function is a wrapper around the SQLite function sqlite3_step(). -** It functions in the same way as step(), except that if a required -** shared-cache lock cannot be obtained, this function may block waiting for -** the lock to become available. In this scenario the normal API step() -** function always returns SQLITE_LOCKED. -** -** If this function returns SQLITE_LOCKED, the caller should rollback -** the current transaction (if any) and try again later. Otherwise, the -** system may become deadlocked. -*/ -int sqlite3_blocking_step(sqlite3_stmt *pStmt){ - int rc; - while( SQLITE_LOCKED==(rc = sqlite3_step(pStmt)) ){ - rc = wait_for_unlock_notify(sqlite3_db_handle(pStmt)); - if( rc!=SQLITE_OK ) break; - sqlite3_reset(pStmt); - } - return rc; -} - -/* -** This function is a wrapper around the SQLite function sqlite3_prepare_v2(). -** It functions in the same way as prepare_v2(), except that if a required -** shared-cache lock cannot be obtained, this function may block waiting for -** the lock to become available. In this scenario the normal API prepare_v2() -** function always returns SQLITE_LOCKED. -** -** If this function returns SQLITE_LOCKED, the caller should rollback -** the current transaction (if any) and try again later. Otherwise, the -** system may become deadlocked. -*/ -int sqlite3_blocking_prepare_v2( - sqlite3 *db, /* Database handle. */ - const char *zSql, /* UTF-8 encoded SQL statement. */ - int nSql, /* Length of zSql in bytes. */ - sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */ - const char **pz /* OUT: End of parsed string */ -){ - int rc; - while( SQLITE_LOCKED==(rc = sqlite3_prepare_v2(db, zSql, nSql, ppStmt, pz)) ){ - rc = wait_for_unlock_notify(db); - if( rc!=SQLITE_OK ) break; - } - return rc; -} -/* END_SQLITE_BLOCKING_STEP */ - -/* -** Usage: sqlite3_blocking_step STMT -** -** Advance the statement to the next row. -*/ -static int blocking_step_proc( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - - sqlite3_stmt *pStmt; - int rc; - - if( objc!=2 ){ - Tcl_WrongNumArgs(interp, 1, objv, "STMT"); - return TCL_ERROR; - } - - pStmt = (sqlite3_stmt*)sqlite3TestTextToPtr(Tcl_GetString(objv[1])); - rc = sqlite3_blocking_step(pStmt); - - Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), 0); - return TCL_OK; -} - -/* -** Usage: sqlite3_blocking_prepare_v2 DB sql bytes ?tailvar? -** Usage: sqlite3_nonblocking_prepare_v2 DB sql bytes ?tailvar? -*/ -static int blocking_prepare_v2_proc( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - sqlite3 *db; - const char *zSql; - int bytes; - const char *zTail = 0; - sqlite3_stmt *pStmt = 0; - char zBuf[50]; - int rc; - int isBlocking = !(clientData==0); - - if( objc!=5 && objc!=4 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", - Tcl_GetString(objv[0]), " DB sql bytes tailvar", 0); - return TCL_ERROR; - } - if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; - zSql = Tcl_GetString(objv[2]); - if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR; - - if( isBlocking ){ - rc = sqlite3_blocking_prepare_v2(db, zSql, bytes, &pStmt, &zTail); - }else{ - rc = sqlite3_prepare_v2(db, zSql, bytes, &pStmt, &zTail); - } - - assert(rc==SQLITE_OK || pStmt==0); - if( zTail && objc>=5 ){ - if( bytes>=0 ){ - bytes = bytes - (zTail-zSql); - } - Tcl_ObjSetVar2(interp, objv[4], 0, Tcl_NewStringObj(zTail, bytes), 0); - } - if( rc!=SQLITE_OK ){ - assert( pStmt==0 ); - sprintf(zBuf, "%s ", (char *)sqlite3ErrName(rc)); - Tcl_AppendResult(interp, zBuf, sqlite3_errmsg(db), 0); - return TCL_ERROR; - } - - if( pStmt ){ - if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR; - Tcl_AppendResult(interp, zBuf, 0); - } - return TCL_OK; -} - -#endif /* SQLITE_OS_UNIX && SQLITE_ENABLE_UNLOCK_NOTIFY */ -/* -** End of implementation of [sqlite3_blocking_step]. -************************************************************************/ - -/* -** Register commands with the TCL interpreter. -*/ -int SqlitetestThread_Init(Tcl_Interp *interp){ - Tcl_CreateObjCommand(interp, "sqlthread", sqlthread_proc, 0, 0); - Tcl_CreateObjCommand(interp, "clock_seconds", clock_seconds_proc, 0, 0); -#if SQLITE_OS_UNIX && defined(SQLITE_ENABLE_UNLOCK_NOTIFY) - Tcl_CreateObjCommand(interp, "sqlite3_blocking_step", blocking_step_proc,0,0); - Tcl_CreateObjCommand(interp, - "sqlite3_blocking_prepare_v2", blocking_prepare_v2_proc, (void *)1, 0); - Tcl_CreateObjCommand(interp, - "sqlite3_nonblocking_prepare_v2", blocking_prepare_v2_proc, 0, 0); -#endif - return TCL_OK; -} -#else -int SqlitetestThread_Init(Tcl_Interp *interp){ - return TCL_OK; -} -#endif diff --git a/components/external/SQLite-3.8.1/SQLiteLib/test/test_vfs.c b/components/external/SQLite-3.8.1/SQLiteLib/test/test_vfs.c deleted file mode 100644 index 613b0fce77..0000000000 --- a/components/external/SQLite-3.8.1/SQLiteLib/test/test_vfs.c +++ /dev/null @@ -1,1510 +0,0 @@ -/* -** 2010 May 05 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -****************************************************************************** -** -** This file contains the implementation of the Tcl [testvfs] command, -** used to create SQLite VFS implementations with various properties and -** instrumentation to support testing SQLite. -** -** testvfs VFSNAME ?OPTIONS? -** -** Available options are: -** -** -noshm BOOLEAN (True to omit shm methods. Default false) -** -default BOOLEAN (True to make the vfs default. Default false) -** -szosfile INTEGER (Value for sqlite3_vfs.szOsFile) -** -mxpathname INTEGER (Value for sqlite3_vfs.mxPathname) -** -iversion INTEGER (Value for sqlite3_vfs.iVersion) -*/ -#if SQLITE_TEST /* This file is used for testing only */ - -#include "sqlite3.h" -#include "sqliteInt.h" -#include <tcl.h> - -typedef struct Testvfs Testvfs; -typedef struct TestvfsShm TestvfsShm; -typedef struct TestvfsBuffer TestvfsBuffer; -typedef struct TestvfsFile TestvfsFile; -typedef struct TestvfsFd TestvfsFd; - -/* -** An open file handle. -*/ -struct TestvfsFile { - sqlite3_file base; /* Base class. Must be first */ - TestvfsFd *pFd; /* File data */ -}; -#define tvfsGetFd(pFile) (((TestvfsFile *)pFile)->pFd) - -struct TestvfsFd { - sqlite3_vfs *pVfs; /* The VFS */ - const char *zFilename; /* Filename as passed to xOpen() */ - sqlite3_file *pReal; /* The real, underlying file descriptor */ - Tcl_Obj *pShmId; /* Shared memory id for Tcl callbacks */ - - TestvfsBuffer *pShm; /* Shared memory buffer */ - u32 excllock; /* Mask of exclusive locks */ - u32 sharedlock; /* Mask of shared locks */ - TestvfsFd *pNext; /* Next handle opened on the same file */ -}; - - -#define FAULT_INJECT_NONE 0 -#define FAULT_INJECT_TRANSIENT 1 -#define FAULT_INJECT_PERSISTENT 2 - -typedef struct TestFaultInject TestFaultInject; -struct TestFaultInject { - int iCnt; /* Remaining calls before fault injection */ - int eFault; /* A FAULT_INJECT_* value */ - int nFail; /* Number of faults injected */ -}; - -/* -** An instance of this structure is allocated for each VFS created. The -** sqlite3_vfs.pAppData field of the VFS structure registered with SQLite -** is set to point to it. -*/ -struct Testvfs { - char *zName; /* Name of this VFS */ - sqlite3_vfs *pParent; /* The VFS to use for file IO */ - sqlite3_vfs *pVfs; /* The testvfs registered with SQLite */ - Tcl_Interp *interp; /* Interpreter to run script in */ - Tcl_Obj *pScript; /* Script to execute */ - TestvfsBuffer *pBuffer; /* List of shared buffers */ - int isNoshm; - int isFullshm; - - int mask; /* Mask controlling [script] and [ioerr] */ - - TestFaultInject ioerr_err; - TestFaultInject full_err; - TestFaultInject cantopen_err; - -#if 0 - int iIoerrCnt; - int ioerr; - int nIoerrFail; - int iFullCnt; - int fullerr; - int nFullFail; -#endif - - int iDevchar; - int iSectorsize; -}; - -/* -** The Testvfs.mask variable is set to a combination of the following. -** If a bit is clear in Testvfs.mask, then calls made by SQLite to the -** corresponding VFS method is ignored for purposes of: -** -** + Simulating IO errors, and -** + Invoking the Tcl callback script. -*/ -#define TESTVFS_SHMOPEN_MASK 0x00000001 -#define TESTVFS_SHMLOCK_MASK 0x00000010 -#define TESTVFS_SHMMAP_MASK 0x00000020 -#define TESTVFS_SHMBARRIER_MASK 0x00000040 -#define TESTVFS_SHMCLOSE_MASK 0x00000080 - -#define TESTVFS_OPEN_MASK 0x00000100 -#define TESTVFS_SYNC_MASK 0x00000200 -#define TESTVFS_DELETE_MASK 0x00000400 -#define TESTVFS_CLOSE_MASK 0x00000800 -#define TESTVFS_WRITE_MASK 0x00001000 -#define TESTVFS_TRUNCATE_MASK 0x00002000 -#define TESTVFS_ACCESS_MASK 0x00004000 -#define TESTVFS_FULLPATHNAME_MASK 0x00008000 -#define TESTVFS_READ_MASK 0x00010000 -#define TESTVFS_UNLOCK_MASK 0x00020000 - -#define TESTVFS_ALL_MASK 0x0003FFFF - - -#define TESTVFS_MAX_PAGES 1024 - -/* -** A shared-memory buffer. There is one of these objects for each shared -** memory region opened by clients. If two clients open the same file, -** there are two TestvfsFile structures but only one TestvfsBuffer structure. -*/ -struct TestvfsBuffer { - char *zFile; /* Associated file name */ - int pgsz; /* Page size */ - u8 *aPage[TESTVFS_MAX_PAGES]; /* Array of ckalloc'd pages */ - TestvfsFd *pFile; /* List of open handles */ - TestvfsBuffer *pNext; /* Next in linked list of all buffers */ -}; - - -#define PARENTVFS(x) (((Testvfs *)((x)->pAppData))->pParent) - -#define TESTVFS_MAX_ARGS 12 - - -/* -** Method declarations for TestvfsFile. -*/ -static int tvfsClose(sqlite3_file*); -static int tvfsRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst); -static int tvfsWrite(sqlite3_file*,const void*,int iAmt, sqlite3_int64 iOfst); -static int tvfsTruncate(sqlite3_file*, sqlite3_int64 size); -static int tvfsSync(sqlite3_file*, int flags); -static int tvfsFileSize(sqlite3_file*, sqlite3_int64 *pSize); -static int tvfsLock(sqlite3_file*, int); -static int tvfsUnlock(sqlite3_file*, int); -static int tvfsCheckReservedLock(sqlite3_file*, int *); -static int tvfsFileControl(sqlite3_file*, int op, void *pArg); -static int tvfsSectorSize(sqlite3_file*); -static int tvfsDeviceCharacteristics(sqlite3_file*); - -/* -** Method declarations for tvfs_vfs. -*/ -static int tvfsOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *); -static int tvfsDelete(sqlite3_vfs*, const char *zName, int syncDir); -static int tvfsAccess(sqlite3_vfs*, const char *zName, int flags, int *); -static int tvfsFullPathname(sqlite3_vfs*, const char *zName, int, char *zOut); -#ifndef SQLITE_OMIT_LOAD_EXTENSION -static void *tvfsDlOpen(sqlite3_vfs*, const char *zFilename); -static void tvfsDlError(sqlite3_vfs*, int nByte, char *zErrMsg); -static void (*tvfsDlSym(sqlite3_vfs*,void*, const char *zSymbol))(void); -static void tvfsDlClose(sqlite3_vfs*, void*); -#endif /* SQLITE_OMIT_LOAD_EXTENSION */ -static int tvfsRandomness(sqlite3_vfs*, int nByte, char *zOut); -static int tvfsSleep(sqlite3_vfs*, int microseconds); -static int tvfsCurrentTime(sqlite3_vfs*, double*); - -static int tvfsShmOpen(sqlite3_file*); -static int tvfsShmLock(sqlite3_file*, int , int, int); -static int tvfsShmMap(sqlite3_file*,int,int,int, void volatile **); -static void tvfsShmBarrier(sqlite3_file*); -static int tvfsShmUnmap(sqlite3_file*, int); - -static int tvfsFetch(sqlite3_file*, sqlite3_int64, int, void**); -static int tvfsUnfetch(sqlite3_file*, sqlite3_int64, void*); - -static sqlite3_io_methods tvfs_io_methods = { - 3, /* iVersion */ - tvfsClose, /* xClose */ - tvfsRead, /* xRead */ - tvfsWrite, /* xWrite */ - tvfsTruncate, /* xTruncate */ - tvfsSync, /* xSync */ - tvfsFileSize, /* xFileSize */ - tvfsLock, /* xLock */ - tvfsUnlock, /* xUnlock */ - tvfsCheckReservedLock, /* xCheckReservedLock */ - tvfsFileControl, /* xFileControl */ - tvfsSectorSize, /* xSectorSize */ - tvfsDeviceCharacteristics, /* xDeviceCharacteristics */ - tvfsShmMap, /* xShmMap */ - tvfsShmLock, /* xShmLock */ - tvfsShmBarrier, /* xShmBarrier */ - tvfsShmUnmap, /* xShmUnmap */ - tvfsFetch, - tvfsUnfetch -}; - -static int tvfsResultCode(Testvfs *p, int *pRc){ - struct errcode { - int eCode; - const char *zCode; - } aCode[] = { - { SQLITE_OK, "SQLITE_OK" }, - { SQLITE_ERROR, "SQLITE_ERROR" }, - { SQLITE_IOERR, "SQLITE_IOERR" }, - { SQLITE_LOCKED, "SQLITE_LOCKED" }, - { SQLITE_BUSY, "SQLITE_BUSY" }, - }; - - const char *z; - int i; - - z = Tcl_GetStringResult(p->interp); - for(i=0; i<ArraySize(aCode); i++){ - if( 0==strcmp(z, aCode[i].zCode) ){ - *pRc = aCode[i].eCode; - return 1; - } - } - - return 0; -} - -static int tvfsInjectFault(TestFaultInject *p){ - int ret = 0; - if( p->eFault ){ - p->iCnt--; - if( p->iCnt==0 || (p->iCnt<0 && p->eFault==FAULT_INJECT_PERSISTENT ) ){ - ret = 1; - p->nFail++; - } - } - return ret; -} - - -static int tvfsInjectIoerr(Testvfs *p){ - return tvfsInjectFault(&p->ioerr_err); -} - -static int tvfsInjectFullerr(Testvfs *p){ - return tvfsInjectFault(&p->full_err); -} -static int tvfsInjectCantopenerr(Testvfs *p){ - return tvfsInjectFault(&p->cantopen_err); -} - - -static void tvfsExecTcl( - Testvfs *p, - const char *zMethod, - Tcl_Obj *arg1, - Tcl_Obj *arg2, - Tcl_Obj *arg3, - Tcl_Obj *arg4 -){ - int rc; /* Return code from Tcl_EvalObj() */ - Tcl_Obj *pEval; - assert( p->pScript ); - - assert( zMethod ); - assert( p ); - assert( arg2==0 || arg1!=0 ); - assert( arg3==0 || arg2!=0 ); - - pEval = Tcl_DuplicateObj(p->pScript); - Tcl_IncrRefCount(p->pScript); - Tcl_ListObjAppendElement(p->interp, pEval, Tcl_NewStringObj(zMethod, -1)); - if( arg1 ) Tcl_ListObjAppendElement(p->interp, pEval, arg1); - if( arg2 ) Tcl_ListObjAppendElement(p->interp, pEval, arg2); - if( arg3 ) Tcl_ListObjAppendElement(p->interp, pEval, arg3); - if( arg4 ) Tcl_ListObjAppendElement(p->interp, pEval, arg4); - - rc = Tcl_EvalObjEx(p->interp, pEval, TCL_EVAL_GLOBAL); - if( rc!=TCL_OK ){ - Tcl_BackgroundError(p->interp); - Tcl_ResetResult(p->interp); - } -} - - -/* -** Close an tvfs-file. -*/ -static int tvfsClose(sqlite3_file *pFile){ - int rc; - TestvfsFile *pTestfile = (TestvfsFile *)pFile; - TestvfsFd *pFd = pTestfile->pFd; - Testvfs *p = (Testvfs *)pFd->pVfs->pAppData; - - if( p->pScript && p->mask&TESTVFS_CLOSE_MASK ){ - tvfsExecTcl(p, "xClose", - Tcl_NewStringObj(pFd->zFilename, -1), pFd->pShmId, 0, 0 - ); - } - - if( pFd->pShmId ){ - Tcl_DecrRefCount(pFd->pShmId); - pFd->pShmId = 0; - } - if( pFile->pMethods ){ - ckfree((char *)pFile->pMethods); - } - rc = sqlite3OsClose(pFd->pReal); - ckfree((char *)pFd); - pTestfile->pFd = 0; - return rc; -} - -/* -** Read data from an tvfs-file. -*/ -static int tvfsRead( - sqlite3_file *pFile, - void *zBuf, - int iAmt, - sqlite_int64 iOfst -){ - int rc = SQLITE_OK; - TestvfsFd *pFd = tvfsGetFd(pFile); - Testvfs *p = (Testvfs *)pFd->pVfs->pAppData; - if( p->pScript && p->mask&TESTVFS_READ_MASK ){ - tvfsExecTcl(p, "xRead", - Tcl_NewStringObj(pFd->zFilename, -1), pFd->pShmId, 0, 0 - ); - tvfsResultCode(p, &rc); - } - if( rc==SQLITE_OK && p->mask&TESTVFS_READ_MASK && tvfsInjectIoerr(p) ){ - rc = SQLITE_IOERR; - } - if( rc==SQLITE_OK ){ - rc = sqlite3OsRead(pFd->pReal, zBuf, iAmt, iOfst); - } - return rc; -} - -/* -** Write data to an tvfs-file. -*/ -static int tvfsWrite( - sqlite3_file *pFile, - const void *zBuf, - int iAmt, - sqlite_int64 iOfst -){ - int rc = SQLITE_OK; - TestvfsFd *pFd = tvfsGetFd(pFile); - Testvfs *p = (Testvfs *)pFd->pVfs->pAppData; - - if( p->pScript && p->mask&TESTVFS_WRITE_MASK ){ - tvfsExecTcl(p, "xWrite", - Tcl_NewStringObj(pFd->zFilename, -1), pFd->pShmId, - Tcl_NewWideIntObj(iOfst), Tcl_NewIntObj(iAmt) - ); - tvfsResultCode(p, &rc); - } - - if( rc==SQLITE_OK && tvfsInjectFullerr(p) ){ - rc = SQLITE_FULL; - } - if( rc==SQLITE_OK && p->mask&TESTVFS_WRITE_MASK && tvfsInjectIoerr(p) ){ - rc = SQLITE_IOERR; - } - - if( rc==SQLITE_OK ){ - rc = sqlite3OsWrite(pFd->pReal, zBuf, iAmt, iOfst); - } - return rc; -} - -/* -** Truncate an tvfs-file. -*/ -static int tvfsTruncate(sqlite3_file *pFile, sqlite_int64 size){ - int rc = SQLITE_OK; - TestvfsFd *pFd = tvfsGetFd(pFile); - Testvfs *p = (Testvfs *)pFd->pVfs->pAppData; - - if( p->pScript && p->mask&TESTVFS_TRUNCATE_MASK ){ - tvfsExecTcl(p, "xTruncate", - Tcl_NewStringObj(pFd->zFilename, -1), pFd->pShmId, 0, 0 - ); - tvfsResultCode(p, &rc); - } - - if( rc==SQLITE_OK ){ - rc = sqlite3OsTruncate(pFd->pReal, size); - } - return rc; -} - -/* -** Sync an tvfs-file. -*/ -static int tvfsSync(sqlite3_file *pFile, int flags){ - int rc = SQLITE_OK; - TestvfsFd *pFd = tvfsGetFd(pFile); - Testvfs *p = (Testvfs *)pFd->pVfs->pAppData; - - if( p->pScript && p->mask&TESTVFS_SYNC_MASK ){ - char *zFlags; - - switch( flags ){ - case SQLITE_SYNC_NORMAL: - zFlags = "normal"; - break; - case SQLITE_SYNC_FULL: - zFlags = "full"; - break; - case SQLITE_SYNC_NORMAL|SQLITE_SYNC_DATAONLY: - zFlags = "normal|dataonly"; - break; - case SQLITE_SYNC_FULL|SQLITE_SYNC_DATAONLY: - zFlags = "full|dataonly"; - break; - default: - assert(0); - } - - tvfsExecTcl(p, "xSync", - Tcl_NewStringObj(pFd->zFilename, -1), pFd->pShmId, - Tcl_NewStringObj(zFlags, -1), 0 - ); - tvfsResultCode(p, &rc); - } - - if( rc==SQLITE_OK && tvfsInjectFullerr(p) ) rc = SQLITE_FULL; - - if( rc==SQLITE_OK ){ - rc = sqlite3OsSync(pFd->pReal, flags); - } - - return rc; -} - -/* -** Return the current file-size of an tvfs-file. -*/ -static int tvfsFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){ - TestvfsFd *p = tvfsGetFd(pFile); - return sqlite3OsFileSize(p->pReal, pSize); -} - -/* -** Lock an tvfs-file. -*/ -static int tvfsLock(sqlite3_file *pFile, int eLock){ - TestvfsFd *p = tvfsGetFd(pFile); - return sqlite3OsLock(p->pReal, eLock); -} - -/* -** Unlock an tvfs-file. -*/ -static int tvfsUnlock(sqlite3_file *pFile, int eLock){ - TestvfsFd *pFd = tvfsGetFd(pFile); - Testvfs *p = (Testvfs *)pFd->pVfs->pAppData; - if( p->mask&TESTVFS_WRITE_MASK && tvfsInjectIoerr(p) ){ - return SQLITE_IOERR_UNLOCK; - } - return sqlite3OsUnlock(pFd->pReal, eLock); -} - -/* -** Check if another file-handle holds a RESERVED lock on an tvfs-file. -*/ -static int tvfsCheckReservedLock(sqlite3_file *pFile, int *pResOut){ - TestvfsFd *p = tvfsGetFd(pFile); - return sqlite3OsCheckReservedLock(p->pReal, pResOut); -} - -/* -** File control method. For custom operations on an tvfs-file. -*/ -static int tvfsFileControl(sqlite3_file *pFile, int op, void *pArg){ - TestvfsFd *p = tvfsGetFd(pFile); - if( op==SQLITE_FCNTL_PRAGMA ){ - char **argv = (char**)pArg; - if( sqlite3_stricmp(argv[1],"error")==0 ){ - int rc = SQLITE_ERROR; - if( argv[2] ){ - const char *z = argv[2]; - int x = atoi(z); - if( x ){ - rc = x; - while( sqlite3Isdigit(z[0]) ){ z++; } - while( sqlite3Isspace(z[0]) ){ z++; } - } - if( z[0] ) argv[0] = sqlite3_mprintf("%s", z); - } - return rc; - } - if( sqlite3_stricmp(argv[1], "filename")==0 ){ - argv[0] = sqlite3_mprintf("%s", p->zFilename); - return SQLITE_OK; - } - } - return sqlite3OsFileControl(p->pReal, op, pArg); -} - -/* -** Return the sector-size in bytes for an tvfs-file. -*/ -static int tvfsSectorSize(sqlite3_file *pFile){ - TestvfsFd *pFd = tvfsGetFd(pFile); - Testvfs *p = (Testvfs *)pFd->pVfs->pAppData; - if( p->iSectorsize>=0 ){ - return p->iSectorsize; - } - return sqlite3OsSectorSize(pFd->pReal); -} - -/* -** Return the device characteristic flags supported by an tvfs-file. -*/ -static int tvfsDeviceCharacteristics(sqlite3_file *pFile){ - TestvfsFd *pFd = tvfsGetFd(pFile); - Testvfs *p = (Testvfs *)pFd->pVfs->pAppData; - if( p->iDevchar>=0 ){ - return p->iDevchar; - } - return sqlite3OsDeviceCharacteristics(pFd->pReal); -} - -/* -** Open an tvfs file handle. -*/ -static int tvfsOpen( - sqlite3_vfs *pVfs, - const char *zName, - sqlite3_file *pFile, - int flags, - int *pOutFlags -){ - int rc; - TestvfsFile *pTestfile = (TestvfsFile *)pFile; - TestvfsFd *pFd; - Tcl_Obj *pId = 0; - Testvfs *p = (Testvfs *)pVfs->pAppData; - - pFd = (TestvfsFd *)ckalloc(sizeof(TestvfsFd) + PARENTVFS(pVfs)->szOsFile); - memset(pFd, 0, sizeof(TestvfsFd) + PARENTVFS(pVfs)->szOsFile); - pFd->pShm = 0; - pFd->pShmId = 0; - pFd->zFilename = zName; - pFd->pVfs = pVfs; - pFd->pReal = (sqlite3_file *)&pFd[1]; - memset(pTestfile, 0, sizeof(TestvfsFile)); - pTestfile->pFd = pFd; - - /* Evaluate the Tcl script: - ** - ** SCRIPT xOpen FILENAME KEY-VALUE-ARGS - ** - ** If the script returns an SQLite error code other than SQLITE_OK, an - ** error is returned to the caller. If it returns SQLITE_OK, the new - ** connection is named "anon". Otherwise, the value returned by the - ** script is used as the connection name. - */ - Tcl_ResetResult(p->interp); - if( p->pScript && p->mask&TESTVFS_OPEN_MASK ){ - Tcl_Obj *pArg = Tcl_NewObj(); - Tcl_IncrRefCount(pArg); - if( flags&SQLITE_OPEN_MAIN_DB ){ - const char *z = &zName[strlen(zName)+1]; - while( *z ){ - Tcl_ListObjAppendElement(0, pArg, Tcl_NewStringObj(z, -1)); - z += strlen(z) + 1; - Tcl_ListObjAppendElement(0, pArg, Tcl_NewStringObj(z, -1)); - z += strlen(z) + 1; - } - } - tvfsExecTcl(p, "xOpen", Tcl_NewStringObj(pFd->zFilename, -1), pArg, 0, 0); - Tcl_DecrRefCount(pArg); - if( tvfsResultCode(p, &rc) ){ - if( rc!=SQLITE_OK ) return rc; - }else{ - pId = Tcl_GetObjResult(p->interp); - } - } - - if( (p->mask&TESTVFS_OPEN_MASK) && tvfsInjectIoerr(p) ) return SQLITE_IOERR; - if( tvfsInjectCantopenerr(p) ) return SQLITE_CANTOPEN; - if( tvfsInjectFullerr(p) ) return SQLITE_FULL; - - if( !pId ){ - pId = Tcl_NewStringObj("anon", -1); - } - Tcl_IncrRefCount(pId); - pFd->pShmId = pId; - Tcl_ResetResult(p->interp); - - rc = sqlite3OsOpen(PARENTVFS(pVfs), zName, pFd->pReal, flags, pOutFlags); - if( pFd->pReal->pMethods ){ - sqlite3_io_methods *pMethods; - int nByte; - - if( pVfs->iVersion>1 ){ - nByte = sizeof(sqlite3_io_methods); - }else{ - nByte = offsetof(sqlite3_io_methods, xShmMap); - } - - pMethods = (sqlite3_io_methods *)ckalloc(nByte); - memcpy(pMethods, &tvfs_io_methods, nByte); - pMethods->iVersion = pFd->pReal->pMethods->iVersion; - if( pMethods->iVersion>pVfs->iVersion ){ - pMethods->iVersion = pVfs->iVersion; - } - if( pVfs->iVersion>1 && ((Testvfs *)pVfs->pAppData)->isNoshm ){ - pMethods->xShmUnmap = 0; - pMethods->xShmLock = 0; - pMethods->xShmBarrier = 0; - pMethods->xShmMap = 0; - } - pFile->pMethods = pMethods; - } - - return rc; -} - -/* -** Delete the file located at zPath. If the dirSync argument is true, -** ensure the file-system modifications are synced to disk before -** returning. -*/ -static int tvfsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){ - int rc = SQLITE_OK; - Testvfs *p = (Testvfs *)pVfs->pAppData; - - if( p->pScript && p->mask&TESTVFS_DELETE_MASK ){ - tvfsExecTcl(p, "xDelete", - Tcl_NewStringObj(zPath, -1), Tcl_NewIntObj(dirSync), 0, 0 - ); - tvfsResultCode(p, &rc); - } - if( rc==SQLITE_OK ){ - rc = sqlite3OsDelete(PARENTVFS(pVfs), zPath, dirSync); - } - return rc; -} - -/* -** Test for access permissions. Return true if the requested permission -** is available, or false otherwise. -*/ -static int tvfsAccess( - sqlite3_vfs *pVfs, - const char *zPath, - int flags, - int *pResOut -){ - Testvfs *p = (Testvfs *)pVfs->pAppData; - if( p->pScript && p->mask&TESTVFS_ACCESS_MASK ){ - int rc; - char *zArg = 0; - if( flags==SQLITE_ACCESS_EXISTS ) zArg = "SQLITE_ACCESS_EXISTS"; - if( flags==SQLITE_ACCESS_READWRITE ) zArg = "SQLITE_ACCESS_READWRITE"; - if( flags==SQLITE_ACCESS_READ ) zArg = "SQLITE_ACCESS_READ"; - tvfsExecTcl(p, "xAccess", - Tcl_NewStringObj(zPath, -1), Tcl_NewStringObj(zArg, -1), 0, 0 - ); - if( tvfsResultCode(p, &rc) ){ - if( rc!=SQLITE_OK ) return rc; - }else{ - Tcl_Interp *interp = p->interp; - if( TCL_OK==Tcl_GetBooleanFromObj(0, Tcl_GetObjResult(interp), pResOut) ){ - return SQLITE_OK; - } - } - } - return sqlite3OsAccess(PARENTVFS(pVfs), zPath, flags, pResOut); -} - -/* -** Populate buffer zOut with the full canonical pathname corresponding -** to the pathname in zPath. zOut is guaranteed to point to a buffer -** of at least (DEVSYM_MAX_PATHNAME+1) bytes. -*/ -static int tvfsFullPathname( - sqlite3_vfs *pVfs, - const char *zPath, - int nOut, - char *zOut -){ - Testvfs *p = (Testvfs *)pVfs->pAppData; - if( p->pScript && p->mask&TESTVFS_FULLPATHNAME_MASK ){ - int rc; - tvfsExecTcl(p, "xFullPathname", Tcl_NewStringObj(zPath, -1), 0, 0, 0); - if( tvfsResultCode(p, &rc) ){ - if( rc!=SQLITE_OK ) return rc; - } - } - return sqlite3OsFullPathname(PARENTVFS(pVfs), zPath, nOut, zOut); -} - -#ifndef SQLITE_OMIT_LOAD_EXTENSION -/* -** Open the dynamic library located at zPath and return a handle. -*/ -static void *tvfsDlOpen(sqlite3_vfs *pVfs, const char *zPath){ - return sqlite3OsDlOpen(PARENTVFS(pVfs), zPath); -} - -/* -** Populate the buffer zErrMsg (size nByte bytes) with a human readable -** utf-8 string describing the most recent error encountered associated -** with dynamic libraries. -*/ -static void tvfsDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){ - sqlite3OsDlError(PARENTVFS(pVfs), nByte, zErrMsg); -} - -/* -** Return a pointer to the symbol zSymbol in the dynamic library pHandle. -*/ -static void (*tvfsDlSym(sqlite3_vfs *pVfs, void *p, const char *zSym))(void){ - return sqlite3OsDlSym(PARENTVFS(pVfs), p, zSym); -} - -/* -** Close the dynamic library handle pHandle. -*/ -static void tvfsDlClose(sqlite3_vfs *pVfs, void *pHandle){ - sqlite3OsDlClose(PARENTVFS(pVfs), pHandle); -} -#endif /* SQLITE_OMIT_LOAD_EXTENSION */ - -/* -** Populate the buffer pointed to by zBufOut with nByte bytes of -** random data. -*/ -static int tvfsRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){ - return sqlite3OsRandomness(PARENTVFS(pVfs), nByte, zBufOut); -} - -/* -** Sleep for nMicro microseconds. Return the number of microseconds -** actually slept. -*/ -static int tvfsSleep(sqlite3_vfs *pVfs, int nMicro){ - return sqlite3OsSleep(PARENTVFS(pVfs), nMicro); -} - -/* -** Return the current time as a Julian Day number in *pTimeOut. -*/ -static int tvfsCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){ - return PARENTVFS(pVfs)->xCurrentTime(PARENTVFS(pVfs), pTimeOut); -} - -static int tvfsShmOpen(sqlite3_file *pFile){ - Testvfs *p; - int rc = SQLITE_OK; /* Return code */ - TestvfsBuffer *pBuffer; /* Buffer to open connection to */ - TestvfsFd *pFd; /* The testvfs file structure */ - - pFd = tvfsGetFd(pFile); - p = (Testvfs *)pFd->pVfs->pAppData; - assert( 0==p->isFullshm ); - assert( pFd->pShmId && pFd->pShm==0 && pFd->pNext==0 ); - - /* Evaluate the Tcl script: - ** - ** SCRIPT xShmOpen FILENAME - */ - Tcl_ResetResult(p->interp); - if( p->pScript && p->mask&TESTVFS_SHMOPEN_MASK ){ - tvfsExecTcl(p, "xShmOpen", Tcl_NewStringObj(pFd->zFilename, -1), 0, 0, 0); - if( tvfsResultCode(p, &rc) ){ - if( rc!=SQLITE_OK ) return rc; - } - } - - assert( rc==SQLITE_OK ); - if( p->mask&TESTVFS_SHMOPEN_MASK && tvfsInjectIoerr(p) ){ - return SQLITE_IOERR; - } - - /* Search for a TestvfsBuffer. Create a new one if required. */ - for(pBuffer=p->pBuffer; pBuffer; pBuffer=pBuffer->pNext){ - if( 0==strcmp(pFd->zFilename, pBuffer->zFile) ) break; - } - if( !pBuffer ){ - int nByte = sizeof(TestvfsBuffer) + (int)strlen(pFd->zFilename) + 1; - pBuffer = (TestvfsBuffer *)ckalloc(nByte); - memset(pBuffer, 0, nByte); - pBuffer->zFile = (char *)&pBuffer[1]; - strcpy(pBuffer->zFile, pFd->zFilename); - pBuffer->pNext = p->pBuffer; - p->pBuffer = pBuffer; - } - - /* Connect the TestvfsBuffer to the new TestvfsShm handle and return. */ - pFd->pNext = pBuffer->pFile; - pBuffer->pFile = pFd; - pFd->pShm = pBuffer; - return SQLITE_OK; -} - -static void tvfsAllocPage(TestvfsBuffer *p, int iPage, int pgsz){ - assert( iPage<TESTVFS_MAX_PAGES ); - if( p->aPage[iPage]==0 ){ - p->aPage[iPage] = (u8 *)ckalloc(pgsz); - memset(p->aPage[iPage], 0, pgsz); - p->pgsz = pgsz; - } -} - -static int tvfsShmMap( - sqlite3_file *pFile, /* Handle open on database file */ - int iPage, /* Page to retrieve */ - int pgsz, /* Size of pages */ - int isWrite, /* True to extend file if necessary */ - void volatile **pp /* OUT: Mapped memory */ -){ - int rc = SQLITE_OK; - TestvfsFd *pFd = tvfsGetFd(pFile); - Testvfs *p = (Testvfs *)(pFd->pVfs->pAppData); - - if( p->isFullshm ){ - return sqlite3OsShmMap(pFd->pReal, iPage, pgsz, isWrite, pp); - } - - if( 0==pFd->pShm ){ - rc = tvfsShmOpen(pFile); - if( rc!=SQLITE_OK ){ - return rc; - } - } - - if( p->pScript && p->mask&TESTVFS_SHMMAP_MASK ){ - Tcl_Obj *pArg = Tcl_NewObj(); - Tcl_IncrRefCount(pArg); - Tcl_ListObjAppendElement(p->interp, pArg, Tcl_NewIntObj(iPage)); - Tcl_ListObjAppendElement(p->interp, pArg, Tcl_NewIntObj(pgsz)); - Tcl_ListObjAppendElement(p->interp, pArg, Tcl_NewIntObj(isWrite)); - tvfsExecTcl(p, "xShmMap", - Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, pArg, 0 - ); - tvfsResultCode(p, &rc); - Tcl_DecrRefCount(pArg); - } - if( rc==SQLITE_OK && p->mask&TESTVFS_SHMMAP_MASK && tvfsInjectIoerr(p) ){ - rc = SQLITE_IOERR; - } - - if( rc==SQLITE_OK && isWrite && !pFd->pShm->aPage[iPage] ){ - tvfsAllocPage(pFd->pShm, iPage, pgsz); - } - *pp = (void volatile *)pFd->pShm->aPage[iPage]; - - return rc; -} - - -static int tvfsShmLock( - sqlite3_file *pFile, - int ofst, - int n, - int flags -){ - int rc = SQLITE_OK; - TestvfsFd *pFd = tvfsGetFd(pFile); - Testvfs *p = (Testvfs *)(pFd->pVfs->pAppData); - int nLock; - char zLock[80]; - - if( p->isFullshm ){ - return sqlite3OsShmLock(pFd->pReal, ofst, n, flags); - } - - if( p->pScript && p->mask&TESTVFS_SHMLOCK_MASK ){ - sqlite3_snprintf(sizeof(zLock), zLock, "%d %d", ofst, n); - nLock = (int)strlen(zLock); - if( flags & SQLITE_SHM_LOCK ){ - strcpy(&zLock[nLock], " lock"); - }else{ - strcpy(&zLock[nLock], " unlock"); - } - nLock += (int)strlen(&zLock[nLock]); - if( flags & SQLITE_SHM_SHARED ){ - strcpy(&zLock[nLock], " shared"); - }else{ - strcpy(&zLock[nLock], " exclusive"); - } - tvfsExecTcl(p, "xShmLock", - Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, - Tcl_NewStringObj(zLock, -1), 0 - ); - tvfsResultCode(p, &rc); - } - - if( rc==SQLITE_OK && p->mask&TESTVFS_SHMLOCK_MASK && tvfsInjectIoerr(p) ){ - rc = SQLITE_IOERR; - } - - if( rc==SQLITE_OK ){ - int isLock = (flags & SQLITE_SHM_LOCK); - int isExcl = (flags & SQLITE_SHM_EXCLUSIVE); - u32 mask = (((1<<n)-1) << ofst); - if( isLock ){ - TestvfsFd *p2; - for(p2=pFd->pShm->pFile; p2; p2=p2->pNext){ - if( p2==pFd ) continue; - if( (p2->excllock&mask) || (isExcl && p2->sharedlock&mask) ){ - rc = SQLITE_BUSY; - break; - } - } - if( rc==SQLITE_OK ){ - if( isExcl ) pFd->excllock |= mask; - if( !isExcl ) pFd->sharedlock |= mask; - } - }else{ - if( isExcl ) pFd->excllock &= (~mask); - if( !isExcl ) pFd->sharedlock &= (~mask); - } - } - - return rc; -} - -static void tvfsShmBarrier(sqlite3_file *pFile){ - TestvfsFd *pFd = tvfsGetFd(pFile); - Testvfs *p = (Testvfs *)(pFd->pVfs->pAppData); - - if( p->isFullshm ){ - sqlite3OsShmBarrier(pFd->pReal); - return; - } - - if( p->pScript && p->mask&TESTVFS_SHMBARRIER_MASK ){ - tvfsExecTcl(p, "xShmBarrier", - Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, 0, 0 - ); - } -} - -static int tvfsShmUnmap( - sqlite3_file *pFile, - int deleteFlag -){ - int rc = SQLITE_OK; - TestvfsFd *pFd = tvfsGetFd(pFile); - Testvfs *p = (Testvfs *)(pFd->pVfs->pAppData); - TestvfsBuffer *pBuffer = pFd->pShm; - TestvfsFd **ppFd; - - if( p->isFullshm ){ - return sqlite3OsShmUnmap(pFd->pReal, deleteFlag); - } - - if( !pBuffer ) return SQLITE_OK; - assert( pFd->pShmId && pFd->pShm ); - - if( p->pScript && p->mask&TESTVFS_SHMCLOSE_MASK ){ - tvfsExecTcl(p, "xShmUnmap", - Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, 0, 0 - ); - tvfsResultCode(p, &rc); - } - - for(ppFd=&pBuffer->pFile; *ppFd!=pFd; ppFd=&((*ppFd)->pNext)); - assert( (*ppFd)==pFd ); - *ppFd = pFd->pNext; - pFd->pNext = 0; - - if( pBuffer->pFile==0 ){ - int i; - TestvfsBuffer **pp; - for(pp=&p->pBuffer; *pp!=pBuffer; pp=&((*pp)->pNext)); - *pp = (*pp)->pNext; - for(i=0; pBuffer->aPage[i]; i++){ - ckfree((char *)pBuffer->aPage[i]); - } - ckfree((char *)pBuffer); - } - pFd->pShm = 0; - - return rc; -} - -static int tvfsFetch( - sqlite3_file *pFile, - sqlite3_int64 iOfst, - int iAmt, - void **pp -){ - TestvfsFd *pFd = tvfsGetFd(pFile); - return sqlite3OsFetch(pFd->pReal, iOfst, iAmt, pp); -} - -static int tvfsUnfetch(sqlite3_file *pFile, sqlite3_int64 iOfst, void *p){ - TestvfsFd *pFd = tvfsGetFd(pFile); - return sqlite3OsUnfetch(pFd->pReal, iOfst, p); -} - -static int testvfs_obj_cmd( - ClientData cd, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - Testvfs *p = (Testvfs *)cd; - - enum DB_enum { - CMD_SHM, CMD_DELETE, CMD_FILTER, CMD_IOERR, CMD_SCRIPT, - CMD_DEVCHAR, CMD_SECTORSIZE, CMD_FULLERR, CMD_CANTOPENERR - }; - struct TestvfsSubcmd { - char *zName; - enum DB_enum eCmd; - } aSubcmd[] = { - { "shm", CMD_SHM }, - { "delete", CMD_DELETE }, - { "filter", CMD_FILTER }, - { "ioerr", CMD_IOERR }, - { "fullerr", CMD_FULLERR }, - { "cantopenerr", CMD_CANTOPENERR }, - { "script", CMD_SCRIPT }, - { "devchar", CMD_DEVCHAR }, - { "sectorsize", CMD_SECTORSIZE }, - { 0, 0 } - }; - int i; - - if( objc<2 ){ - Tcl_WrongNumArgs(interp, 1, objv, "SUBCOMMAND ..."); - return TCL_ERROR; - } - if( Tcl_GetIndexFromObjStruct( - interp, objv[1], aSubcmd, sizeof(aSubcmd[0]), "subcommand", 0, &i) - ){ - return TCL_ERROR; - } - Tcl_ResetResult(interp); - - switch( aSubcmd[i].eCmd ){ - case CMD_SHM: { - Tcl_Obj *pObj; - int i, rc; - TestvfsBuffer *pBuffer; - char *zName; - if( objc!=3 && objc!=4 ){ - Tcl_WrongNumArgs(interp, 2, objv, "FILE ?VALUE?"); - return TCL_ERROR; - } - zName = ckalloc(p->pParent->mxPathname); - rc = p->pParent->xFullPathname( - p->pParent, Tcl_GetString(objv[2]), - p->pParent->mxPathname, zName - ); - if( rc!=SQLITE_OK ){ - Tcl_AppendResult(interp, "failed to get full path: ", - Tcl_GetString(objv[2]), 0); - ckfree(zName); - return TCL_ERROR; - } - for(pBuffer=p->pBuffer; pBuffer; pBuffer=pBuffer->pNext){ - if( 0==strcmp(pBuffer->zFile, zName) ) break; - } - ckfree(zName); - if( !pBuffer ){ - Tcl_AppendResult(interp, "no such file: ", Tcl_GetString(objv[2]), 0); - return TCL_ERROR; - } - if( objc==4 ){ - int n; - u8 *a = Tcl_GetByteArrayFromObj(objv[3], &n); - int pgsz = pBuffer->pgsz; - if( pgsz==0 ) pgsz = 65536; - for(i=0; i*pgsz<n; i++){ - int nByte = pgsz; - tvfsAllocPage(pBuffer, i, pgsz); - if( n-i*pgsz<pgsz ){ - nByte = n; - } - memcpy(pBuffer->aPage[i], &a[i*pgsz], nByte); - } - } - - pObj = Tcl_NewObj(); - for(i=0; pBuffer->aPage[i]; i++){ - int pgsz = pBuffer->pgsz; - if( pgsz==0 ) pgsz = 65536; - Tcl_AppendObjToObj(pObj, Tcl_NewByteArrayObj(pBuffer->aPage[i], pgsz)); - } - Tcl_SetObjResult(interp, pObj); - break; - } - - case CMD_FILTER: { - static struct VfsMethod { - char *zName; - int mask; - } vfsmethod [] = { - { "xShmOpen", TESTVFS_SHMOPEN_MASK }, - { "xShmLock", TESTVFS_SHMLOCK_MASK }, - { "xShmBarrier", TESTVFS_SHMBARRIER_MASK }, - { "xShmUnmap", TESTVFS_SHMCLOSE_MASK }, - { "xShmMap", TESTVFS_SHMMAP_MASK }, - { "xSync", TESTVFS_SYNC_MASK }, - { "xDelete", TESTVFS_DELETE_MASK }, - { "xWrite", TESTVFS_WRITE_MASK }, - { "xRead", TESTVFS_READ_MASK }, - { "xTruncate", TESTVFS_TRUNCATE_MASK }, - { "xOpen", TESTVFS_OPEN_MASK }, - { "xClose", TESTVFS_CLOSE_MASK }, - { "xAccess", TESTVFS_ACCESS_MASK }, - { "xFullPathname", TESTVFS_FULLPATHNAME_MASK }, - { "xUnlock", TESTVFS_UNLOCK_MASK }, - }; - Tcl_Obj **apElem = 0; - int nElem = 0; - int i; - int mask = 0; - if( objc!=3 ){ - Tcl_WrongNumArgs(interp, 2, objv, "LIST"); - return TCL_ERROR; - } - if( Tcl_ListObjGetElements(interp, objv[2], &nElem, &apElem) ){ - return TCL_ERROR; - } - Tcl_ResetResult(interp); - for(i=0; i<nElem; i++){ - int iMethod; - char *zElem = Tcl_GetString(apElem[i]); - for(iMethod=0; iMethod<ArraySize(vfsmethod); iMethod++){ - if( strcmp(zElem, vfsmethod[iMethod].zName)==0 ){ - mask |= vfsmethod[iMethod].mask; - break; - } - } - if( iMethod==ArraySize(vfsmethod) ){ - Tcl_AppendResult(interp, "unknown method: ", zElem, 0); - return TCL_ERROR; - } - } - p->mask = mask; - break; - } - - case CMD_SCRIPT: { - if( objc==3 ){ - int nByte; - if( p->pScript ){ - Tcl_DecrRefCount(p->pScript); - p->pScript = 0; - } - Tcl_GetStringFromObj(objv[2], &nByte); - if( nByte>0 ){ - p->pScript = Tcl_DuplicateObj(objv[2]); - Tcl_IncrRefCount(p->pScript); - } - }else if( objc!=2 ){ - Tcl_WrongNumArgs(interp, 2, objv, "?SCRIPT?"); - return TCL_ERROR; - } - - Tcl_ResetResult(interp); - if( p->pScript ) Tcl_SetObjResult(interp, p->pScript); - - break; - } - - /* - ** TESTVFS ioerr ?IFAIL PERSIST? - ** - ** Where IFAIL is an integer and PERSIST is boolean. - */ - case CMD_CANTOPENERR: - case CMD_IOERR: - case CMD_FULLERR: { - TestFaultInject *pTest; - int iRet; - - switch( aSubcmd[i].eCmd ){ - case CMD_IOERR: pTest = &p->ioerr_err; break; - case CMD_FULLERR: pTest = &p->full_err; break; - case CMD_CANTOPENERR: pTest = &p->cantopen_err; break; - default: assert(0); - } - iRet = pTest->nFail; - pTest->nFail = 0; - pTest->eFault = 0; - pTest->iCnt = 0; - - if( objc==4 ){ - int iCnt, iPersist; - if( TCL_OK!=Tcl_GetIntFromObj(interp, objv[2], &iCnt) - || TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[3], &iPersist) - ){ - return TCL_ERROR; - } - pTest->eFault = iPersist?FAULT_INJECT_PERSISTENT:FAULT_INJECT_TRANSIENT; - pTest->iCnt = iCnt; - }else if( objc!=2 ){ - Tcl_WrongNumArgs(interp, 2, objv, "?CNT PERSIST?"); - return TCL_ERROR; - } - Tcl_SetObjResult(interp, Tcl_NewIntObj(iRet)); - break; - } - - case CMD_DELETE: { - Tcl_DeleteCommand(interp, Tcl_GetString(objv[0])); - break; - } - - case CMD_DEVCHAR: { - struct DeviceFlag { - char *zName; - int iValue; - } aFlag[] = { - { "default", -1 }, - { "atomic", SQLITE_IOCAP_ATOMIC }, - { "atomic512", SQLITE_IOCAP_ATOMIC512 }, - { "atomic1k", SQLITE_IOCAP_ATOMIC1K }, - { "atomic2k", SQLITE_IOCAP_ATOMIC2K }, - { "atomic4k", SQLITE_IOCAP_ATOMIC4K }, - { "atomic8k", SQLITE_IOCAP_ATOMIC8K }, - { "atomic16k", SQLITE_IOCAP_ATOMIC16K }, - { "atomic32k", SQLITE_IOCAP_ATOMIC32K }, - { "atomic64k", SQLITE_IOCAP_ATOMIC64K }, - { "sequential", SQLITE_IOCAP_SEQUENTIAL }, - { "safe_append", SQLITE_IOCAP_SAFE_APPEND }, - { "undeletable_when_open", SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN }, - { "powersafe_overwrite", SQLITE_IOCAP_POWERSAFE_OVERWRITE }, - { 0, 0 } - }; - Tcl_Obj *pRet; - int iFlag; - - if( objc>3 ){ - Tcl_WrongNumArgs(interp, 2, objv, "?ATTR-LIST?"); - return TCL_ERROR; - } - if( objc==3 ){ - int j; - int iNew = 0; - Tcl_Obj **flags = 0; - int nFlags = 0; - - if( Tcl_ListObjGetElements(interp, objv[2], &nFlags, &flags) ){ - return TCL_ERROR; - } - - for(j=0; j<nFlags; j++){ - int idx = 0; - if( Tcl_GetIndexFromObjStruct(interp, flags[j], aFlag, - sizeof(aFlag[0]), "flag", 0, &idx) - ){ - return TCL_ERROR; - } - if( aFlag[idx].iValue<0 && nFlags>1 ){ - Tcl_AppendResult(interp, "bad flags: ", Tcl_GetString(objv[2]), 0); - return TCL_ERROR; - } - iNew |= aFlag[idx].iValue; - } - - p->iDevchar = iNew| 0x10000000; - } - - pRet = Tcl_NewObj(); - for(iFlag=0; iFlag<sizeof(aFlag)/sizeof(aFlag[0]); iFlag++){ - if( p->iDevchar & aFlag[iFlag].iValue ){ - Tcl_ListObjAppendElement( - interp, pRet, Tcl_NewStringObj(aFlag[iFlag].zName, -1) - ); - } - } - Tcl_SetObjResult(interp, pRet); - - break; - } - - case CMD_SECTORSIZE: { - if( objc>3 ){ - Tcl_WrongNumArgs(interp, 2, objv, "?VALUE?"); - return TCL_ERROR; - } - if( objc==3 ){ - int iNew = 0; - if( Tcl_GetIntFromObj(interp, objv[2], &iNew) ){ - return TCL_ERROR; - } - p->iSectorsize = iNew; - } - Tcl_SetObjResult(interp, Tcl_NewIntObj(p->iSectorsize)); - break; - } - } - - return TCL_OK; -} - -static void testvfs_obj_del(ClientData cd){ - Testvfs *p = (Testvfs *)cd; - if( p->pScript ) Tcl_DecrRefCount(p->pScript); - sqlite3_vfs_unregister(p->pVfs); - ckfree((char *)p->pVfs); - ckfree((char *)p); -} - -/* -** Usage: testvfs VFSNAME ?SWITCHES? -** -** Switches are: -** -** -noshm BOOLEAN (True to omit shm methods. Default false) -** -default BOOLEAN (True to make the vfs default. Default false) -** -** This command creates two things when it is invoked: an SQLite VFS, and -** a Tcl command. Both are named VFSNAME. The VFS is installed. It is not -** installed as the default VFS. -** -** The VFS passes all file I/O calls through to the underlying VFS. -** -** Whenever the xShmMap method of the VFS -** is invoked, the SCRIPT is executed as follows: -** -** SCRIPT xShmMap FILENAME ID -** -** The value returned by the invocation of SCRIPT above is interpreted as -** an SQLite error code and returned to SQLite. Either a symbolic -** "SQLITE_OK" or numeric "0" value may be returned. -** -** The contents of the shared-memory buffer associated with a given file -** may be read and set using the following command: -** -** VFSNAME shm FILENAME ?NEWVALUE? -** -** When the xShmLock method is invoked by SQLite, the following script is -** run: -** -** SCRIPT xShmLock FILENAME ID LOCK -** -** where LOCK is of the form "OFFSET NBYTE lock/unlock shared/exclusive" -*/ -static int testvfs_cmd( - ClientData cd, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - static sqlite3_vfs tvfs_vfs = { - 3, /* iVersion */ - 0, /* szOsFile */ - 0, /* mxPathname */ - 0, /* pNext */ - 0, /* zName */ - 0, /* pAppData */ - tvfsOpen, /* xOpen */ - tvfsDelete, /* xDelete */ - tvfsAccess, /* xAccess */ - tvfsFullPathname, /* xFullPathname */ -#ifndef SQLITE_OMIT_LOAD_EXTENSION - tvfsDlOpen, /* xDlOpen */ - tvfsDlError, /* xDlError */ - tvfsDlSym, /* xDlSym */ - tvfsDlClose, /* xDlClose */ -#else - 0, /* xDlOpen */ - 0, /* xDlError */ - 0, /* xDlSym */ - 0, /* xDlClose */ -#endif /* SQLITE_OMIT_LOAD_EXTENSION */ - tvfsRandomness, /* xRandomness */ - tvfsSleep, /* xSleep */ - tvfsCurrentTime, /* xCurrentTime */ - 0, /* xGetLastError */ - 0, /* xCurrentTimeInt64 */ - 0, /* xSetSystemCall */ - 0, /* xGetSystemCall */ - 0, /* xNextSystemCall */ - }; - - Testvfs *p; /* New object */ - sqlite3_vfs *pVfs; /* New VFS */ - char *zVfs; - int nByte; /* Bytes of space to allocate at p */ - - int i; - int isNoshm = 0; /* True if -noshm is passed */ - int isFullshm = 0; /* True if -fullshm is passed */ - int isDefault = 0; /* True if -default is passed */ - int szOsFile = 0; /* Value passed to -szosfile */ - int mxPathname = -1; /* Value passed to -mxpathname */ - int iVersion = 3; /* Value passed to -iversion */ - - if( objc<2 || 0!=(objc%2) ) goto bad_args; - for(i=2; i<objc; i += 2){ - int nSwitch; - char *zSwitch; - zSwitch = Tcl_GetStringFromObj(objv[i], &nSwitch); - - if( nSwitch>2 && 0==strncmp("-noshm", zSwitch, nSwitch) ){ - if( Tcl_GetBooleanFromObj(interp, objv[i+1], &isNoshm) ){ - return TCL_ERROR; - } - if( isNoshm ) isFullshm = 0; - } - else if( nSwitch>2 && 0==strncmp("-default", zSwitch, nSwitch) ){ - if( Tcl_GetBooleanFromObj(interp, objv[i+1], &isDefault) ){ - return TCL_ERROR; - } - } - else if( nSwitch>2 && 0==strncmp("-szosfile", zSwitch, nSwitch) ){ - if( Tcl_GetIntFromObj(interp, objv[i+1], &szOsFile) ){ - return TCL_ERROR; - } - } - else if( nSwitch>2 && 0==strncmp("-mxpathname", zSwitch, nSwitch) ){ - if( Tcl_GetIntFromObj(interp, objv[i+1], &mxPathname) ){ - return TCL_ERROR; - } - } - else if( nSwitch>2 && 0==strncmp("-iversion", zSwitch, nSwitch) ){ - if( Tcl_GetIntFromObj(interp, objv[i+1], &iVersion) ){ - return TCL_ERROR; - } - } - else if( nSwitch>2 && 0==strncmp("-fullshm", zSwitch, nSwitch) ){ - if( Tcl_GetBooleanFromObj(interp, objv[i+1], &isFullshm) ){ - return TCL_ERROR; - } - if( isFullshm ) isNoshm = 0; - } - else{ - goto bad_args; - } - } - - if( szOsFile<sizeof(TestvfsFile) ){ - szOsFile = sizeof(TestvfsFile); - } - - zVfs = Tcl_GetString(objv[1]); - nByte = sizeof(Testvfs) + (int)strlen(zVfs)+1; - p = (Testvfs *)ckalloc(nByte); - memset(p, 0, nByte); - p->iDevchar = -1; - p->iSectorsize = -1; - - /* Create the new object command before querying SQLite for a default VFS - ** to use for 'real' IO operations. This is because creating the new VFS - ** may delete an existing [testvfs] VFS of the same name. If such a VFS - ** is currently the default, the new [testvfs] may end up calling the - ** methods of a deleted object. - */ - Tcl_CreateObjCommand(interp, zVfs, testvfs_obj_cmd, p, testvfs_obj_del); - p->pParent = sqlite3_vfs_find(0); - p->interp = interp; - - p->zName = (char *)&p[1]; - memcpy(p->zName, zVfs, strlen(zVfs)+1); - - pVfs = (sqlite3_vfs *)ckalloc(sizeof(sqlite3_vfs)); - memcpy(pVfs, &tvfs_vfs, sizeof(sqlite3_vfs)); - pVfs->pAppData = (void *)p; - pVfs->iVersion = iVersion; - pVfs->zName = p->zName; - pVfs->mxPathname = p->pParent->mxPathname; - if( mxPathname>=0 && mxPathname<pVfs->mxPathname ){ - pVfs->mxPathname = mxPathname; - } - pVfs->szOsFile = szOsFile; - p->pVfs = pVfs; - p->isNoshm = isNoshm; - p->isFullshm = isFullshm; - p->mask = TESTVFS_ALL_MASK; - - sqlite3_vfs_register(pVfs, isDefault); - - return TCL_OK; - - bad_args: - Tcl_WrongNumArgs(interp, 1, objv, "VFSNAME ?-noshm BOOL? ?-default BOOL? ?-mxpathname INT? ?-szosfile INT? ?-iversion INT?"); - return TCL_ERROR; -} - -int Sqlitetestvfs_Init(Tcl_Interp *interp){ - Tcl_CreateObjCommand(interp, "testvfs", testvfs_cmd, 0, 0); - return TCL_OK; -} - -#endif diff --git a/components/external/SQLite-3.8.1/SQLiteLib/test/test_vfstrace.c b/components/external/SQLite-3.8.1/SQLiteLib/test/test_vfstrace.c deleted file mode 100644 index 0aacc01fe4..0000000000 --- a/components/external/SQLite-3.8.1/SQLiteLib/test/test_vfstrace.c +++ /dev/null @@ -1,887 +0,0 @@ -/* -** 2011 March 16 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -****************************************************************************** -** -** This file contains code implements a VFS shim that writes diagnostic -** output for each VFS call, similar to "strace". -** -** USAGE: -** -** This source file exports a single symbol which is the name of a -** function: -** -** int vfstrace_register( -** const char *zTraceName, // Name of the newly constructed VFS -** const char *zOldVfsName, // Name of the underlying VFS -** int (*xOut)(const char*,void*), // Output routine. ex: fputs -** void *pOutArg, // 2nd argument to xOut. ex: stderr -** int makeDefault // Make the new VFS the default -** ); -** -** Applications that want to trace their VFS usage must provide a callback -** function with this prototype: -** -** int traceOutput(const char *zMessage, void *pAppData); -** -** This function will "output" the trace messages, where "output" can -** mean different things to different applications. The traceOutput function -** for the command-line shell (see shell.c) is "fputs" from the standard -** library, which means that all trace output is written on the stream -** specified by the second argument. In the case of the command-line shell -** the second argument is stderr. Other applications might choose to output -** trace information to a file, over a socket, or write it into a buffer. -** -** The vfstrace_register() function creates a new "shim" VFS named by -** the zTraceName parameter. A "shim" VFS is an SQLite backend that does -** not really perform the duties of a true backend, but simply filters or -** interprets VFS calls before passing them off to another VFS which does -** the actual work. In this case the other VFS - the one that does the -** real work - is identified by the second parameter, zOldVfsName. If -** the 2nd parameter is NULL then the default VFS is used. The common -** case is for the 2nd parameter to be NULL. -** -** The third and fourth parameters are the pointer to the output function -** and the second argument to the output function. For the SQLite -** command-line shell, when the -vfstrace option is used, these parameters -** are fputs and stderr, respectively. -** -** The fifth argument is true (non-zero) to cause the newly created VFS -** to become the default VFS. The common case is for the fifth parameter -** to be true. -** -** The call to vfstrace_register() simply creates the shim VFS that does -** tracing. The application must also arrange to use the new VFS for -** all database connections that are created and for which tracing is -** desired. This can be done by specifying the trace VFS using URI filename -** notation, or by specifying the trace VFS as the 4th parameter to -** sqlite3_open_v2() or by making the trace VFS be the default (by setting -** the 5th parameter of vfstrace_register() to 1). -** -** -** ENABLING VFSTRACE IN A COMMAND-LINE SHELL -** -** The SQLite command line shell implemented by the shell.c source file -** can be used with this module. To compile in -vfstrace support, first -** gather this file (test_vfstrace.c), the shell source file (shell.c), -** and the SQLite amalgamation source files (sqlite3.c, sqlite3.h) into -** the working directory. Then compile using a command like the following: -** -** gcc -o sqlite3 -Os -I. -DSQLITE_ENABLE_VFSTRACE \ -** -DSQLITE_THREADSAFE=0 -DSQLITE_ENABLE_FTS3 -DSQLITE_ENABLE_RTREE \ -** -DHAVE_READLINE -DHAVE_USLEEP=1 \ -** shell.c test_vfstrace.c sqlite3.c -ldl -lreadline -lncurses -** -** The gcc command above works on Linux and provides (in addition to the -** -vfstrace option) support for FTS3 and FTS4, RTREE, and command-line -** editing using the readline library. The command-line shell does not -** use threads so we added -DSQLITE_THREADSAFE=0 just to make the code -** run a little faster. For compiling on a Mac, you'll probably need -** to omit the -DHAVE_READLINE, the -lreadline, and the -lncurses options. -** The compilation could be simplified to just this: -** -** gcc -DSQLITE_ENABLE_VFSTRACE \ -** shell.c test_vfstrace.c sqlite3.c -ldl -lpthread -** -** In this second example, all unnecessary options have been removed -** Note that since the code is now threadsafe, we had to add the -lpthread -** option to pull in the pthreads library. -** -** To cross-compile for windows using MinGW, a command like this might -** work: -** -** /opt/mingw/bin/i386-mingw32msvc-gcc -o sqlite3.exe -Os -I \ -** -DSQLITE_THREADSAFE=0 -DSQLITE_ENABLE_VFSTRACE \ -** shell.c test_vfstrace.c sqlite3.c -** -** Similar compiler commands will work on different systems. The key -** invariants are (1) you must have -DSQLITE_ENABLE_VFSTRACE so that -** the shell.c source file will know to include the -vfstrace command-line -** option and (2) you must compile and link the three source files -** shell,c, test_vfstrace.c, and sqlite3.c. -*/ -#include <stdlib.h> -#include <string.h> -#include "sqlite3.h" - -/* -** An instance of this structure is attached to the each trace VFS to -** provide auxiliary information. -*/ -typedef struct vfstrace_info vfstrace_info; -struct vfstrace_info { - sqlite3_vfs *pRootVfs; /* The underlying real VFS */ - int (*xOut)(const char*, void*); /* Send output here */ - void *pOutArg; /* First argument to xOut */ - const char *zVfsName; /* Name of this trace-VFS */ - sqlite3_vfs *pTraceVfs; /* Pointer back to the trace VFS */ -}; - -/* -** The sqlite3_file object for the trace VFS -*/ -typedef struct vfstrace_file vfstrace_file; -struct vfstrace_file { - sqlite3_file base; /* Base class. Must be first */ - vfstrace_info *pInfo; /* The trace-VFS to which this file belongs */ - const char *zFName; /* Base name of the file */ - sqlite3_file *pReal; /* The real underlying file */ -}; - -/* -** Method declarations for vfstrace_file. -*/ -static int vfstraceClose(sqlite3_file*); -static int vfstraceRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst); -static int vfstraceWrite(sqlite3_file*,const void*,int iAmt, sqlite3_int64); -static int vfstraceTruncate(sqlite3_file*, sqlite3_int64 size); -static int vfstraceSync(sqlite3_file*, int flags); -static int vfstraceFileSize(sqlite3_file*, sqlite3_int64 *pSize); -static int vfstraceLock(sqlite3_file*, int); -static int vfstraceUnlock(sqlite3_file*, int); -static int vfstraceCheckReservedLock(sqlite3_file*, int *); -static int vfstraceFileControl(sqlite3_file*, int op, void *pArg); -static int vfstraceSectorSize(sqlite3_file*); -static int vfstraceDeviceCharacteristics(sqlite3_file*); -static int vfstraceShmLock(sqlite3_file*,int,int,int); -static int vfstraceShmMap(sqlite3_file*,int,int,int, void volatile **); -static void vfstraceShmBarrier(sqlite3_file*); -static int vfstraceShmUnmap(sqlite3_file*,int); - -/* -** Method declarations for vfstrace_vfs. -*/ -static int vfstraceOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *); -static int vfstraceDelete(sqlite3_vfs*, const char *zName, int syncDir); -static int vfstraceAccess(sqlite3_vfs*, const char *zName, int flags, int *); -static int vfstraceFullPathname(sqlite3_vfs*, const char *zName, int, char *); -static void *vfstraceDlOpen(sqlite3_vfs*, const char *zFilename); -static void vfstraceDlError(sqlite3_vfs*, int nByte, char *zErrMsg); -static void (*vfstraceDlSym(sqlite3_vfs*,void*, const char *zSymbol))(void); -static void vfstraceDlClose(sqlite3_vfs*, void*); -static int vfstraceRandomness(sqlite3_vfs*, int nByte, char *zOut); -static int vfstraceSleep(sqlite3_vfs*, int microseconds); -static int vfstraceCurrentTime(sqlite3_vfs*, double*); -static int vfstraceGetLastError(sqlite3_vfs*, int, char*); -static int vfstraceCurrentTimeInt64(sqlite3_vfs*, sqlite3_int64*); -static int vfstraceSetSystemCall(sqlite3_vfs*,const char*, sqlite3_syscall_ptr); -static sqlite3_syscall_ptr vfstraceGetSystemCall(sqlite3_vfs*, const char *); -static const char *vfstraceNextSystemCall(sqlite3_vfs*, const char *zName); - -/* -** Return a pointer to the tail of the pathname. Examples: -** -** /home/drh/xyzzy.txt -> xyzzy.txt -** xyzzy.txt -> xyzzy.txt -*/ -static const char *fileTail(const char *z){ - int i; - if( z==0 ) return 0; - i = strlen(z)-1; - while( i>0 && z[i-1]!='/' ){ i--; } - return &z[i]; -} - -/* -** Send trace output defined by zFormat and subsequent arguments. -*/ -static void vfstrace_printf( - vfstrace_info *pInfo, - const char *zFormat, - ... -){ - va_list ap; - char *zMsg; - va_start(ap, zFormat); - zMsg = sqlite3_vmprintf(zFormat, ap); - va_end(ap); - pInfo->xOut(zMsg, pInfo->pOutArg); - sqlite3_free(zMsg); -} - -/* -** Convert value rc into a string and print it using zFormat. zFormat -** should have exactly one %s -*/ -static void vfstrace_print_errcode( - vfstrace_info *pInfo, - const char *zFormat, - int rc -){ - char zBuf[50]; - char *zVal; - switch( rc ){ - case SQLITE_OK: zVal = "SQLITE_OK"; break; - case SQLITE_ERROR: zVal = "SQLITE_ERROR"; break; - case SQLITE_PERM: zVal = "SQLITE_PERM"; break; - case SQLITE_ABORT: zVal = "SQLITE_ABORT"; break; - case SQLITE_BUSY: zVal = "SQLITE_BUSY"; break; - case SQLITE_NOMEM: zVal = "SQLITE_NOMEM"; break; - case SQLITE_READONLY: zVal = "SQLITE_READONLY"; break; - case SQLITE_INTERRUPT: zVal = "SQLITE_INTERRUPT"; break; - case SQLITE_IOERR: zVal = "SQLITE_IOERR"; break; - case SQLITE_CORRUPT: zVal = "SQLITE_CORRUPT"; break; - case SQLITE_FULL: zVal = "SQLITE_FULL"; break; - case SQLITE_CANTOPEN: zVal = "SQLITE_CANTOPEN"; break; - case SQLITE_PROTOCOL: zVal = "SQLITE_PROTOCOL"; break; - case SQLITE_EMPTY: zVal = "SQLITE_EMPTY"; break; - case SQLITE_SCHEMA: zVal = "SQLITE_SCHEMA"; break; - case SQLITE_CONSTRAINT: zVal = "SQLITE_CONSTRAINT"; break; - case SQLITE_MISMATCH: zVal = "SQLITE_MISMATCH"; break; - case SQLITE_MISUSE: zVal = "SQLITE_MISUSE"; break; - case SQLITE_NOLFS: zVal = "SQLITE_NOLFS"; break; - case SQLITE_IOERR_READ: zVal = "SQLITE_IOERR_READ"; break; - case SQLITE_IOERR_SHORT_READ: zVal = "SQLITE_IOERR_SHORT_READ"; break; - case SQLITE_IOERR_WRITE: zVal = "SQLITE_IOERR_WRITE"; break; - case SQLITE_IOERR_FSYNC: zVal = "SQLITE_IOERR_FSYNC"; break; - case SQLITE_IOERR_DIR_FSYNC: zVal = "SQLITE_IOERR_DIR_FSYNC"; break; - case SQLITE_IOERR_TRUNCATE: zVal = "SQLITE_IOERR_TRUNCATE"; break; - case SQLITE_IOERR_FSTAT: zVal = "SQLITE_IOERR_FSTAT"; break; - case SQLITE_IOERR_UNLOCK: zVal = "SQLITE_IOERR_UNLOCK"; break; - case SQLITE_IOERR_RDLOCK: zVal = "SQLITE_IOERR_RDLOCK"; break; - case SQLITE_IOERR_DELETE: zVal = "SQLITE_IOERR_DELETE"; break; - case SQLITE_IOERR_BLOCKED: zVal = "SQLITE_IOERR_BLOCKED"; break; - case SQLITE_IOERR_NOMEM: zVal = "SQLITE_IOERR_NOMEM"; break; - case SQLITE_IOERR_ACCESS: zVal = "SQLITE_IOERR_ACCESS"; break; - case SQLITE_IOERR_CHECKRESERVEDLOCK: - zVal = "SQLITE_IOERR_CHECKRESERVEDLOCK"; break; - case SQLITE_IOERR_LOCK: zVal = "SQLITE_IOERR_LOCK"; break; - case SQLITE_IOERR_CLOSE: zVal = "SQLITE_IOERR_CLOSE"; break; - case SQLITE_IOERR_DIR_CLOSE: zVal = "SQLITE_IOERR_DIR_CLOSE"; break; - case SQLITE_IOERR_SHMOPEN: zVal = "SQLITE_IOERR_SHMOPEN"; break; - case SQLITE_IOERR_SHMSIZE: zVal = "SQLITE_IOERR_SHMSIZE"; break; - case SQLITE_IOERR_SHMLOCK: zVal = "SQLITE_IOERR_SHMLOCK"; break; - case SQLITE_LOCKED_SHAREDCACHE: zVal = "SQLITE_LOCKED_SHAREDCACHE"; break; - case SQLITE_BUSY_RECOVERY: zVal = "SQLITE_BUSY_RECOVERY"; break; - case SQLITE_CANTOPEN_NOTEMPDIR: zVal = "SQLITE_CANTOPEN_NOTEMPDIR"; break; - default: { - sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", rc); - zVal = zBuf; - break; - } - } - vfstrace_printf(pInfo, zFormat, zVal); -} - -/* -** Append to a buffer. -*/ -static void strappend(char *z, int *pI, const char *zAppend){ - int i = *pI; - while( zAppend[0] ){ z[i++] = *(zAppend++); } - z[i] = 0; - *pI = i; -} - -/* -** Close an vfstrace-file. -*/ -static int vfstraceClose(sqlite3_file *pFile){ - vfstrace_file *p = (vfstrace_file *)pFile; - vfstrace_info *pInfo = p->pInfo; - int rc; - vfstrace_printf(pInfo, "%s.xClose(%s)", pInfo->zVfsName, p->zFName); - rc = p->pReal->pMethods->xClose(p->pReal); - vfstrace_print_errcode(pInfo, " -> %s\n", rc); - if( rc==SQLITE_OK ){ - sqlite3_free((void*)p->base.pMethods); - p->base.pMethods = 0; - } - return rc; -} - -/* -** Read data from an vfstrace-file. -*/ -static int vfstraceRead( - sqlite3_file *pFile, - void *zBuf, - int iAmt, - sqlite_int64 iOfst -){ - vfstrace_file *p = (vfstrace_file *)pFile; - vfstrace_info *pInfo = p->pInfo; - int rc; - vfstrace_printf(pInfo, "%s.xRead(%s,n=%d,ofst=%lld)", - pInfo->zVfsName, p->zFName, iAmt, iOfst); - rc = p->pReal->pMethods->xRead(p->pReal, zBuf, iAmt, iOfst); - vfstrace_print_errcode(pInfo, " -> %s\n", rc); - return rc; -} - -/* -** Write data to an vfstrace-file. -*/ -static int vfstraceWrite( - sqlite3_file *pFile, - const void *zBuf, - int iAmt, - sqlite_int64 iOfst -){ - vfstrace_file *p = (vfstrace_file *)pFile; - vfstrace_info *pInfo = p->pInfo; - int rc; - vfstrace_printf(pInfo, "%s.xWrite(%s,n=%d,ofst=%lld)", - pInfo->zVfsName, p->zFName, iAmt, iOfst); - rc = p->pReal->pMethods->xWrite(p->pReal, zBuf, iAmt, iOfst); - vfstrace_print_errcode(pInfo, " -> %s\n", rc); - return rc; -} - -/* -** Truncate an vfstrace-file. -*/ -static int vfstraceTruncate(sqlite3_file *pFile, sqlite_int64 size){ - vfstrace_file *p = (vfstrace_file *)pFile; - vfstrace_info *pInfo = p->pInfo; - int rc; - vfstrace_printf(pInfo, "%s.xTruncate(%s,%lld)", pInfo->zVfsName, p->zFName, - size); - rc = p->pReal->pMethods->xTruncate(p->pReal, size); - vfstrace_printf(pInfo, " -> %d\n", rc); - return rc; -} - -/* -** Sync an vfstrace-file. -*/ -static int vfstraceSync(sqlite3_file *pFile, int flags){ - vfstrace_file *p = (vfstrace_file *)pFile; - vfstrace_info *pInfo = p->pInfo; - int rc; - int i; - char zBuf[100]; - memcpy(zBuf, "|0", 3); - i = 0; - if( flags & SQLITE_SYNC_FULL ) strappend(zBuf, &i, "|FULL"); - else if( flags & SQLITE_SYNC_NORMAL ) strappend(zBuf, &i, "|NORMAL"); - if( flags & SQLITE_SYNC_DATAONLY ) strappend(zBuf, &i, "|DATAONLY"); - if( flags & ~(SQLITE_SYNC_FULL|SQLITE_SYNC_DATAONLY) ){ - sqlite3_snprintf(sizeof(zBuf)-i, &zBuf[i], "|0x%x", flags); - } - vfstrace_printf(pInfo, "%s.xSync(%s,%s)", pInfo->zVfsName, p->zFName, - &zBuf[1]); - rc = p->pReal->pMethods->xSync(p->pReal, flags); - vfstrace_printf(pInfo, " -> %d\n", rc); - return rc; -} - -/* -** Return the current file-size of an vfstrace-file. -*/ -static int vfstraceFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){ - vfstrace_file *p = (vfstrace_file *)pFile; - vfstrace_info *pInfo = p->pInfo; - int rc; - vfstrace_printf(pInfo, "%s.xFileSize(%s)", pInfo->zVfsName, p->zFName); - rc = p->pReal->pMethods->xFileSize(p->pReal, pSize); - vfstrace_print_errcode(pInfo, " -> %s,", rc); - vfstrace_printf(pInfo, " size=%lld\n", *pSize); - return rc; -} - -/* -** Return the name of a lock. -*/ -static const char *lockName(int eLock){ - const char *azLockNames[] = { - "NONE", "SHARED", "RESERVED", "PENDING", "EXCLUSIVE" - }; - if( eLock<0 || eLock>=sizeof(azLockNames)/sizeof(azLockNames[0]) ){ - return "???"; - }else{ - return azLockNames[eLock]; - } -} - -/* -** Lock an vfstrace-file. -*/ -static int vfstraceLock(sqlite3_file *pFile, int eLock){ - vfstrace_file *p = (vfstrace_file *)pFile; - vfstrace_info *pInfo = p->pInfo; - int rc; - vfstrace_printf(pInfo, "%s.xLock(%s,%s)", pInfo->zVfsName, p->zFName, - lockName(eLock)); - rc = p->pReal->pMethods->xLock(p->pReal, eLock); - vfstrace_print_errcode(pInfo, " -> %s\n", rc); - return rc; -} - -/* -** Unlock an vfstrace-file. -*/ -static int vfstraceUnlock(sqlite3_file *pFile, int eLock){ - vfstrace_file *p = (vfstrace_file *)pFile; - vfstrace_info *pInfo = p->pInfo; - int rc; - vfstrace_printf(pInfo, "%s.xUnlock(%s,%s)", pInfo->zVfsName, p->zFName, - lockName(eLock)); - rc = p->pReal->pMethods->xUnlock(p->pReal, eLock); - vfstrace_print_errcode(pInfo, " -> %s\n", rc); - return rc; -} - -/* -** Check if another file-handle holds a RESERVED lock on an vfstrace-file. -*/ -static int vfstraceCheckReservedLock(sqlite3_file *pFile, int *pResOut){ - vfstrace_file *p = (vfstrace_file *)pFile; - vfstrace_info *pInfo = p->pInfo; - int rc; - vfstrace_printf(pInfo, "%s.xCheckReservedLock(%s,%d)", - pInfo->zVfsName, p->zFName); - rc = p->pReal->pMethods->xCheckReservedLock(p->pReal, pResOut); - vfstrace_print_errcode(pInfo, " -> %s", rc); - vfstrace_printf(pInfo, ", out=%d\n", *pResOut); - return rc; -} - -/* -** File control method. For custom operations on an vfstrace-file. -*/ -static int vfstraceFileControl(sqlite3_file *pFile, int op, void *pArg){ - vfstrace_file *p = (vfstrace_file *)pFile; - vfstrace_info *pInfo = p->pInfo; - int rc; - char zBuf[100]; - char *zOp; - switch( op ){ - case SQLITE_FCNTL_LOCKSTATE: zOp = "LOCKSTATE"; break; - case SQLITE_GET_LOCKPROXYFILE: zOp = "GET_LOCKPROXYFILE"; break; - case SQLITE_SET_LOCKPROXYFILE: zOp = "SET_LOCKPROXYFILE"; break; - case SQLITE_LAST_ERRNO: zOp = "LAST_ERRNO"; break; - case SQLITE_FCNTL_SIZE_HINT: { - sqlite3_snprintf(sizeof(zBuf), zBuf, "SIZE_HINT,%lld", - *(sqlite3_int64*)pArg); - zOp = zBuf; - break; - } - case SQLITE_FCNTL_CHUNK_SIZE: { - sqlite3_snprintf(sizeof(zBuf), zBuf, "CHUNK_SIZE,%d", *(int*)pArg); - zOp = zBuf; - break; - } - case SQLITE_FCNTL_FILE_POINTER: zOp = "FILE_POINTER"; break; - case SQLITE_FCNTL_SYNC_OMITTED: zOp = "SYNC_OMITTED"; break; - case SQLITE_FCNTL_WIN32_AV_RETRY: zOp = "WIN32_AV_RETRY"; break; - case SQLITE_FCNTL_PERSIST_WAL: zOp = "PERSIST_WAL"; break; - case SQLITE_FCNTL_OVERWRITE: zOp = "OVERWRITE"; break; - case SQLITE_FCNTL_VFSNAME: zOp = "VFSNAME"; break; - case SQLITE_FCNTL_TEMPFILENAME: zOp = "TEMPFILENAME"; break; - case 0xca093fa0: zOp = "DB_UNCHANGED"; break; - case SQLITE_FCNTL_PRAGMA: { - const char *const* a = (const char*const*)pArg; - sqlite3_snprintf(sizeof(zBuf), zBuf, "PRAGMA,[%s,%s]",a[1],a[2]); - zOp = zBuf; - break; - } - default: { - sqlite3_snprintf(sizeof zBuf, zBuf, "%d", op); - zOp = zBuf; - break; - } - } - vfstrace_printf(pInfo, "%s.xFileControl(%s,%s)", - pInfo->zVfsName, p->zFName, zOp); - rc = p->pReal->pMethods->xFileControl(p->pReal, op, pArg); - vfstrace_print_errcode(pInfo, " -> %s\n", rc); - if( op==SQLITE_FCNTL_VFSNAME && rc==SQLITE_OK ){ - *(char**)pArg = sqlite3_mprintf("vfstrace.%s/%z", - pInfo->zVfsName, *(char**)pArg); - } - if( (op==SQLITE_FCNTL_PRAGMA || op==SQLITE_FCNTL_TEMPFILENAME) - && rc==SQLITE_OK && *(char**)pArg ){ - vfstrace_printf(pInfo, "%s.xFileControl(%s,%s) returns %s", - pInfo->zVfsName, p->zFName, zOp, *(char**)pArg); - } - return rc; -} - -/* -** Return the sector-size in bytes for an vfstrace-file. -*/ -static int vfstraceSectorSize(sqlite3_file *pFile){ - vfstrace_file *p = (vfstrace_file *)pFile; - vfstrace_info *pInfo = p->pInfo; - int rc; - vfstrace_printf(pInfo, "%s.xSectorSize(%s)", pInfo->zVfsName, p->zFName); - rc = p->pReal->pMethods->xSectorSize(p->pReal); - vfstrace_printf(pInfo, " -> %d\n", rc); - return rc; -} - -/* -** Return the device characteristic flags supported by an vfstrace-file. -*/ -static int vfstraceDeviceCharacteristics(sqlite3_file *pFile){ - vfstrace_file *p = (vfstrace_file *)pFile; - vfstrace_info *pInfo = p->pInfo; - int rc; - vfstrace_printf(pInfo, "%s.xDeviceCharacteristics(%s)", - pInfo->zVfsName, p->zFName); - rc = p->pReal->pMethods->xDeviceCharacteristics(p->pReal); - vfstrace_printf(pInfo, " -> 0x%08x\n", rc); - return rc; -} - -/* -** Shared-memory operations. -*/ -static int vfstraceShmLock(sqlite3_file *pFile, int ofst, int n, int flags){ - vfstrace_file *p = (vfstrace_file *)pFile; - vfstrace_info *pInfo = p->pInfo; - int rc; - char zLck[100]; - int i = 0; - memcpy(zLck, "|0", 3); - if( flags & SQLITE_SHM_UNLOCK ) strappend(zLck, &i, "|UNLOCK"); - if( flags & SQLITE_SHM_LOCK ) strappend(zLck, &i, "|LOCK"); - if( flags & SQLITE_SHM_SHARED ) strappend(zLck, &i, "|SHARED"); - if( flags & SQLITE_SHM_EXCLUSIVE ) strappend(zLck, &i, "|EXCLUSIVE"); - if( flags & ~(0xf) ){ - sqlite3_snprintf(sizeof(zLck)-i, &zLck[i], "|0x%x", flags); - } - vfstrace_printf(pInfo, "%s.xShmLock(%s,ofst=%d,n=%d,%s)", - pInfo->zVfsName, p->zFName, ofst, n, &zLck[1]); - rc = p->pReal->pMethods->xShmLock(p->pReal, ofst, n, flags); - vfstrace_print_errcode(pInfo, " -> %s\n", rc); - return rc; -} -static int vfstraceShmMap( - sqlite3_file *pFile, - int iRegion, - int szRegion, - int isWrite, - void volatile **pp -){ - vfstrace_file *p = (vfstrace_file *)pFile; - vfstrace_info *pInfo = p->pInfo; - int rc; - vfstrace_printf(pInfo, "%s.xShmMap(%s,iRegion=%d,szRegion=%d,isWrite=%d,*)", - pInfo->zVfsName, p->zFName, iRegion, szRegion, isWrite); - rc = p->pReal->pMethods->xShmMap(p->pReal, iRegion, szRegion, isWrite, pp); - vfstrace_print_errcode(pInfo, " -> %s\n", rc); - return rc; -} -static void vfstraceShmBarrier(sqlite3_file *pFile){ - vfstrace_file *p = (vfstrace_file *)pFile; - vfstrace_info *pInfo = p->pInfo; - vfstrace_printf(pInfo, "%s.xShmBarrier(%s)\n", pInfo->zVfsName, p->zFName); - p->pReal->pMethods->xShmBarrier(p->pReal); -} -static int vfstraceShmUnmap(sqlite3_file *pFile, int delFlag){ - vfstrace_file *p = (vfstrace_file *)pFile; - vfstrace_info *pInfo = p->pInfo; - int rc; - vfstrace_printf(pInfo, "%s.xShmUnmap(%s,delFlag=%d)", - pInfo->zVfsName, p->zFName, delFlag); - rc = p->pReal->pMethods->xShmUnmap(p->pReal, delFlag); - vfstrace_print_errcode(pInfo, " -> %s\n", rc); - return rc; -} - - - -/* -** Open an vfstrace file handle. -*/ -static int vfstraceOpen( - sqlite3_vfs *pVfs, - const char *zName, - sqlite3_file *pFile, - int flags, - int *pOutFlags -){ - int rc; - vfstrace_file *p = (vfstrace_file *)pFile; - vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData; - sqlite3_vfs *pRoot = pInfo->pRootVfs; - p->pInfo = pInfo; - p->zFName = zName ? fileTail(zName) : "<temp>"; - p->pReal = (sqlite3_file *)&p[1]; - rc = pRoot->xOpen(pRoot, zName, p->pReal, flags, pOutFlags); - vfstrace_printf(pInfo, "%s.xOpen(%s,flags=0x%x)", - pInfo->zVfsName, p->zFName, flags); - if( p->pReal->pMethods ){ - sqlite3_io_methods *pNew = sqlite3_malloc( sizeof(*pNew) ); - const sqlite3_io_methods *pSub = p->pReal->pMethods; - memset(pNew, 0, sizeof(*pNew)); - pNew->iVersion = pSub->iVersion; - pNew->xClose = vfstraceClose; - pNew->xRead = vfstraceRead; - pNew->xWrite = vfstraceWrite; - pNew->xTruncate = vfstraceTruncate; - pNew->xSync = vfstraceSync; - pNew->xFileSize = vfstraceFileSize; - pNew->xLock = vfstraceLock; - pNew->xUnlock = vfstraceUnlock; - pNew->xCheckReservedLock = vfstraceCheckReservedLock; - pNew->xFileControl = vfstraceFileControl; - pNew->xSectorSize = vfstraceSectorSize; - pNew->xDeviceCharacteristics = vfstraceDeviceCharacteristics; - if( pNew->iVersion>=2 ){ - pNew->xShmMap = pSub->xShmMap ? vfstraceShmMap : 0; - pNew->xShmLock = pSub->xShmLock ? vfstraceShmLock : 0; - pNew->xShmBarrier = pSub->xShmBarrier ? vfstraceShmBarrier : 0; - pNew->xShmUnmap = pSub->xShmUnmap ? vfstraceShmUnmap : 0; - } - pFile->pMethods = pNew; - } - vfstrace_print_errcode(pInfo, " -> %s", rc); - if( pOutFlags ){ - vfstrace_printf(pInfo, ", outFlags=0x%x\n", *pOutFlags); - }else{ - vfstrace_printf(pInfo, "\n"); - } - return rc; -} - -/* -** Delete the file located at zPath. If the dirSync argument is true, -** ensure the file-system modifications are synced to disk before -** returning. -*/ -static int vfstraceDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){ - vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData; - sqlite3_vfs *pRoot = pInfo->pRootVfs; - int rc; - vfstrace_printf(pInfo, "%s.xDelete(\"%s\",%d)", - pInfo->zVfsName, zPath, dirSync); - rc = pRoot->xDelete(pRoot, zPath, dirSync); - vfstrace_print_errcode(pInfo, " -> %s\n", rc); - return rc; -} - -/* -** Test for access permissions. Return true if the requested permission -** is available, or false otherwise. -*/ -static int vfstraceAccess( - sqlite3_vfs *pVfs, - const char *zPath, - int flags, - int *pResOut -){ - vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData; - sqlite3_vfs *pRoot = pInfo->pRootVfs; - int rc; - vfstrace_printf(pInfo, "%s.xDelete(\"%s\",%d)", - pInfo->zVfsName, zPath, flags); - rc = pRoot->xAccess(pRoot, zPath, flags, pResOut); - vfstrace_print_errcode(pInfo, " -> %s", rc); - vfstrace_printf(pInfo, ", out=%d\n", *pResOut); - return rc; -} - -/* -** Populate buffer zOut with the full canonical pathname corresponding -** to the pathname in zPath. zOut is guaranteed to point to a buffer -** of at least (DEVSYM_MAX_PATHNAME+1) bytes. -*/ -static int vfstraceFullPathname( - sqlite3_vfs *pVfs, - const char *zPath, - int nOut, - char *zOut -){ - vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData; - sqlite3_vfs *pRoot = pInfo->pRootVfs; - int rc; - vfstrace_printf(pInfo, "%s.xFullPathname(\"%s\")", - pInfo->zVfsName, zPath); - rc = pRoot->xFullPathname(pRoot, zPath, nOut, zOut); - vfstrace_print_errcode(pInfo, " -> %s", rc); - vfstrace_printf(pInfo, ", out=\"%.*s\"\n", nOut, zOut); - return rc; -} - -/* -** Open the dynamic library located at zPath and return a handle. -*/ -static void *vfstraceDlOpen(sqlite3_vfs *pVfs, const char *zPath){ - vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData; - sqlite3_vfs *pRoot = pInfo->pRootVfs; - vfstrace_printf(pInfo, "%s.xDlOpen(\"%s\")\n", pInfo->zVfsName, zPath); - return pRoot->xDlOpen(pRoot, zPath); -} - -/* -** Populate the buffer zErrMsg (size nByte bytes) with a human readable -** utf-8 string describing the most recent error encountered associated -** with dynamic libraries. -*/ -static void vfstraceDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){ - vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData; - sqlite3_vfs *pRoot = pInfo->pRootVfs; - vfstrace_printf(pInfo, "%s.xDlError(%d)", pInfo->zVfsName, nByte); - pRoot->xDlError(pRoot, nByte, zErrMsg); - vfstrace_printf(pInfo, " -> \"%s\"", zErrMsg); -} - -/* -** Return a pointer to the symbol zSymbol in the dynamic library pHandle. -*/ -static void (*vfstraceDlSym(sqlite3_vfs *pVfs,void *p,const char *zSym))(void){ - vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData; - sqlite3_vfs *pRoot = pInfo->pRootVfs; - vfstrace_printf(pInfo, "%s.xDlSym(\"%s\")\n", pInfo->zVfsName, zSym); - return pRoot->xDlSym(pRoot, p, zSym); -} - -/* -** Close the dynamic library handle pHandle. -*/ -static void vfstraceDlClose(sqlite3_vfs *pVfs, void *pHandle){ - vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData; - sqlite3_vfs *pRoot = pInfo->pRootVfs; - vfstrace_printf(pInfo, "%s.xDlOpen()\n", pInfo->zVfsName); - pRoot->xDlClose(pRoot, pHandle); -} - -/* -** Populate the buffer pointed to by zBufOut with nByte bytes of -** random data. -*/ -static int vfstraceRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){ - vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData; - sqlite3_vfs *pRoot = pInfo->pRootVfs; - vfstrace_printf(pInfo, "%s.xRandomness(%d)\n", pInfo->zVfsName, nByte); - return pRoot->xRandomness(pRoot, nByte, zBufOut); -} - -/* -** Sleep for nMicro microseconds. Return the number of microseconds -** actually slept. -*/ -static int vfstraceSleep(sqlite3_vfs *pVfs, int nMicro){ - vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData; - sqlite3_vfs *pRoot = pInfo->pRootVfs; - return pRoot->xSleep(pRoot, nMicro); -} - -/* -** Return the current time as a Julian Day number in *pTimeOut. -*/ -static int vfstraceCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){ - vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData; - sqlite3_vfs *pRoot = pInfo->pRootVfs; - return pRoot->xCurrentTime(pRoot, pTimeOut); -} -static int vfstraceCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *pTimeOut){ - vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData; - sqlite3_vfs *pRoot = pInfo->pRootVfs; - return pRoot->xCurrentTimeInt64(pRoot, pTimeOut); -} - -/* -** Return th3 emost recent error code and message -*/ -static int vfstraceGetLastError(sqlite3_vfs *pVfs, int iErr, char *zErr){ - vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData; - sqlite3_vfs *pRoot = pInfo->pRootVfs; - return pRoot->xGetLastError(pRoot, iErr, zErr); -} - -/* -** Override system calls. -*/ -static int vfstraceSetSystemCall( - sqlite3_vfs *pVfs, - const char *zName, - sqlite3_syscall_ptr pFunc -){ - vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData; - sqlite3_vfs *pRoot = pInfo->pRootVfs; - return pRoot->xSetSystemCall(pRoot, zName, pFunc); -} -static sqlite3_syscall_ptr vfstraceGetSystemCall( - sqlite3_vfs *pVfs, - const char *zName -){ - vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData; - sqlite3_vfs *pRoot = pInfo->pRootVfs; - return pRoot->xGetSystemCall(pRoot, zName); -} -static const char *vfstraceNextSystemCall(sqlite3_vfs *pVfs, const char *zName){ - vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData; - sqlite3_vfs *pRoot = pInfo->pRootVfs; - return pRoot->xNextSystemCall(pRoot, zName); -} - - -/* -** Clients invoke this routine to construct a new trace-vfs shim. -** -** Return SQLITE_OK on success. -** -** SQLITE_NOMEM is returned in the case of a memory allocation error. -** SQLITE_NOTFOUND is returned if zOldVfsName does not exist. -*/ -int vfstrace_register( - const char *zTraceName, /* Name of the newly constructed VFS */ - const char *zOldVfsName, /* Name of the underlying VFS */ - int (*xOut)(const char*,void*), /* Output routine. ex: fputs */ - void *pOutArg, /* 2nd argument to xOut. ex: stderr */ - int makeDefault /* True to make the new VFS the default */ -){ - sqlite3_vfs *pNew; - sqlite3_vfs *pRoot; - vfstrace_info *pInfo; - int nName; - int nByte; - - pRoot = sqlite3_vfs_find(zOldVfsName); - if( pRoot==0 ) return SQLITE_NOTFOUND; - nName = strlen(zTraceName); - nByte = sizeof(*pNew) + sizeof(*pInfo) + nName + 1; - pNew = sqlite3_malloc( nByte ); - if( pNew==0 ) return SQLITE_NOMEM; - memset(pNew, 0, nByte); - pInfo = (vfstrace_info*)&pNew[1]; - pNew->iVersion = pRoot->iVersion; - pNew->szOsFile = pRoot->szOsFile + sizeof(vfstrace_file); - pNew->mxPathname = pRoot->mxPathname; - pNew->zName = (char*)&pInfo[1]; - memcpy((char*)&pInfo[1], zTraceName, nName+1); - pNew->pAppData = pInfo; - pNew->xOpen = vfstraceOpen; - pNew->xDelete = vfstraceDelete; - pNew->xAccess = vfstraceAccess; - pNew->xFullPathname = vfstraceFullPathname; - pNew->xDlOpen = pRoot->xDlOpen==0 ? 0 : vfstraceDlOpen; - pNew->xDlError = pRoot->xDlError==0 ? 0 : vfstraceDlError; - pNew->xDlSym = pRoot->xDlSym==0 ? 0 : vfstraceDlSym; - pNew->xDlClose = pRoot->xDlClose==0 ? 0 : vfstraceDlClose; - pNew->xRandomness = vfstraceRandomness; - pNew->xSleep = vfstraceSleep; - pNew->xCurrentTime = vfstraceCurrentTime; - pNew->xGetLastError = pRoot->xGetLastError==0 ? 0 : vfstraceGetLastError; - if( pNew->iVersion>=2 ){ - pNew->xCurrentTimeInt64 = pRoot->xCurrentTimeInt64==0 ? 0 : - vfstraceCurrentTimeInt64; - if( pNew->iVersion>=3 ){ - pNew->xSetSystemCall = pRoot->xSetSystemCall==0 ? 0 : - vfstraceSetSystemCall; - pNew->xGetSystemCall = pRoot->xGetSystemCall==0 ? 0 : - vfstraceGetSystemCall; - pNew->xNextSystemCall = pRoot->xNextSystemCall==0 ? 0 : - vfstraceNextSystemCall; - } - } - pInfo->pRootVfs = pRoot; - pInfo->xOut = xOut; - pInfo->pOutArg = pOutArg; - pInfo->zVfsName = pNew->zName; - pInfo->pTraceVfs = pNew; - vfstrace_printf(pInfo, "%s.enabled_for(\"%s\")\n", - pInfo->zVfsName, pRoot->zName); - return sqlite3_vfs_register(pNew, makeDefault); -} diff --git a/components/external/SQLite-3.8.1/SQLiteLib/test/test_wsd.c b/components/external/SQLite-3.8.1/SQLiteLib/test/test_wsd.c deleted file mode 100644 index 99e4a05658..0000000000 --- a/components/external/SQLite-3.8.1/SQLiteLib/test/test_wsd.c +++ /dev/null @@ -1,84 +0,0 @@ -/* -** 2008 September 1 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** -** The code in this file contains sample implementations of the -** sqlite3_wsd_init() and sqlite3_wsd_find() functions required if the -** SQLITE_OMIT_WSD symbol is defined at build time. -*/ - -#if defined(SQLITE_OMIT_WSD) && defined(SQLITE_TEST) - -#include "sqliteInt.h" - -#define PLS_HASHSIZE 43 - -typedef struct ProcessLocalStorage ProcessLocalStorage; -typedef struct ProcessLocalVar ProcessLocalVar; - -struct ProcessLocalStorage { - ProcessLocalVar *aData[PLS_HASHSIZE]; - int nFree; - u8 *pFree; -}; - -struct ProcessLocalVar { - void *pKey; - ProcessLocalVar *pNext; -}; - -static ProcessLocalStorage *pGlobal = 0; - -int sqlite3_wsd_init(int N, int J){ - if( !pGlobal ){ - int nMalloc = N + sizeof(ProcessLocalStorage) + J*sizeof(ProcessLocalVar); - pGlobal = (ProcessLocalStorage *)malloc(nMalloc); - if( pGlobal ){ - memset(pGlobal, 0, sizeof(ProcessLocalStorage)); - pGlobal->nFree = nMalloc - sizeof(ProcessLocalStorage); - pGlobal->pFree = (u8 *)&pGlobal[1]; - } - } - - return pGlobal ? SQLITE_OK : SQLITE_NOMEM; -} - -void *sqlite3_wsd_find(void *K, int L){ - int i; - int iHash = 0; - ProcessLocalVar *pVar; - - /* Calculate a hash of K */ - for(i=0; i<sizeof(void*); i++){ - iHash = (iHash<<3) + ((unsigned char *)&K)[i]; - } - iHash = iHash%PLS_HASHSIZE; - - /* Search the hash table for K. */ - for(pVar=pGlobal->aData[iHash]; pVar && pVar->pKey!=K; pVar=pVar->pNext); - - /* If no entry for K was found, create and populate a new one. */ - if( !pVar ){ - int nByte = ROUND8(sizeof(ProcessLocalVar) + L); - assert( pGlobal->nFree>=nByte ); - pVar = (ProcessLocalVar *)pGlobal->pFree; - pVar->pKey = K; - pVar->pNext = pGlobal->aData[iHash]; - pGlobal->aData[iHash] = pVar; - pGlobal->nFree -= nByte; - pGlobal->pFree += nByte; - memcpy(&pVar[1], K, L); - } - - return (void *)&pVar[1]; -} - -#endif |
