Update tests in returning1.test to account for [c7896e88].
[sqlite.git] / ext / rbu / test_rbu.c
blobaf794d80f8a0b8ac1864de17f043cf7d203ccfca
1 /*
2 ** 2015 February 16
3 **
4 ** The author disclaims copyright to this source code. In place of
5 ** a legal notice, here is a blessing:
6 **
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 *************************************************************************
14 #include "sqlite3.h"
16 #if defined(SQLITE_TEST)
17 #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_RBU)
19 #include "sqlite3rbu.h"
20 #if defined(INCLUDE_SQLITE_TCL_H)
21 # include "sqlite_tcl.h"
22 #else
23 # include "tcl.h"
24 # ifndef SQLITE_TCLAPI
25 # define SQLITE_TCLAPI
26 # endif
27 #endif
28 #include <assert.h>
29 #include <string.h>
31 typedef struct TestRbu TestRbu;
32 struct TestRbu {
33 sqlite3rbu *pRbu;
34 Tcl_Interp *interp;
35 Tcl_Obj *xRename;
38 /* From main.c */
39 extern const char *sqlite3ErrName(int);
40 extern int sqlite3TestMakePointerStr(Tcl_Interp*, char*, void*);
42 void test_rbu_delta(sqlite3_context *pCtx, int nArg, sqlite3_value **apVal){
43 Tcl_Interp *interp = (Tcl_Interp*)sqlite3_user_data(pCtx);
44 Tcl_Obj *pScript;
45 int i;
47 pScript = Tcl_NewObj();
48 Tcl_IncrRefCount(pScript);
49 Tcl_ListObjAppendElement(0, pScript, Tcl_NewStringObj("rbu_delta", -1));
50 for(i=0; i<nArg; i++){
51 sqlite3_value *pIn = apVal[i];
52 const char *z = (const char*)sqlite3_value_text(pIn);
53 Tcl_ListObjAppendElement(0, pScript, Tcl_NewStringObj(z, -1));
56 if( TCL_OK==Tcl_EvalObjEx(interp, pScript, TCL_GLOBAL_ONLY) ){
57 const char *z = Tcl_GetStringResult(interp);
58 sqlite3_result_text(pCtx, z, -1, SQLITE_TRANSIENT);
59 }else{
60 Tcl_BackgroundError(interp);
63 Tcl_DecrRefCount(pScript);
66 static int xRenameCallback(void *pArg, const char *zOld, const char *zNew){
67 int rc = SQLITE_OK;
68 TestRbu *pTest = (TestRbu*)pArg;
69 Tcl_Obj *pEval = Tcl_DuplicateObj(pTest->xRename);
71 Tcl_IncrRefCount(pEval);
72 Tcl_ListObjAppendElement(pTest->interp, pEval, Tcl_NewStringObj(zOld, -1));
73 Tcl_ListObjAppendElement(pTest->interp, pEval, Tcl_NewStringObj(zNew, -1));
75 rc = Tcl_EvalObjEx(pTest->interp, pEval, TCL_GLOBAL_ONLY);
76 Tcl_DecrRefCount(pEval);
78 return rc ? SQLITE_IOERR : SQLITE_OK;
81 static int SQLITE_TCLAPI test_sqlite3rbu_cmd(
82 ClientData clientData,
83 Tcl_Interp *interp,
84 int objc,
85 Tcl_Obj *CONST objv[]
87 int ret = TCL_OK;
88 TestRbu *pTest = (TestRbu*)clientData;
89 sqlite3rbu *pRbu = pTest->pRbu;
90 struct RbuCmd {
91 const char *zName;
92 int nArg;
93 const char *zUsage;
94 } aCmd[] = {
95 {"step", 2, ""}, /* 0 */
96 {"close", 2, ""}, /* 1 */
97 {"create_rbu_delta", 2, ""}, /* 2 */
98 {"savestate", 2, ""}, /* 3 */
99 {"dbMain_eval", 3, "SQL"}, /* 4 */
100 {"bp_progress", 2, ""}, /* 5 */
101 {"db", 3, "RBU"}, /* 6 */
102 {"state", 2, ""}, /* 7 */
103 {"progress", 2, ""}, /* 8 */
104 {"close_no_error", 2, ""}, /* 9 */
105 {"temp_size_limit", 3, "LIMIT"}, /* 10 */
106 {"temp_size", 2, ""}, /* 11 */
107 {"dbRbu_eval", 3, "SQL"}, /* 12 */
108 {"rename_handler", 3, "SCRIPT"},/* 13 */
109 {0,0,0}
111 int iCmd;
113 if( objc<2 ){
114 Tcl_WrongNumArgs(interp, 1, objv, "METHOD");
115 return TCL_ERROR;
117 ret = Tcl_GetIndexFromObjStruct(
118 interp, objv[1], aCmd, sizeof(aCmd[0]), "method", 0, &iCmd
120 if( ret ) return TCL_ERROR;
121 if( objc!=aCmd[iCmd].nArg ){
122 Tcl_WrongNumArgs(interp, 1, objv, aCmd[iCmd].zUsage);
123 return TCL_ERROR;
126 switch( iCmd ){
127 case 0: /* step */ {
128 int rc = sqlite3rbu_step(pRbu);
129 Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
130 break;
133 case 9: /* close_no_error */
134 case 1: /* close */ {
135 char *zErrmsg = 0;
136 int rc;
137 Tcl_DeleteCommand(interp, Tcl_GetString(objv[0]));
138 if( iCmd==1 ){
139 rc = sqlite3rbu_close(pRbu, &zErrmsg);
140 }else{
141 rc = sqlite3rbu_close(pRbu, 0);
143 if( rc==SQLITE_OK || rc==SQLITE_DONE ){
144 Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
145 assert( zErrmsg==0 );
146 }else{
147 Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
148 if( zErrmsg ){
149 Tcl_AppendResult(interp, " - ", zErrmsg, 0);
150 sqlite3_free(zErrmsg);
152 ret = TCL_ERROR;
154 if( pTest->xRename ) Tcl_DecrRefCount(pTest->xRename);
155 ckfree(pTest);
156 break;
159 case 2: /* create_rbu_delta */ {
160 sqlite3 *db = sqlite3rbu_db(pRbu, 0);
161 int rc = sqlite3_create_function(
162 db, "rbu_delta", -1, SQLITE_UTF8, (void*)interp, test_rbu_delta, 0, 0
164 Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
165 ret = (rc==SQLITE_OK ? TCL_OK : TCL_ERROR);
166 break;
169 case 3: /* savestate */ {
170 int rc = sqlite3rbu_savestate(pRbu);
171 Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
172 ret = (rc==SQLITE_OK ? TCL_OK : TCL_ERROR);
173 break;
176 case 12: /* dbRbu_eval */
177 case 4: /* dbMain_eval */ {
178 sqlite3 *db = sqlite3rbu_db(pRbu, (iCmd==12));
179 int rc = sqlite3_exec(db, Tcl_GetString(objv[2]), 0, 0, 0);
180 if( rc!=SQLITE_OK ){
181 Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3_errmsg(db), -1));
182 ret = TCL_ERROR;
184 break;
187 case 5: /* bp_progress */ {
188 int one, two;
189 Tcl_Obj *pObj;
190 sqlite3rbu_bp_progress(pRbu, &one, &two);
192 pObj = Tcl_NewObj();
193 Tcl_ListObjAppendElement(interp, pObj, Tcl_NewIntObj(one));
194 Tcl_ListObjAppendElement(interp, pObj, Tcl_NewIntObj(two));
195 Tcl_SetObjResult(interp, pObj);
196 break;
199 case 6: /* db */ {
200 int bArg;
201 if( Tcl_GetBooleanFromObj(interp, objv[2], &bArg) ){
202 ret = TCL_ERROR;
203 }else{
204 char zBuf[50];
205 sqlite3 *db = sqlite3rbu_db(pRbu, bArg);
206 if( sqlite3TestMakePointerStr(interp, zBuf, (void*)db) ){
207 ret = TCL_ERROR;
208 }else{
209 Tcl_SetResult(interp, zBuf, TCL_VOLATILE);
212 break;
214 case 7: /* state */ {
215 const char *aRes[] = { 0, "oal", "move", "checkpoint", "done", "error" };
216 int eState = sqlite3rbu_state(pRbu);
217 assert( eState>0 && eState<=5 );
218 Tcl_SetResult(interp, (char*)aRes[eState], TCL_STATIC);
219 break;
221 case 8: /* progress */ {
222 sqlite3_int64 nStep = sqlite3rbu_progress(pRbu);
223 Tcl_SetObjResult(interp, Tcl_NewWideIntObj(nStep));
224 break;
227 case 10: /* temp_size_limit */ {
228 sqlite3_int64 nLimit;
229 if( Tcl_GetWideIntFromObj(interp, objv[2], &nLimit) ){
230 ret = TCL_ERROR;
231 }else{
232 nLimit = sqlite3rbu_temp_size_limit(pRbu, nLimit);
233 Tcl_SetObjResult(interp, Tcl_NewWideIntObj(nLimit));
235 break;
237 case 11: /* temp_size */ {
238 sqlite3_int64 sz = sqlite3rbu_temp_size(pRbu);
239 Tcl_SetObjResult(interp, Tcl_NewWideIntObj(sz));
240 break;
243 case 13: /* rename_handler */ {
244 Tcl_Obj *pScript = objv[2];
245 assert( !sqlite3_stricmp(aCmd[13].zName, "rename_handler") );
246 if( Tcl_GetCharLength(pScript)==0 ){
247 sqlite3rbu_rename_handler(pRbu, 0, 0);
248 }else{
249 pTest->xRename = Tcl_DuplicateObj(pScript);
250 Tcl_IncrRefCount(pTest->xRename);
251 sqlite3rbu_rename_handler(pRbu, pTest, xRenameCallback);
253 break;
256 default: /* seems unlikely */
257 assert( !"cannot happen" );
258 break;
261 return ret;
264 static void createRbuWrapper(
265 Tcl_Interp *interp,
266 const char *zCmd,
267 sqlite3rbu *pRbu
269 TestRbu *pTest = (TestRbu*)ckalloc(sizeof(TestRbu));
270 memset(pTest, 0, sizeof(TestRbu));
271 pTest->pRbu = pRbu;
272 pTest->interp = interp;
273 Tcl_CreateObjCommand(interp, zCmd, test_sqlite3rbu_cmd, (ClientData)pTest, 0);
277 ** Tclcmd: sqlite3rbu CMD <target-db> <rbu-db> ?<state-db>?
279 static int SQLITE_TCLAPI test_sqlite3rbu(
280 ClientData clientData,
281 Tcl_Interp *interp,
282 int objc,
283 Tcl_Obj *CONST objv[]
285 sqlite3rbu *pRbu = 0;
286 const char *zCmd;
287 const char *zTarget;
288 const char *zRbu;
289 const char *zStateDb = 0;
291 if( objc!=4 && objc!=5 ){
292 Tcl_WrongNumArgs(interp, 1, objv, "NAME TARGET-DB RBU-DB ?STATE-DB?");
293 return TCL_ERROR;
295 zCmd = Tcl_GetString(objv[1]);
296 zTarget = Tcl_GetString(objv[2]);
297 zRbu = Tcl_GetString(objv[3]);
298 if( objc==5 ) zStateDb = Tcl_GetString(objv[4]);
300 pRbu = sqlite3rbu_open(zTarget, zRbu, zStateDb);
301 createRbuWrapper(interp, zCmd, pRbu);
302 Tcl_SetObjResult(interp, objv[1]);
303 return TCL_OK;
307 ** Tclcmd: sqlite3rbu_vacuum CMD <target-db> <state-db>
309 static int SQLITE_TCLAPI test_sqlite3rbu_vacuum(
310 ClientData clientData,
311 Tcl_Interp *interp,
312 int objc,
313 Tcl_Obj *CONST objv[]
315 sqlite3rbu *pRbu = 0;
316 const char *zCmd;
317 const char *zTarget;
318 const char *zStateDb = 0;
320 if( objc!=3 && objc!=4 ){
321 Tcl_WrongNumArgs(interp, 1, objv, "NAME TARGET-DB ?STATE-DB?");
322 return TCL_ERROR;
324 zCmd = Tcl_GetString(objv[1]);
325 zTarget = Tcl_GetString(objv[2]);
326 if( objc==4 ) zStateDb = Tcl_GetString(objv[3]);
327 if( zStateDb && zStateDb[0]=='\0' ) zStateDb = 0;
329 pRbu = sqlite3rbu_vacuum(zTarget, zStateDb);
330 createRbuWrapper(interp, zCmd, pRbu);
331 Tcl_SetObjResult(interp, objv[1]);
332 return TCL_OK;
336 ** Tclcmd: sqlite3rbu_create_vfs ?-default? NAME PARENT
338 static int SQLITE_TCLAPI test_sqlite3rbu_create_vfs(
339 ClientData clientData,
340 Tcl_Interp *interp,
341 int objc,
342 Tcl_Obj *CONST objv[]
344 const char *zName;
345 const char *zParent;
346 int rc;
348 if( objc!=3 && objc!=4 ){
349 Tcl_WrongNumArgs(interp, 1, objv, "?-default? NAME PARENT");
350 return TCL_ERROR;
353 zName = Tcl_GetString(objv[objc-2]);
354 zParent = Tcl_GetString(objv[objc-1]);
355 if( zParent[0]=='\0' ) zParent = 0;
357 rc = sqlite3rbu_create_vfs(zName, zParent);
358 if( rc!=SQLITE_OK ){
359 Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
360 return TCL_ERROR;
361 }else if( objc==4 ){
362 sqlite3_vfs *pVfs = sqlite3_vfs_find(zName);
363 sqlite3_vfs_register(pVfs, 1);
366 Tcl_ResetResult(interp);
367 return TCL_OK;
371 ** Tclcmd: sqlite3rbu_destroy_vfs NAME
373 static int SQLITE_TCLAPI test_sqlite3rbu_destroy_vfs(
374 ClientData clientData,
375 Tcl_Interp *interp,
376 int objc,
377 Tcl_Obj *CONST objv[]
379 const char *zName;
381 if( objc!=2 ){
382 Tcl_WrongNumArgs(interp, 1, objv, "NAME");
383 return TCL_ERROR;
386 zName = Tcl_GetString(objv[1]);
387 sqlite3rbu_destroy_vfs(zName);
388 return TCL_OK;
392 ** Tclcmd: sqlite3rbu_internal_test
394 static int SQLITE_TCLAPI test_sqlite3rbu_internal_test(
395 ClientData clientData,
396 Tcl_Interp *interp,
397 int objc,
398 Tcl_Obj *CONST objv[]
400 sqlite3 *db;
402 if( objc!=1 ){
403 Tcl_WrongNumArgs(interp, 1, objv, "");
404 return TCL_ERROR;
407 db = sqlite3rbu_db(0, 0);
408 if( db!=0 ){
409 Tcl_AppendResult(interp, "sqlite3rbu_db(0, 0)!=0", 0);
410 return TCL_ERROR;
413 return TCL_OK;
416 int SqliteRbu_Init(Tcl_Interp *interp){
417 static struct {
418 char *zName;
419 Tcl_ObjCmdProc *xProc;
420 } aObjCmd[] = {
421 { "sqlite3rbu", test_sqlite3rbu },
422 { "sqlite3rbu_vacuum", test_sqlite3rbu_vacuum },
423 { "sqlite3rbu_create_vfs", test_sqlite3rbu_create_vfs },
424 { "sqlite3rbu_destroy_vfs", test_sqlite3rbu_destroy_vfs },
425 { "sqlite3rbu_internal_test", test_sqlite3rbu_internal_test },
427 int i;
428 for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
429 Tcl_CreateObjCommand(interp, aObjCmd[i].zName, aObjCmd[i].xProc, 0, 0);
431 return TCL_OK;
434 #else
435 #if defined(INCLUDE_SQLITE_TCL_H)
436 # include "sqlite_tcl.h"
437 #else
438 # include "tcl.h"
439 #endif
440 int SqliteRbu_Init(Tcl_Interp *interp){ return TCL_OK; }
441 #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_RBU) */
442 #endif /* defined(SQLITE_TEST) */