| OLD | NEW |
| (Empty) |
| 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. | |
| 10 ** | |
| 11 ************************************************************************* | |
| 12 */ | |
| 13 | |
| 14 #include "sqlite3.h" | |
| 15 | |
| 16 #if defined(SQLITE_TEST) | |
| 17 #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_RBU) | |
| 18 | |
| 19 #include "sqlite3rbu.h" | |
| 20 #include <tcl.h> | |
| 21 #include <assert.h> | |
| 22 | |
| 23 /* From main.c (apparently...) */ | |
| 24 extern const char *sqlite3ErrName(int); | |
| 25 | |
| 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; | |
| 30 | |
| 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)); | |
| 38 } | |
| 39 | |
| 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); | |
| 45 } | |
| 46 | |
| 47 Tcl_DecrRefCount(pScript); | |
| 48 } | |
| 49 | |
| 50 | |
| 51 static int test_sqlite3rbu_cmd( | |
| 52 ClientData clientData, | |
| 53 Tcl_Interp *interp, | |
| 54 int objc, | |
| 55 Tcl_Obj *CONST objv[] | |
| 56 ){ | |
| 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} | |
| 70 }; | |
| 71 int iCmd; | |
| 72 | |
| 73 if( objc<2 ){ | |
| 74 Tcl_WrongNumArgs(interp, 1, objv, "METHOD"); | |
| 75 return TCL_ERROR; | |
| 76 } | |
| 77 ret = Tcl_GetIndexFromObjStruct( | |
| 78 interp, objv[1], aCmd, sizeof(aCmd[0]), "method", 0, &iCmd | |
| 79 ); | |
| 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; | |
| 84 } | |
| 85 | |
| 86 switch( iCmd ){ | |
| 87 case 0: /* step */ { | |
| 88 int rc = sqlite3rbu_step(pRbu); | |
| 89 Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1)); | |
| 90 break; | |
| 91 } | |
| 92 | |
| 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); | |
| 106 } | |
| 107 ret = TCL_ERROR; | |
| 108 } | |
| 109 break; | |
| 110 } | |
| 111 | |
| 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 | |
| 116 ); | |
| 117 Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1)); | |
| 118 ret = (rc==SQLITE_OK ? TCL_OK : TCL_ERROR); | |
| 119 break; | |
| 120 } | |
| 121 | |
| 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; | |
| 127 } | |
| 128 | |
| 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; | |
| 135 } | |
| 136 break; | |
| 137 } | |
| 138 | |
| 139 default: /* seems unlikely */ | |
| 140 assert( !"cannot happen" ); | |
| 141 break; | |
| 142 } | |
| 143 | |
| 144 return ret; | |
| 145 } | |
| 146 | |
| 147 /* | |
| 148 ** Tclcmd: sqlite3rbu CMD <target-db> <rbu-db> ?<state-db>? | |
| 149 */ | |
| 150 static int test_sqlite3rbu( | |
| 151 ClientData clientData, | |
| 152 Tcl_Interp *interp, | |
| 153 int objc, | |
| 154 Tcl_Obj *CONST objv[] | |
| 155 ){ | |
| 156 sqlite3rbu *pRbu = 0; | |
| 157 const char *zCmd; | |
| 158 const char *zTarget; | |
| 159 const char *zRbu; | |
| 160 const char *zStateDb = 0; | |
| 161 | |
| 162 if( objc!=4 && objc!=5 ){ | |
| 163 Tcl_WrongNumArgs(interp, 1, objv, "NAME TARGET-DB RBU-DB ?STATE-DB?"); | |
| 164 return TCL_ERROR; | |
| 165 } | |
| 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]); | |
| 170 | |
| 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; | |
| 175 } | |
| 176 | |
| 177 /* | |
| 178 ** Tclcmd: sqlite3rbu_create_vfs ?-default? NAME PARENT | |
| 179 */ | |
| 180 static int test_sqlite3rbu_create_vfs( | |
| 181 ClientData clientData, | |
| 182 Tcl_Interp *interp, | |
| 183 int objc, | |
| 184 Tcl_Obj *CONST objv[] | |
| 185 ){ | |
| 186 const char *zName; | |
| 187 const char *zParent; | |
| 188 int rc; | |
| 189 | |
| 190 if( objc!=3 && objc!=4 ){ | |
| 191 Tcl_WrongNumArgs(interp, 1, objv, "?-default? NAME PARENT"); | |
| 192 return TCL_ERROR; | |
| 193 } | |
| 194 | |
| 195 zName = Tcl_GetString(objv[objc-2]); | |
| 196 zParent = Tcl_GetString(objv[objc-1]); | |
| 197 if( zParent[0]=='\0' ) zParent = 0; | |
| 198 | |
| 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); | |
| 206 } | |
| 207 | |
| 208 Tcl_ResetResult(interp); | |
| 209 return TCL_OK; | |
| 210 } | |
| 211 | |
| 212 /* | |
| 213 ** Tclcmd: sqlite3rbu_destroy_vfs NAME | |
| 214 */ | |
| 215 static int test_sqlite3rbu_destroy_vfs( | |
| 216 ClientData clientData, | |
| 217 Tcl_Interp *interp, | |
| 218 int objc, | |
| 219 Tcl_Obj *CONST objv[] | |
| 220 ){ | |
| 221 const char *zName; | |
| 222 | |
| 223 if( objc!=2 ){ | |
| 224 Tcl_WrongNumArgs(interp, 1, objv, "NAME"); | |
| 225 return TCL_ERROR; | |
| 226 } | |
| 227 | |
| 228 zName = Tcl_GetString(objv[1]); | |
| 229 sqlite3rbu_destroy_vfs(zName); | |
| 230 return TCL_OK; | |
| 231 } | |
| 232 | |
| 233 /* | |
| 234 ** Tclcmd: sqlite3rbu_internal_test | |
| 235 */ | |
| 236 static int test_sqlite3rbu_internal_test( | |
| 237 ClientData clientData, | |
| 238 Tcl_Interp *interp, | |
| 239 int objc, | |
| 240 Tcl_Obj *CONST objv[] | |
| 241 ){ | |
| 242 sqlite3 *db; | |
| 243 | |
| 244 if( objc!=1 ){ | |
| 245 Tcl_WrongNumArgs(interp, 1, objv, ""); | |
| 246 return TCL_ERROR; | |
| 247 } | |
| 248 | |
| 249 db = sqlite3rbu_db(0, 0); | |
| 250 if( db!=0 ){ | |
| 251 Tcl_AppendResult(interp, "sqlite3rbu_db(0, 0)!=0", 0); | |
| 252 return TCL_ERROR; | |
| 253 } | |
| 254 | |
| 255 return TCL_OK; | |
| 256 } | |
| 257 | |
| 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 }, | |
| 267 }; | |
| 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); | |
| 271 } | |
| 272 return TCL_OK; | |
| 273 } | |
| 274 | |
| 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) */ | |
| OLD | NEW |