using System; using System.Diagnostics; using System.Text; using i64 = System.Int64; using u32 = System.UInt32; namespace Community.CsharpSqlite { #if TCLSH using tcl.lang; using ClientData = System.Object; using sqlite3_int64 = System.Int64; using sqlite3_stmt = Sqlite3.Vdbe; using sqlite3_u3264 = System.UInt64; using sqlite3_value = Sqlite3.Mem; using Tcl_Interp = tcl.lang.Interp; using Tcl_Obj = tcl.lang.TclObject; public partial class Sqlite3 { /* ** 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. ************************************************************************* ** Included in SQLite3 port to C#-SQLite; 2008 Noah B Hart ** C#-SQLite is an independent reimplementation of the SQLite software library ** ** SQLITE_SOURCE_ID: 2011-06-23 19:49:22 4374b7e83ea0a3fbc3691f9c0c936272862f32f2 ** ************************************************************************* */ //#include "sqliteInt.h" //#include "tcl.h" //#include //#include /* ** 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=null; //}; /* ** 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 { Debug.Assert( h >= 'A' && h <= 'F' ); return h - 'A' + 10; } } static object sqlite3TestTextToPtr( Tcl_Interp interp, string z ) { //object p ; //var v = new u64[1]; //u32 v2; //int zIndex = 0; //if ( z[0] == '0' && z[1] == 'x' ) //{ // zIndex += 2; //} //v[0] = 0; //while ( zIndex < z.Length )* z ) //{ // v[0] = ( v[0] << 4 ) + (ulong)testHexToInt( z[zIndex] ); // zIndex++; //} //if ( sizeof( object ) == sizeof( u64 ) ) //{ // Marshal.Copy( v, 0, (IntPtr)p, 1 );// memcpy( &p, v, sizeof( p ) ); //} //else //{ // Debug.Assert( sizeof( p ) == sizeof( v2 ) ); // v2 = (u32)v; // memcpy( &p, v2, sizeof( p ) ); //} WrappedCommand cmdInfo = new WrappedCommand(); if ( TCL.Tcl_GetCommandInfo( interp, z, out cmdInfo ) || cmdInfo == null ) { return null; } else { return cmdInfo.objClientData; } } /* ** 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( object clientdata, Tcl_Interp interp, int objc, Tcl_Obj[] objv ) { SqliteDb p; WrappedCommand cmdInfo = null; //string zBuf ;//[100]; if ( objc != 2 ) { TCL.Tcl_WrongNumArgs( interp, 1, objv, "SQLITE-CONNECTION" ); return TCL.TCL_ERROR; } if ( TCL.Tcl_GetCommandInfo( interp, objv[1].ToString(), out cmdInfo ) ) { TCL.Tcl_AppendResult( interp, "command not found: ", TCL.Tcl_GetString( objv[1] ), null ); return TCL.TCL_ERROR; } //p = (SqliteDb)cmdInfo.objclientdata; //zBuf = p.db.GetHashCode().ToString(); //sqlite3_snprintf( zBuf, "%p", p.db ); //if( strncmp(zBuf,"0x",2) ){ // sqlite3_snprintf(zBuf, "0x%p", p.db); //} //TCL.Tcl_AppendResult(interp, zBuf,null ); TCL.Tcl_AppendResult( interp, objv[1].ToString() ); return TCL.TCL_OK; } /* ** Decode a pointer to an sqlite3 object. */ static int getDbPointer( Tcl_Interp interp, string zA, out sqlite3 ppDb ) { SqliteDb p; WrappedCommand cmdInfo = new WrappedCommand(); if ( !TCL.Tcl_GetCommandInfo( interp, zA, out cmdInfo ) ) { if ( cmdInfo == null ) { ppDb = new sqlite3(); } else { p = (SqliteDb)cmdInfo.objClientData; ppDb = p.db; } } else { ppDb = null; } return TCL.TCL_OK; } static string sqlite3TestErrorName( int rc ) { string zName = ""; switch ( rc ) { case SQLITE_OK: zName = "SQLITE_OK"; break; case SQLITE_ERROR: zName = "SQLITE_ERROR"; break; case SQLITE_INTERNAL: zName = "SQLITE_INTERNAL"; break; case SQLITE_PERM: zName = "SQLITE_PERM"; break; case SQLITE_ABORT: zName = "SQLITE_ABORT"; break; case SQLITE_BUSY: zName = "SQLITE_BUSY"; break; case SQLITE_LOCKED: zName = "SQLITE_LOCKED"; break; case SQLITE_LOCKED_SHAREDCACHE: zName = "SQLITE_LOCKED_SHAREDCACHE"; break; case SQLITE_NOMEM: zName = "SQLITE_NOMEM"; break; case SQLITE_READONLY: zName = "SQLITE_READONLY"; break; case SQLITE_INTERRUPT: zName = "SQLITE_INTERRUPT"; break; case SQLITE_IOERR: zName = "SQLITE_IOERR"; break; case SQLITE_CORRUPT: zName = "SQLITE_CORRUPT"; break; case SQLITE_NOTFOUND: zName = "SQLITE_NOTFOUND"; break; case SQLITE_FULL: zName = "SQLITE_FULL"; break; case SQLITE_CANTOPEN: zName = "SQLITE_CANTOPEN"; break; case SQLITE_PROTOCOL: zName = "SQLITE_PROTOCOL"; break; case SQLITE_EMPTY: zName = "SQLITE_EMPTY"; break; case SQLITE_SCHEMA: zName = "SQLITE_SCHEMA"; break; case SQLITE_TOOBIG: zName = "SQLITE_TOOBIG"; break; case SQLITE_CONSTRAINT: zName = "SQLITE_CONSTRAINT"; break; case SQLITE_MISMATCH: zName = "SQLITE_MISMATCH"; break; case SQLITE_MISUSE: zName = "SQLITE_MISUSE"; break; case SQLITE_NOLFS: zName = "SQLITE_NOLFS"; break; case SQLITE_AUTH: zName = "SQLITE_AUTH"; break; case SQLITE_FORMAT: zName = "SQLITE_FORMAT"; break; case SQLITE_RANGE: zName = "SQLITE_RANGE"; break; case SQLITE_NOTADB: zName = "SQLITE_NOTADB"; break; case SQLITE_ROW: zName = "SQLITE_ROW"; break; case SQLITE_DONE: zName = "SQLITE_DONE"; break; case SQLITE_IOERR_READ: zName = "SQLITE_IOERR_READ"; break; case SQLITE_IOERR_SHORT_READ: zName = "SQLITE_IOERR_SHORT_READ"; break; case SQLITE_IOERR_WRITE: zName = "SQLITE_IOERR_WRITE"; break; case SQLITE_IOERR_FSYNC: zName = "SQLITE_IOERR_FSYNC"; break; case SQLITE_IOERR_DIR_FSYNC: zName = "SQLITE_IOERR_DIR_FSYNC"; break; case SQLITE_IOERR_TRUNCATE: zName = "SQLITE_IOERR_TRUNCATE"; break; case SQLITE_IOERR_FSTAT: zName = "SQLITE_IOERR_FSTAT"; break; case SQLITE_IOERR_UNLOCK: zName = "SQLITE_IOERR_UNLOCK"; break; case SQLITE_IOERR_RDLOCK: zName = "SQLITE_IOERR_RDLOCK"; break; case SQLITE_IOERR_DELETE: zName = "SQLITE_IOERR_DELETE"; break; case SQLITE_IOERR_BLOCKED: zName = "SQLITE_IOERR_BLOCKED"; break; case SQLITE_IOERR_NOMEM: zName = "SQLITE_IOERR_NOMEM"; break; case SQLITE_IOERR_ACCESS: zName = "SQLITE_IOERR_ACCESS"; break; case SQLITE_IOERR_CHECKRESERVEDLOCK: zName = "SQLITE_IOERR_CHECKRESERVEDLOCK"; break; case SQLITE_IOERR_LOCK: zName = "SQLITE_IOERR_LOCK"; break; case SQLITE_CORRUPT_VTAB: zName = "SQLITE_CORRUPT_VTAB"; break; case SQLITE_READONLY_RECOVERY: zName = "SQLITE_READONLY_RECOVERY"; break; case SQLITE_READONLY_CANTLOCK: zName = "SQLITE_READONLY_CANTLOCK"; break; default: zName = "SQLITE_Unknown"; break; } return zName; } //#define t1ErrorName sqlite3TestErrorName static string t1ErrorName( int i ) { return sqlite3TestErrorName( i ); } /* ** 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) static sqlite3 StmtToDb( Vdbe v ) { return sqlite3_db_handle( v ); } /* ** Check a return value to make sure it agrees with the results ** from sqlite3_errcode. */ static int sqlite3TestErrCode( Tcl_Interp interp, sqlite3 db, int rc ) { if ( sqlite3_threadsafe() == 0 && rc != SQLITE_MISUSE && rc != SQLITE_OK && sqlite3_errcode( db ) != rc ) { StringBuilder zBuf = new StringBuilder( 200 );//char zBuf[200]; int r2 = sqlite3_errcode( db ); sqlite3_snprintf( 200, zBuf, "error code %s (%d) does not match sqlite3_errcode %s (%d)", sqlite3TestErrorName( rc ), rc, sqlite3TestErrorName( r2 ), r2 );//t1ErrorName( rc ), rc, t1ErrorName( r2 ), r2 ); TCL.Tcl_ResetResult( interp ); TCL.Tcl_AppendResult( interp, zBuf.ToString() ); return 1; } return 0; } /* ** Decode a pointer to an sqlite3_stmt object. */ static int getStmtPointer( Tcl_Interp interp, string zArg, out sqlite3_stmt ppStmt ) { ppStmt = (sqlite3_stmt)sqlite3TestTextToPtr( interp, zArg ); WrappedCommand cmdInfo = new WrappedCommand(); TCL.Tcl_GetCommandInfo( interp, zArg, out cmdInfo ); ppStmt = cmdInfo == null ? null : (sqlite3_stmt)cmdInfo.objClientData; return TCL.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. */ /* ** Decode a pointer to an sqlite3_stmt object. */ static int sqlite3TestMakePointerStr( Tcl_Interp interp, StringBuilder zPtr, object p ) { sqlite3_snprintf( 100, zPtr, "->%p", p ); if ( TCL.Tcl_CreateCommandPointer( interp, zPtr, p ) ) { return TCL.TCL_ERROR; } return TCL.TCL_OK; } /* ** The callback routine for sqlite3_exec_printf(). */ static int exec_printf_cb( object pArg, sqlite3_int64 argc, object p2, object p3 ) { string[] name = (string[])p3; string[] argv = (string[])p2; TclObject str = (TclObject)pArg; int i; if ( TCL.Tcl_DStringLength( str ) == 0 ) { for ( i = 0; i < argc; i++ ) { TCL.Tcl_DStringAppendElement( str, name[i] != null ? name[i] + " " : "NULL " ); } } string beginbrace = "", endbrace = ""; for ( i = 0; i < argc; i++ ) { if ( argc > 1 ) { if ( Util.scanElement( null, argv[i].ToString() ) != 0 ) { beginbrace = "{"; endbrace = "}"; } else { beginbrace = ""; endbrace = ""; } } TCL.Tcl_DStringAppendElement( str, argv[i] != null ? beginbrace + argv[i] + endbrace + ( i < argc - 1 ? " " : "" ) : "NULL" ); } return 0; } /* ** The I/O tracing callback. */ #if !(SQLITE_OMIT_TRACE) && TRACE //static FILE *iotrace_file = 0; //static void io_trace_callback(string 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( // object NotUsed, // Tcl_Interp interp, /* The TCL interpreter that invoked this command */ // int argc, /* Number of arguments */ // Tcl_Obj[] argv /* Text of each argument */ //){ #if !(SQLITE_OMIT_TRACE) && (TRACE) // if( argc!=2 ){ // TCL.Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], // " FILENAME\"", 0); // return TCL.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.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( object NotUsed, Tcl_Interp interp, /* The TCL interpreter that invoked this command */ int argc, /* Number of arguments */ Tcl_Obj[] argv /* Text of each argument */ ) { sqlite3 db = null; TclObject str = null; int rc; string zErr = ""; string zSql = ""; StringBuilder zBuf = new StringBuilder( 30 ); if ( argc != 4 ) { TCL.Tcl_AppendResult( interp, "wrong # args: should be \"", argv[0], " DB FORMAT STRING" ); return TCL.TCL_ERROR; } if ( getDbPointer( interp, argv[1].ToString(), out db ) != 0 ) return TCL.TCL_ERROR; TCL.Tcl_DStringInit( out str ); zSql = sqlite3_mprintf( argv[2].ToString(), argv[3].ToString() ); rc = sqlite3_exec( db, zSql, (dxCallback)exec_printf_cb, str, ref zErr ); sqlite3DbFree( db, ref zSql ); sqlite3_snprintf( 30, zBuf, "%d", rc ); TCL.Tcl_AppendElement( interp, zBuf ); TCL.Tcl_AppendElement( interp, rc == SQLITE_OK ? str.ToString() : zErr ); //TCL.Tcl_DStringValue(ref str) TCL.Tcl_DStringFree( ref str ); if ( zErr != null ) sqlite3DbFree( db, ref zErr ); if ( sqlite3TestErrCode( interp, db, rc ) != 0 ) return TCL.TCL_ERROR; return TCL.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( object NotUsed, Tcl_Interp interp, /* The TCL interpreter that invoked this command */ int argc, /* Number of arguments */ Tcl_Obj[] argv /* Text of each argument */ ) { sqlite3 db = null; TclObject str = null; int rc, i, j; string zErr = ""; string zHex; StringBuilder zSql = new StringBuilder( 500 ); string zBuf = ""; if ( argc != 3 ) { TCL.Tcl_AppendResult( interp, "wrong # args: should be \"", argv[0], " DB HEX" ); return TCL.TCL_ERROR; } if ( getDbPointer( interp, argv[1].ToString(), out db ) != 0 ) return TCL.TCL_ERROR; zHex = argv[2].ToString(); for ( i = j = 0; j < zHex.Length && zHex[j] != 0; i++, j++ ) { if ( zHex[j] == '%' && zHex[j + 2] != 0 && zHex[j + 2] != 0 ) { zSql.Append( (char)( ( testHexToInt( zHex[j + 1] ) << 4 ) + testHexToInt( zHex[j + 2] ) ) ); j += 2; } else { zSql.Append( zHex[j] ); } } //zSql[i] = '\0'; TCL.Tcl_DStringInit( out str ); rc = sqlite3_exec( db, zSql.ToString(), (dxCallback)exec_printf_cb, str, ref zErr ); zBuf = rc.ToString();// sprintf( zBuf, "%d", rc ); TCL.Tcl_AppendElement( interp, zBuf ); TCL.Tcl_AppendElement( interp, rc == SQLITE_OK ? str.ToString() : zErr ); TCL.Tcl_DStringFree( ref str ); // //sqlite3_free(ref zErr); if ( sqlite3TestErrCode( interp, db, rc ) != 0 ) return TCL.TCL_ERROR; return TCL.TCL_OK; } /* ** Usage: db_enter DB ** db_leave DB ** ** Enter or leave the mutex on a database connection. */ static int db_enter( object NotUsed, Tcl_Interp interp, /* The TCL interpreter that invoked this command */ int argc, /* Number of arguments */ Tcl_Obj[] argv /* Text of each argument */ ) { sqlite3 db = null; if ( argc != 2 ) { TCL.Tcl_AppendResult( interp, "wrong # args: should be \"", argv[0], " DB" ); return TCL.TCL_ERROR; } if ( getDbPointer( interp, argv[1].ToString(), out db ) != 0 ) return TCL.TCL_ERROR; sqlite3_mutex_enter( db.mutex ); return TCL.TCL_OK; } static int db_leave( object NotUsed, Tcl_Interp interp, /* The TCL interpreter that invoked this command */ int argc, /* Number of arguments */ Tcl_Obj[] argv /* Text of each argument */ ) { sqlite3 db = null; if ( argc != 2 ) { TCL.Tcl_AppendResult( interp, "wrong # args: should be \"", argv[0], " DB" ); return TCL.TCL_ERROR; } if ( getDbPointer( interp, argv[1].ToString(), out db ) != 0 ) return TCL.TCL_ERROR; sqlite3_mutex_leave( db.mutex ); return TCL.TCL_OK; } /* ** Usage: sqlite3_exec DB SQL ** ** Invoke the sqlite3_exec interface using the open database DB */ static int test_exec( object NotUsed, Tcl_Interp interp, /* The TCL interpreter that invoked this command */ int argc, /* Number of arguments */ Tcl_Obj[] argv /* Text of each argument */ ) { sqlite3 db = null; TclObject str = TclString.newInstance( "" ); int rc; string zErr = ""; string zSql; int i, j; StringBuilder zBuf = new StringBuilder( 30 ); if ( argc != 3 ) { TCL.Tcl_AppendResult( interp, "wrong # args: should be \"", argv[0], " DB SQL" ); return TCL.TCL_ERROR; } if ( getDbPointer( interp, argv[1].ToString(), out db ) != 0 ) return TCL.TCL_ERROR; TCL.Tcl_DStringInit( out str ); zSql = sqlite3_mprintf( "%s", argv[2].ToString() ); StringBuilder sb = new StringBuilder( zSql.Length ); for ( i = 0; i < zSql.Length; i++ ) { if ( zSql[i] == '%' ) { sb.Append( (char)( ( testHexToInt( zSql[i + 1] ) << 4 ) + testHexToInt( zSql[i + 2] ) ) ); i += 2; } else sb.Append( zSql[i] ); } ////zSql[j] = 0; rc = sqlite3_exec( db, sb.ToString(), exec_printf_cb, str, ref zErr ); sqlite3DbFree( db, ref zSql ); sqlite3_snprintf( 30, zBuf, "%d", rc ); TCL.Tcl_AppendElement( interp, zBuf ); TCL.Tcl_AppendElement( interp, rc == SQLITE_OK ? str.ToString() : zErr ); //TCL.Tcl_DStringFree(&str); if ( zErr != "" ) sqlite3DbFree( db, ref zErr ); if ( sqlite3TestErrCode( interp, db, rc ) != 0 ) return TCL.TCL_ERROR; return TCL.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( object NotUsed, Tcl_Interp interp, /* The TCL interpreter that invoked this command */ int argc, /* Number of arguments */ Tcl_Obj[] argv /* Text of each argument */ ) { sqlite3 db = null; int rc; string zErr = ""; if ( argc != 3 ) { TCL.Tcl_AppendResult( interp, "wrong # args: should be \"", argv[0], " DB SQL" ); return TCL.TCL_ERROR; } if ( getDbPointer( interp, argv[1].ToString(), out db ) != 0 ) return TCL.TCL_ERROR; rc = sqlite3_exec( db, argv[2].ToString(), null, null, ref zErr ); if ( sqlite3TestErrCode( interp, db, rc ) != 0 ) return TCL.TCL_ERROR; return TCL.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( object NotUsed, Tcl_Interp interp, /* The TCL interpreter that invoked this command */ int argc, /* Number of arguments */ Tcl_Obj[] argv /* Text of each argument */ ) { string zResult = ""; int i; for ( i = 2; i < argc && ( i == 2 || zResult != "" ); i++ ) { zResult = sqlite3_mprintf( "%z%s%s", zResult, argv[1].ToString(), argv[i].ToString() ); } TCL.Tcl_AppendResult( interp, zResult ); //sqlite3DbFree( db, zResult ); return TCL.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( object NotUsed, Tcl_Interp interp, /* The TCL interpreter that invoked this command */ int argc, /* Number of arguments */ Tcl_Obj[] argv /* Text of each argument */ ) { string zStr; int n = 0; zStr = sqlite3_mprintf( "%s%n", argv[1].ToString() ); n = zStr.Length; //sqlite3DbFree( db, zStr ); TCL.Tcl_SetObjResult( interp, TCL.Tcl_NewIntObj( n ) ); return TCL.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( object NotUsed, Tcl_Interp interp, /* The TCL interpreter that invoked this command */ int argc, /* Number of arguments */ Tcl_Obj[] argv /* Text of each argument */ ) { StringBuilder zStr = new StringBuilder( 100 ); int n = atoi( argv[1].ToString() ); string zFormat = argv[2].ToString(); int a1 = atoi( argv[3].ToString() ); if ( n > zStr.Capacity ) n = zStr.Capacity;// sizeof( zStr ); zStr = new StringBuilder( "abcdefghijklmnopqrstuvwxyz" ); sqlite3_snprintf( n, zStr, zFormat, a1 ); TCL.Tcl_AppendResult( interp, zStr ); return TCL.TCL_OK; } #if !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( object NotUsed, Tcl_Interp interp, /* The TCL interpreter that invoked this command */ int argc, /* Number of arguments */ Tcl_Obj[] argv /* Text of each argument */ ){ sqlite3 db=null; TCL.Tcl_DString str; int rc; string zErr = 0; int nRow, nCol; char **aResult; int i; char zBuf[30]; string zSql; int resCount = -1; if( argc==5 ){ if( TCL.Tcl_GetInt(interp, argv[4], out resCount) ) return TCL.TCL_ERROR; } if( argc!=4 && argc!=5 ){ TCL.Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " DB FORMAT STRING ?COUNT?", 0); return TCL.TCL_ERROR; } if( getDbPointer(interp, argv[1].ToString(), out db) !=0) return TCL.TCL_ERROR; TCL.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; } sqlite3DbFree(db,zSql); sqlite3_snprintf(zBuf, "%d", rc); TCL.Tcl_AppendElement(interp, zBuf); if( rc==SQLITE_OK ){ if( argc==4 ){ sqlite3_snprintf(zBuf, "%d", nRow); TCL.Tcl_AppendElement(interp, zBuf); sqlite3_snprintf(zBuf, "%d", nCol); TCL.Tcl_AppendElement(interp, zBuf); } for(i=0; i p.nAlloc ){ // string zNew; p.nAlloc = p.nAlloc * 2 + n + 200; p.z.Capacity = p.nAlloc; // zNew = sqlite3_realloc(p.z, p.nAlloc); // if( zNew==0 ){ // sqlite3DbFree(db,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; p.z.Append( divider + z ); } /* ** Invoked for each callback from sqlite3ExecFunc */ static int execFuncCallback( object pData, sqlite3_int64 argc, object _argv, object NotUsed ) { Tcl_Obj[] argv = (Tcl_Obj[])_argv; dstr p = (dstr)pData; int i; for ( i = 0; i < argc; i++ ) { if ( argv[i] == null ) { dstrAppend( p, "NULL", ' ' ); } else { dstrAppend( p, argv[i].ToString(), ' ' ); } } 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 ) { dstr x = new dstr(); //memset(&x, 0, sizeof(x)); string sDummy = ""; sqlite3_exec( (sqlite3)sqlite3_context_db_handle( context ), sqlite3_value_text( argv[0] ), (dxCallback)execFuncCallback, (object)x, ref sDummy ); sqlite3_result_text( context, x.z, x.nUsed, SQLITE_TRANSIENT ); x.z = null;// sqlite3DbFree( db, ref 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; string zText1; string zText2; string 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 { //string zCopy = (char )sqlite3Malloc(nText); //memcpy(zCopy, zText1, nText); sqlite3_result_text( context, zText1, nText, null ); //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 ) { sqlite3_result_int( context, 0 ); return; //Debugger.Break(); //TODO -- //string p1 = "", p2 = ""; //string zCmd; //if ( argc != 4 ) // return; //zCmd = sqlite3_value_text( argv[1] ); //if ( zCmd == null ) // return; // if( strcmp(zCmd,"text")==0 ){ // p1 = (const void)sqlite3_value_text(argv[0]); //#if !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]); //#if !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]); //#if !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 ? 1 : 0 ); } /* ** 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( object NotUsed, Tcl_Interp interp, /* The TCL interpreter that invoked this command */ int argc, /* Number of arguments */ Tcl_Obj[] argv /* Text of each argument */ ) { int rc; sqlite3 db = null; if ( argc != 2 ) { TCL.Tcl_AppendResult( interp, "wrong # args: should be \"", argv[0], " DB\"" ); return TCL.TCL_ERROR; } if ( getDbPointer( interp, argv[1].ToString(), out db ) != 0 ) return TCL.TCL_ERROR; rc = sqlite3_create_function( db, "x_coalesce", -1, SQLITE_ANY, 0, t1_ifnullFunc, null, null ); if ( rc == SQLITE_OK ) { rc = sqlite3_create_function( db, "hex8", 1, SQLITE_ANY, 0, hex8Func, null, null ); } #if !SQLITE_OMIT_UTF16 if( rc==SQLITE_OK ){ rc = sqlite3_create_function(db, "hex16", 1, SQLITE_ANY, null, hex16Func, null,null); } #endif if ( rc == SQLITE_OK ) { rc = sqlite3_create_function( db, "tkt2213func", 1, SQLITE_ANY, 0, tkt2213Function, null, null ); } if ( rc == SQLITE_OK ) { rc = sqlite3_create_function( db, "pointer_change", 4, SQLITE_ANY, 0, ptrChngFunction, null, null ); } #if !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 ){ string 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 !=0{ rc = SQLITE_NOMEM; }else{ rc = sqlite3_create_function16(db, zUtf16, 1, SQLITE_UTF16, db, sqlite3ExecFunc,null,null ); } sqlite3ValueFree(ref pVal); sqlite3_mutex_leave(db.mutex); } #endif if ( sqlite3TestErrCode( interp, db, rc ) != 0 ) return TCL.TCL_ERROR; TCL.Tcl_SetResult( interp, sqlite3TestErrorName( rc ), 0 ); return TCL.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; static void t1CountStep( sqlite3_context context, int argc, sqlite3_value[] argv ) { SumCtx p; Mem pMem = sqlite3_aggregate_context( context, 1 );//sizeof(*p)); if ( pMem._SumCtx == null ) pMem._SumCtx = new SumCtx(); p = pMem._SumCtx; if ( p.Context == null ) p.Context = pMem; if ( ( argc == 0 || SQLITE_NULL != sqlite3_value_type( argv[0] ) ) && p != null ) { p.cnt++; } 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 ); #if !SQLITE_OMIT_UTF16 }else if( v==41 ){ Debugger.Break (); // TODO -- //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 ) { SumCtx p; Mem pMem = sqlite3_aggregate_context( context, 0 );//sizeof(*p)); p = pMem._SumCtx; if ( p != null ) { if ( p.cnt == 42 ) { sqlite3_result_error( context, "x_count totals to 42", -1 ); } else { sqlite3_result_int( context, p != null ? (int)p.cnt : 0 ); } } } #if !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( object NotUsed, Tcl_Interp interp, /* The TCL interpreter that invoked this command */ int argc, /* Number of arguments */ Tcl_Obj[] argv /* Text of each argument */ ) { sqlite3 db = new sqlite3(); int rc; if ( argc != 2 ) { TCL.Tcl_AppendResult( interp, "wrong # args: should be \"", argv[0].ToString(), " FILENAME\"" ); return TCL.TCL_ERROR; } if ( getDbPointer( interp, argv[1].ToString(), out db ) != 0 ) return TCL.TCL_ERROR; rc = sqlite3_create_function( db, "x_count", 0, SQLITE_UTF8, 0, null, t1CountStep, t1CountFinalize ); if ( rc == SQLITE_OK ) { rc = sqlite3_create_function( db, "x_count", 1, SQLITE_UTF8, 0, null, t1CountStep, t1CountFinalize ); } #if !SQLITE_OMIT_DEPRECATED if ( rc == SQLITE_OK ) { rc = sqlite3_create_function( db, "legacy_count", 0, SQLITE_ANY, 0, null, legacyCountStep, legacyCountFinalize ); } #endif if ( sqlite3TestErrCode( interp, db, rc ) != 0 ) return TCL.TCL_ERROR; TCL.Tcl_SetResult( interp, t1ErrorName( rc ), 0 ); return TCL.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( // object NotUsed, // Tcl_Interp interp, /* The TCL interpreter that invoked this command */ // int argc, /* Number of arguments */ // Tcl_Obj[] argv /* Text of each argument */ //){ // if( argc!=2 ){ // TCL.Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], // " TEXT\""); // return TCL.TCL_ERROR; // } // printf("%s\n", argv[1]); // return TCL.TCL_OK; //} /* ** Usage: sqlite3_mprintf_int FORMAT INTEGER INTEGER INTEGER ** ** Call mprintf with three integer arguments */ static int sqlite3_mprintf_int( object NotUsed, Tcl_Interp interp, /* The TCL interpreter that invoked this command */ int argc, /* Number of arguments */ Tcl_Obj[] argv /* Text of each argument */ ) { long[] a = new long[3]; int i; string z; if ( argc != 5 ) { TCL.Tcl_AppendResult( interp, "wrong # args: should be \"", argv[0], " FORMAT INT INT INT\"" ); return TCL.TCL_ERROR; } for ( i = 2; i < 5; i++ ) { if ( TCL.Tcl_GetLong( interp, argv[i], out a[i - 2] ) ) return TCL.TCL_ERROR; } z = sqlite3_mprintf( argv[1].ToString(), a[0], a[1], a[2] ); TCL.Tcl_AppendResult( interp, z ); //sqlite3DbFree(db,z); return TCL.TCL_OK; } /* ** Usage: sqlite3_mprintf_int64 FORMAT INTEGER INTEGER INTEGER ** ** Call mprintf with three 64-bit integer arguments */ static int sqlite3_mprintf_int64( object NotUsed, Tcl_Interp interp, /* The TCL interpreter that invoked this command */ int argc, /* Number of arguments */ Tcl_Obj[] argv /* Text of each argument */ ) { int i; sqlite3_int64[] a = new sqlite3_int64[3]; string z; if ( argc != 5 ) { TCL.Tcl_AppendResult( interp, "wrong # args: should be \"", argv[0], " FORMAT INT INT INT\"" ); return TCL.TCL_ERROR; } for ( i = 2; i < 5; i++ ) { if ( sqlite3Atoi64( argv[i].ToString(), ref a[i - 2], argv[i].ToString().Length, SQLITE_UTF8 ) != 0 ) { TCL.Tcl_AppendResult( interp, "argument is not a valid 64-bit integer" ); return TCL.TCL_ERROR; } } z = sqlite3_mprintf( argv[1].ToString(), a[0], a[1], a[2] ); TCL.Tcl_AppendResult( interp, z ); //sqlite3DbFree(db,z); return TCL.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( object NotUsed, Tcl_Interp interp, /* The TCL interpreter that invoked this command */ int argc, /* Number of arguments */ Tcl_Obj[] argv /* Text of each argument */ ) { int i; long[] a = new long[3]; long[] b = new long[3]; string z; if ( argc != 5 ) { TCL.Tcl_AppendResult( interp, "wrong # args: should be \"", argv[0], " FORMAT INT INT INT\"" ); return TCL.TCL_ERROR; } for ( i = 2; i < 5; i++ ) { if ( TCL.Tcl_GetLong( interp, argv[i], out b[i - 2] ) ) return TCL.TCL_ERROR; a[i - 2] = b[i - 2]; //a[i-2] &= (((u64)1)<<(sizeof(int)*8))-1; } z = sqlite3_mprintf( argv[1].ToString(), a[0], a[1], a[2] ); TCL.Tcl_AppendResult( interp, z ); ////sqlite3_free(z); return TCL.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( object NotUsed, Tcl_Interp interp, /* The TCL interpreter that invoked this command */ int argc, /* Number of arguments */ Tcl_Obj[] argv /* Text of each argument */ ) { long[] a = new long[3]; int i; string z; if ( argc < 4 || argc > 5 ) { TCL.Tcl_AppendResult( interp, "wrong # args: should be \"", argv[0], " FORMAT INT INT ?STRING?\"" ); return TCL.TCL_ERROR; } for ( i = 2; i < 4; i++ ) { if ( TCL.Tcl_GetLong( interp, argv[i], out a[i - 2] ) ) return TCL.TCL_ERROR; } z = sqlite3_mprintf( argv[1].ToString(), a[0], a[1], argc > 4 ? argv[4].ToString() : null ); TCL.Tcl_AppendResult( interp, z ); //sqlite3DbFree(db,z); return TCL.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( object NotUsed, Tcl_Interp interp, /* The TCL interpreter that invoked this command */ int argc, /* Number of arguments */ Tcl_Obj[] argv /* Text of each argument */ ) { long[] a = new long[3]; int i; int n = 0; StringBuilder z; if ( argc < 5 || argc > 6 ) { TCL.Tcl_AppendResult( interp, "wrong # args: should be \"", argv[0], " INT FORMAT INT INT ?STRING?\"" ); return TCL.TCL_ERROR; } if ( TCL.Tcl_GetInt( interp, argv[1], out n ) ) return TCL.TCL_ERROR; if ( n < 0 ) { TCL.Tcl_AppendResult( interp, "N must be non-negative" ); return TCL.TCL_ERROR; } for ( i = 3; i < 5; i++ ) { if ( TCL.Tcl_GetLong( interp, argv[i], out a[i - 3] ) ) return TCL.TCL_ERROR; } z = new StringBuilder( n + 1 );//sqlite3Malloc( n+1 ); sqlite3_snprintf( n, z, argv[2].ToString(), a[0], a[1], argc > 4 ? argv[5].ToString() : null ); TCL.Tcl_AppendResult( interp, z ); //sqlite3DbFree(db,z); return TCL.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( object NotUsed, Tcl_Interp interp, /* The TCL interpreter that invoked this command */ int argc, /* Number of arguments */ Tcl_Obj[] argv /* Text of each argument */ ) { long[] a = new long[3]; int i; double r = 0; string z; if ( argc != 5 ) { TCL.Tcl_AppendResult( interp, "wrong # args: should be \"", argv[0], " FORMAT INT INT DOUBLE\"" ); return TCL.TCL_ERROR; } for ( i = 2; i < 4; i++ ) { if ( TCL.Tcl_GetLong( interp, argv[i], out a[i - 2] ) ) return TCL.TCL_ERROR; } if ( TCL.Tcl_GetDouble( interp, argv[4], out r ) ) return TCL.TCL_ERROR; z = sqlite3_mprintf( argv[1].ToString(), a[0], a[1], r ); TCL.Tcl_AppendResult( interp, z ); //sqlite3DbFree(db,z); return TCL.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( object NotUsed, Tcl_Interp interp, /* The TCL interpreter that invoked this command */ int argc, /* Number of arguments */ Tcl_Obj[] argv /* Text of each argument */ ) { int i; double[] r = new double[2]; string z; if ( argc != 4 ) { TCL.Tcl_AppendResult( interp, "wrong # args: should be \"", argv[0], " FORMAT DOUBLE DOUBLE\"" ); return TCL.TCL_ERROR; } for ( i = 2; i < 4; i++ ) { if ( TCL.Tcl_GetDouble( interp, argv[i], out r[i - 2] ) ) return TCL.TCL_ERROR; } z = sqlite3_mprintf( argv[1].ToString(), r[0] * r[1] ); TCL.Tcl_AppendResult( interp, z ); //sqlite3DbFree(db,z); return TCL.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( object NotUsed, Tcl_Interp interp, /* The TCL interpreter that invoked this command */ int argc, /* Number of arguments */ Tcl_Obj[] argv /* Text of each argument */ ) { string z; if ( argc != 3 ) { TCL.Tcl_AppendResult( interp, "wrong # args: should be \"", argv[0], " FORMAT STRING\"" ); return TCL.TCL_ERROR; } z = sqlite3_mprintf( argv[1].ToString(), argv[2].ToString() ); TCL.Tcl_AppendResult( interp, z ); //sqlite3DbFree( db, z ); return TCL.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( object NotUsed, Tcl_Interp interp, /* The TCL interpreter that invoked this command */ int argc, /* Number of arguments */ Tcl_Obj[] argv /* Text of each argument */ ) { string z; double r; u32 x1, x2; i64 d = 0; if ( argc != 3 ) { TCL.Tcl_AppendResult( interp, "wrong # args: should be \"", argv[0], " FORMAT STRING\"" ); return TCL.TCL_ERROR; } //if( sscanf(argv[2].ToString(), "%08x%08x", ref x2, ref x1)!=2 ){ if ( argv[2].ToString().Length != 16 || !u32.TryParse( argv[2].ToString().Substring( 0, 8 ), System.Globalization.NumberStyles.HexNumber, null, out x2 ) || !u32.TryParse( argv[2].ToString().Substring( 8, 8 ), System.Globalization.NumberStyles.HexNumber, null, out x1 ) ) { TCL.Tcl_AppendResult( interp, "2nd argument should be 16-characters of hex" ); return TCL.TCL_ERROR; } d = x2; d = ( d << 32 ) + x1; #if WINDOWS_PHONE r = BitConverter.ToDouble(BitConverter.GetBytes((long)d), 0); #else r = BitConverter.Int64BitsToDouble( d );// memcpy( &r, d, sizeof( r ) ); #endif z = sqlite3_mprintf( argv[1].ToString(), r ); TCL.Tcl_AppendResult( interp, z ); //sqlite3DbFree(db,z); return TCL.TCL_OK; } /* ** Usage: sqlite3_enable_shared_cache ?BOOLEAN? ** */ #if !SQLITE_OMIT_SHARED_CACHE static int test_enable_shared( object clientdata, /* Pointer to sqlite3_enable_XXX function */ Tcl_Interp interp, /* The TCL interpreter that invoked this command */ int objc, /* Number of arguments */ Tcl_Obj[] objv /* Command arguments */ ) { int rc; bool enable = false; int ret = 0; if ( objc != 2 && objc != 1 ) { TCL.Tcl_WrongNumArgs( interp, 1, objv, "?BOOLEAN?" ); return TCL.TCL_ERROR; } ret = sqlite3GlobalConfig.sharedCacheEnabled ? 1 : 0; if ( objc == 2 ) { if ( TCL.Tcl_GetBooleanFromObj( interp, objv[1], out enable ) ) { return TCL.TCL_ERROR; } rc = sqlite3_enable_shared_cache( enable ); if ( rc != SQLITE_OK ) { TCL.Tcl_SetResult( interp, sqlite3ErrStr( rc ), TCL.TCL_STATIC ); return TCL.TCL_ERROR; } } TCL.Tcl_SetObjResult( interp, TCL.Tcl_NewBooleanObj( ret ) ); return TCL.TCL_OK; } #endif /* ** Usage: sqlite3_extended_result_codes DB BOOLEAN ** */ static int test_extended_result_codes( object clientdata, /* Pointer to sqlite3_enable_XXX function */ Tcl_Interp interp, /* The TCL interpreter that invoked this command */ int objc, /* Number of arguments */ Tcl_Obj[] objv /* Command arguments */ ) { bool enable = false; sqlite3 db = null; if ( objc != 3 ) { TCL.Tcl_WrongNumArgs( interp, 1, objv, "DB BOOLEAN" ); return TCL.TCL_ERROR; } if ( getDbPointer( interp, objv[1].ToString(), out db ) != 0 ) return TCL.TCL_ERROR; if ( TCL.Tcl_GetBooleanFromObj( interp, objv[2], out enable ) ) return TCL.TCL_ERROR; sqlite3_extended_result_codes( db, enable ); return TCL.TCL_OK; } /* ** Usage: sqlite3_libversion_number ** */ static int test_libversion_number( object clientdata, /* Pointer to sqlite3_enable_XXX function */ Tcl_Interp interp, /* The TCL interpreter that invoked this command */ int objc, /* Number of arguments */ Tcl_Obj[] objv /* Command arguments */ ) { TCL.Tcl_SetObjResult( interp, TCL.Tcl_NewIntObj( sqlite3_libversion_number() ) ); return TCL.TCL_OK; } /* ** Usage: sqlite3_table_column_metadata DB dbname tblname colname ** */ #if SQLITE_ENABLE_COLUMN_METADATA static int test_table_column_metadata( object clientdata, /* Pointer to sqlite3_enable_XXX function */ Tcl_Interp interp, /* The TCL interpreter that invoked this command */ int objc, /* Number of arguments */ Tcl_Obj[] objv /* Command arguments */ ) { sqlite3 db = null; string zDb = null; string zTbl = null; string zCol = null; int rc; Tcl_Obj pRet; string zDatatype = null; string zCollseq = null; int notnull = 0; int primarykey = 0; int autoincrement = 0; if ( objc != 5 ) { TCL.Tcl_WrongNumArgs( interp, 1, objv, "DB dbname tblname colname" ); return TCL.TCL_ERROR; } if ( getDbPointer( interp, TCL.Tcl_GetString( objv[1] ), out db ) != 0 ) return TCL.TCL_ERROR; zDb = TCL.Tcl_GetString( objv[2] ); zTbl = TCL.Tcl_GetString( objv[3] ); zCol = TCL.Tcl_GetString( objv[4] ); if ( zDb.Length == 0 ) zDb = null; rc = sqlite3_table_column_metadata( db, zDb, zTbl, zCol, ref zDatatype, ref zCollseq, ref notnull, ref primarykey, ref autoincrement ); if ( rc != SQLITE_OK ) { TCL.Tcl_AppendResult( interp, sqlite3_errmsg( db ) ); return TCL.TCL_ERROR; } pRet = TCL.Tcl_NewObj(); TCL.Tcl_ListObjAppendElement( null, pRet, TCL.Tcl_NewStringObj( zDatatype, -1 ) ); TCL.Tcl_ListObjAppendElement( null, pRet, TCL.Tcl_NewStringObj( zCollseq, -1 ) ); TCL.Tcl_ListObjAppendElement( null, pRet, TCL.Tcl_NewIntObj( notnull ) ); TCL.Tcl_ListObjAppendElement( null, pRet, TCL.Tcl_NewIntObj( primarykey ) ); TCL.Tcl_ListObjAppendElement( null, pRet, TCL.Tcl_NewIntObj( autoincrement ) ); TCL.Tcl_SetObjResult( interp, pRet ); return TCL.TCL_OK; } #endif #if !SQLITE_OMIT_INCRBLOB static int blobHandleFromObj( Tcl_Interp interp, Tcl_Obj *pObj, sqlite3_blob **ppBlob ){ string z; int n; z = TCL.Tcl_GetStringFromObj(pObj, &n); if( n==0 ){ *ppBlob = 0; }else{ int notUsed; TCL.Tcl_Channel channel; ClientData instanceData; channel = TCL.Tcl_GetChannel(interp, z, ¬Used); if( null==channel ) return TCL.TCL_ERROR; TCL.Tcl_Flush(channel); TCL.Tcl_Seek(channel, 0, SEEK_SET); instanceData = TCL.Tcl_GetChannelInstanceData(channel); *ppBlob = *((sqlite3_blob *)instanceData); } return TCL.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[] objv /* Command arguments */ ){ sqlite3_blob *pBlob; int nByte; if( objc!=2 ){ TCL.Tcl_WrongNumArgs(interp, 1, objv, "CHANNEL"); return TCL.TCL_ERROR; } if( blobHandleFromObj(interp, objv[1], &pBlob) ) return TCL.TCL_ERROR; nByte = sqlite3_blob_bytes(pBlob); TCL.Tcl_SetObjResult(interp, TCL.Tcl_NewIntObj(nByte)); return TCL.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[] objv /* Command arguments */ ){ sqlite3_blob *pBlob; if( objc!=2 ){ TCL.Tcl_WrongNumArgs(interp, 1, objv, "CHANNEL"); return TCL.TCL_ERROR; } if( blobHandleFromObj(interp, objv[1], &pBlob) ) return TCL.TCL_ERROR; sqlite3_blob_close(pBlob); return TCL.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[] objv /* Command arguments */ ){ sqlite3_blob *pBlob; int nByte; int iOffset; unsigned string zBuf = 0; int rc; if( objc!=4 ){ TCL.Tcl_WrongNumArgs(interp, 1, objv, "CHANNEL OFFSET N"); return TCL.TCL_ERROR; } if( blobHandleFromObj(interp, objv[1], &pBlob) ) return TCL.TCL_ERROR; if( TCL_OK!=TCL.Tcl_GetIntFromObj(interp, objv[2], &iOffset) || TCL_OK!=TCL.Tcl_GetIntFromObj(interp, objv[3], &nByte) ){ return TCL.TCL_ERROR; } if( nByte>0 ){ zBuf = (unsigned char )TCL.Tcl_Alloc(nByte); } rc = sqlite3_blob_read(pBlob, zBuf, nByte, iOffset); if( rc==SQLITE_OK ){ TCL.Tcl_SetObjResult(interp, TCL.Tcl_NewByteArrayObj(zBuf, nByte)); }else{ TCL.Tcl_SetResult(interp, (char )sqlite3TestErrorName(rc), TCL.TCL_VOLATILE); } TCL.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[] objv /* Command arguments */ ){ sqlite3_blob *pBlob; int iOffset; int rc; unsigned string zBuf; int nBuf; if( objc!=4 && objc!=5 ){ TCL.Tcl_WrongNumArgs(interp, 1, objv, "CHANNEL OFFSET DATA ?NDATA?"); return TCL.TCL_ERROR; } if( blobHandleFromObj(interp, objv[1], &pBlob) ) return TCL.TCL_ERROR; if( TCL_OK!=TCL.Tcl_GetIntFromObj(interp, objv[2], &iOffset) ){ return TCL.TCL_ERROR; } zBuf = TCL.Tcl_GetByteArrayFromObj(objv[3], &nBuf); if( objc==5 && TCL.Tcl_GetIntFromObj(interp, objv[4], &nBuf) ){ return TCL.TCL_ERROR; } rc = sqlite3_blob_write(pBlob, zBuf, nBuf, iOffset); if( rc!=SQLITE_OK ){ TCL.Tcl_SetResult(interp, (char )sqlite3TestErrorName(rc), TCL.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[] objv /* Command arguments */ ){ TCL.Tcl_WideInt iRowid; sqlite3_blob *pBlob; int rc; if( objc!=3 ){ TCL.Tcl_WrongNumArgs(interp, 1, objv, "CHANNEL ROWID"); return TCL.TCL_ERROR; } if( blobHandleFromObj(interp, objv[1], &pBlob) ) return TCL.TCL_ERROR; if( TCL.Tcl_GetWideIntFromObj(interp, objv[2], &iRowid) ) return TCL.TCL_ERROR; rc = sqlite3_blob_reopen(pBlob, iRowid); if( rc!=SQLITE_OK ){ TCL.Tcl_SetResult(interp, (char )sqlite3TestErrorName(rc), TCL.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. */ public struct TestCollationX { public Tcl_Interp interp; public Tcl_Obj pCmp; public Tcl_Obj pDel; }; //typedef struct TestCollationX TestCollationX; static void testCreateCollationDel( ref object pCtx ) { TestCollationX p = (TestCollationX)pCtx; int rc = TCL.Tcl_EvalObjEx( p.interp, p.pDel, TCL.TCL_EVAL_DIRECT | TCL.TCL_EVAL_GLOBAL ); if ( rc != TCL.TCL_OK ) { TCL.Tcl_BackgroundError( p.interp ); } TCL.Tcl_DecrRefCount( ref p.pCmp ); TCL.Tcl_DecrRefCount( ref p.pDel ); //sqlite3Free(ref p); } static int testCreateCollationCmp( object pCtx, int nLeft, string zLeft, int nRight, string zRight ) { TestCollationX p = (TestCollationX)pCtx; Tcl_Obj pScript = TCL.Tcl_DuplicateObj( p.pCmp ); int iRes = 0; TCL.Tcl_IncrRefCount( pScript ); TCL.Tcl_ListObjAppendElement( null, pScript, TCL.Tcl_NewStringObj( zLeft, nLeft ) ); TCL.Tcl_ListObjAppendElement( null, pScript, TCL.Tcl_NewStringObj( zRight, nRight ) ); if ( TCL.TCL_OK != TCL.Tcl_EvalObjEx( p.interp, pScript, TCL.TCL_EVAL_DIRECT | TCL.TCL_EVAL_GLOBAL ) || ( TCL.Tcl_GetIntFromObj( p.interp, TCL.Tcl_GetObjResult( p.interp ), out iRes ) != TCL.TCL_OK ) ) { TCL.Tcl_BackgroundError( p.interp ); } TCL.Tcl_DecrRefCount( ref pScript ); return iRes; } static int test_create_collation_v2( object clientdata, /* Not used */ Tcl_Interp interp, /* The TCL interpreter that invoked this command */ int objc, /* Number of arguments */ Tcl_Obj[] objv /* Command arguments */ ) { TestCollationX p; sqlite3 db = null; int rc; if ( objc != 5 ) { TCL.Tcl_WrongNumArgs( interp, 1, objv, "DB-HANDLE NAME CMP-PROC DEL-PROC" ); return TCL.TCL_ERROR; } if ( getDbPointer( interp, TCL.Tcl_GetString( objv[1] ), out db ) != 0 ) return TCL.TCL_ERROR; p = new TestCollationX(); //(TestCollationX )sqlite3Malloc(sizeof(TestCollationX)); p.pCmp = objv[3]; p.pDel = objv[4]; p.interp = interp; TCL.Tcl_IncrRefCount( p.pCmp ); TCL.Tcl_IncrRefCount( p.pDel ); rc = sqlite3_create_collation_v2( db, TCL.Tcl_GetString( objv[2] ), 16, p, (dxCompare)testCreateCollationCmp, testCreateCollationDel ); if ( rc != SQLITE_MISUSE ) { TCL.Tcl_AppendResult( interp, "sqlite3_create_collate_v2() failed to detect " + "an invalid encoding" ); return TCL.TCL_ERROR; } rc = sqlite3_create_collation_v2( db, TCL.Tcl_GetString( objv[2] ), SQLITE_UTF8, p, (dxCompare)testCreateCollationCmp, testCreateCollationDel ); return TCL.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; public class CreateFunctionV2 { public Tcl_Interp interp; public Tcl_Obj pFunc; /* Script for function invocation */ public Tcl_Obj pStep; /* Script for agg. step invocation */ public Tcl_Obj pFinal; /* Script for agg. finalization invocation */ public 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( object pUser ) { CreateFunctionV2 p = (CreateFunctionV2)pUser; if ( p.interp != null && p.pDestroy != null ) { int rc = TCL.Tcl_EvalObjEx( p.interp, p.pDestroy, 0 ); if ( rc != TCL.TCL_OK ) TCL.Tcl_BackgroundError( p.interp ); } if ( p.pFunc != null ) TCL.Tcl_DecrRefCount( ref p.pFunc ); if ( p.pStep != null ) TCL.Tcl_DecrRefCount( ref p.pStep ); if ( p.pFinal != null ) TCL.Tcl_DecrRefCount( ref p.pFinal ); if ( p.pDestroy != null ) TCL.Tcl_DecrRefCount( ref p.pDestroy ); //sqlite3_free( p); } public class EncTable { public string zEnc; public int enc; public EncTable( string zEnc, int enc ) { this.zEnc = zEnc; this.enc = enc; } } static int test_create_function_v2( ClientData clientData, /* Not used */ Tcl_Interp interp, /* The invoking TCL interpreter */ int objc, /* Number of arguments */ Tcl_Obj[] objv /* Command arguments */ ) { sqlite3 db = null; string zFunc; int nArg = 0; int enc = 0; CreateFunctionV2 p; int i; int rc; EncTable[] aEnc = { new EncTable("utf8", SQLITE_UTF8 ), new EncTable("utf16", SQLITE_UTF16 ), new EncTable("utf16le", SQLITE_UTF16LE ), new EncTable("utf16be", SQLITE_UTF16BE ), new EncTable("any", SQLITE_ANY ), new EncTable("0", 0 ) }; if ( objc < 5 || ( objc % 2 ) == 0 ) { TCL.Tcl_WrongNumArgs( interp, 1, objv, "DB NAME NARG ENC SWITCHES..." ); return TCL.TCL_ERROR; } if ( getDbPointer( interp, TCL.Tcl_GetString( objv[1] ), out db ) != 0 ) return TCL.TCL_ERROR; zFunc = TCL.Tcl_GetString( objv[2] ); if ( TCL.Tcl_GetIntFromObj( interp, objv[3], out nArg ) != 0 ) return TCL.TCL_ERROR; //if ( TCL.Tcl_GetIndexFromObjStruct( interp, objv[4], aEnc,//sizeof(aEnc[0]), // "encoding", 0, ref enc) //) int iEnc; for ( iEnc = 0; iEnc < aEnc.Length && ( aEnc[iEnc].zEnc != objv[4].ToString() ); iEnc++ ) { } if ( iEnc >= aEnc.Length ) return TCL.TCL_ERROR; enc = aEnc[iEnc].enc; p = new CreateFunctionV2();//sqlite3_malloc( sizeof( CreateFunctionV2 ) ); //Debug.Assert( p ); //memset(p, 0, sizeof(CreateFunctionV2)); p.interp = interp; for ( i = 5; i < objc; i += 2 ) { int iSwitch = 0; string[] azSwitch = { "-func", "-step", "-final", "-destroy", "" }; if ( TCL.Tcl_GetIndexFromObj( interp, objv[i], azSwitch, "switch", 0, out iSwitch ) ) { //sqlite3_free(p); return TCL.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 != null ) p.pFunc = TCL.Tcl_DuplicateObj( p.pFunc ); if ( p.pStep != null ) p.pStep = TCL.Tcl_DuplicateObj( p.pStep ); if ( p.pFinal != null ) p.pFinal = TCL.Tcl_DuplicateObj( p.pFinal ); if ( p.pDestroy != null ) p.pDestroy = TCL.Tcl_DuplicateObj( p.pDestroy ); if ( p.pFunc != null ) TCL.Tcl_IncrRefCount( p.pFunc ); if ( p.pStep != null ) TCL.Tcl_IncrRefCount( p.pStep ); if ( p.pFinal != null ) TCL.Tcl_IncrRefCount( p.pFinal ); if ( p.pDestroy != null ) TCL.Tcl_IncrRefCount( p.pDestroy ); rc = sqlite3_create_function_v2( db, zFunc, nArg, enc, p, ( p.pFunc != null ? (dxFunc)cf2Func : (dxFunc)null ), ( p.pStep != null ? (dxStep)cf2Step : (dxStep)null ), ( p.pFinal != null ? (dxFinal)cf2Final : (dxFinal)null ), (dxFDestroy)cf2Destroy ); if ( rc != SQLITE_OK ) { TCL.Tcl_ResetResult( interp ); TCL.Tcl_AppendResult( interp, sqlite3TestErrorName( rc ) ); return TCL.TCL_ERROR; } return TCL.TCL_OK; } /* ** Usage: sqlite3_load_extension DB-HANDLE FILE ?PROC? */ //static int test_load_extension( // object clientdata, /* Not used */ // Tcl_Interp interp, /* The TCL interpreter that invoked this command */ // int objc, /* Number of arguments */ // Tcl_Obj[] objv /* Command arguments */ //){ // TCL.Tcl_CmdInfo cmdInfo; // sqlite3 db=null; // int rc; // string zDb; // string zFile; // string zProc = 0; // string zErr = 0; // if( objc!=4 && objc!=3 ){ // TCL.Tcl_WrongNumArgs(interp, 1, objv, "DB-HANDLE FILE ?PROC?"); // return TCL.TCL_ERROR; // } // zDb = TCL.Tcl_GetString(objv[1]); // zFile = TCL.Tcl_GetString(objv[2]); // if( objc==4 ){ // zProc = TCL.Tcl_GetString(objv[3]); // } // /* Extract the C database handle from the Tcl command name */ // if( null==TCL.Tcl_GetCommandInfo(interp, zDb, cmdInfo) ){ // TCL.Tcl_AppendResult(interp, "command not found: ", zDb); // return TCL.TCL_ERROR; // } // db = ((struct SqliteDb)cmdInfo.objclientdata).db; // Debug.Assert(db); // /* Call the underlying C function. If an error occurs, set rc to // ** TCL.TCL_ERROR and load any error string into the interpreter. If no // ** error occurs, set rc to TCL.TCL_OK. // */ #if 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.Tcl_SetResult(interp, zErr ? zErr : "", TCL.Tcl_VOLATILE); // rc = TCL.TCL_ERROR; // }else{ // rc = TCL.TCL_OK; // } // sqlite3DbFree(db,zErr); // return rc; //} /* ** Usage: sqlite3_enable_load_extension DB-HANDLE ONOFF */ //static int test_enable_load( // object clientdata, /* Not used */ // Tcl_Interp interp, /* The TCL interpreter that invoked this command */ // int objc, /* Number of arguments */ // Tcl_Obj[] objv /* Command arguments */ //){ // TCL.Tcl_CmdInfo cmdInfo; // sqlite3 db=null; // string zDb; // int onoff; // if( objc!=3 ){ // TCL.Tcl_WrongNumArgs(interp, 1, objv, "DB-HANDLE ONOFF"); // return TCL.TCL_ERROR; // } // zDb = TCL.Tcl_GetString(objv[1]); // /* Extract the C database handle from the Tcl command name */ // if( null==TCL.Tcl_GetCommandInfo(interp, zDb, cmdInfo) ){ // TCL.Tcl_AppendResult(interp, "command not found: ", zDb); // return TCL.TCL_ERROR; // } // db = ((struct SqliteDb)cmdInfo.objclientdata).db; // Debug.Assert(db); // /* Get the onoff parameter */ // if( TCL.Tcl_GetBooleanFromObj(interp, objv[2], out onoff) ){ // return TCL.TCL_ERROR; // } #if SQLITE_OMIT_LOAD_EXTENSION // TCL.Tcl_AppendResult(interp, "this build omits sqlite3_load_extension()"); // return TCL.TCL_ERROR; #else // sqlite3_enable_load_extension(db, onoff); // return TCL.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( // object NotUsed, // Tcl_Interp interp, /* The TCL interpreter that invoked this command */ // int argc, /* Number of arguments */ // Tcl_Obj[] 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); // Debug.Assert( interp==0 ); /* This will always fail */ // return TCL.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 ) { int ARGV = 0; while ( argc >= 2 ) { string zArg0 = sqlite3_value_text( argv[ARGV] ); if ( zArg0 != null ) { if ( zArg0.Equals( "int", StringComparison.InvariantCultureIgnoreCase ) ) { sqlite3_result_int( context, sqlite3_value_int( argv[ARGV + 1] ) ); } else if ( zArg0.Equals( "int64", StringComparison.InvariantCultureIgnoreCase ) ) { sqlite3_result_int64( context, sqlite3_value_int64( argv[ARGV + 1] ) ); } else if ( zArg0.Equals( "string", StringComparison.InvariantCultureIgnoreCase ) ) { sqlite3_result_text( context, sqlite3_value_text( argv[ARGV + 1] ), -1, SQLITE_TRANSIENT ); } else if ( zArg0.Equals( "double", StringComparison.InvariantCultureIgnoreCase ) ) { sqlite3_result_double( context, sqlite3_value_double( argv[ARGV + 1] ) ); } else if ( zArg0.Equals( "null", StringComparison.InvariantCultureIgnoreCase ) ) { sqlite3_result_null( context ); } else if ( zArg0.Equals( "value", StringComparison.InvariantCultureIgnoreCase ) ) { sqlite3_result_value( context, argv[sqlite3_value_int( argv[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( object NotUsed, Tcl_Interp interp, /* The TCL interpreter that invoked this command */ int argc, /* Number of arguments */ Tcl_Obj[] argv /* Text of each argument */ ) { sqlite3 db = null; int rc; if ( argc != 3 ) { TCL.Tcl_AppendResult( interp, "wrong # args: should be \"", argv[0], " DB FUNCTION-NAME" ); return TCL.TCL_ERROR; } if ( getDbPointer( interp, argv[1].ToString(), out db ) != 0 ) return TCL.TCL_ERROR; rc = sqlite3_create_function( db, argv[2].ToString(), -1, SQLITE_UTF8, 0, testFunc, null, null ); if ( rc != 0 ) { TCL.Tcl_AppendResult( interp, sqlite3ErrStr( rc ) ); return TCL.TCL_ERROR; } if ( sqlite3TestErrCode( interp, db, rc ) != 0 ) return TCL.TCL_ERROR; return TCL.TCL_OK; } /* ** Usage: sqlite3_finalize STMT ** ** Finalize a statement handle. */ static int test_finalize( object clientdata, Tcl_Interp interp, int objc, Tcl_Obj[] objv ) { sqlite3_stmt pStmt = null; int rc; sqlite3 db = null; if ( objc != 2 ) { TCL.Tcl_AppendResult( interp, "wrong # args: should be \"", TCL.Tcl_GetStringFromObj( objv[0], 0 ), " " ); return TCL.TCL_ERROR; } if ( getStmtPointer( interp, TCL.Tcl_GetString( objv[1] ), out pStmt ) != 0 ) return TCL.TCL_ERROR; if ( pStmt != null ) { db = sqlite3_db_handle( pStmt );// StmtToDb( pStmt ); } rc = sqlite3_finalize( pStmt ); TCL.Tcl_SetResult( interp, sqlite3TestErrorName( rc ), TCL.TCL_STATIC );//t1ErrorName( rc ), TCL.TCL_STATIC ); if ( db != null && sqlite3TestErrCode( interp, db, rc ) != 0 ) return TCL.TCL_ERROR; return TCL.TCL_OK; } /* ** Usage: sqlite3_stmt_status STMT CODE RESETFLAG ** ** Get the value of a status counter from a statement. */ static int test_stmt_status( object clientdata, Tcl_Interp interp, int objc, Tcl_Obj[] objv ) { int iValue; int i, op = 0; bool resetFlag = false; string zOpName; sqlite3_stmt pStmt = null; //struct _aOp{ // string zName; // int op; //} _aOp[] aOp = { new _aOp( "SQLITE_STMTSTATUS_FULLSCAN_STEP", SQLITE_STMTSTATUS_FULLSCAN_STEP ), new _aOp( "SQLITE_STMTSTATUS_SORT", SQLITE_STMTSTATUS_SORT ), new _aOp( "SQLITE_STMTSTATUS_AUTOINDEX", SQLITE_STMTSTATUS_AUTOINDEX ) }; if ( objc != 4 ) { TCL.Tcl_WrongNumArgs( interp, 1, objv, "STMT PARAMETER RESETFLAG" ); return TCL.TCL_ERROR; } if ( getStmtPointer( interp, TCL.Tcl_GetString( objv[1] ), out pStmt ) != 0 ) return TCL.TCL_ERROR; zOpName = TCL.Tcl_GetString( objv[2] ); for ( i = 0; i < ArraySize( aOp ); i++ ) { if ( aOp[i].zName == zOpName ) { op = aOp[i].op; break; } } if ( i >= ArraySize( aOp ) ) { if ( TCL.Tcl_GetIntFromObj( interp, objv[2], out op ) != 0 ) return TCL.TCL_ERROR; } if ( TCL.Tcl_GetBooleanFromObj( interp, objv[3], out resetFlag ) ) return TCL.TCL_ERROR; iValue = sqlite3_stmt_status( pStmt, op, resetFlag ? 1 : 0 ); TCL.Tcl_SetObjResult( interp, TCL.Tcl_NewIntObj( iValue ) ); return TCL.TCL_OK; } /* ** Usage: sqlite3_next_stmt DB STMT ** ** Return the next statment in sequence after STMT. */ static int test_next_stmt( object clientdata, Tcl_Interp interp, int objc, Tcl_Obj[] objv ) { sqlite3_stmt pStmt = null; sqlite3 db = null; StringBuilder zBuf = new StringBuilder( 50 ); if ( objc != 3 ) { TCL.Tcl_AppendResult( interp, "wrong # args: should be \"", TCL.Tcl_GetStringFromObj( objv[0], 0 ), " DB STMT" ); return TCL.TCL_ERROR; } if ( getDbPointer( interp, TCL.Tcl_GetString( objv[1] ), out db ) != 0 ) return TCL.TCL_ERROR; if ( getStmtPointer( interp, TCL.Tcl_GetString( objv[2] ), out pStmt ) != 0 ) return TCL.TCL_ERROR; pStmt = sqlite3_next_stmt( db, pStmt ); if ( pStmt != null ) { if ( sqlite3TestMakePointerStr( interp, zBuf, pStmt ) != 0 ) return TCL.TCL_ERROR; TCL.Tcl_AppendResult( interp, zBuf ); } return TCL.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( object clientData, Tcl_Interp interp, int objc, Tcl_Obj[] objv ) { sqlite3_stmt pStmt = null; int rc; if ( objc != 2 ) { TCL.Tcl_AppendResult( interp, "wrong # args: should be \"", TCL.Tcl_GetStringFromObj( objv[0], 0 ), " STMT", 0 ); return TCL.TCL_ERROR; } if ( getStmtPointer( interp, TCL.Tcl_GetString( objv[1] ), out pStmt ) != 0 ) return TCL.TCL_ERROR; rc = sqlite3_stmt_readonly( pStmt ) ? 1 : 0; TCL.Tcl_SetObjResult( interp, TCL.Tcl_NewBooleanObj( rc ) ); return TCL.TCL_OK; } /* ** Usage: uses_stmt_journal STMT ** ** Return true if STMT uses a statement journal. */ static int uses_stmt_journal( object clientdata, Tcl_Interp interp, int objc, Tcl_Obj[] objv ) { sqlite3_stmt pStmt = null; int rc; if ( objc != 2 ) { TCL.Tcl_AppendResult( interp, "wrong # args: should be \"", TCL.Tcl_GetStringFromObj( objv[0], 0 ), " STMT", 0 ); return TCL.TCL_ERROR; } if ( getStmtPointer( interp, TCL.Tcl_GetString( objv[1] ), out pStmt ) != 0 ) return TCL.TCL_ERROR; rc = sqlite3_stmt_readonly( pStmt ) ? 1 : 0; TCL.Tcl_SetObjResult( interp, TCL.Tcl_NewBooleanObj( pStmt.usesStmtJournal ? 1 : 0 ) ); return TCL.TCL_OK; } /* ** Usage: sqlite3_reset STMT ** ** Reset a statement handle. */ static int test_reset( object clientdata, Tcl_Interp interp, int objc, Tcl_Obj[] objv ) { sqlite3_stmt pStmt = null; int rc; if ( objc != 2 ) { TCL.Tcl_AppendResult( interp, "wrong # args: should be \"", TCL.Tcl_GetStringFromObj( objv[0], 0 ), " " ); return TCL.TCL_ERROR; } if ( getStmtPointer( interp, TCL.Tcl_GetString( objv[1] ), out pStmt ) != 0 ) return TCL.TCL_ERROR; rc = sqlite3_reset( pStmt ); if ( pStmt != null && sqlite3TestErrCode( interp, StmtToDb( pStmt ), rc ) != 0 ) { return TCL.TCL_ERROR; } TCL.Tcl_SetResult( interp, t1ErrorName( rc ), TCL.TCL_STATIC ); /* if( rc !=0){ return TCL.TCL_ERROR; } */ return TCL.TCL_OK; } /* ** Usage: sqlite3_expired STMT ** ** Return TRUE if a recompilation of the statement is recommended. */ static int test_expired( object clientdata, Tcl_Interp interp, int objc, Tcl_Obj[] objv ) { #if !SQLITE_OMIT_DEPRECATED sqlite3_stmt pStmt = null; if ( objc != 2 ) { TCL.Tcl_AppendResult( interp, "wrong # args: should be \"", TCL.Tcl_GetStringFromObj( objv[0], 0 ), " " ); return TCL.TCL_ERROR; } if ( getStmtPointer( interp, TCL.Tcl_GetString( objv[1] ), out pStmt ) != 0 ) return TCL.TCL_ERROR; TCL.Tcl_SetObjResult( interp, TCL.Tcl_NewBooleanObj( sqlite3_expired( pStmt ) ) ); #endif TCL.Tcl_SetResult( interp, "0", 0 ); return TCL.TCL_OK; } /* ** Usage: sqlite3TransferBindings FROMSTMT TOSTMT ** ** Transfer all bindings from FROMSTMT over to TOSTMT */ static int test_transfer_bind( object clientdata, Tcl_Interp interp, int objc, Tcl_Obj[] objv ) { #if !SQLITE_OMIT_DEPRECATED sqlite3_stmt pStmt1 = null, pStmt2 = null; if ( objc != 3 ) { TCL.Tcl_AppendResult( interp, "wrong # args: should be \"", TCL.Tcl_GetStringFromObj( objv[0], 0 ), " FROM-STMT TO-STMT" ); return TCL.TCL_ERROR; } if ( getStmtPointer( interp, TCL.Tcl_GetString( objv[1] ), out pStmt1 ) != 0 ) return TCL.TCL_ERROR; if ( getStmtPointer( interp, TCL.Tcl_GetString( objv[2] ), out pStmt2 ) != 0 ) return TCL.TCL_ERROR; TCL.Tcl_SetObjResult( interp, TCL.Tcl_NewIntObj( pStmt1.nVar == pStmt2.nVar ? sqlite3TransferBindings( pStmt1, pStmt2 ) : TCL.TCL_ERROR ) ); #endif return TCL.TCL_OK; } /* ** Usage: sqlite3_changes DB ** ** Return the number of changes made to the database by the last SQL ** execution. */ static int test_changes( object clientdata, Tcl_Interp interp, int objc, Tcl_Obj[] objv ) { sqlite3 db = null; if ( objc != 2 ) { TCL.Tcl_AppendResult( interp, "wrong # args: should be \"", TCL.Tcl_GetString( objv[0] ), " DB" ); return TCL.TCL_ERROR; } if ( getDbPointer( interp, TCL.Tcl_GetString( objv[1] ), out db ) != 0 ) return TCL.TCL_ERROR; TCL.Tcl_SetObjResult( interp, TCL.Tcl_NewIntObj( sqlite3_changes( db ) ) ); return TCL.TCL_OK; } /* ** This is the "static_bind_value" that variables are bound to when ** the FLAG option of sqlite3_bind is "static" */ //static string sqlite_static_bind_value = ""; //static int sqlite_static_bind_nbyte = 0; /* ** Usage: sqlite3_bind VM IDX VALUE FLAGS ** ** Sets the value of the IDX-th occurance of "?" in the original SQL ** 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( object NotUsed, Tcl_Interp interp, /* The TCL interpreter that invoked this command */ int argc, /* Number of arguments */ Tcl_Obj[] argv /* Text of each argument */ ) { sqlite3_stmt pStmt = null; int rc; int idx = 0; if ( argc != 5 ) { TCL.Tcl_AppendResult( interp, "wrong # args: should be \"", argv[0], " VM IDX VALUE (null|static|normal)\"" ); return TCL.TCL_ERROR; } if ( getStmtPointer( interp, argv[1].ToString(), out pStmt ) != 0 ) return TCL.TCL_ERROR; if ( TCL.Tcl_GetInt( interp, argv[2], out idx ) ) return TCL.TCL_ERROR; if ( argv[4].ToString() == "null" ) { rc = sqlite3_bind_null( pStmt, idx ); } else if ( argv[4].ToString() == "static" ) { rc = sqlite3_bind_text( pStmt, idx, sqlite_static_bind_value.sValue, -1, null ); } else if ( argv[4].ToString() == "static-nbytes" ) { rc = sqlite3_bind_text( pStmt, idx, sqlite_static_bind_value.sValue, sqlite_static_bind_nbyte.iValue, null ); } else if ( argv[4].ToString() == "normal" ) { rc = sqlite3_bind_text( pStmt, idx, argv[3].ToString(), -1, SQLITE_TRANSIENT ); } else if ( argv[4].ToString() == "blob10" ) { rc = sqlite3_bind_text( pStmt, idx, "abc\0xyz\0pq", 10, SQLITE_STATIC ); } else { TCL.Tcl_AppendResult( interp, "4th argument should be " + "\"null\" or \"static\" or \"normal\"" ); return TCL.TCL_ERROR; } if ( sqlite3TestErrCode( interp, StmtToDb( pStmt ), rc ) != 0 ) return TCL.TCL_ERROR; if ( rc != 0 ) { StringBuilder zBuf = new StringBuilder( 50 ); sqlite3_snprintf( 50, zBuf, "(%d) ", rc ); TCL.Tcl_SetResult( interp, zBuf + sqlite3ErrStr( rc ), 0 ); return TCL.TCL_ERROR; } return TCL.TCL_OK; } #if !SQLITE_OMIT_UTF16 /* ** Usage: add_test_collate ** ** 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 . 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 " ** ** The and are the two values being compared, encoded in UTF-8. ** The 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( // object pCtx,, // int nA, string zA, // int nB, string zB //){ // Tcl_Interp *i = pTestCollateInterp; // int encin = SQLITE_PTR_TO_INT(pCtx); // int res; // int n; // sqlite3_value pVal; // Tcl_Obj pX; // pX = TCL.Tcl_NewStringObj("test_collate", -1); // TCL.Tcl_IncrRefCount(pX); // switch( encin ){ // case SQLITE_UTF8: // TCL.Tcl_ListObjAppendElement(i,pX,TCL.Tcl_NewStringObj("UTF-8",-1)); // break; // case SQLITE_UTF16LE: // TCL.Tcl_ListObjAppendElement(i,pX,TCL.Tcl_NewStringObj("UTF-16LE",-1)); // break; // case SQLITE_UTF16BE: // TCL.Tcl_ListObjAppendElement(i,pX,TCL.Tcl_NewStringObj("UTF-16BE",-1)); // break; // default: // Debug.Assert(false); // } //sqlite3BeginBenignMalloc(); // pVal = sqlite3ValueNew(0); // if( pVal ){ // sqlite3ValueSetStr(pVal, nA, zA, encin, SQLITE_STATIC); // n = sqlite3_value_bytes(pVal); // TCL.Tcl_ListObjAppendElement(i,pX, // TCL.Tcl_NewStringObj((char)sqlite3_value_text(pVal),n)); // sqlite3ValueSetStr(pVal, nB, zB, encin, SQLITE_STATIC); // n = sqlite3_value_bytes(pVal); // TCL.Tcl_ListObjAppendElement(i,pX, // TCL.Tcl_NewStringObj((char)sqlite3_value_text(pVal),n)); // sqlite3ValueFree(pVal); //} //sqlite3EndBenignMalloc(); // TCL.Tcl_EvalObjEx(i, pX, 0); // TCL.Tcl_DecrRefCount(pX); // TCL.Tcl_GetIntFromObj(i, TCL.Tcl_GetObjResult(i), res); // return res; //} //static int test_collate( // object clientdata, // Tcl_Interp interp, // int objc, // Tcl_Obj[] objv //){ // sqlite3 db=null; // int val; // sqlite3_value pVal; // int rc; // if( objc!=5 ) goto bad_args; // pTestCollateInterp = interp; // if( getDbPointer(interp, TCL.Tcl_GetString(objv[1]), out db) !=0) return TCL.TCL_ERROR; // if( TCL.TCL_OK!=TCL.Tcl_GetBooleanFromObj(interp, objv[2], out val) ) return TCL.TCL_ERROR; // rc = sqlite3_create_collation(db, "test_collate", SQLITE_UTF8, // (void )SQLITE_UTF8, val?test_collate_func:0); // if( rc==SQLITE_OK ){ // string zUtf16; // if( TCL.TCL_OK!=TCL.Tcl_GetBooleanFromObj(interp, objv[3], out val) ) return TCL.TCL_ERROR; // rc = sqlite3_create_collation(db, "test_collate", SQLITE_UTF16LE, // (void )SQLITE_UTF16LE, val?test_collate_func:0); // if( TCL.TCL_OK!=TCL.Tcl_GetBooleanFromObj(interp, objv[4], out val) ) return TCL.TCL_ERROR; //#if FALSE // 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 !=0{ // 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.TCL_ERROR; // if( rc!=SQLITE_OK ){ // TCL.Tcl_AppendResult(interp, sqlite3TestErrorName(rc)); // return TCL.TCL_ERROR; // } // return TCL.TCL_OK; //bad_args: // TCL.Tcl_AppendResult(interp, "wrong # args: should be \"", // TCL.Tcl_GetStringFromObj(objv[0], 0), " ", 0); // return TCL.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( // object pCtx,, // sqlite3 db, // int eTextRep, // const void pName //){ // int enc = ENC(db); // int i; // string 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( // object clientdata, // Tcl_Interp interp, // int objc, // Tcl_Obj[] objv //){ // sqlite3 db=null; // int rc; // if( objc!=2 ) goto bad_args; // if( getDbPointer(interp, TCL.Tcl_GetString(objv[1]), out db) !=0) return TCL.TCL_ERROR; // rc = sqlite3_collation_needed16(db, 0, test_collate_needed_cb); // zNeededCollation[0] = 0; // if( sqlite3TestErrCode(interp, db, rc) ) return TCL.TCL_ERROR; // return TCL.TCL_OK; //bad_args: // TCL.Tcl_WrongNumArgs(interp, 1, objv, "DB"); // return TCL.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( // object NotUsed, // int nKey1, const void pKey1, // int nKey2, const void pKey2 //){ // int rc, n; // n = nKey10 && 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( // object clientdata, // Tcl_Interp interp, // int objc, // Tcl_Obj[] objv //){ // sqlite3 db=null; // if( objc>=2 ){ // if( getDbPointer(interp, TCL.Tcl_GetString(objv[1]), out db) !=0) return TCL.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 // * !SQLITE_OMIT_UTF16) */ /* ** Usage: add_test_function ** ** 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 . 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 " ** ** Where is one of UTF-8, UTF-16LE or UTF16BE, and 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. */ #if !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_context_db_handle(pCtx); // pX = TCL.Tcl_NewStringObj("test_function", -1); // TCL.Tcl_IncrRefCount(pX); // TCL.Tcl_ListObjAppendElement(interp, pX, TCL.Tcl_NewStringObj("UTF-8", -1)); // TCL.Tcl_ListObjAppendElement(interp, pX, // TCL.Tcl_NewStringObj((char)sqlite3_value_text(argv[0]), -1)); // TCL.Tcl_EvalObjEx(interp, pX, 0); // TCL.Tcl_DecrRefCount(pX); // sqlite3_result_text(pCtx, TCL.Tcl_GetStringResult(interp), -1, SQLITE_TRANSIENT); // pVal = sqlite3ValueNew(0); // sqlite3ValueSetStr(pVal, -1, TCL.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_context_db_handle(pCtx); // pX = TCL.Tcl_NewStringObj("test_function", -1); // TCL.Tcl_IncrRefCount(pX); // TCL.Tcl_ListObjAppendElement(interp, pX, TCL.Tcl_NewStringObj("UTF-16LE", -1)); // TCL.Tcl_ListObjAppendElement(interp, pX, // TCL.Tcl_NewStringObj((char)sqlite3_value_text(argv[0]), -1)); // TCL.Tcl_EvalObjEx(interp, pX, 0); // TCL.Tcl_DecrRefCount(pX); // pVal = sqlite3ValueNew(0); // sqlite3ValueSetStr(pVal, -1, TCL.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_context_db_handle(pCtx); // pX = TCL.Tcl_NewStringObj("test_function", -1); // TCL.Tcl_IncrRefCount(pX); // TCL.Tcl_ListObjAppendElement(interp, pX, TCL.Tcl_NewStringObj("UTF-16BE", -1)); // TCL.Tcl_ListObjAppendElement(interp, pX, // TCL.Tcl_NewStringObj((char)sqlite3_value_text(argv[0]), -1)); // TCL.Tcl_EvalObjEx(interp, pX, 0); // TCL.Tcl_DecrRefCount(pX); // pVal = sqlite3ValueNew(0); // sqlite3ValueSetStr(pVal, -1, TCL.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( // object clientdata, // Tcl_Interp interp, // int objc, // Tcl_Obj[] objv //){ #if !SQLITE_OMIT_UTF16 // sqlite3 db=null; // int val; // if( objc!=5 ) goto bad_args; // if( getDbPointer(interp, TCL.Tcl_GetString(objv[1]), out db) !=0) return TCL.TCL_ERROR; // if( TCL.TCL_OK!=TCL.Tcl_GetBooleanFromObj(interp, objv[2], out val) ) return TCL.TCL_ERROR; // if( val ){ // sqlite3_create_function(db, "test_function", 1, SQLITE_UTF8, // interp, test_function_utf8, 0, 0); // } // if( TCL.TCL_OK!=TCL.Tcl_GetBooleanFromObj(interp, objv[3], out val) ) return TCL.TCL_ERROR; // if( val ){ // sqlite3_create_function(db, "test_function", 1, SQLITE_UTF16LE, // interp, test_function_utf16le, 0, 0); // } // if( TCL.TCL_OK!=TCL.Tcl_GetBooleanFromObj(interp, objv[4], out val) ) return TCL.TCL_ERROR; // if( val ){ // sqlite3_create_function(db, "test_function", 1, SQLITE_UTF16BE, // interp, test_function_utf16be, 0, 0); // } // return TCL.TCL_OK; //bad_args: // TCL.Tcl_AppendResult(interp, "wrong # args: should be \"", // TCL.Tcl_GetStringFromObj(objv[0], 0), " ", 0); #endif // * SQLITE_OMIT_UTF16 */ // return TCL.TCL_ERROR; //} /* ** Usage: test_errstr ** ** 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( object clientdata, Tcl_Interp interp, int objc, Tcl_Obj[] objv ) { string zCode; int i; if ( objc != 2 ) { TCL.Tcl_WrongNumArgs( interp, 1, objv, "" ); } zCode = TCL.Tcl_GetString( objv[1] ); for ( i = 0; i < 200; i++ ) { if ( t1ErrorName( i ).Equals( zCode ) ) break; } TCL.Tcl_SetResult( interp, sqlite3ErrStr( i ), 0 ); return TCL.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( object NotUsed, Tcl_Interp interp, /* The TCL interpreter that invoked this command */ int argc, /* Number of arguments */ Tcl_Obj[] argv /* Text of each argument */ ) { return TCL.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( object clientdata, Tcl_Interp interp, int objc, Tcl_Obj[] objv ) { sqlite3_stmt pStmt = null; int idx = 0; int n = 0; int rc; if ( objc != 4 ) { TCL.Tcl_WrongNumArgs( interp, 1, objv, "STMT IDX N" ); return TCL.TCL_ERROR; } if ( getStmtPointer( interp, TCL.Tcl_GetString( objv[1] ), out pStmt ) != 0 ) return TCL.TCL_ERROR; if ( TCL.TCL_OK != TCL.Tcl_GetIntFromObj( interp, objv[2], out idx ) ) return TCL.TCL_ERROR; if ( TCL.TCL_OK != TCL.Tcl_GetIntFromObj( interp, objv[3], out n ) ) return TCL.TCL_ERROR; rc = sqlite3_bind_zeroblob( pStmt, idx, n ); if ( sqlite3TestErrCode( interp, StmtToDb( pStmt ), rc ) != 0 ) return TCL.TCL_ERROR; if ( rc != SQLITE_OK ) { return TCL.TCL_ERROR; } return TCL.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( object clientdata, Tcl_Interp interp, int objc, Tcl_Obj[] objv ) { sqlite3_stmt pStmt = null; int idx = 0; int value = 0; int rc; if ( objc != 4 ) { TCL.Tcl_AppendResult( interp, "wrong # args: should be \"", TCL.Tcl_GetStringFromObj( objv[0], 0 ), " STMT N VALUE" ); return TCL.TCL_ERROR; } if ( getStmtPointer( interp, TCL.Tcl_GetString( objv[1] ), out pStmt ) != 0 ) return TCL.TCL_ERROR; if ( TCL.TCL_OK != TCL.Tcl_GetIntFromObj( interp, objv[2], out idx ) ) return TCL.TCL_ERROR; if ( TCL.TCL_OK != TCL.Tcl_GetIntFromObj( interp, objv[3], out value ) ) return TCL.TCL_ERROR; rc = sqlite3_bind_int( pStmt, idx, value ); if ( sqlite3TestErrCode( interp, StmtToDb( pStmt ), rc ) != 0 ) return TCL.TCL_ERROR; if ( rc != SQLITE_OK ) { return TCL.TCL_ERROR; } return TCL.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( object clientdata, Tcl_Interp interp, int objc, Tcl_Obj[] objv ) { sqlite3_stmt pStmt = null; int idx = 0; i64 value = 0; int rc; if ( objc != 4 ) { TCL.Tcl_AppendResult( interp, "wrong # args: should be \"", TCL.Tcl_GetStringFromObj( objv[0], 0 ), " STMT N VALUE" ); return TCL.TCL_ERROR; } if ( getStmtPointer( interp, TCL.Tcl_GetString( objv[1] ), out pStmt ) != 0 ) return TCL.TCL_ERROR; if ( TCL.TCL_OK != TCL.Tcl_GetIntFromObj( interp, objv[2], out idx ) ) return TCL.TCL_ERROR; if ( TCL.Tcl_GetWideIntFromObj( interp, objv[3], out value ) ) return TCL.TCL_ERROR; rc = sqlite3_bind_int64( pStmt, idx, value ); if ( sqlite3TestErrCode( interp, StmtToDb( pStmt ), rc ) != 0 ) return TCL.TCL_ERROR; if ( rc != SQLITE_OK ) { return TCL.TCL_ERROR; } return TCL.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. */ class _aSpecialFp { public string zName; /* Name of the special floating point value */ public u32 iUpper; /* Upper 32 bits */ public u32 iLower; /* Lower 32 bits */ public _aSpecialFp( string zName, u32 iUpper, u32 iLower ) { this.zName = zName; this.iUpper = iUpper; this.iLower = iLower; } } static int test_bind_double( object clientdata, Tcl_Interp interp, int objc, Tcl_Obj[] objv ) { sqlite3_stmt pStmt = null; ; int idx = 0; double value = 0; int rc; string zVal; int i; _aSpecialFp[] aSpecialFp = new _aSpecialFp[] { new _aSpecialFp( "NaN", 0x7fffffff, 0xffffffff ), new _aSpecialFp( "SNaN", 0x7ff7ffff, 0xffffffff ), new _aSpecialFp( "-NaN", 0xffffffff, 0xffffffff ), new _aSpecialFp( "-SNaN", 0xfff7ffff, 0xffffffff ), new _aSpecialFp( "+Inf", 0x7ff00000, 0x00000000 ), new _aSpecialFp( "-Inf", 0xfff00000, 0x00000000 ), new _aSpecialFp( "Epsilon", 0x00000000, 0x00000001 ), new _aSpecialFp( "-Epsilon", 0x80000000, 0x00000001 ), new _aSpecialFp( "NaN0", 0x7ff80000, 0x00000000 ), new _aSpecialFp( "-NaN0", 0xfff80000, 0x00000000 ), }; if ( objc != 4 ) { TCL.Tcl_AppendResult( interp, "wrong # args: should be \"", TCL.Tcl_GetStringFromObj( objv[0], 0 ), " STMT N VALUE" ); return TCL.TCL_ERROR; } if ( getStmtPointer( interp, TCL.Tcl_GetString( objv[1] ), out pStmt ) != 0 ) return TCL.TCL_ERROR; if ( TCL.TCL_OK != TCL.Tcl_GetIntFromObj( interp, objv[2], out idx ) ) return TCL.TCL_ERROR; /* Intercept the string "NaN" and generate a NaN value for it. ** All other strings are passed through to TCL.Tcl_GetDoubleFromObj(). ** TCL.Tcl_GetDoubleFromObj() should understand "NaN" but some versions ** contain a bug. */ zVal = TCL.Tcl_GetString( objv[3] ); for ( i = 0; i < aSpecialFp.Length; i++ ) {//sizeof(aSpecialFp)/sizeof(aSpecialFp[0]); i++){ if ( aSpecialFp[i].zName == zVal ) { i64 x; x = aSpecialFp[i].iUpper; x <<= 32; x |= aSpecialFp[i].iLower; Debug.Assert( sizeof( double ) == 8 ); Debug.Assert( sizeof( sqlite3_u3264 ) == 8 ); #if WINDOWS_PHONE value = BitConverter.ToDouble(BitConverter.GetBytes((long)x), 0); #else value = BitConverter.Int64BitsToDouble( x );//memcpy(&value, x, 8); #endif //value = Double.NaN; break; } } if ( ( i >= aSpecialFp.Length ) && //sizeof(aSpecialFp)/sizeof(aSpecialFp[0]) && TCL.Tcl_GetDoubleFromObj( interp, objv[3], out value ) ) { return TCL.TCL_ERROR; } rc = sqlite3_bind_double( pStmt, idx, value ); if ( sqlite3TestErrCode( interp, StmtToDb( pStmt ), rc ) != 0 ) return TCL.TCL_ERROR; if ( rc != SQLITE_OK ) { return TCL.TCL_ERROR; } return TCL.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( object clientdata, Tcl_Interp interp, int objc, Tcl_Obj[] objv ) { sqlite3_stmt pStmt = null; ; int idx = 0; int rc; if ( objc != 3 ) { TCL.Tcl_AppendResult( interp, "wrong # args: should be \"", TCL.Tcl_GetStringFromObj( objv[0], 0 ), " STMT N" ); return TCL.TCL_ERROR; } if ( getStmtPointer( interp, TCL.Tcl_GetString( objv[1] ), out pStmt ) != 0 ) return TCL.TCL_ERROR; if ( TCL.TCL_OK != TCL.Tcl_GetIntFromObj( interp, objv[2], out idx ) ) return TCL.TCL_ERROR; rc = sqlite3_bind_null( pStmt, idx ); if ( sqlite3TestErrCode( interp, StmtToDb( pStmt ), rc ) != 0 ) return TCL.TCL_ERROR; if ( rc != SQLITE_OK ) { return TCL.TCL_ERROR; } return TCL.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( object clientdata, Tcl_Interp interp, int objc, Tcl_Obj[] objv ) { sqlite3_stmt pStmt = null; int idx = 0; int bytes = 0; byte[] value; int rc; if ( objc != 5 ) { TCL.Tcl_AppendResult( interp, "wrong # args: should be \"", TCL.Tcl_GetStringFromObj( objv[0], 0 ), " STMT N VALUE BYTES" ); return TCL.TCL_ERROR; } if ( getStmtPointer( interp, TCL.Tcl_GetString( objv[1] ), out pStmt ) != 0 ) return TCL.TCL_ERROR; if ( TCL.TCL_OK != TCL.Tcl_GetIntFromObj( interp, objv[2], out idx ) ) return TCL.TCL_ERROR; value = TCL.Tcl_GetByteArrayFromObj( objv[3], out bytes ); if ( TCL.TCL_OK != TCL.Tcl_GetIntFromObj( interp, objv[4], out bytes ) ) return TCL.TCL_ERROR; rc = sqlite3_bind_text( pStmt, idx, Encoding.UTF8.GetString( value, 0, value.Length ), bytes, SQLITE_TRANSIENT ); if ( sqlite3TestErrCode( interp, StmtToDb( pStmt ), rc ) != 0 ) return TCL.TCL_ERROR; if ( rc != SQLITE_OK ) { TCL.Tcl_AppendResult( interp, sqlite3TestErrorName( rc ) ); return TCL.TCL_ERROR; } return TCL.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( object clientdata, Tcl_Interp interp, int objc, Tcl_Obj[] objv ) { #if !SQLITE_OMIT_UTF16 sqlite3_stmt pStmt=null; int idx=0; int bytes=0; string value; int rc; dxDel xDel = (objc==6?SQLITE_STATIC:SQLITE_TRANSIENT); Tcl_Obj oStmt = objv[objc-4]; Tcl_Obj oN = objv[objc-3]; Tcl_Obj oString = objv[objc-2]; Tcl_Obj oBytes = objv[objc-1]; if( objc!=5 && objc!=6){ TCL.Tcl_AppendResult(interp, "wrong # args: should be \"", TCL.Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE BYTES", 0); return TCL.TCL_ERROR; } if( getStmtPointer(interp, TCL.Tcl_GetString(oStmt), out pStmt)!=0 ) return TCL.TCL_ERROR; if( TCL.Tcl_GetIntFromObj(interp, oN, out idx) ) return TCL.TCL_ERROR; int dummy0 = 0; value = Encoding.UTF8.GetString(TCL.Tcl_GetByteArrayFromObj( oString, out dummy0 )); if( TCL.Tcl_GetIntFromObj(interp, oBytes, out bytes) ) return TCL.TCL_ERROR; rc = sqlite3_bind_text16(pStmt, idx, value, bytes, xDel); if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) !=0) return TCL.TCL_ERROR; if( rc!=SQLITE_OK ){ TCL.Tcl_AppendResult(interp, sqlite3TestErrorName(rc)); return TCL.TCL_ERROR; } #endif // * SQLITE_OMIT_UTF16 */ return TCL.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( object clientdata, Tcl_Interp interp, int objc, Tcl_Obj[] objv ) { sqlite3_stmt pStmt = null; int idx = 0; int bytes = 0; byte[] value; int rc; dxDel xDestructor = SQLITE_TRANSIENT; int iObjv = 0; if ( objc != 5 && objc != 6 ) { TCL.Tcl_AppendResult( interp, "wrong # args: should be \"", TCL.Tcl_GetStringFromObj( objv[0], 0 ), " STMT N DATA BYTES" ); return TCL.TCL_ERROR; } if ( objc == 6 ) { xDestructor = SQLITE_STATIC; iObjv++; } if ( getStmtPointer( interp, TCL.Tcl_GetString( objv[iObjv + 1] ), out pStmt ) != 0 ) return TCL.TCL_ERROR; if ( TCL.TCL_OK != TCL.Tcl_GetIntFromObj( interp, objv[iObjv + 2], out idx ) ) return TCL.TCL_ERROR; value = Encoding.UTF8.GetBytes( TCL.Tcl_GetString( objv[iObjv + 3] ) ); if ( TCL.TCL_OK != TCL.Tcl_GetIntFromObj( interp, objv[iObjv + 4], out bytes ) ) return TCL.TCL_ERROR; rc = sqlite3_bind_blob( pStmt, idx, value, bytes, xDestructor ); if ( sqlite3TestErrCode( interp, StmtToDb( pStmt ), rc ) != 0 ) return TCL.TCL_ERROR; if ( rc != SQLITE_OK ) { return TCL.TCL_ERROR; } return TCL.TCL_OK; } /* ** Usage: sqlite3_bind_parameter_count STMT ** ** Return the number of wildcards in the given statement. */ static int test_bind_parameter_count( object clientdata, Tcl_Interp interp, int objc, Tcl_Obj[] objv ) { sqlite3_stmt pStmt = null; if ( objc != 2 ) { TCL.Tcl_WrongNumArgs( interp, 1, objv, "STMT" ); return TCL.TCL_ERROR; } if ( getStmtPointer( interp, TCL.Tcl_GetString( objv[1] ), out pStmt ) != 0 ) return TCL.TCL_ERROR; TCL.Tcl_SetObjResult( interp, TCL.Tcl_NewIntObj( sqlite3_bind_parameter_count( pStmt ) ) ); return TCL.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( object clientdata, Tcl_Interp interp, int objc, Tcl_Obj[] objv ) { sqlite3_stmt pStmt = null; int i = 0; if ( objc != 3 ) { TCL.Tcl_WrongNumArgs( interp, 1, objv, "STMT N" ); return TCL.TCL_ERROR; } if ( getStmtPointer( interp, TCL.Tcl_GetString( objv[1] ), out pStmt ) != 0 ) return TCL.TCL_ERROR; if ( TCL.TCL_OK != TCL.Tcl_GetIntFromObj( interp, objv[2], out i ) ) return TCL.TCL_ERROR; TCL.Tcl_SetObjResult( interp, TCL.Tcl_NewStringObj( sqlite3_bind_parameter_name( pStmt, i ), -1 ) ); return TCL.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( object clientdata, Tcl_Interp interp, int objc, Tcl_Obj[] objv ) { sqlite3_stmt pStmt = null; if ( objc != 3 ) { TCL.Tcl_WrongNumArgs( interp, 1, objv, "STMT NAME" ); return TCL.TCL_ERROR; } if ( getStmtPointer( interp, TCL.Tcl_GetString( objv[1] ), out pStmt ) != 0 ) return TCL.TCL_ERROR; TCL.Tcl_SetObjResult( interp, TCL.Tcl_NewIntObj( sqlite3_bind_parameter_index( pStmt, TCL.Tcl_GetString( objv[2] ) ) ) ); return TCL.TCL_OK; } /* ** Usage: sqlite3_clear_bindings STMT ** */ static int test_clear_bindings( object clientdata, Tcl_Interp interp, int objc, Tcl_Obj[] objv ) { sqlite3_stmt pStmt = null; if ( objc != 2 ) { TCL.Tcl_WrongNumArgs( interp, 1, objv, "STMT" ); return TCL.TCL_ERROR; } if ( getStmtPointer( interp, TCL.Tcl_GetString( objv[1] ), out pStmt ) != 0 ) return TCL.TCL_ERROR; TCL.Tcl_SetObjResult( interp, TCL.Tcl_NewIntObj( sqlite3_clear_bindings( pStmt ) ) ); return TCL.TCL_OK; } /* ** Usage: sqlite3_sleep MILLISECONDS */ static int test_sleep( object clientdata, Tcl_Interp interp, int objc, Tcl_Obj[] objv ) { int ms = 0; if ( objc != 2 ) { TCL.Tcl_WrongNumArgs( interp, 1, objv, "MILLISECONDS" ); return TCL.TCL_ERROR; } if ( TCL.TCL_OK != TCL.Tcl_GetIntFromObj( interp, objv[1], out ms ) ) { return TCL.TCL_ERROR; } TCL.Tcl_SetObjResult( interp, TCL.Tcl_NewIntObj( sqlite3_sleep( ms ) ) ); return TCL.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( object clientdata, Tcl_Interp interp, int objc, Tcl_Obj[] objv ) { sqlite3 db = null; int rc; if ( objc != 2 ) { TCL.Tcl_AppendResult( interp, "wrong # args: should be \"", TCL.Tcl_GetString( objv[0] ), " DB" ); return TCL.TCL_ERROR; } if ( getDbPointer( interp, TCL.Tcl_GetString( objv[1] ), out db ) != 0 ) return TCL.TCL_ERROR; rc = sqlite3_extended_errcode( db ); TCL.Tcl_AppendResult( interp, t1ErrorName( rc ) ); return TCL.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( object clientdata, Tcl_Interp interp, int objc, Tcl_Obj[] objv ) { sqlite3 db = null; int rc; StringBuilder zBuf = new StringBuilder( 50 ); if ( objc != 2 ) { TCL.Tcl_AppendResult( interp, "wrong # args: should be \"", TCL.Tcl_GetString( objv[0] ), " DB" ); return TCL.TCL_ERROR; } if ( getDbPointer( interp, TCL.Tcl_GetString( objv[1] ), out db ) != 0 ) return TCL.TCL_ERROR; rc = sqlite3_errcode( db ); if ( ( rc & 0xff ) == rc ) { zBuf.Length = 0; } else { sqlite3_snprintf( 30, zBuf, "+%d", rc >> 8 ); } TCL.Tcl_AppendResult( interp, t1ErrorName( rc ), zBuf ); return TCL.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( object clientdata, Tcl_Interp interp, int objc, Tcl_Obj[] objv ) { sqlite3 db = null; string zErr; if ( objc != 2 ) { TCL.Tcl_AppendResult( interp, "wrong # args: should be \"", TCL.Tcl_GetString( objv[0] ), " DB" ); return TCL.TCL_ERROR; } if ( getDbPointer( interp, TCL.Tcl_GetString( objv[1] ), out db ) != 0 ) return TCL.TCL_ERROR; zErr = sqlite3_errmsg( db ); TCL.Tcl_SetObjResult( interp, TCL.Tcl_NewStringObj( zErr, -1 ) ); return TCL.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( // object clientdata, // Tcl_Interp interp, // int objc, // Tcl_Obj[] objv //){ #if !SQLITE_OMIT_UTF16 sqlite3 db; string zErr; string z; int bytes = 0; if( objc!=2 ){ TCL.Tcl_AppendResult(interp, "wrong # args: should be \"", TCL.Tcl_GetString(objv[0]), " DB", 0); return TCL.TCL_ERROR; } if( getDbPointer(interp, TCL.Tcl_GetString(objv[1]), &db) ) return TCL.TCL_ERROR; zErr = sqlite3_errmsg16(db); if( zErr ){ z = zErr; for(bytes=0; z[bytes] || z[bytes+1]; bytes+=2){} } TCL.Tcl_SetObjResult(interp, TCL.Tcl_NewByteArrayObj(zErr, bytes)); #endif // * SQLITE_OMIT_UTF16 */ // return TCL.TCL_OK; //} /* ** Usage: sqlite3_prepare DB sql bytes ?tailvar? ** ** Compile up to bytes of the supplied SQL string using ** database handle . The parameter is the name of a global ** variable that is set to the unused portion of (if any). A ** STMT handle is returned. */ static int test_prepare( object clientdata, Tcl_Interp interp, int objc, Tcl_Obj[] objv ) { sqlite3 db = null; string zSql; int bytes = 0; string zTail = ""; sqlite3_stmt pStmt = null; StringBuilder zBuf = new StringBuilder( 50 ); int rc; if ( objc != 5 && objc != 4 ) { TCL.Tcl_AppendResult( interp, "wrong # args: should be \"", TCL.Tcl_GetString( objv[0] ), " DB sql bytes ?tailvar?" ); return TCL.TCL_ERROR; } if ( getDbPointer( interp, TCL.Tcl_GetString( objv[1] ), out db ) != 0 ) return TCL.TCL_ERROR; zSql = TCL.Tcl_GetString( objv[2] ); if ( TCL.TCL_OK != TCL.Tcl_GetIntFromObj( interp, objv[3], out bytes ) ) return TCL.TCL_ERROR; if ( bytes > zSql.Length ) bytes = zSql.Length; rc = sqlite3_prepare( db, zSql, bytes, ref pStmt, ref zTail ); TCL.Tcl_ResetResult( interp ); if ( sqlite3TestErrCode( interp, db, rc ) != 0 ) return TCL.TCL_ERROR; if ( zTail != null && objc >= 5 ) { if ( bytes >= 0 ) { bytes = bytes - zSql.Length - zTail.Length;// ( zTail - zSql ); } if ( zTail.Length < bytes ) { bytes = zTail.Length; } TCL.Tcl_ObjSetVar2( interp, objv[4], null, TCL.Tcl_NewStringObj( zTail, bytes ), 0 ); } if ( rc != SQLITE_OK ) { Debug.Assert( pStmt == null ); sqlite3_snprintf( 200, zBuf, "(%d) ", rc ); TCL.Tcl_SetResult( interp, zBuf + sqlite3_errmsg( db ), 0 ); return TCL.TCL_ERROR; } if ( pStmt != null ) { if ( sqlite3TestMakePointerStr( interp, zBuf, pStmt ) != 0 ) return TCL.TCL_ERROR; TCL.Tcl_AppendResult( interp, zBuf, null ); } return TCL.TCL_OK; } /* ** Usage: sqlite3_prepare_v2 DB sql bytes ?tailvar? ** ** Compile up to bytes of the supplied SQL string using ** database handle . The parameter is the name of a global ** variable that is set to the unused portion of (if any). A ** STMT handle is returned. */ static int test_prepare_v2( object clientdata, Tcl_Interp interp, int objc, Tcl_Obj[] objv ) { sqlite3 db = null; string zSql; int bytes = 0; string zTail = ""; sqlite3_stmt pStmt = null; StringBuilder zBuf = new StringBuilder( 50 ); int rc; if ( objc != 5 && objc != 4 ) { TCL.Tcl_AppendResult( interp, "wrong # args: should be \"", TCL.Tcl_GetString( objv[0] ), " DB sql bytes ?tailvar?", null ); return TCL.TCL_ERROR; } if ( getDbPointer( interp, TCL.Tcl_GetString( objv[1] ), out db ) != 0 ) return TCL.TCL_ERROR; zSql = TCL.Tcl_GetString( objv[2] ); if ( TCL.TCL_OK != TCL.Tcl_GetIntFromObj( interp, objv[3], out bytes ) ) return TCL.TCL_ERROR; rc = sqlite3_prepare_v2( db, zSql, bytes, ref pStmt, ref zTail ); Debug.Assert( rc == SQLITE_OK || pStmt == null ); TCL.Tcl_ResetResult( interp ); if ( sqlite3TestErrCode( interp, db, rc ) != 0 ) return TCL.TCL_ERROR; if ( zTail != null && objc >= 5 ) { if ( bytes >= 0 ) { bytes = bytes - zSql.Length - zTail.Length;// ( zTail - zSql ); } TCL.Tcl_ObjSetVar2( interp, objv[4], null, TCL.Tcl_NewStringObj( zTail, bytes ), 0 ); } if ( rc != SQLITE_OK ) { Debug.Assert( pStmt == null ); sqlite3_snprintf( 50, zBuf, "(%d) ", rc ); TCL.Tcl_AppendResult( interp, zBuf, sqlite3_errmsg( db ) ); return TCL.TCL_ERROR; } if ( pStmt != null ) { if ( sqlite3TestMakePointerStr( interp, zBuf, pStmt ) != 0 ) return TCL.TCL_ERROR; TCL.Tcl_AppendResult( interp, zBuf ); } return TCL.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( object clientdata, Tcl_Interp interp, int objc, Tcl_Obj[] objv ) { sqlite3 db = null; string zSql = "\000SELECT 1"; sqlite3_stmt pStmt = null; StringBuilder zBuf = new StringBuilder( 50 ); int rc; if ( objc != 2 ) { TCL.Tcl_AppendResult( interp, "wrong # args: should be \"", TCL.Tcl_GetString( objv[0] ), " DB sql bytes tailvar" ); return TCL.TCL_ERROR; } if ( getDbPointer( interp, TCL.Tcl_GetString( objv[1] ), out db ) != 0 ) return TCL.TCL_ERROR; rc = sqlite3_prepare_v2( db, zSql.Substring( 1 ), 0, ref pStmt, 0 ); Debug.Assert( rc == SQLITE_OK || pStmt == null ); if ( sqlite3TestErrCode( interp, db, rc ) != 0 ) return TCL.TCL_ERROR; if ( rc != SQLITE_OK ) { Debug.Assert( pStmt == null ); zBuf.Length = 0; zBuf.Append( rc.ToString() ); //sprintf( zBuf, "(%d) ", rc ); TCL.Tcl_AppendResult( interp, zBuf, sqlite3_errmsg( db ) ); return TCL.TCL_ERROR; } if ( pStmt != null ) { if ( sqlite3TestMakePointerStr( interp, zBuf, pStmt ) != 0 ) return TCL.TCL_ERROR; TCL.Tcl_AppendResult( interp, zBuf ); } return TCL.TCL_OK; } /* ** Usage: sqlite3_prepare16 DB sql bytes tailvar ** ** Compile up to bytes of the supplied SQL string using ** database handle . The parameter is the name of a global ** variable that is set to the unused portion of (if any). A ** STMT handle is returned. */ static int test_prepare16( object clientdata, Tcl_Interp interp, int objc, Tcl_Obj[] objv ) { #if !SQLITE_OMIT_UTF16 sqlite3 db=null; string zSql; string zTail = 0; Tcl_Obj pTail = 0; sqlite3_stmt pStmt = null; 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.Tcl_AppendResult(interp, "wrong # args: should be \"", TCL.Tcl_GetString(objv[0]), " DB sql bytes ?tailvar?", 0); return TCL.TCL_ERROR; } if( getDbPointer(interp, TCL.Tcl_GetString(objv[1]), out db) !=0) return TCL.TCL_ERROR; zSql = TCL.Tcl_GetByteArrayFromObj(objv[2], out objlen); if( TCL.Tcl_GetIntFromObj(interp, objv[3], out bytes) ) return TCL.TCL_ERROR; rc = sqlite3_prepare16(db, zSql, bytes, pStmt, objc>=5 ? &zTail : 0); if( sqlite3TestErrCode(interp, db, rc) ) return TCL.TCL_ERROR; if( rc !=0){ return TCL.TCL_ERROR; } if( objc>=5 ){ if( zTail ){ objlen = objlen - ((u8 )zTail-(u8 )zSql); }else{ objlen = 0; } pTail = TCL.Tcl_NewByteArrayObj((u8 )zTail, objlen); TCL.Tcl_IncrRefCount(pTail); Tcl_ObjSetVar2(interp, objv[4], 0, pTail, 0); TCL.Tcl_DecrRefCount(pTail); } if( pStmt ){ if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL.TCL_ERROR; } TCL.Tcl_AppendResult(interp, zBuf); #endif // * SQLITE_OMIT_UTF16 */ return TCL.TCL_OK; } /* ** Usage: sqlite3_prepare16_v2 DB sql bytes tailvar ** ** Compile up to bytes of the supplied SQL string using ** database handle . The parameter is the name of a global ** variable that is set to the unused portion of (if any). A ** STMT handle is returned. */ //static int test_prepare16_v2( // object clientdata, // Tcl_Interp interp, // int objc, // Tcl_Obj[] objv //){ #if !SQLITE_OMIT_UTF16 // sqlite3 db=null; // string zSql; // string zTail = 0; // Tcl_Obj pTail = 0; // sqlite3_stmt pStmt = null; // 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.Tcl_AppendResult(interp, "wrong # args: should be \"", // TCL.Tcl_GetString(objv[0]), " DB sql bytes ?tailvar?", 0); // return TCL.TCL_ERROR; // } // if( getDbPointer(interp, TCL.Tcl_GetString(objv[1]), out db) !=0) return TCL.TCL_ERROR; // zSql = TCL.Tcl_GetByteArrayFromObj(objv[2], out objlen); // if( TCL.Tcl_GetIntFromObj(interp, objv[3], out bytes) ) return TCL.TCL_ERROR; // rc = sqlite3_prepare16_v2(db, zSql, bytes, pStmt,objc>=5 ? &zTail : 0); // if( sqlite3TestErrCode(interp, db, rc) ) return TCL.TCL_ERROR; // if( rc !=0){ // return TCL.TCL_ERROR; // } if( objc>=5 ){ if( zTail ){ objlen = objlen - ((u8 )zTail-(u8 )zSql); }else{ objlen = 0; } pTail = TCL.Tcl_NewByteArrayObj((u8 )zTail, objlen); TCL.Tcl_IncrRefCount(pTail); Tcl_ObjSetVar2(interp, objv[4], 0, pTail, 0); TCL.Tcl_DecrRefCount(pTail); // } // if( pStmt ){ // if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL.TCL_ERROR; // } // TCL.Tcl_AppendResult(interp, zBuf); #endif // * SQLITE_OMIT_UTF16 */ // return TCL.TCL_OK; //} /* ** Usage: sqlite3_open filename ?options-list? */ static int test_open( object clientdata, Tcl_Interp interp, int objc, Tcl_Obj[] objv ) { string zFilename; SqliteDb db = new SqliteDb(); int rc; StringBuilder zBuf = new StringBuilder( 100 ); if ( objc != 3 && objc != 2 && objc != 1 ) { TCL.Tcl_AppendResult( interp, "wrong # args: should be \"", TCL.Tcl_GetString( objv[0] ), " filename options-list" ); return TCL.TCL_ERROR; } zFilename = objc > 1 ? TCL.Tcl_GetString( objv[1] ) : null; rc = sqlite3_open( zFilename, out db.db ); if ( sqlite3TestMakePointerStr( interp, zBuf, db ) != TCL.TCL_OK ) return TCL.TCL_ERROR; TCL.Tcl_AppendResult( interp, zBuf ); return TCL.TCL_OK; } class OpenFlag { public string zFlag; public int flag; public OpenFlag( string zFlag, int flag ) { this.zFlag = zFlag; this.flag = flag; } } /* ** Usage: sqlite3_open_v2 FILENAME FLAGS VFS */ static int test_open_v2( object clientdata, Tcl_Interp interp, int objc, Tcl_Obj[] objv ) { string zFilename; string zVfs; int flags = 0; sqlite3 db = null; int rc; StringBuilder zBuf = new StringBuilder( 100 ); int nFlag = 0; Tcl_Obj[] apFlag = null; int i; if ( objc != 4 ) { TCL.Tcl_WrongNumArgs( interp, 1, objv, "FILENAME FLAGS VFS" ); return TCL.TCL_ERROR; } zFilename = TCL.Tcl_GetString( objv[1] ); zVfs = TCL.Tcl_GetString( objv[3] ); if ( zVfs[0] == 0x00 ) zVfs = null; rc = TCL.Tcl_ListObjGetElements( interp, objv[2], out nFlag, out apFlag ) ? TCL.TCL_OK : 1; if ( rc != TCL.TCL_OK ) return rc; for ( i = 0; i < nFlag; i++ ) { int iFlag; OpenFlag[] aFlag = new OpenFlag[] { new OpenFlag( "SQLITE_OPEN_READONLY", SQLITE_OPEN_READONLY ), new OpenFlag( "SQLITE_OPEN_READWRITE", SQLITE_OPEN_READWRITE ), new OpenFlag( "SQLITE_OPEN_CREATE", SQLITE_OPEN_CREATE ), new OpenFlag( "SQLITE_OPEN_DELETEONCLOSE", SQLITE_OPEN_DELETEONCLOSE ), new OpenFlag( "SQLITE_OPEN_EXCLUSIVE", SQLITE_OPEN_EXCLUSIVE ), new OpenFlag( "SQLITE_OPEN_AUTOPROXY", SQLITE_OPEN_AUTOPROXY ), new OpenFlag( "SQLITE_OPEN_MAIN_DB", SQLITE_OPEN_MAIN_DB ), new OpenFlag( "SQLITE_OPEN_TEMP_DB", SQLITE_OPEN_TEMP_DB ), new OpenFlag( "SQLITE_OPEN_TRANSIENT_DB", SQLITE_OPEN_TRANSIENT_DB ), new OpenFlag( "SQLITE_OPEN_MAIN_JOURNAL", SQLITE_OPEN_MAIN_JOURNAL ), new OpenFlag( "SQLITE_OPEN_TEMP_JOURNAL", SQLITE_OPEN_TEMP_JOURNAL ), new OpenFlag( "SQLITE_OPEN_SUBJOURNAL", SQLITE_OPEN_SUBJOURNAL ), new OpenFlag( "SQLITE_OPEN_MASTER_JOURNAL", SQLITE_OPEN_MASTER_JOURNAL ), new OpenFlag( "SQLITE_OPEN_NOMUTEX", SQLITE_OPEN_NOMUTEX ), new OpenFlag( "SQLITE_OPEN_FULLMUTEX", SQLITE_OPEN_FULLMUTEX ), new OpenFlag( "SQLITE_OPEN_SHAREDCACHE", SQLITE_OPEN_SHAREDCACHE ), new OpenFlag( "SQLITE_OPEN_PRIVATECACHE", SQLITE_OPEN_PRIVATECACHE ), new OpenFlag( "SQLITE_OPEN_WAL", SQLITE_OPEN_WAL ), new OpenFlag( "SQLITE_OPEN_URI", SQLITE_OPEN_URI ), new OpenFlag( null, 0 ) }; //rc = TCL.Tcl_GetIndexFromObjStruct( interp, apFlag[i], aFlag, sizeof( aFlag[0] ), // "flag", 0, ref iFlag ); for ( iFlag = 0; iFlag < aFlag.Length && ( aFlag[iFlag].zFlag != objv[4].ToString() ); iFlag++ ) { } if ( iFlag >= aFlag.Length ) return TCL.TCL_ERROR; flags |= aFlag[iFlag].flag; } rc = sqlite3_open_v2( zFilename, out db, flags, zVfs ); if ( sqlite3TestMakePointerStr( interp, zBuf, db ) != 0 ) return TCL.TCL_ERROR; TCL.Tcl_AppendResult( interp, zBuf, 0 ); return TCL.TCL_OK; } /* ** Usage: sqlite3_open16 filename options */ //static int test_open16( // object clientdata, // Tcl_Interp interp, // int objc, // Tcl_Obj[] objv //){ #if !SQLITE_OMIT_UTF16 // string zFilename; // sqlite3 db=null; // int rc; // char zBuf[100]; // if( objc!=3 ){ // TCL.Tcl_AppendResult(interp, "wrong # args: should be \"", // TCL.Tcl_GetString(objv[0]), " filename options-list", 0); // return TCL.TCL_ERROR; // } // zFilename = TCL.Tcl_GetByteArrayFromObj(objv[1], 0); // rc = sqlite3_open16(zFilename, ref db); // if ( sqlite3TestMakePointerStr( interp, zBuf, db ) != TCL.TCL_OK ) return TCL.TCL_ERROR; // TCL.Tcl_AppendResult(interp, zBuf); #endif // * SQLITE_OMIT_UTF16 */ // return TCL.TCL_OK; //} /* ** Usage: sqlite3_complete16 ** ** Return 1 if the supplied argument is a complete SQL statement, or zero ** otherwise. */ //static int test_complete16( // object clientdata, // Tcl_Interp interp, // int objc, // Tcl_Obj[] objv //){ #if !SQLITE_OMIT_COMPLETE && !SQLITE_OMIT_UTF16 // string zBuf; // if( objc!=2 ){ // TCL.Tcl_WrongNumArgs(interp, 1, objv, ""); // return TCL.TCL_ERROR; // } // zBuf = (char)TCL.Tcl_GetByteArrayFromObj(objv[1], 0); // TCL.Tcl_SetObjResult(interp, TCL.Tcl_NewIntObj(sqlite3_complete16(zBuf))); #endif // * SQLITE_OMIT_COMPLETE && SQLITE_OMIT_UTF16 */ // return TCL.TCL_OK; //} /* ** Usage: sqlite3_step STMT ** ** Advance the statement to the next row. */ static int test_step( object clientdata, Tcl_Interp interp, int objc, Tcl_Obj[] objv ) { sqlite3_stmt pStmt = null; int rc; if ( objc != 2 ) { TCL.Tcl_AppendResult( interp, "wrong # args: should be \"", TCL.Tcl_GetString( objv[0] ), " STMT" ); return TCL.TCL_ERROR; } if ( getStmtPointer( interp, TCL.Tcl_GetString( objv[1] ), out pStmt ) != 0 ) return TCL.TCL_ERROR; rc = sqlite3_step( pStmt ); /* if( rc!=SQLITE_DONE && rc!=SQLITE_ROW ) return TCL.TCL_ERROR; */ TCL.Tcl_SetResult( interp, t1ErrorName( rc ), 0 ); return TCL.TCL_OK; } static int test_sql( object clientdata, Tcl_Interp interp, int objc, Tcl_Obj[] objv ) { sqlite3_stmt pStmt = null; if ( objc != 2 ) { TCL.Tcl_WrongNumArgs( interp, 1, objv, "STMT" ); return TCL.TCL_ERROR; } if ( getStmtPointer( interp, TCL.Tcl_GetString( objv[1] ), out pStmt ) != 0 ) return TCL.TCL_ERROR; TCL.Tcl_SetResult( interp, sqlite3_sql( pStmt ), TCL.TCL_VOLATILE ); return TCL.TCL_OK; } /* ** Usage: sqlite3_column_count STMT ** ** Return the number of columns returned by the sql statement STMT. */ static int test_column_count( object clientdata, Tcl_Interp interp, int objc, Tcl_Obj[] objv ) { sqlite3_stmt pStmt = null; if ( objc != 2 ) { TCL.Tcl_AppendResult( interp, "wrong # args: should be \"", TCL.Tcl_GetString( objv[0] ), " STMT column" ); return TCL.TCL_ERROR; } if ( getStmtPointer( interp, TCL.Tcl_GetString( objv[1] ), out pStmt ) != 0 ) return TCL.TCL_ERROR; TCL.Tcl_SetObjResult( interp, TCL.Tcl_NewIntObj( sqlite3_column_count( pStmt ) ) ); return TCL.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( object clientdata, Tcl_Interp interp, int objc, Tcl_Obj[] objv ) { sqlite3_stmt pStmt = null; int col = 0; int tp; if ( objc != 3 ) { TCL.Tcl_AppendResult( interp, "wrong # args: should be \"", TCL.Tcl_GetString( objv[0] ), " STMT column" ); return TCL.TCL_ERROR; } if ( getStmtPointer( interp, TCL.Tcl_GetString( objv[1] ), out pStmt ) != 0 ) return TCL.TCL_ERROR; if ( TCL.TCL_OK != TCL.Tcl_GetIntFromObj( interp, objv[2], out col ) ) return TCL.TCL_ERROR; tp = sqlite3_column_type( pStmt, col ); switch ( tp ) { case SQLITE_INTEGER: TCL.Tcl_SetResult( interp, "INTEGER", TCL.TCL_STATIC ); break; case SQLITE_NULL: TCL.Tcl_SetResult( interp, "NULL", TCL.TCL_STATIC ); break; case SQLITE_FLOAT: TCL.Tcl_SetResult( interp, "FLOAT", TCL.TCL_STATIC ); break; case SQLITE_TEXT: TCL.Tcl_SetResult( interp, "TEXT", TCL.TCL_STATIC ); break; case SQLITE_BLOB: TCL.Tcl_SetResult( interp, "BLOB", TCL.TCL_STATIC ); break; default: Debugger.Break(); break; } return TCL.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( object clientdata, Tcl_Interp interp, int objc, Tcl_Obj[] objv ) { sqlite3_stmt pStmt = new sqlite3_stmt(); int col = 0; i64 iVal; if ( objc != 3 ) { TCL.Tcl_AppendResult( interp, "wrong # args: should be \"", TCL.Tcl_GetString( objv[0] ), " STMT column" ); return TCL.TCL_ERROR; } if ( getStmtPointer( interp, TCL.Tcl_GetString( objv[1] ), out pStmt ) != TCL.TCL_OK ) return TCL.TCL_ERROR; if ( TCL.TCL_OK != TCL.Tcl_GetIntFromObj( interp, objv[2], out col ) ) return TCL.TCL_ERROR; iVal = sqlite3_column_int64( pStmt, col ); TCL.Tcl_SetObjResult( interp, TCL.Tcl_NewWideIntObj( iVal ) ); return TCL.TCL_OK; } /* ** Usage: sqlite3_column_blob STMT column */ static int test_column_blob( object clientdata, Tcl_Interp interp, int objc, Tcl_Obj[] objv ) { sqlite3_stmt pStmt = new sqlite3_stmt(); int col = 0; int len; byte[] pBlob; if ( objc != 3 ) { TCL.Tcl_AppendResult( interp, "wrong # args: should be \"", TCL.Tcl_GetString( objv[0] ), " STMT column" ); return TCL.TCL_ERROR; } if ( getStmtPointer( interp, TCL.Tcl_GetString( objv[1] ), out pStmt ) != TCL.TCL_OK ) return TCL.TCL_ERROR; if ( TCL.TCL_OK != TCL.Tcl_GetIntFromObj( interp, objv[2], out col ) ) return TCL.TCL_ERROR; len = sqlite3_column_bytes( pStmt, col ); pBlob = sqlite3_column_blob( pStmt, col ); TCL.Tcl_SetObjResult( interp, TCL.Tcl_NewByteArrayObj( pBlob, len ) ); return TCL.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( object clientdata, Tcl_Interp interp, int objc, Tcl_Obj[] objv ) { sqlite3_stmt pStmt = new sqlite3_stmt(); int col = 0; double rVal; if ( objc != 3 ) { TCL.Tcl_AppendResult( interp, "wrong # args: should be \"", TCL.Tcl_GetString( objv[0] ), " STMT column" ); return TCL.TCL_ERROR; } if ( getStmtPointer( interp, TCL.Tcl_GetString( objv[1] ), out pStmt ) != TCL.TCL_OK ) return TCL.TCL_ERROR; if ( TCL.TCL_OK != TCL.Tcl_GetIntFromObj( interp, objv[2], out col ) ) return TCL.TCL_ERROR; rVal = sqlite3_column_double( pStmt, col ); TCL.Tcl_SetObjResult( interp, TCL.Tcl_NewDoubleObj( rVal ) ); return TCL.TCL_OK; } /* ** Usage: sqlite3_data_count STMT ** ** Return the number of columns returned by the sql statement STMT. */ static int test_data_count( object clientdata, Tcl_Interp interp, int objc, Tcl_Obj[] objv ) { sqlite3_stmt pStmt = null; if ( objc != 2 ) { TCL.Tcl_AppendResult( interp, "wrong # args: should be \"", TCL.Tcl_GetString( objv[0] ), " STMT column" ); return TCL.TCL_ERROR; } if ( getStmtPointer( interp, TCL.Tcl_GetString( objv[1] ), out pStmt ) != TCL.TCL_OK ) return TCL.TCL_ERROR; TCL.Tcl_SetObjResult( interp, TCL.Tcl_NewIntObj( sqlite3_data_count( pStmt ) ) ); return TCL.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( object clientdata, /* Pointer to SQLite API function to be invoke */ Tcl_Interp interp, int objc, Tcl_Obj[] objv ) { sqlite3_stmt pStmt = null; int col = 0; dxColumn xFunc;//string (*xFunc)(sqlite3_stmt*, int); string zRet; xFunc = (dxColumn)clientdata; //(string ()(sqlite3_stmt*, int))clientData; if ( objc != 3 ) { TCL.Tcl_AppendResult( interp, "wrong # args: should be \"", TCL.Tcl_GetString( objv[0] ), " STMT column" ); return TCL.TCL_ERROR; } if ( getStmtPointer( interp, TCL.Tcl_GetString( objv[1] ), out pStmt ) != 0 ) return TCL.TCL_ERROR; if ( TCL.TCL_OK != TCL.Tcl_GetIntFromObj( interp, objv[2], out col ) ) return TCL.TCL_ERROR; zRet = (string)xFunc( pStmt, col ); if ( zRet != null ) { TCL.Tcl_SetResult( interp, zRet, 0 ); } return TCL.TCL_OK; } static int test_global_recover( object clientdata, Tcl_Interp interp, int objc, Tcl_Obj[] objv ) { #if !SQLITE_OMIT_DEPRECATED int rc; if ( objc != 1 ) { TCL.Tcl_WrongNumArgs( interp, 1, objv, "" ); return TCL.TCL_ERROR; } rc = sqlite3_global_recover(); TCL.Tcl_SetResult( interp, t1ErrorName( rc ), TCL.TCL_STATIC ); #else TCL.Tcl_SetResult( interp, t1ErrorName( SQLITE_OK ), TCL.TCL_STATIC ); #endif return TCL.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( // object clientdata, /* Pointer to SQLite API function to be invoked */ // Tcl_Interp interp, // int objc, // Tcl_Obj[] objv //){ #if !SQLITE_OMIT_UTF16 // sqlite3_stmt pStmt; // int col; // Tcl_Obj pRet; // string zName16; // const void *(*xFunc)(sqlite3_stmt*, int); xFunc = (dxColumn)clientdata; //(string ()(sqlite3_stmt*, int))clientData; // if( objc!=3 ){ // TCL.Tcl_AppendResult(interp, "wrong # args: should be \"", // TCL.Tcl_GetString(objv[0]), " STMT column", 0); // return TCL.TCL_ERROR; // } // if( getStmtPointer(interp, TCL.Tcl_GetString(objv[1]), pStmt) ) return TCL.TCL_ERROR; // if( TCL.Tcl_GetIntFromObj(interp, objv[2], out col) ) return TCL.TCL_ERROR; // zName16 = xFunc(pStmt, col); // if( zName16 ){ int n; string z = zName16; for(n=0; z[n] || z[n+1]; n+=2){} pRet = TCL.Tcl_NewByteArrayObj(zName16, n+2); // TCL.Tcl_SetObjResult(interp, pRet); // } #endif // * SQLITE_OMIT_UTF16 */ // return TCL.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( object clientdata, /* Pointer to SQLite API function to be invoked */ Tcl_Interp interp, int objc, Tcl_Obj[] objv ) { sqlite3_stmt pStmt = null; int col = 0; dxColumn_I xFunc;//(sqlite3_stmt*, int) ; xFunc = (dxColumn_I)clientdata; //(int ()(sqlite3_stmt*, int))clientData; if ( objc != 3 ) { TCL.Tcl_AppendResult( interp, "wrong # args: should be \"", TCL.Tcl_GetString( objv[0] ), " STMT column" ); return TCL.TCL_ERROR; } if ( getStmtPointer( interp, TCL.Tcl_GetString( objv[1] ), out pStmt ) != 0 ) return TCL.TCL_ERROR; if ( TCL.TCL_OK != TCL.Tcl_GetIntFromObj( interp, objv[2], out col ) ) return TCL.TCL_ERROR; TCL.Tcl_SetObjResult( interp, TCL.Tcl_NewIntObj( xFunc( pStmt, col ) ) ); return TCL.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( object clientdata, /* Pointer to SQLite API function to be invoked */ Tcl_Interp interp, int argc, Tcl_Obj[] argv ) { sqlite3 db = null; if ( argc != 3 ) { TCL.Tcl_AppendResult( interp, "wrong # args: should be \"", argv[0], " DB MAGIC" ); return TCL.TCL_ERROR; } if ( getDbPointer( interp, argv[1].ToString(), out db ) != 0 ) return TCL.TCL_ERROR; if ( argv[2].ToString() == "SQLITE_MAGIC_OPEN" ) { db.magic = SQLITE_MAGIC_OPEN; } else if ( argv[2].ToString() == "SQLITE_MAGIC_CLOSED" ) { db.magic = SQLITE_MAGIC_CLOSED; } else if ( argv[2].ToString() == "SQLITE_MAGIC_BUSY" ) { db.magic = SQLITE_MAGIC_BUSY; } else if ( argv[2].ToString() == "SQLITE_MAGIC_ERROR" ) { db.magic = SQLITE_MAGIC_ERROR; } else if ( TCL.Tcl_GetInt( interp, argv[2], out db.magic ) ) { return TCL.TCL_ERROR; } return TCL.TCL_OK; } /* ** Usage: sqlite3_interrupt DB ** ** Trigger an interrupt on DB */ static int test_interrupt( object clientdata, Tcl_Interp interp, int argc, Tcl_Obj[] argv ) { sqlite3 db = null; if ( argc != 2 ) { TCL.Tcl_AppendResult( interp, "wrong # args: should be \"", argv[0], " DB" ); return TCL.TCL_ERROR; } if ( getDbPointer( interp, argv[1].ToString(), out db ) != 0 ) return TCL.TCL_ERROR; sqlite3_interrupt( db ); return TCL.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=0 && ((u32)sqlite3_stack_baseline)[-i]==0xdeadbeef; i--){} // TCL.Tcl_SetObjResult(interp, TCL.Tcl_NewIntObj(i*4)); // return TCL.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( object clientdata, Tcl_Interp interp, int argc, Tcl_Obj[] argv ) { int rc; sqlite3 db = null; if ( argc != 3 ) { TCL.Tcl_AppendResult( interp, "wrong # args: should be \"", argv[0], " DB function-name", null ); return TCL.TCL_ERROR; } if ( getDbPointer( interp, argv[1].ToString(), out db ) != 0 ) return TCL.TCL_ERROR; rc = sqlite3_create_function( db, argv[2].ToString(), -1, SQLITE_UTF8, null, null, null, null ); TCL.Tcl_SetResult( interp, t1ErrorName( rc ), TCL.TCL_STATIC ); return TCL.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( object clientdata, Tcl_Interp interp, int argc, Tcl_Obj[] argv ) { int rc; sqlite3 db = null; if ( argc != 3 ) { TCL.Tcl_AppendResult( interp, "wrong # args: should be \"", argv[0], " DB function-name", null ); return TCL.TCL_ERROR; } if ( getDbPointer( interp, argv[1].ToString(), out db ) != 0 ) return TCL.TCL_ERROR; rc = sqlite3_create_collation( db, argv[2].ToString(), SQLITE_UTF8, null, null ); TCL.Tcl_SetResult( interp, t1ErrorName( rc ), TCL.TCL_STATIC ); return TCL.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( object clientdata, Tcl_Interp interp, int argc, Tcl_Obj[] argv ) { StringBuilder zBuf = new StringBuilder( 30 ); sqlite3 db = null; if ( argc != 2 ) { TCL.Tcl_AppendResult( interp, "wrong # args: should be \"", argv[0], " DB" ); return TCL.TCL_ERROR; } if ( getDbPointer( interp, argv[1].ToString(), out db ) != 0 ) return TCL.TCL_ERROR; sqlite3_snprintf( 30, zBuf, "%d", sqlite3_get_autocommit( db ) ); TCL.Tcl_AppendResult( interp, zBuf ); return TCL.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( object clientdata, Tcl_Interp interp, int argc, Tcl_Obj[] argv ) { int rc, ms = 0; sqlite3 db = null; if ( argc != 3 ) { TCL.Tcl_AppendResult( interp, "wrong # args: should be \"", argv[0], " DB" ); return TCL.TCL_ERROR; } if ( getDbPointer( interp, argv[1].ToString(), out db ) != 0 ) return TCL.TCL_ERROR; if ( TCL.Tcl_GetInt( interp, argv[2], out ms ) ) return TCL.TCL_ERROR; rc = sqlite3_busy_timeout( db, ms ); TCL.Tcl_AppendResult( interp, sqlite3TestErrorName( rc ) ); return TCL.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( object clientdata, Tcl_Interp interp, int objc, Tcl_Obj[] objv ) { Tcl_Obj pVar; if ( objc != 2 ) { TCL.Tcl_WrongNumArgs( interp, 1, objv, "VARIABLE" ); return TCL.TCL_ERROR; } pVar = TCL.Tcl_GetVar2Ex( interp, TCL.Tcl_GetString( objv[1] ), null, (TCL.VarFlag)TCL.TCL_LEAVE_ERR_MSG ); if ( pVar == null ) return TCL.TCL_ERROR; if ( pVar.typePtr != "" ) { TCL.Tcl_SetObjResult( interp, TCL.Tcl_NewStringObj( pVar.typePtr, -1 ) ); } return TCL.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( object clientdata, Tcl_Interp interp, int objc, Tcl_Obj[] objv ) { #if SQLITE_ENABLE_MEMORY_MANAGEMENT && !SQLITE_OMIT_DISKIO int N; int amt; if( objc!=1 && objc!=2 ){ TCL.Tcl_WrongNumArgs(interp, 1, objv, "?N?"); return TCL.TCL_ERROR; } if( objc==2 ){ if( TCL.Tcl_GetIntFromObj(interp, objv[1], out N) ) return TCL.TCL_ERROR; }else{ N = -1; } amt = sqlite3_release_memory(N); TCL.Tcl_SetObjResult(interp, TCL.Tcl_NewIntObj(amt)); #endif return TCL.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( object clientdata, Tcl_Interp interp, int objc, Tcl_Obj[] objv ) { sqlite3_int64 amt; sqlite3_int64 N = -1; if ( objc != 1 && objc != 2 ) { TCL.Tcl_WrongNumArgs( interp, 1, objv, "?N?" ); return TCL.TCL_ERROR; } if ( objc == 2 ) { if ( TCL.Tcl_GetWideIntFromObj( interp, objv[1], out N ) ) return TCL.TCL_ERROR; } amt = sqlite3_soft_heap_limit64( N ); TCL.Tcl_SetObjResult( interp, TCL.Tcl_NewWideIntObj( amt ) ); return TCL.TCL_OK; } /* ** Usage: sqlite3_thread_cleanup ** ** Call the sqlite3_thread_cleanup API. */ //static int test_thread_cleanup( // object clientdata, // Tcl_Interp interp, // int objc, // Tcl_Obj[] objv //){ // sqlite3_thread_cleanup(); // return TCL.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( // object clientdata, // Tcl_Interp interp, // int objc, // Tcl_Obj[] objv //){ // sqlite3 db=null; // int i; // int v, *a; // Tcl_Obj pResult; // if( objc!=2 ){ // TCL.Tcl_AppendResult(interp, "wrong # args: should be \"", // TCL.Tcl_GetStringFromObj(objv[0], 0), " DB", 0); // return TCL.TCL_ERROR; // } // if( getDbPointer(interp, TCL.Tcl_GetString(objv[1]), out db) !=0) return TCL.TCL_ERROR; // pResult = TCL.Tcl_NewObj(); // for(i=0; i= 0; i-- ) {//sizeof(apVfs)/sizeof(apVfs[0])-1; i>=0; i--){ if ( apVfs[i] != null ) { sqlite3_vfs_register( apVfs[i], 1 ); Debug.Assert( apVfs[i] == sqlite3_vfs_find( null ) ); Debug.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 ); Debug.Assert( sqlite3_vfs_find( "__one" ) == null ); Debug.Assert( sqlite3_vfs_find( "__two" ) == null ); /* We should be left with the original default VFS back as the ** original */ Debug.Assert( sqlite3_vfs_find( null ) == pMain ); return TCL.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[] objv /* Command arguments */ //){ // sqlite3_vfs one; // one.zName = "__one"; // if( sqlite3_vfs_find(0) ) return TCL.TCL_ERROR; // sqlite3_vfs_register(&one, 0); // if( sqlite3_vfs_find(0) ) return TCL.TCL_ERROR; // sqlite3_vfs_register(&one, 1); // if( sqlite3_vfs_find(0) ) return TCL.TCL_ERROR; // return TCL.TCL_OK; //} /* ** Saved VFSes */ static sqlite3_vfs[] apVfs = new sqlite3_vfs[20]; static int nVfs = 0; /* ** tclcmd: vfs_unregister_all ** ** Unregister all VFSes. */ static int vfs_unregister_all( object clientdata, /* Pointer to sqlite3_enable_XXX function */ Tcl_Interp interp, /* The TCL interpreter that invoked this command */ int objc, /* Number of arguments */ Tcl_Obj[] objv /* Command arguments */ ) { int i; for ( i = 0; i < apVfs.Length; i++ ) { apVfs[i] = sqlite3_vfs_find( null ); if ( apVfs[i] == null ) break; sqlite3_vfs_unregister( apVfs[i] ); } nVfs = i; return TCL.TCL_OK; } /* ** tclcmd: vfs_reregister_all ** ** Restore all VFSes that were removed using vfs_unregister_all */ static int vfs_reregister_all( object clientdata, /* Pointer to sqlite3_enable_XXX function */ Tcl_Interp interp, /* The TCL interpreter that invoked this command */ int objc, /* Number of arguments */ Tcl_Obj[] objv /* Command arguments */ ) { int i; for ( i = 0; i < nVfs; i++ ) { sqlite3_vfs_register( apVfs[i], i == 0 ? 1 : 0 ); } return TCL.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( object clientdata, /* Pointer to sqlite3_enable_XXX function */ Tcl_Interp interp, /* The TCL interpreter that invoked this command */ int objc, /* Number of arguments */ Tcl_Obj[] objv /* Command arguments */ ) { sqlite3_int64 iArg = 0; sqlite3 db = null; int rc; if ( objc != 2 ) { TCL.Tcl_AppendResult( interp, "wrong # args: should be \"", TCL.Tcl_GetStringFromObj( objv[0], 0 ), " DB" ); return TCL.TCL_ERROR; } if ( getDbPointer( interp, TCL.Tcl_GetString( objv[1] ), out db ) != 0 ) return TCL.TCL_ERROR; rc = sqlite3_file_control( db, null, 0, ref iArg ); Debug.Assert( rc == SQLITE_NOTFOUND ); rc = sqlite3_file_control( db, "notadatabase", SQLITE_FCNTL_LOCKSTATE, ref iArg ); Debug.Assert( rc == SQLITE_ERROR ); rc = sqlite3_file_control( db, "main", -1, ref iArg ); Debug.Assert( rc == SQLITE_NOTFOUND ); rc = sqlite3_file_control( db, "temp", -1, ref iArg ); Debug.Assert( rc == SQLITE_NOTFOUND || rc == SQLITE_ERROR ); return TCL.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[] objv /* Command arguments */ ) { sqlite3_int64 iArg = 0; sqlite3 db = null; int rc; if ( objc != 2 ) { TCL.Tcl_AppendResult( interp, "wrong # args: should be \"", TCL.Tcl_GetStringFromObj( objv[0], 0 ), " DB" ); return TCL.TCL_ERROR; } if ( getDbPointer( interp, TCL.Tcl_GetString( objv[1] ), out db ) != 0 ) { return TCL.TCL_ERROR; } rc = sqlite3_file_control( db, null, SQLITE_LAST_ERRNO, ref iArg ); if ( rc != 0 ) { TCL.Tcl_SetObjResult( interp, TCL.Tcl_NewIntObj( rc ) ); return TCL.TCL_ERROR; } if ( iArg != 0 ) { TCL.Tcl_AppendResult( interp, "Unexpected non-zero errno: ", iArg.ToString(), "" ); //TCL.Tcl_GetStringFromObj(TCL.Tcl_NewIntObj(iArg), 0), " ", 0); return TCL.TCL_ERROR; } return TCL.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[] objv /* Command arguments */ ) { int nSize = 0; /* New chunk size */ string zDb; /* Db name ("main", "temp" etc.) */ sqlite3 db = null; /* Database handle */ int rc; /* file_control() return code */ if ( objc != 4 ) { TCL.Tcl_WrongNumArgs( interp, 1, objv, "DB DBNAME SIZE" ); return TCL.TCL_ERROR; } if ( getDbPointer( interp, TCL.Tcl_GetString( objv[1] ), out db ) != 0 || TCL.Tcl_GetIntFromObj( interp, objv[3], out nSize ) != 0 ) { return TCL.TCL_ERROR; } zDb = TCL.Tcl_GetString( objv[2] ); if ( zDb == "" ) zDb = null; i64 iSize = 0; rc = sqlite3_file_control( db, zDb, SQLITE_FCNTL_CHUNK_SIZE, ref iSize ); nSize = (int)iSize; if ( rc != 0 ) { TCL.Tcl_SetResult( interp, sqlite3TestErrorName( rc ), TCL.TCL_STATIC ); return TCL.TCL_ERROR; } return TCL.TCL_OK; } /* ** tclcmd: file_control_sizehint_test DB DBNAME SIZE ** ** This TCL command runs the sqlite3_file_control interface and ** verifies correct operation of the SQLITE_GET_LOCKPROXYFILE and ** SQLITE_SET_LOCKPROXYFILE verbs. */ 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[] objv /* Command arguments */ ) { sqlite3_int64 nSize = 0; /* Hinted size */ string zDb; /* Db name ("main", "temp" etc.) */ sqlite3 db = null; /* Database handle */ int rc; /* file_control() return code */ if ( objc != 4 ) { TCL.Tcl_WrongNumArgs( interp, 1, objv, "DB DBNAME SIZE" ); return TCL.TCL_ERROR; } if ( getDbPointer( interp, TCL.Tcl_GetString( objv[1] ), out db ) != 0 || TCL.Tcl_GetWideIntFromObj( interp, objv[3], out nSize ) ) { return TCL.TCL_ERROR; } zDb = TCL.Tcl_GetString( objv[2] ); if ( zDb[0] == '\0' ) zDb = null; rc = sqlite3_file_control( db, zDb, SQLITE_FCNTL_SIZE_HINT, ref nSize ); if ( rc != 0 ) { TCL.Tcl_SetResult( interp, sqlite3TestErrorName( rc ), TCL.TCL_STATIC ); return TCL.TCL_ERROR; } return TCL.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[] objv /* Command arguments */ ) { sqlite3 db = null; string zPwd; int nPwd = 0; if ( objc != 3 ) { TCL.Tcl_AppendResult( interp, "wrong # args: should be \"", TCL.Tcl_GetStringFromObj( objv[0], 0 ), " DB PWD" ); return TCL.TCL_ERROR; } if ( getDbPointer( interp, TCL.Tcl_GetString( objv[1] ), out db ) != 0 ) { return TCL.TCL_ERROR; } zPwd = TCL.Tcl_GetStringFromObj( objv[2], out nPwd ); //#if !(SQLITE_ENABLE_LOCKING_STYLE) && (__APPLE__) //{ // char *testPath; // int rc; // char proxyPath[400]; // if( sizeof(proxyPath)= aId.Length ) { TCL.Tcl_AppendResult( interp, "unknown limit type: ", zId, '\0' ); return TCL.TCL_ERROR; } if ( TCL.TCL_OK != TCL.Tcl_GetIntFromObj( interp, objv[3], out val ) ) return TCL.TCL_ERROR; rc = sqlite3_limit( db, id, val ); TCL.Tcl_SetObjResult( interp, TCL.Tcl_NewIntObj( rc ) ); return TCL.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( object clientdata, /* Pointer to sqlite3_enable_XXX function */ Tcl_Interp interp, /* The TCL interpreter that invoked this command */ int objc, /* Number of arguments */ Tcl_Obj[] objv /* Command arguments */ ) { int rc = sqlite3_test_control( 9999 ); Debug.Assert( rc == 0 ); rc = sqlite3_test_control( -1 ); Debug.Assert( rc == 0 ); sqlite3_test_control( SQLITE_TESTCTRL_PRNG_SAVE ); return TCL.TCL_OK; } /* ** tclcmd: restore_prng_state */ static int restore_prng_state( object clientdata, /* Pointer to sqlite3_enable_XXX function */ Tcl_Interp interp, /* The TCL interpreter that invoked this command */ int objc, /* Number of arguments */ Tcl_Obj[] objv /* Command arguments */ ) { sqlite3_test_control( SQLITE_TESTCTRL_PRNG_RESTORE ); return TCL.TCL_OK; } /* ** tclcmd: reset_prng_state */ static int reset_prng_state( object clientdata, /* Pointer to sqlite3_enable_XXX function */ Tcl_Interp interp, /* The TCL interpreter that invoked this command */ int objc, /* Number of arguments */ Tcl_Obj[] objv /* Command arguments */ ) { sqlite3_test_control( SQLITE_TESTCTRL_PRNG_RESET ); return TCL.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[] objv /* Command arguments */ ) { int nMin; int nMax; int nCurrent; int nRecyclable; Tcl_Obj pRet; sqlite3PcacheStats( out nCurrent, out nMax, out nMin, out nRecyclable ); pRet = TCL.Tcl_NewObj(); TCL.Tcl_ListObjAppendElement( interp, pRet, TCL.Tcl_NewStringObj( "current", -1 ) ); TCL.Tcl_ListObjAppendElement( interp, pRet, TCL.Tcl_NewIntObj( nCurrent ) ); TCL.Tcl_ListObjAppendElement( interp, pRet, TCL.Tcl_NewStringObj( "max", -1 ) ); TCL.Tcl_ListObjAppendElement( interp, pRet, TCL.Tcl_NewIntObj( nMax ) ); TCL.Tcl_ListObjAppendElement( interp, pRet, TCL.Tcl_NewStringObj( "min", -1 ) ); TCL.Tcl_ListObjAppendElement( interp, pRet, TCL.Tcl_NewIntObj( nMin ) ); TCL.Tcl_ListObjAppendElement( interp, pRet, TCL.Tcl_NewStringObj( "recyclable", -1 ) ); TCL.Tcl_ListObjAppendElement( interp, pRet, TCL.Tcl_NewIntObj( nRecyclable ) ); TCL.Tcl_SetObjResult( interp, pRet ); return TCL.TCL_OK; } public class _aObjCmd { public string zName; public Interp.dxObjCmdProc xProc; public object clientData; public _aObjCmd( string zName, Interp.dxObjCmdProc xProc ) { this.zName = zName; this.xProc = xProc; this.clientData = null; } public _aObjCmd( string zName, Interp.dxObjCmdProc xProc, object clientdata ) { this.zName = zName; this.xProc = xProc; this.clientData = clientdata.GetType().Name == "Int32" && (int)clientdata == 0 ? null : clientdata; } } #if SQLITE_ENABLE_UNLOCK_NOTIFY static void test_unlock_notify_cb(void **aArg, int nArg){ int ii; for(ii=0; ii 2 ) { TCL.Tcl_WrongNumArgs( interp, 1, objv, "SCRIPT" ); return TCL.TCL_ERROR; } if ( logcallback.pObj != null ) { TCL.Tcl_DecrRefCount( ref logcallback.pObj ); logcallback.pObj = null; logcallback.pInterp = null; sqlite3_config( SQLITE_CONFIG_LOG, 0, 0 ); } if ( objc > 1 ) { logcallback.pObj = objv[1]; TCL.Tcl_IncrRefCount( logcallback.pObj ); logcallback.pInterp = interp; sqlite3_config( SQLITE_CONFIG_LOG, (dxLogcallback)xLogcallback, 0 ); } return TCL.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[] objv //){ // TCL.Tcl_CmdInfo cmdInfo; // if( objc<2 ){ // TCL.Tcl_WrongNumArgs(interp, 1, objv, "COMMAND ..."); // return TCL.TCL_ERROR; // } // if( null==TCL.Tcl_GetCommandInfo(interp, TCL.Tcl_GetString(objv[1]), &cmdInfo) ){ // TCL.Tcl_AppendResult(interp, "command not found: ", // TCL.Tcl_GetString(objv[1]), (char)0); // return TCL.TCL_ERROR; // } // if( cmdInfo.objProc==0 ){ // TCL.Tcl_AppendResult(interp, "command has no objProc: ", // TCL.Tcl_GetString(objv[1]), (char)0); // return TCL.TCL_ERROR; // } // return cmdInfo.objProc(cmdInfo.objClientData, interp, objc-1, objv+1); //} /* ** Register commands with the TCL interpreter. */ #if !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(). */ static int printExplainQueryPlan( sqlite3_stmt pStmt ) { string zSql; /* Input SQL */ string zExplain; /* SQL with EXPLAIN QUERY PLAN prepended */ sqlite3_stmt pExplain = null; /* Compiled EXPLAIN QUERY PLAN command */ int rc; /* Return code from sqlite3_prepare_v2() */ zSql = sqlite3_sql( pStmt ); if ( zSql == null ) return SQLITE_ERROR; zExplain = sqlite3_mprintf( "EXPLAIN QUERY PLAN %s", zSql ); //if ( zExplain == null ) // return SQLITE_NOMEM; rc = sqlite3_prepare_v2( sqlite3_db_handle( pStmt ), zExplain, -1, ref 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 ); string zDetail = sqlite3_column_text( pExplain, 3 ); printf( "%d %d %d %s\n", iSelectid, iOrder, iFrom, zDetail ); } return sqlite3_finalize( pExplain ); } static int test_print_eqp( object clientData, Tcl_Interp interp, int objc, Tcl_Obj[] objv ) { int rc; sqlite3_stmt pStmt = null; if ( objc != 2 ) { TCL.Tcl_WrongNumArgs( interp, 1, objv, "STMT" ); return TCL.TCL_ERROR; } if ( getStmtPointer( interp, TCL.Tcl_GetString( objv[1] ), out pStmt ) != 0 ) return TCL.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.Tcl_SetResult( interp, t1ErrorName( rc ), 0 ); return TCL.TCL_OK; } #endif //* SQLITE_OMIT_EXPLAIN */ class Verb { public string zName; public int i; public Verb( string zName, int i ) { this.zName = zName; this.i = i; } } /* ** sqlite3_test_control VERB ARGS... */ static int test_test_control( object clientData, Tcl_Interp interp, int objc, Tcl_Obj[] objv ) { Verb[] aVerb = new Verb[] { new Verb( "SQLITE_TESTCTRL_LOCALTIME_FAULT", SQLITE_TESTCTRL_LOCALTIME_FAULT ), }; int iVerb; int iFlag; int rc; if ( objc < 2 ) { TCL.Tcl_WrongNumArgs( interp, 1, objv, "VERB ARGS..." ); return TCL.TCL_ERROR; } //rc = TCL.Tcl_GetIndexFromObjStruct( // interp, objv[1], aVerb, sizeof(aVerb[0]), "VERB", 0, &iVerb //); for ( iVerb = 0; iVerb < aVerb.Length && ( aVerb[iVerb].zName != objv[1].ToString() ); iVerb++ ) { } if ( iVerb >= aVerb.Length ) return TCL.TCL_ERROR; iFlag = aVerb[iVerb].i; switch ( iFlag ) { case SQLITE_TESTCTRL_LOCALTIME_FAULT: { bool val = false; if ( objc != 3 ) { TCL.Tcl_WrongNumArgs( interp, 2, objv, "ONOFF" ); return TCL.TCL_ERROR; } if ( TCL.Tcl_GetBooleanFromObj( interp, objv[2], out val ) ) return TCL.TCL_ERROR; sqlite3_test_control( SQLITE_TESTCTRL_LOCALTIME_FAULT, val ); break; } } TCL.Tcl_ResetResult( interp ); return TCL.TCL_OK; } /* ** 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. */ public class _aOpt { public string zOptName; public int mask; public _aOpt( string zOptName, int mask ) { this.zOptName = zOptName; this.mask = mask; } } static int optimization_control( object clientData, Tcl_Interp interp, int objc, Tcl_Obj[] objv ) { int i; sqlite3 db = null; string zOpt; bool onoff = false; int mask = 0; _aOpt[] aOpt = { new _aOpt( "all", SQLITE_OptMask ), new _aOpt( "query-flattener", SQLITE_QueryFlattener ), new _aOpt( "column-cache", SQLITE_ColumnCache ), new _aOpt( "index-sort", SQLITE_IndexSort ), new _aOpt( "index-search", SQLITE_IndexSearch ), new _aOpt( "index-cover", SQLITE_IndexCover ), new _aOpt( "groupby-order", SQLITE_GroupByOrder ), new _aOpt( "factor-constants", SQLITE_FactorOutConst ), new _aOpt( "real-as-int", SQLITE_IdxRealAsInt ), }; if ( objc != 4 ) { TCL.Tcl_WrongNumArgs( interp, 1, objv, "DB OPT BOOLEAN" ); return TCL.TCL_ERROR; } if ( getDbPointer( interp, TCL.Tcl_GetString( objv[1] ), out db ) != 0 ) return TCL.TCL_ERROR; if ( TCL.Tcl_GetBooleanFromObj( interp, objv[3], out onoff ) ) return TCL.TCL_ERROR; zOpt = TCL.Tcl_GetString( objv[2] ); for ( i = 0; i < aOpt.Length; i++ )//sizeof(aOpt)/sizeof(aOpt[0]); i++) { if ( zOpt == aOpt[i].zOptName ) { mask = aOpt[i].mask; break; } } if ( onoff ) mask = ~mask; if ( i >= aOpt.Length )//sizeof(aOpt)/sizeof(aOpt[0]) ) { TCL.Tcl_AppendResult( interp, "unknown optimization - should be one of:", null ); for ( i = 0; i < aOpt.Length; i++ )//sizeof(aOpt)/sizeof(aOpt[0]); i++) { TCL.Tcl_AppendResult( interp, " ", aOpt[i].zOptName ); } return TCL.TCL_ERROR; } sqlite3_test_control( SQLITE_TESTCTRL_OPTIMIZATIONS, db, mask ); return TCL.TCL_OK; } static Var.SQLITE3_GETSET bitmask_size = new Var.SQLITE3_GETSET( "bitmask_size" ); #if SQLITE_OS_UNIX && (__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE extern int sqlite3_hostid_num; #endif static Var.SQLITE3_GETSET sqlite_static_bind_nbyte = new Var.SQLITE3_GETSET( "static_bind_nbyte" ); static Var.SQLITE3_GETSET sqlite_static_bind_value = new Var.SQLITE3_GETSET( "static_bind_value" ); public static int Sqlitetest1_Init( Tcl_Interp interp ) { // extern int sqlite3_search_count; // extern int sqlite3_found_count; // extern int sqlite3_interrupt_count; // extern int sqlite3_sort_count; // extern int sqlite3_current_time; // extern int sqlite3_max_blobsize; // extern int sqlite3BtreeSharedCacheReport(void*, // Tcl_Interp *,int,Tcl_Obj*CONST); // static struct { // string zName; // TCL.Tcl_CmdProc *xProc; _aCmd[] aCmd = new _aCmd[] { new _aCmd( "db_enter", db_enter ), new _aCmd( "db_leave", db_leave ), new _aCmd( "sqlite3_mprintf_int", sqlite3_mprintf_int ), new _aCmd( "sqlite3_mprintf_int64", sqlite3_mprintf_int64 ), new _aCmd( "sqlite3_mprintf_long", sqlite3_mprintf_long ), new _aCmd( "sqlite3_mprintf_str", sqlite3_mprintf_str ), new _aCmd( "sqlite3_snprintf_str", sqlite3_snprintf_str ), new _aCmd( "sqlite3_mprintf_stronly", sqlite3_mprintf_stronly), new _aCmd( "sqlite3_mprintf_double", sqlite3_mprintf_double ), new _aCmd( "sqlite3_mprintf_scaled", sqlite3_mprintf_scaled ), new _aCmd( "sqlite3_mprintf_hexdouble", sqlite3_mprintf_hexdouble), new _aCmd( "sqlite3_mprintf_z_test", test_mprintf_z ), new _aCmd( "sqlite3_mprintf_n_test", test_mprintf_n ), new _aCmd( "sqlite3_snprintf_int", test_snprintf_int ), // new _aCmd( "sqlite3_last_insert_rowid", test_last_rowid ), new _aCmd( "sqlite3_exec_printf", test_exec_printf ), new _aCmd( "sqlite3_exec_hex", test_exec_hex ), new _aCmd( "sqlite3_exec", test_exec ), new _aCmd( "sqlite3_exec_nr", test_exec_nr ), #if !SQLITE_OMIT_GET_TABLE new _aCmd( "sqlite3_get_table_printf", test_get_table_printf ), #endif new _aCmd( "sqlite3_close", sqlite_test_close ), new _aCmd( "sqlite3_create_function", test_create_function ), new _aCmd( "sqlite3_create_aggregate", test_create_aggregate ), new _aCmd( "sqlite_register_test_function", test_register_func ), // new _aCmd( "sqlite_abort", sqlite_abort ), new _aCmd( "sqlite_bind", test_bind ), new _aCmd( "breakpoint", test_breakpoint ), new _aCmd( "sqlite3_key", test_key ), new _aCmd( "sqlite3_rekey", test_rekey ), new _aCmd( "sqlite_set_magic", sqlite_set_magic ), new _aCmd( "sqlite3_interrupt", test_interrupt ), new _aCmd( "sqlite_delete_function", delete_function ), new _aCmd( "sqlite_delete_collation", delete_collation ), new _aCmd( "sqlite3_get_autocommit", get_autocommit ), // new _aCmd( "sqlite3_stack_used", test_stack_used ), new _aCmd( "sqlite3_busy_timeout", test_busy_timeout ), // new _aCmd( "printf", test_printf ), // new _aCmd( "sqlite3IoTrace", test_io_trace ), }; // static struct { // string zName; // Tcl_ObjCmdProc *xProc; // void *object; _aObjCmd[] aObjCmd = new _aObjCmd[]{ new _aObjCmd( "sqlite3_connection_pointer", get_sqlite_pointer, 0 ), new _aObjCmd( "sqlite3_bind_int", test_bind_int, 0 ), new _aObjCmd( "sqlite3_bind_zeroblob", test_bind_zeroblob, 0 ), new _aObjCmd( "sqlite3_bind_int64", test_bind_int64, 0 ), new _aObjCmd( "sqlite3_bind_double", test_bind_double, 0 ), new _aObjCmd( "sqlite3_bind_null", test_bind_null ,0 ), new _aObjCmd( "sqlite3_bind_text", test_bind_text ,0 ), new _aObjCmd( "sqlite3_bind_text16", test_bind_text16 ,0 ), new _aObjCmd( "sqlite3_bind_blob", test_bind_blob ,0 ), new _aObjCmd( "sqlite3_bind_parameter_count", test_bind_parameter_count, 0), new _aObjCmd( "sqlite3_bind_parameter_name", test_bind_parameter_name, 0), new _aObjCmd( "sqlite3_bind_parameter_index", test_bind_parameter_index, 0), new _aObjCmd( "sqlite3_clear_bindings", test_clear_bindings, 0), new _aObjCmd( "sqlite3_sleep", test_sleep, 0), new _aObjCmd( "sqlite3_errcode", test_errcode ,0 ), new _aObjCmd( "sqlite3_extended_errcode", test_ex_errcode ,0 ), new _aObjCmd( "sqlite3_errmsg", test_errmsg ,0 ), // new _aObjCmd( "sqlite3_errmsg16", test_errmsg16 ,0 ), new _aObjCmd( "sqlite3_open", test_open ,0 ), // new _aObjCmd( "sqlite3_open16", test_open16 ,0 ), new _aObjCmd( "sqlite3_open_v2", test_open_v2 ,0 ), // new _aObjCmd( "sqlite3_complete16", test_complete16 ,0 ), new _aObjCmd( "sqlite3_prepare", test_prepare ,0 ), new _aObjCmd( "sqlite3_prepare16", test_prepare16 ,0 ), new _aObjCmd( "sqlite3_prepare_v2", test_prepare_v2 ,0 ), new _aObjCmd( "sqlite3_prepare_tkt3134", test_prepare_tkt3134, 0), // new _aObjCmd( "sqlite3_prepare16_v2", test_prepare16_v2 ,0 ), new _aObjCmd( "sqlite3_finalize", test_finalize ,0 ), new _aObjCmd( "sqlite3_reset", test_reset ,0 ), new _aObjCmd( "sqlite3_expired", test_expired ,0 ), new _aObjCmd( "sqlite3_transfer_bindings", test_transfer_bind ,0 ), new _aObjCmd( "sqlite3_changes", test_changes ,0 ), new _aObjCmd( "sqlite3_step", test_step ,0 ), // { "sqlite3_sql", test_sql ,0 }, new _aObjCmd( "sqlite3_next_stmt", test_next_stmt ,0 ), new _aObjCmd( "sqlite3_stmt_readonly", test_stmt_readonly ,0 ), new _aObjCmd( "uses_stmt_journal", uses_stmt_journal ,0 ), new _aObjCmd( "sqlite3_release_memory", test_release_memory, 0), new _aObjCmd( "sqlite3_soft_heap_limit", test_soft_heap_limit, 0), // new _aObjCmd( "sqlite3_thread_cleanup", test_thread_cleanup, 0), // new _aObjCmd( "sqlite3_pager_refcounts", test_pager_refcounts, 0), // new _aObjCmd( "sqlite3_load_extension", test_load_extension, 0), // new _aObjCmd( "sqlite3_enable_load_extension", test_enable_load, 0), new _aObjCmd( "sqlite3_extended_result_codes", test_extended_result_codes, 0), new _aObjCmd( "sqlite3_limit", test_limit, 0), new _aObjCmd( "save_prng_state", save_prng_state, 0 ), new _aObjCmd( "restore_prng_state", restore_prng_state, 0 ), new _aObjCmd( "reset_prng_state", reset_prng_state, 0 ), new _aObjCmd( "optimization_control", optimization_control,0), // { "tcl_objproc", runAsObjProc, 0 }, // /* sqlite3_column_*() API */ new _aObjCmd( "sqlite3_column_count", test_column_count ,0 ), new _aObjCmd( "sqlite3_data_count", test_data_count ,0 ), new _aObjCmd( "sqlite3_column_type", test_column_type ,0 ), new _aObjCmd( "sqlite3_column_blob", test_column_blob ,0 ), new _aObjCmd( "sqlite3_column_double", test_column_double ,0 ), new _aObjCmd( "sqlite3_column_int64", test_column_int64 ,0 ), new _aObjCmd( "sqlite3_column_text", test_stmt_utf8, (dxColumn)sqlite3_column_text ), new _aObjCmd( "sqlite3_column_name", test_stmt_utf8, (dxColumn)sqlite3_column_name ), new _aObjCmd( "sqlite3_column_int", test_stmt_int, (dxColumn_I)sqlite3_column_int ), new _aObjCmd( "sqlite3_column_bytes", test_stmt_int, (dxColumn_I)sqlite3_column_bytes ), #if !SQLITE_OMIT_DECLTYPE new _aObjCmd( "sqlite3_column_decltype", test_stmt_utf8, (dxColumn) sqlite3_column_decltype ), #endif #if SQLITE_ENABLE_COLUMN_METADATA new _aObjCmd( "sqlite3_column_database_name", test_stmt_utf8, (dxColumn)sqlite3_column_database_name), new _aObjCmd( "sqlite3_column_table_name", test_stmt_utf8, (dxColumn)sqlite3_column_table_name), new _aObjCmd( "sqlite3_column_origin_name", test_stmt_utf8, (dxColumn)sqlite3_column_origin_name), #endif #if !SQLITE_OMIT_UTF16 // { "sqlite3_column_bytes16", test_stmt_int, sqlite3_column_bytes16 ), // { "sqlite3_column_text16", test_stmt_utf16, sqlite3_column_text16 ), // { "sqlite3_column_decltype16", test_stmt_utf16, sqlite3_column_decltype16), // { "sqlite3_column_name16", test_stmt_utf16, sqlite3_column_name16 ), // { "add_alignment_test_collations", add_alignment_test_collations, 0 ), #if SQLITE_ENABLE_COLUMN_METADATA //{"sqlite3_column_database_name16", // test_stmt_utf16, sqlite3_column_database_name16), //{"sqlite3_column_table_name16", test_stmt_utf16, sqlite3_column_table_name16), //{"sqlite3_column_origin_name16", test_stmt_utf16, sqlite3_column_origin_name16), #endif #endif new _aObjCmd( "sqlite3_create_collation_v2", test_create_collation_v2, 0 ), new _aObjCmd( "sqlite3_global_recover", test_global_recover, 0 ), new _aObjCmd( "working_64bit_int", working_64bit_int, 0 ), new _aObjCmd( "vfs_unlink_test", vfs_unlink_test, 0 ), //{ "vfs_initfail_test", vfs_initfail_test, 0 }, new _aObjCmd( "vfs_unregister_all", vfs_unregister_all, 0 ), new _aObjCmd("vfs_reregister_all", vfs_reregister_all, 0 ), new _aObjCmd( "file_control_test", file_control_test, 0 ), new _aObjCmd("file_control_lasterrno_test", file_control_lasterrno_test, 0 ), new _aObjCmd("file_control_lockproxy_test", file_control_lockproxy_test, 0 ), new _aObjCmd("file_control_chunksize_test", file_control_chunksize_test, 0 ), new _aObjCmd("file_control_sizehint_test", file_control_sizehint_test, 0), //new _aObjCmd( "sqlite3_vfs_list", vfs_list, 0 ), new _aObjCmd( "sqlite3_create_function_v2", test_create_function_v2, 0 ), // /* Functions from os.h */ #if !SQLITE_OMIT_UTF16 // { "add_test_collate", test_collate, 0 ), // { "add_test_collate_needed", test_collate_needed, 0 ), // { "add_test_function", test_function, 0 ), #endif new _aObjCmd( "sqlite3_test_errstr", test_errstr, 0 ), new _aObjCmd( "tcl_variable_type", tcl_variable_type, 0 ), #if !SQLITE_OMIT_SHARED_CACHE new _aObjCmd( "sqlite3_enable_shared_cache", test_enable_shared, 0 ), //{ "sqlite3_shared_cache_report", sqlite3BtreeSharedCacheReport, 0), #endif new _aObjCmd( "sqlite3_libversion_number", test_libversion_number, 0 ), #if SQLITE_ENABLE_COLUMN_METADATA new _aObjCmd( "sqlite3_table_column_metadata", test_table_column_metadata, 0 ), #endif #if !SQLITE_OMIT_INCRBLOB // new _aObjCmd( "sqlite3_blob_read", test_blob_read, 0 ), // new _aObjCmd( "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 new _aObjCmd( "pcache_stats", test_pcache_stats, 0 ), #if SQLITE_ENABLE_UNLOCK_NOTIFY { "sqlite3_unlock_notify", test_unlock_notify, 0 }, #endif new _aObjCmd( "sqlite3_wal_checkpoint", test_wal_checkpoint, 0 ), new _aObjCmd( "sqlite3_wal_checkpoint_v2", test_wal_checkpoint_v2, 0 ), new _aObjCmd( "test_sqlite3_log", test_sqlite3_log, 0 ), #if !SQLITE_OMIT_EXPLAIN new _aObjCmd( "print_explain_query_plan", test_print_eqp, 0 ), #endif new _aObjCmd( "sqlite3_test_control", test_test_control ), }; bitmask_size.iValue = BMS; 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 #if SQLITE_DEBUG // extern int sqlite3WhereTrace; // extern int sqlite3OSTrace; // extern int sqlite3VdbeAddopTrace; // extern int sqlite3WalTrace; #endif #if SQLITE_TEST // extern char sqlite3_query_plan[]; // static char *query_plan = sqlite3_query_plan; #if SQLITE_ENABLE_FTS3 extern int sqlite3_fts3_enable_parentheses; #endif #endif for ( i = 0; i < aCmd.Length; i++ ) {//sizeof(aCmd)/sizeof(aCmd[0]); i++){ TCL.Tcl_CreateCommand( interp, aCmd[i].zName, aCmd[i].xProc, null, null ); } for ( i = 0; i < aObjCmd.Length; i++ ) {// i