OLD | NEW |
1 /* | 1 /* |
2 ** 2015 February 16 | 2 ** 2015 February 16 |
3 ** | 3 ** |
4 ** The author disclaims copyright to this source code. In place of | 4 ** The author disclaims copyright to this source code. In place of |
5 ** a legal notice, here is a blessing: | 5 ** a legal notice, here is a blessing: |
6 ** | 6 ** |
7 ** May you do good and not evil. | 7 ** May you do good and not evil. |
8 ** May you find forgiveness for yourself and forgive others. | 8 ** May you find forgiveness for yourself and forgive others. |
9 ** May you share freely, never taking more than you give. | 9 ** May you share freely, never taking more than you give. |
10 ** | 10 ** |
11 ************************************************************************* | 11 ************************************************************************* |
12 */ | 12 */ |
13 | 13 |
14 #include "sqlite3.h" | 14 #include "sqlite3.h" |
15 | 15 |
16 #if defined(SQLITE_TEST) | 16 #if defined(SQLITE_TEST) |
17 #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_RBU) | 17 #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_RBU) |
18 | 18 |
19 #include "sqlite3rbu.h" | 19 #include "sqlite3rbu.h" |
20 #include <tcl.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 |
21 #include <assert.h> | 28 #include <assert.h> |
22 | 29 |
23 /* From main.c (apparently...) */ | 30 /* From main.c */ |
24 extern const char *sqlite3ErrName(int); | 31 extern const char *sqlite3ErrName(int); |
| 32 extern int sqlite3TestMakePointerStr(Tcl_Interp*, char*, void*); |
25 | 33 |
26 void test_rbu_delta(sqlite3_context *pCtx, int nArg, sqlite3_value **apVal){ | 34 void test_rbu_delta(sqlite3_context *pCtx, int nArg, sqlite3_value **apVal){ |
27 Tcl_Interp *interp = (Tcl_Interp*)sqlite3_user_data(pCtx); | 35 Tcl_Interp *interp = (Tcl_Interp*)sqlite3_user_data(pCtx); |
28 Tcl_Obj *pScript; | 36 Tcl_Obj *pScript; |
29 int i; | 37 int i; |
30 | 38 |
31 pScript = Tcl_NewObj(); | 39 pScript = Tcl_NewObj(); |
32 Tcl_IncrRefCount(pScript); | 40 Tcl_IncrRefCount(pScript); |
33 Tcl_ListObjAppendElement(0, pScript, Tcl_NewStringObj("rbu_delta", -1)); | 41 Tcl_ListObjAppendElement(0, pScript, Tcl_NewStringObj("rbu_delta", -1)); |
34 for(i=0; i<nArg; i++){ | 42 for(i=0; i<nArg; i++){ |
35 sqlite3_value *pIn = apVal[i]; | 43 sqlite3_value *pIn = apVal[i]; |
36 const char *z = (const char*)sqlite3_value_text(pIn); | 44 const char *z = (const char*)sqlite3_value_text(pIn); |
37 Tcl_ListObjAppendElement(0, pScript, Tcl_NewStringObj(z, -1)); | 45 Tcl_ListObjAppendElement(0, pScript, Tcl_NewStringObj(z, -1)); |
38 } | 46 } |
39 | 47 |
40 if( TCL_OK==Tcl_EvalObjEx(interp, pScript, TCL_GLOBAL_ONLY) ){ | 48 if( TCL_OK==Tcl_EvalObjEx(interp, pScript, TCL_GLOBAL_ONLY) ){ |
41 const char *z = Tcl_GetStringResult(interp); | 49 const char *z = Tcl_GetStringResult(interp); |
42 sqlite3_result_text(pCtx, z, -1, SQLITE_TRANSIENT); | 50 sqlite3_result_text(pCtx, z, -1, SQLITE_TRANSIENT); |
43 }else{ | 51 }else{ |
44 Tcl_BackgroundError(interp); | 52 Tcl_BackgroundError(interp); |
45 } | 53 } |
46 | 54 |
47 Tcl_DecrRefCount(pScript); | 55 Tcl_DecrRefCount(pScript); |
48 } | 56 } |
49 | 57 |
50 | 58 |
51 static int test_sqlite3rbu_cmd( | 59 static int SQLITE_TCLAPI test_sqlite3rbu_cmd( |
52 ClientData clientData, | 60 ClientData clientData, |
53 Tcl_Interp *interp, | 61 Tcl_Interp *interp, |
54 int objc, | 62 int objc, |
55 Tcl_Obj *CONST objv[] | 63 Tcl_Obj *CONST objv[] |
56 ){ | 64 ){ |
57 int ret = TCL_OK; | 65 int ret = TCL_OK; |
58 sqlite3rbu *pRbu = (sqlite3rbu*)clientData; | 66 sqlite3rbu *pRbu = (sqlite3rbu*)clientData; |
59 struct RbuCmd { | 67 struct RbuCmd { |
60 const char *zName; | 68 const char *zName; |
61 int nArg; | 69 int nArg; |
62 const char *zUsage; | 70 const char *zUsage; |
63 } aCmd[] = { | 71 } aCmd[] = { |
64 {"step", 2, ""}, /* 0 */ | 72 {"step", 2, ""}, /* 0 */ |
65 {"close", 2, ""}, /* 1 */ | 73 {"close", 2, ""}, /* 1 */ |
66 {"create_rbu_delta", 2, ""}, /* 2 */ | 74 {"create_rbu_delta", 2, ""}, /* 2 */ |
67 {"savestate", 2, ""}, /* 3 */ | 75 {"savestate", 2, ""}, /* 3 */ |
68 {"dbMain_eval", 3, "SQL"}, /* 4 */ | 76 {"dbMain_eval", 3, "SQL"}, /* 4 */ |
| 77 {"bp_progress", 2, ""}, /* 5 */ |
| 78 {"db", 3, "RBU"}, /* 6 */ |
| 79 {"state", 2, ""}, /* 7 */ |
| 80 {"progress", 2, ""}, /* 8 */ |
69 {0,0,0} | 81 {0,0,0} |
70 }; | 82 }; |
71 int iCmd; | 83 int iCmd; |
72 | 84 |
73 if( objc<2 ){ | 85 if( objc<2 ){ |
74 Tcl_WrongNumArgs(interp, 1, objv, "METHOD"); | 86 Tcl_WrongNumArgs(interp, 1, objv, "METHOD"); |
75 return TCL_ERROR; | 87 return TCL_ERROR; |
76 } | 88 } |
77 ret = Tcl_GetIndexFromObjStruct( | 89 ret = Tcl_GetIndexFromObjStruct( |
78 interp, objv[1], aCmd, sizeof(aCmd[0]), "method", 0, &iCmd | 90 interp, objv[1], aCmd, sizeof(aCmd[0]), "method", 0, &iCmd |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
129 case 4: /* dbMain_eval */ { | 141 case 4: /* dbMain_eval */ { |
130 sqlite3 *db = sqlite3rbu_db(pRbu, 0); | 142 sqlite3 *db = sqlite3rbu_db(pRbu, 0); |
131 int rc = sqlite3_exec(db, Tcl_GetString(objv[2]), 0, 0, 0); | 143 int rc = sqlite3_exec(db, Tcl_GetString(objv[2]), 0, 0, 0); |
132 if( rc!=SQLITE_OK ){ | 144 if( rc!=SQLITE_OK ){ |
133 Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3_errmsg(db), -1)); | 145 Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3_errmsg(db), -1)); |
134 ret = TCL_ERROR; | 146 ret = TCL_ERROR; |
135 } | 147 } |
136 break; | 148 break; |
137 } | 149 } |
138 | 150 |
| 151 case 5: /* bp_progress */ { |
| 152 int one, two; |
| 153 Tcl_Obj *pObj; |
| 154 sqlite3rbu_bp_progress(pRbu, &one, &two); |
| 155 |
| 156 pObj = Tcl_NewObj(); |
| 157 Tcl_ListObjAppendElement(interp, pObj, Tcl_NewIntObj(one)); |
| 158 Tcl_ListObjAppendElement(interp, pObj, Tcl_NewIntObj(two)); |
| 159 Tcl_SetObjResult(interp, pObj); |
| 160 break; |
| 161 } |
| 162 |
| 163 case 6: /* db */ { |
| 164 int bArg; |
| 165 if( Tcl_GetBooleanFromObj(interp, objv[2], &bArg) ){ |
| 166 ret = TCL_ERROR; |
| 167 }else{ |
| 168 char zBuf[50]; |
| 169 sqlite3 *db = sqlite3rbu_db(pRbu, bArg); |
| 170 if( sqlite3TestMakePointerStr(interp, zBuf, (void*)db) ){ |
| 171 ret = TCL_ERROR; |
| 172 }else{ |
| 173 Tcl_SetResult(interp, zBuf, TCL_VOLATILE); |
| 174 } |
| 175 } |
| 176 break; |
| 177 } |
| 178 case 7: /* state */ { |
| 179 const char *aRes[] = { 0, "oal", "move", "checkpoint", "done", "error" }; |
| 180 int eState = sqlite3rbu_state(pRbu); |
| 181 assert( eState>0 && eState<=5 ); |
| 182 Tcl_SetResult(interp, (char*)aRes[eState], TCL_STATIC); |
| 183 break; |
| 184 } |
| 185 case 8: /* progress */ { |
| 186 sqlite3_int64 nStep = sqlite3rbu_progress(pRbu); |
| 187 Tcl_SetObjResult(interp, Tcl_NewWideIntObj(nStep)); |
| 188 break; |
| 189 } |
| 190 |
139 default: /* seems unlikely */ | 191 default: /* seems unlikely */ |
140 assert( !"cannot happen" ); | 192 assert( !"cannot happen" ); |
141 break; | 193 break; |
142 } | 194 } |
143 | 195 |
144 return ret; | 196 return ret; |
145 } | 197 } |
146 | 198 |
147 /* | 199 /* |
148 ** Tclcmd: sqlite3rbu CMD <target-db> <rbu-db> ?<state-db>? | 200 ** Tclcmd: sqlite3rbu CMD <target-db> <rbu-db> ?<state-db>? |
149 */ | 201 */ |
150 static int test_sqlite3rbu( | 202 static int SQLITE_TCLAPI test_sqlite3rbu( |
151 ClientData clientData, | 203 ClientData clientData, |
152 Tcl_Interp *interp, | 204 Tcl_Interp *interp, |
153 int objc, | 205 int objc, |
154 Tcl_Obj *CONST objv[] | 206 Tcl_Obj *CONST objv[] |
155 ){ | 207 ){ |
156 sqlite3rbu *pRbu = 0; | 208 sqlite3rbu *pRbu = 0; |
157 const char *zCmd; | 209 const char *zCmd; |
158 const char *zTarget; | 210 const char *zTarget; |
159 const char *zRbu; | 211 const char *zRbu; |
160 const char *zStateDb = 0; | 212 const char *zStateDb = 0; |
161 | 213 |
162 if( objc!=4 && objc!=5 ){ | 214 if( objc!=4 && objc!=5 ){ |
163 Tcl_WrongNumArgs(interp, 1, objv, "NAME TARGET-DB RBU-DB ?STATE-DB?"); | 215 Tcl_WrongNumArgs(interp, 1, objv, "NAME TARGET-DB RBU-DB ?STATE-DB?"); |
164 return TCL_ERROR; | 216 return TCL_ERROR; |
165 } | 217 } |
166 zCmd = Tcl_GetString(objv[1]); | 218 zCmd = Tcl_GetString(objv[1]); |
167 zTarget = Tcl_GetString(objv[2]); | 219 zTarget = Tcl_GetString(objv[2]); |
168 zRbu = Tcl_GetString(objv[3]); | 220 zRbu = Tcl_GetString(objv[3]); |
169 if( objc==5 ) zStateDb = Tcl_GetString(objv[4]); | 221 if( objc==5 ) zStateDb = Tcl_GetString(objv[4]); |
170 | 222 |
171 pRbu = sqlite3rbu_open(zTarget, zRbu, zStateDb); | 223 pRbu = sqlite3rbu_open(zTarget, zRbu, zStateDb); |
172 Tcl_CreateObjCommand(interp, zCmd, test_sqlite3rbu_cmd, (ClientData)pRbu, 0); | 224 Tcl_CreateObjCommand(interp, zCmd, test_sqlite3rbu_cmd, (ClientData)pRbu, 0); |
173 Tcl_SetObjResult(interp, objv[1]); | 225 Tcl_SetObjResult(interp, objv[1]); |
174 return TCL_OK; | 226 return TCL_OK; |
175 } | 227 } |
176 | 228 |
177 /* | 229 /* |
| 230 ** Tclcmd: sqlite3rbu_vacuum CMD <target-db> <state-db> |
| 231 */ |
| 232 static int SQLITE_TCLAPI test_sqlite3rbu_vacuum( |
| 233 ClientData clientData, |
| 234 Tcl_Interp *interp, |
| 235 int objc, |
| 236 Tcl_Obj *CONST objv[] |
| 237 ){ |
| 238 sqlite3rbu *pRbu = 0; |
| 239 const char *zCmd; |
| 240 const char *zTarget; |
| 241 const char *zStateDb = 0; |
| 242 |
| 243 if( objc!=3 && objc!=4 ){ |
| 244 Tcl_WrongNumArgs(interp, 1, objv, "NAME TARGET-DB ?STATE-DB?"); |
| 245 return TCL_ERROR; |
| 246 } |
| 247 zCmd = Tcl_GetString(objv[1]); |
| 248 zTarget = Tcl_GetString(objv[2]); |
| 249 if( objc==4 ) zStateDb = Tcl_GetString(objv[3]); |
| 250 |
| 251 pRbu = sqlite3rbu_vacuum(zTarget, zStateDb); |
| 252 Tcl_CreateObjCommand(interp, zCmd, test_sqlite3rbu_cmd, (ClientData)pRbu, 0); |
| 253 Tcl_SetObjResult(interp, objv[1]); |
| 254 return TCL_OK; |
| 255 } |
| 256 |
| 257 /* |
178 ** Tclcmd: sqlite3rbu_create_vfs ?-default? NAME PARENT | 258 ** Tclcmd: sqlite3rbu_create_vfs ?-default? NAME PARENT |
179 */ | 259 */ |
180 static int test_sqlite3rbu_create_vfs( | 260 static int SQLITE_TCLAPI test_sqlite3rbu_create_vfs( |
181 ClientData clientData, | 261 ClientData clientData, |
182 Tcl_Interp *interp, | 262 Tcl_Interp *interp, |
183 int objc, | 263 int objc, |
184 Tcl_Obj *CONST objv[] | 264 Tcl_Obj *CONST objv[] |
185 ){ | 265 ){ |
186 const char *zName; | 266 const char *zName; |
187 const char *zParent; | 267 const char *zParent; |
188 int rc; | 268 int rc; |
189 | 269 |
190 if( objc!=3 && objc!=4 ){ | 270 if( objc!=3 && objc!=4 ){ |
(...skipping 14 matching lines...) Expand all Loading... |
205 sqlite3_vfs_register(pVfs, 1); | 285 sqlite3_vfs_register(pVfs, 1); |
206 } | 286 } |
207 | 287 |
208 Tcl_ResetResult(interp); | 288 Tcl_ResetResult(interp); |
209 return TCL_OK; | 289 return TCL_OK; |
210 } | 290 } |
211 | 291 |
212 /* | 292 /* |
213 ** Tclcmd: sqlite3rbu_destroy_vfs NAME | 293 ** Tclcmd: sqlite3rbu_destroy_vfs NAME |
214 */ | 294 */ |
215 static int test_sqlite3rbu_destroy_vfs( | 295 static int SQLITE_TCLAPI test_sqlite3rbu_destroy_vfs( |
216 ClientData clientData, | 296 ClientData clientData, |
217 Tcl_Interp *interp, | 297 Tcl_Interp *interp, |
218 int objc, | 298 int objc, |
219 Tcl_Obj *CONST objv[] | 299 Tcl_Obj *CONST objv[] |
220 ){ | 300 ){ |
221 const char *zName; | 301 const char *zName; |
222 | 302 |
223 if( objc!=2 ){ | 303 if( objc!=2 ){ |
224 Tcl_WrongNumArgs(interp, 1, objv, "NAME"); | 304 Tcl_WrongNumArgs(interp, 1, objv, "NAME"); |
225 return TCL_ERROR; | 305 return TCL_ERROR; |
226 } | 306 } |
227 | 307 |
228 zName = Tcl_GetString(objv[1]); | 308 zName = Tcl_GetString(objv[1]); |
229 sqlite3rbu_destroy_vfs(zName); | 309 sqlite3rbu_destroy_vfs(zName); |
230 return TCL_OK; | 310 return TCL_OK; |
231 } | 311 } |
232 | 312 |
233 /* | 313 /* |
234 ** Tclcmd: sqlite3rbu_internal_test | 314 ** Tclcmd: sqlite3rbu_internal_test |
235 */ | 315 */ |
236 static int test_sqlite3rbu_internal_test( | 316 static int SQLITE_TCLAPI test_sqlite3rbu_internal_test( |
237 ClientData clientData, | 317 ClientData clientData, |
238 Tcl_Interp *interp, | 318 Tcl_Interp *interp, |
239 int objc, | 319 int objc, |
240 Tcl_Obj *CONST objv[] | 320 Tcl_Obj *CONST objv[] |
241 ){ | 321 ){ |
242 sqlite3 *db; | 322 sqlite3 *db; |
243 | 323 |
244 if( objc!=1 ){ | 324 if( objc!=1 ){ |
245 Tcl_WrongNumArgs(interp, 1, objv, ""); | 325 Tcl_WrongNumArgs(interp, 1, objv, ""); |
246 return TCL_ERROR; | 326 return TCL_ERROR; |
247 } | 327 } |
248 | 328 |
249 db = sqlite3rbu_db(0, 0); | 329 db = sqlite3rbu_db(0, 0); |
250 if( db!=0 ){ | 330 if( db!=0 ){ |
251 Tcl_AppendResult(interp, "sqlite3rbu_db(0, 0)!=0", 0); | 331 Tcl_AppendResult(interp, "sqlite3rbu_db(0, 0)!=0", 0); |
252 return TCL_ERROR; | 332 return TCL_ERROR; |
253 } | 333 } |
254 | 334 |
255 return TCL_OK; | 335 return TCL_OK; |
256 } | 336 } |
257 | 337 |
258 int SqliteRbu_Init(Tcl_Interp *interp){ | 338 int SqliteRbu_Init(Tcl_Interp *interp){ |
259 static struct { | 339 static struct { |
260 char *zName; | 340 char *zName; |
261 Tcl_ObjCmdProc *xProc; | 341 Tcl_ObjCmdProc *xProc; |
262 } aObjCmd[] = { | 342 } aObjCmd[] = { |
263 { "sqlite3rbu", test_sqlite3rbu }, | 343 { "sqlite3rbu", test_sqlite3rbu }, |
| 344 { "sqlite3rbu_vacuum", test_sqlite3rbu_vacuum }, |
264 { "sqlite3rbu_create_vfs", test_sqlite3rbu_create_vfs }, | 345 { "sqlite3rbu_create_vfs", test_sqlite3rbu_create_vfs }, |
265 { "sqlite3rbu_destroy_vfs", test_sqlite3rbu_destroy_vfs }, | 346 { "sqlite3rbu_destroy_vfs", test_sqlite3rbu_destroy_vfs }, |
266 { "sqlite3rbu_internal_test", test_sqlite3rbu_internal_test }, | 347 { "sqlite3rbu_internal_test", test_sqlite3rbu_internal_test }, |
267 }; | 348 }; |
268 int i; | 349 int i; |
269 for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){ | 350 for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){ |
270 Tcl_CreateObjCommand(interp, aObjCmd[i].zName, aObjCmd[i].xProc, 0, 0); | 351 Tcl_CreateObjCommand(interp, aObjCmd[i].zName, aObjCmd[i].xProc, 0, 0); |
271 } | 352 } |
272 return TCL_OK; | 353 return TCL_OK; |
273 } | 354 } |
274 | 355 |
275 #else | 356 #else |
276 #include <tcl.h> | 357 #if defined(INCLUDE_SQLITE_TCL_H) |
| 358 # include "sqlite_tcl.h" |
| 359 #else |
| 360 # include "tcl.h" |
| 361 #endif |
277 int SqliteRbu_Init(Tcl_Interp *interp){ return TCL_OK; } | 362 int SqliteRbu_Init(Tcl_Interp *interp){ return TCL_OK; } |
278 #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_RBU) */ | 363 #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_RBU) */ |
279 #endif /* defined(SQLITE_TEST) */ | 364 #endif /* defined(SQLITE_TEST) */ |
OLD | NEW |