Snapshot of upstream SQLite 3.11.0
[sqlcipher.git] / ext / rbu / test_rbu.c
blob3fa85b756909b72f2c01874c4422f2e5f9b0a594
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 #include <tcl.h>
21 #include <assert.h>
23 /* From main.c (apparently...) */
24 extern const char *sqlite3ErrName(int);
26 void test_rbu_delta(sqlite3_context *pCtx, int nArg, sqlite3_value **apVal){
27 Tcl_Interp *interp = (Tcl_Interp*)sqlite3_user_data(pCtx);
28 Tcl_Obj *pScript;
29 int i;
31 pScript = Tcl_NewObj();
32 Tcl_IncrRefCount(pScript);
33 Tcl_ListObjAppendElement(0, pScript, Tcl_NewStringObj("rbu_delta", -1));
34 for(i=0; i<nArg; i++){
35 sqlite3_value *pIn = apVal[i];
36 const char *z = (const char*)sqlite3_value_text(pIn);
37 Tcl_ListObjAppendElement(0, pScript, Tcl_NewStringObj(z, -1));
40 if( TCL_OK==Tcl_EvalObjEx(interp, pScript, TCL_GLOBAL_ONLY) ){
41 const char *z = Tcl_GetStringResult(interp);
42 sqlite3_result_text(pCtx, z, -1, SQLITE_TRANSIENT);
43 }else{
44 Tcl_BackgroundError(interp);
47 Tcl_DecrRefCount(pScript);
51 static int test_sqlite3rbu_cmd(
52 ClientData clientData,
53 Tcl_Interp *interp,
54 int objc,
55 Tcl_Obj *CONST objv[]
57 int ret = TCL_OK;
58 sqlite3rbu *pRbu = (sqlite3rbu*)clientData;
59 struct RbuCmd {
60 const char *zName;
61 int nArg;
62 const char *zUsage;
63 } aCmd[] = {
64 {"step", 2, ""}, /* 0 */
65 {"close", 2, ""}, /* 1 */
66 {"create_rbu_delta", 2, ""}, /* 2 */
67 {"savestate", 2, ""}, /* 3 */
68 {"dbMain_eval", 3, "SQL"}, /* 4 */
69 {0,0,0}
71 int iCmd;
73 if( objc<2 ){
74 Tcl_WrongNumArgs(interp, 1, objv, "METHOD");
75 return TCL_ERROR;
77 ret = Tcl_GetIndexFromObjStruct(
78 interp, objv[1], aCmd, sizeof(aCmd[0]), "method", 0, &iCmd
80 if( ret ) return TCL_ERROR;
81 if( objc!=aCmd[iCmd].nArg ){
82 Tcl_WrongNumArgs(interp, 1, objv, aCmd[iCmd].zUsage);
83 return TCL_ERROR;
86 switch( iCmd ){
87 case 0: /* step */ {
88 int rc = sqlite3rbu_step(pRbu);
89 Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
90 break;
93 case 1: /* close */ {
94 char *zErrmsg = 0;
95 int rc;
96 Tcl_DeleteCommand(interp, Tcl_GetString(objv[0]));
97 rc = sqlite3rbu_close(pRbu, &zErrmsg);
98 if( rc==SQLITE_OK || rc==SQLITE_DONE ){
99 Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
100 assert( zErrmsg==0 );
101 }else{
102 Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
103 if( zErrmsg ){
104 Tcl_AppendResult(interp, " - ", zErrmsg, 0);
105 sqlite3_free(zErrmsg);
107 ret = TCL_ERROR;
109 break;
112 case 2: /* create_rbu_delta */ {
113 sqlite3 *db = sqlite3rbu_db(pRbu, 0);
114 int rc = sqlite3_create_function(
115 db, "rbu_delta", -1, SQLITE_UTF8, (void*)interp, test_rbu_delta, 0, 0
117 Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
118 ret = (rc==SQLITE_OK ? TCL_OK : TCL_ERROR);
119 break;
122 case 3: /* savestate */ {
123 int rc = sqlite3rbu_savestate(pRbu);
124 Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
125 ret = (rc==SQLITE_OK ? TCL_OK : TCL_ERROR);
126 break;
129 case 4: /* dbMain_eval */ {
130 sqlite3 *db = sqlite3rbu_db(pRbu, 0);
131 int rc = sqlite3_exec(db, Tcl_GetString(objv[2]), 0, 0, 0);
132 if( rc!=SQLITE_OK ){
133 Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3_errmsg(db), -1));
134 ret = TCL_ERROR;
136 break;
139 default: /* seems unlikely */
140 assert( !"cannot happen" );
141 break;
144 return ret;
148 ** Tclcmd: sqlite3rbu CMD <target-db> <rbu-db> ?<state-db>?
150 static int test_sqlite3rbu(
151 ClientData clientData,
152 Tcl_Interp *interp,
153 int objc,
154 Tcl_Obj *CONST objv[]
156 sqlite3rbu *pRbu = 0;
157 const char *zCmd;
158 const char *zTarget;
159 const char *zRbu;
160 const char *zStateDb = 0;
162 if( objc!=4 && objc!=5 ){
163 Tcl_WrongNumArgs(interp, 1, objv, "NAME TARGET-DB RBU-DB ?STATE-DB?");
164 return TCL_ERROR;
166 zCmd = Tcl_GetString(objv[1]);
167 zTarget = Tcl_GetString(objv[2]);
168 zRbu = Tcl_GetString(objv[3]);
169 if( objc==5 ) zStateDb = Tcl_GetString(objv[4]);
171 pRbu = sqlite3rbu_open(zTarget, zRbu, zStateDb);
172 Tcl_CreateObjCommand(interp, zCmd, test_sqlite3rbu_cmd, (ClientData)pRbu, 0);
173 Tcl_SetObjResult(interp, objv[1]);
174 return TCL_OK;
178 ** Tclcmd: sqlite3rbu_create_vfs ?-default? NAME PARENT
180 static int test_sqlite3rbu_create_vfs(
181 ClientData clientData,
182 Tcl_Interp *interp,
183 int objc,
184 Tcl_Obj *CONST objv[]
186 const char *zName;
187 const char *zParent;
188 int rc;
190 if( objc!=3 && objc!=4 ){
191 Tcl_WrongNumArgs(interp, 1, objv, "?-default? NAME PARENT");
192 return TCL_ERROR;
195 zName = Tcl_GetString(objv[objc-2]);
196 zParent = Tcl_GetString(objv[objc-1]);
197 if( zParent[0]=='\0' ) zParent = 0;
199 rc = sqlite3rbu_create_vfs(zName, zParent);
200 if( rc!=SQLITE_OK ){
201 Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
202 return TCL_ERROR;
203 }else if( objc==4 ){
204 sqlite3_vfs *pVfs = sqlite3_vfs_find(zName);
205 sqlite3_vfs_register(pVfs, 1);
208 Tcl_ResetResult(interp);
209 return TCL_OK;
213 ** Tclcmd: sqlite3rbu_destroy_vfs NAME
215 static int test_sqlite3rbu_destroy_vfs(
216 ClientData clientData,
217 Tcl_Interp *interp,
218 int objc,
219 Tcl_Obj *CONST objv[]
221 const char *zName;
223 if( objc!=2 ){
224 Tcl_WrongNumArgs(interp, 1, objv, "NAME");
225 return TCL_ERROR;
228 zName = Tcl_GetString(objv[1]);
229 sqlite3rbu_destroy_vfs(zName);
230 return TCL_OK;
234 ** Tclcmd: sqlite3rbu_internal_test
236 static int test_sqlite3rbu_internal_test(
237 ClientData clientData,
238 Tcl_Interp *interp,
239 int objc,
240 Tcl_Obj *CONST objv[]
242 sqlite3 *db;
244 if( objc!=1 ){
245 Tcl_WrongNumArgs(interp, 1, objv, "");
246 return TCL_ERROR;
249 db = sqlite3rbu_db(0, 0);
250 if( db!=0 ){
251 Tcl_AppendResult(interp, "sqlite3rbu_db(0, 0)!=0", 0);
252 return TCL_ERROR;
255 return TCL_OK;
258 int SqliteRbu_Init(Tcl_Interp *interp){
259 static struct {
260 char *zName;
261 Tcl_ObjCmdProc *xProc;
262 } aObjCmd[] = {
263 { "sqlite3rbu", test_sqlite3rbu },
264 { "sqlite3rbu_create_vfs", test_sqlite3rbu_create_vfs },
265 { "sqlite3rbu_destroy_vfs", test_sqlite3rbu_destroy_vfs },
266 { "sqlite3rbu_internal_test", test_sqlite3rbu_internal_test },
268 int i;
269 for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
270 Tcl_CreateObjCommand(interp, aObjCmd[i].zName, aObjCmd[i].xProc, 0, 0);
272 return TCL_OK;
275 #else
276 #include <tcl.h>
277 int SqliteRbu_Init(Tcl_Interp *interp){ return TCL_OK; }
278 #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_RBU) */
279 #endif /* defined(SQLITE_TEST) */