Index: ext/repair/sqlite3_checker.c.in ================================================================== --- ext/repair/sqlite3_checker.c.in +++ ext/repair/sqlite3_checker.c.in @@ -16,14 +16,66 @@ INCLUDE sqlite3.c INCLUDE $ROOT/src/tclsqlite.c INCLUDE $ROOT/ext/misc/btreeinfo.c INCLUDE $ROOT/ext/repair/checkindex.c INCLUDE $ROOT/ext/repair/checkfreelist.c + +/* +** Decode a pointer to an sqlite3 object. +*/ +int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb){ + struct SqliteDb *p; + Tcl_CmdInfo cmdInfo; + if( Tcl_GetCommandInfo(interp, zA, &cmdInfo) ){ + p = (struct SqliteDb*)cmdInfo.objClientData; + *ppDb = p->db; + return TCL_OK; + }else{ + *ppDb = 0; + return TCL_ERROR; + } + return TCL_OK; +} + +/* +** sqlite3_imposter db main rootpage {CREATE TABLE...} ;# setup an imposter +** sqlite3_imposter db main ;# rm all imposters +*/ +static int sqlite3_imposter( + void *clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + sqlite3 *db; + const char *zSchema; + int iRoot; + const char *zSql; + + if( objc!=3 && objc!=5 ){ + Tcl_WrongNumArgs(interp, 1, objv, "DB SCHEMA [ROOTPAGE SQL]"); + return TCL_ERROR; + } + if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; + zSchema = Tcl_GetString(objv[2]); + if( objc==3 ){ + sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, db, zSchema, 0, 1); + }else{ + if( Tcl_GetIntFromObj(interp, objv[3], &iRoot) ) return TCL_ERROR; + zSql = Tcl_GetString(objv[4]); + sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, db, zSchema, 1, iRoot); + sqlite3_exec(db, zSql, 0, 0, 0); + sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, db, zSchema, 0, 0); + } + return TCL_OK; +} #include const char *sqlite3_checker_init_proc(Tcl_Interp *interp){ + Tcl_CreateObjCommand(interp, "sqlite3_imposter", + (Tcl_ObjCmdProc*)sqlite3_imposter, 0, 0); sqlite3_auto_extension((void(*)(void))sqlite3_btreeinfo_init); sqlite3_auto_extension((void(*)(void))sqlite3_checkindex_init); sqlite3_auto_extension((void(*)(void))sqlite3_checkfreelist_init); return BEGIN_STRING Index: ext/repair/test/checkindex01.test ================================================================== --- ext/repair/test/checkindex01.test +++ ext/repair/test/checkindex01.test @@ -69,20 +69,16 @@ {} 'five',5 } do_test 1.5 { set tblroot [db one { SELECT rootpage FROM sqlite_master WHERE name='t1' }] - sqlite3_test_control SQLITE_TESTCTRL_IMPOSTER db main 1 $tblroot - db eval {CREATE TABLE xt1(a, b)} - sqlite3_test_control SQLITE_TESTCTRL_IMPOSTER db main 0 0 - - execsql { + sqlite3_imposter db main $tblroot {CREATE TABLE xt1(a,b)} + db eval { UPDATE xt1 SET a='six' WHERE rowid=3; DELETE FROM xt1 WHERE rowid = 5; } - - sqlite3_test_control SQLITE_TESTCTRL_IMPOSTER db main 0 1 + sqlite3_imposter db main } {} do_index_check_test 1.6 i1 { {row missing} 'five',5 {} 'four',4 @@ -209,20 +205,18 @@ {} 'AAB','EEE',4 } do_test 4.2 { set tblroot [db one { SELECT rootpage FROM sqlite_master WHERE name='t4' }] - sqlite3_test_control SQLITE_TESTCTRL_IMPOSTER db main 1 $tblroot - db eval {CREATE TABLE xt4(a INTEGER PRIMARY KEY, c1 TEXT, c2 TEXT)} - sqlite3_test_control SQLITE_TESTCTRL_IMPOSTER db main 0 0 + sqlite3_imposter db main $tblroot \ + {CREATE TABLE xt4(a INTEGER PRIMARY KEY, c1 TEXT, c2 TEXT)} - execsql { + db eval { UPDATE xt4 SET c1='hello' WHERE rowid=2; DELETE FROM xt4 WHERE rowid = 3; } - - sqlite3_test_control SQLITE_TESTCTRL_IMPOSTER db main 0 1 + sqlite3_imposter db main } {} do_index_check_test 4.3 t4cc { {} 'aaa','bbb',1 {row data mismatch} 'AAA','CCC',2 @@ -261,18 +255,17 @@ {} {'{"x":5, "y":5}',5} } do_test 5.2 { set tblroot [db one { SELECT rootpage FROM sqlite_master WHERE name='t5' }] - sqlite3_test_control SQLITE_TESTCTRL_IMPOSTER db main 1 $tblroot - db eval {CREATE TABLE xt5(a INTEGER PRIMARY KEY, c1 TEXT);} - sqlite3_test_control SQLITE_TESTCTRL_IMPOSTER db main 0 0 - execsql { + sqlite3_imposter db main $tblroot \ + {CREATE TABLE xt5(a INTEGER PRIMARY KEY, c1 TEXT);} + db eval { UPDATE xt5 SET c1='{"x":22, "y":11}' WHERE rowid=1; DELETE FROM xt5 WHERE rowid = 4; } - sqlite3_test_control SQLITE_TESTCTRL_IMPOSTER db main 0 1 + sqlite3_imposter db main } {} do_index_check_test 5.3.1 t5x { {row missing} NULL,4 {row data mismatch} 1,1