/* ** Usage: sqlite_compile DB SQL ?TAILVAR? ** ** Attempt to compile an SQL statement. Return a pointer to the virtual ** machine used to execute that statement. Unprocessed SQL is written ** into TAILVAR. */ static int test_compile( void *NotUsed, Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ int argc, /* Number of arguments */ char **argv /* Text of each argument */ ){ sqlite *db; sqlite_vm *vm; int rc; char *zErr = 0; const char *zTail; char zBuf[50]; if( argc!=3 && argc!=4 ){ Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " DB SQL TAILVAR", 0); return TCL_ERROR; } if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; rc = sqlite_compile(db, argv[2], argc==4 ? &zTail : 0, &vm, &zErr); if( argc==4 ) Tcl_SetVar(interp, argv[3], zTail, 0); if( rc ){ assert( vm==0 ); sprintf(zBuf, "(%d) ", rc); Tcl_AppendResult(interp, zBuf, zErr, 0); sqlite_freemem(zErr); return TCL_ERROR; } if( vm ){ if( makePointerStr(interp, zBuf, vm) ) return TCL_ERROR; Tcl_AppendResult(interp, zBuf, 0); } return TCL_OK; }
/* ** Usage: sqlite_exec_printf DB FORMAT STRING ** ** Invoke the sqlite_exec_printf() interface using the open database ** DB. The SQL is the string FORMAT. The format string should contain ** one %s or %q. STRING is the value inserted into %s or %q. */ static int test_exec_printf( void *NotUsed, Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ int argc, /* Number of arguments */ char **argv /* Text of each argument */ ){ sqlite *db; Tcl_DString str; int rc; char *zErr = 0; char zBuf[30]; if( argc!=4 ){ Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " DB FORMAT STRING", 0); return TCL_ERROR; } if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; Tcl_DStringInit(&str); rc = sqlite_exec_printf(db, argv[2], exec_printf_cb, &str, &zErr, argv[3]); sprintf(zBuf, "%d", rc); Tcl_AppendElement(interp, zBuf); Tcl_AppendElement(interp, rc==SQLITE_OK ? Tcl_DStringValue(&str) : zErr); Tcl_DStringFree(&str); if( zErr ) free(zErr); return TCL_OK; }
/* ** sqlite3_backup CMDNAME DESTHANDLE DESTNAME SRCHANDLE SRCNAME ** */ static int backupTestInit( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const*objv ){ sqlite3_backup *pBackup; sqlite3 *pDestDb; sqlite3 *pSrcDb; const char *zDestName; const char *zSrcName; const char *zCmd; if( objc!=6 ){ Tcl_WrongNumArgs( interp, 1, objv, "CMDNAME DESTHANDLE DESTNAME SRCHANDLE SRCNAME" ); return TCL_ERROR; } zCmd = Tcl_GetString(objv[1]); getDbPointer(interp, Tcl_GetString(objv[2]), &pDestDb); zDestName = Tcl_GetString(objv[3]); getDbPointer(interp, Tcl_GetString(objv[4]), &pSrcDb); zSrcName = Tcl_GetString(objv[5]); pBackup = sqlite3_backup_init(pDestDb, zDestName, pSrcDb, zSrcName); if( !pBackup ){ Tcl_AppendResult(interp, "sqlite3_backup_init() failed", 0); return TCL_ERROR; } Tcl_CreateObjCommand(interp, zCmd, backupTestCmd, pBackup, backupTestFinish); Tcl_SetObjResult(interp, objv[1]); return TCL_OK; }
/* ** Usage: sqlite_close DB ** ** Closes the database opened by sqlite_open. */ static int sqlite_test_close( void *NotUsed, Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ int argc, /* Number of arguments */ char **argv /* Text of each argument */ ){ sqlite *db; if( argc!=2 ){ Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " FILENAME\"", 0); return TCL_ERROR; } if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; sqlite_close(db); return TCL_OK; }
/* ** Usage: sqlite_test_create_function DB ** ** Call the sqlite_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 sqlite_exec(). Invoking sqlite_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 ** sqlite_create_function function while a query is in progress in order ** to test the SQLITE_MISUSE detection logic. */ static int test_create_function( void *NotUsed, Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ int argc, /* Number of arguments */ char **argv /* Text of each argument */ ){ sqlite *db; extern void Md5_Register(sqlite*); if( argc!=2 ){ Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " FILENAME\"", 0); return TCL_ERROR; } if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; sqlite_create_function(db, "x_coalesce", -1, ifnullFunc, 0); sqlite_create_function(db, "x_sqlite_exec", 1, sqliteExecFunc, db); return TCL_OK; }
/* ** Usage: sqlite_last_insert_rowid DB ** ** Returns the integer ROWID of the most recent insert. */ static int test_last_rowid( void *NotUsed, Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ int argc, /* Number of arguments */ char **argv /* Text of each argument */ ){ sqlite *db; char zBuf[30]; if( argc!=2 ){ Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " DB\"", 0); return TCL_ERROR; } if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; sprintf(zBuf, "%d", sqlite_last_insert_rowid(db)); Tcl_AppendResult(interp, zBuf, 0); return SQLITE_OK; }
/* ** Invoke an SQL statement but ignore all the data in the result. Instead, ** return a list that consists of the datatypes of the various columns. ** ** This only works if "PRAGMA show_datatypes=on" has been executed against ** the database connection. */ static int sqlite_datatypes( void *NotUsed, Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ int argc, /* Number of arguments */ char **argv /* Text of each argument */ ){ sqlite *db; int rc; if( argc!=3 ){ Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " DB SQL", 0); return TCL_ERROR; } if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; rc = sqlite_exec(db, argv[2], rememberDataTypes, interp, 0); if( rc!=0 && rc!=SQLITE_ABORT ){ Tcl_AppendResult(interp, sqlite_error_string(rc), 0); return TCL_ERROR; } return TCL_OK; }
/* ** Usage: sqlite_register_test_function DB NAME ** ** Register the test SQL function on the database DB under the name NAME. */ static int test_register_func( void *NotUsed, Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ int argc, /* Number of arguments */ char **argv /* Text of each argument */ ){ sqlite *db; int rc; if( argc!=3 ){ Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " DB FUNCTION-NAME", 0); return TCL_ERROR; } if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; rc = sqlite_create_function(db, argv[2], -1, testFunc, 0); if( rc!=0 ){ Tcl_AppendResult(interp, sqlite_error_string(rc), 0); return TCL_ERROR; } return TCL_OK; }
/* ** Usage: sqlite_get_table_printf DB FORMAT STRING ** ** Invoke the sqlite_get_table_printf() interface using the open database ** DB. The SQL is the string FORMAT. The format string should contain ** one %s or %q. STRING is the value inserted into %s or %q. */ static int test_get_table_printf( void *NotUsed, Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ int argc, /* Number of arguments */ char **argv /* Text of each argument */ ){ sqlite *db; Tcl_DString str; int rc; char *zErr = 0; int nRow, nCol; char **aResult; int i; char zBuf[30]; if( argc!=4 ){ Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " DB FORMAT STRING", 0); return TCL_ERROR; } if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; Tcl_DStringInit(&str); rc = sqlite_get_table_printf(db, argv[2], &aResult, &nRow, &nCol, &zErr, argv[3]); sprintf(zBuf, "%d", rc); Tcl_AppendElement(interp, zBuf); if( rc==SQLITE_OK ){ sprintf(zBuf, "%d", nRow); Tcl_AppendElement(interp, zBuf); sprintf(zBuf, "%d", nCol); Tcl_AppendElement(interp, zBuf); for(i=0; i<(nRow+1)*nCol; i++){ Tcl_AppendElement(interp, aResult[i] ? aResult[i] : "NULL"); } }else{ Tcl_AppendElement(interp, zErr); } sqlite_free_table(aResult); if( zErr ) free(zErr); return TCL_OK; }