4 ** The author disclaims copyright to this source code. In place of
5 ** a legal notice, here is a blessing:
7 ** May you do good and not evil.
8 ** May you find forgiveness for yourself and forgive others.
9 ** May you share freely, never taking more than you give.
11 *************************************************************************
15 #include "sqlite3recover.h"
16 #include "sqliteInt.h"
21 #ifndef SQLITE_OMIT_VIRTUALTABLE
23 typedef struct TestRecover TestRecover
;
30 static int xSqlCallback(void *pSqlArg
, const char *zSql
){
31 TestRecover
*p
= (TestRecover
*)pSqlArg
;
35 pEval
= Tcl_DuplicateObj(p
->pScript
);
36 Tcl_IncrRefCount(pEval
);
38 res
= Tcl_ListObjAppendElement(p
->interp
, pEval
, Tcl_NewStringObj(zSql
, -1));
40 res
= Tcl_EvalObjEx(p
->interp
, pEval
, 0);
43 Tcl_DecrRefCount(pEval
);
45 Tcl_BackgroundError(p
->interp
);
48 Tcl_Obj
*pObj
= Tcl_GetObjResult(p
->interp
);
49 if( Tcl_GetCharLength(pObj
)==0 ){
51 }else if( Tcl_GetIntFromObj(p
->interp
, pObj
, &res
) ){
52 Tcl_BackgroundError(p
->interp
);
59 static int getDbPointer(Tcl_Interp
*interp
, Tcl_Obj
*pObj
, sqlite3
**pDb
){
61 if( 0==Tcl_GetCommandInfo(interp
, Tcl_GetString(pObj
), &info
) ){
62 Tcl_AppendResult(interp
, "no such handle: ", Tcl_GetString(pObj
), 0);
65 *pDb
= *(sqlite3
**)info
.objClientData
;
70 ** Implementation of the command created by [sqlite3_recover_init]:
78 static int testRecoverCmd(
84 static struct RecoverSub
{
89 { "config", 2, "ARG" }, /* 0 */
90 { "run", 0, "" }, /* 1 */
91 { "errmsg", 0, "" }, /* 2 */
92 { "errcode", 0, "" }, /* 3 */
93 { "finish", 0, "" }, /* 4 */
94 { "step", 0, "" }, /* 5 */
99 TestRecover
*pTest
= (TestRecover
*)clientData
;
102 Tcl_WrongNumArgs(interp
, 1, objv
, "SUBCOMMAND ...");
105 rc
= Tcl_GetIndexFromObjStruct(interp
,
106 objv
[1], aSub
, sizeof(aSub
[0]), "sub-command", 0, &iSub
108 if( rc
!=TCL_OK
) return rc
;
109 if( (objc
-2)!=aSub
[iSub
].nArg
){
110 Tcl_WrongNumArgs(interp
, 2, objv
, aSub
[iSub
].zMsg
);
115 case 0: assert( sqlite3_stricmp("config", aSub
[iSub
].zSub
)==0 ); {
116 const char *aOp
[] = {
118 "lostandfound", /* 1 */
119 "freelistcorrupt", /* 2 */
121 "slowindexes", /* 4 */
127 if( Tcl_GetIndexFromObj(interp
, objv
[2], aOp
, "option", 0, &iOp
) ){
132 res
= sqlite3_recover_config(pTest
->p
,
133 789, (void*)Tcl_GetString(objv
[3]) /* MAGIC NUMBER! */
137 const char *zStr
= Tcl_GetString(objv
[3]);
138 res
= sqlite3_recover_config(pTest
->p
,
139 SQLITE_RECOVER_LOST_AND_FOUND
, (void*)(zStr
[0] ? zStr
: 0)
145 if( Tcl_GetBooleanFromObj(interp
, objv
[3], &iVal
) ) return TCL_ERROR
;
146 res
= sqlite3_recover_config(pTest
->p
,
147 SQLITE_RECOVER_FREELIST_CORRUPT
, (void*)&iVal
153 if( Tcl_GetBooleanFromObj(interp
, objv
[3], &iVal
) ) return TCL_ERROR
;
154 res
= sqlite3_recover_config(pTest
->p
,
155 SQLITE_RECOVER_ROWIDS
, (void*)&iVal
161 if( Tcl_GetBooleanFromObj(interp
, objv
[3], &iVal
) ) return TCL_ERROR
;
162 res
= sqlite3_recover_config(pTest
->p
,
163 SQLITE_RECOVER_SLOWINDEXES
, (void*)&iVal
168 res
= sqlite3_recover_config(pTest
->p
, 12345, 0);
172 Tcl_SetObjResult(interp
, Tcl_NewIntObj(res
));
175 case 1: assert( sqlite3_stricmp("run", aSub
[iSub
].zSub
)==0 ); {
176 int res
= sqlite3_recover_run(pTest
->p
);
177 Tcl_SetObjResult(interp
, Tcl_NewIntObj(res
));
180 case 2: assert( sqlite3_stricmp("errmsg", aSub
[iSub
].zSub
)==0 ); {
181 const char *zErr
= sqlite3_recover_errmsg(pTest
->p
);
182 Tcl_SetObjResult(interp
, Tcl_NewStringObj(zErr
, -1));
185 case 3: assert( sqlite3_stricmp("errcode", aSub
[iSub
].zSub
)==0 ); {
186 int errCode
= sqlite3_recover_errcode(pTest
->p
);
187 Tcl_SetObjResult(interp
, Tcl_NewIntObj(errCode
));
190 case 4: assert( sqlite3_stricmp("finish", aSub
[iSub
].zSub
)==0 ); {
191 int res
= sqlite3_recover_errcode(pTest
->p
);
193 if( res
!=SQLITE_OK
){
194 const char *zErr
= sqlite3_recover_errmsg(pTest
->p
);
195 Tcl_SetObjResult(interp
, Tcl_NewStringObj(zErr
, -1));
197 res2
= sqlite3_recover_finish(pTest
->p
);
199 if( res
) return TCL_ERROR
;
202 case 5: assert( sqlite3_stricmp("step", aSub
[iSub
].zSub
)==0 ); {
203 int res
= sqlite3_recover_step(pTest
->p
);
204 Tcl_SetObjResult(interp
, Tcl_NewIntObj(res
));
213 ** sqlite3_recover_init DB DBNAME URI
215 static int test_sqlite3_recover_init(
219 Tcl_Obj
*CONST objv
[]
221 static int iTestRecoverCmd
= 1;
223 TestRecover
*pNew
= 0;
226 const char *zUri
= 0;
228 int bSql
= clientData
? 1 : 0;
231 const char *zErr
= (bSql
? "DB DBNAME SCRIPT" : "DB DBNAME URI");
232 Tcl_WrongNumArgs(interp
, 1, objv
, zErr
);
235 if( getDbPointer(interp
, objv
[1], &db
) ) return TCL_ERROR
;
236 zDb
= Tcl_GetString(objv
[2]);
237 if( zDb
[0]=='\0' ) zDb
= 0;
239 pNew
= (TestRecover
*)ckalloc(sizeof(TestRecover
));
241 zUri
= Tcl_GetString(objv
[3]);
242 pNew
->p
= sqlite3_recover_init(db
, zDb
, zUri
);
244 pNew
->interp
= interp
;
245 pNew
->pScript
= objv
[3];
246 Tcl_IncrRefCount(pNew
->pScript
);
247 pNew
->p
= sqlite3_recover_init_sql(db
, zDb
, xSqlCallback
, (void*)pNew
);
250 sprintf(zCmd
, "sqlite_recover%d", iTestRecoverCmd
++);
251 Tcl_CreateObjCommand(interp
, zCmd
, testRecoverCmd
, (void*)pNew
, 0);
253 Tcl_SetObjResult(interp
, Tcl_NewStringObj(zCmd
, -1));
258 ** Declaration for public API function in file dbdata.c. This may be called
259 ** with NULL as the final two arguments to register the sqlite_dbptr and
260 ** sqlite_dbdata virtual tables with a database handle.
263 __declspec(dllexport
)
265 int sqlite3_dbdata_init(sqlite3
*, char**, const sqlite3_api_routines
*);
268 ** sqlite3_recover_init DB DBNAME URI
270 static int test_sqlite3_dbdata_init(
274 Tcl_Obj
*CONST objv
[]
279 Tcl_WrongNumArgs(interp
, 1, objv
, "DB");
282 if( getDbPointer(interp
, objv
[1], &db
) ) return TCL_ERROR
;
283 sqlite3_dbdata_init(db
, 0, 0);
285 Tcl_ResetResult(interp
);
289 #endif /* SQLITE_OMIT_VIRTUALTABLE */
291 int TestRecover_Init(Tcl_Interp
*interp
){
292 #ifndef SQLITE_OMIT_VIRTUALTABLE
295 Tcl_ObjCmdProc
*xProc
;
298 { "sqlite3_recover_init", test_sqlite3_recover_init
, 0 },
299 { "sqlite3_recover_init_sql", test_sqlite3_recover_init
, (void*)1 },
300 { "sqlite3_dbdata_init", test_sqlite3_dbdata_init
, (void*)1 },
304 for(i
=0; i
<sizeof(aCmd
)/sizeof(struct Cmd
); i
++){
305 struct Cmd
*p
= &aCmd
[i
];
306 Tcl_CreateObjCommand(interp
, p
->zCmd
, p
->xProc
, p
->pArg
, 0);