modernc.org/cc@v1.0.1/v2/testdata/_sqlite/ext/rbu/test_rbu.c (about) 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 #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 30 /* From main.c */ 31 extern const char *sqlite3ErrName(int); 32 extern int sqlite3TestMakePointerStr(Tcl_Interp*, char*, void*); 33 34 void test_rbu_delta(sqlite3_context *pCtx, int nArg, sqlite3_value **apVal){ 35 Tcl_Interp *interp = (Tcl_Interp*)sqlite3_user_data(pCtx); 36 Tcl_Obj *pScript; 37 int i; 38 39 pScript = Tcl_NewObj(); 40 Tcl_IncrRefCount(pScript); 41 Tcl_ListObjAppendElement(0, pScript, Tcl_NewStringObj("rbu_delta", -1)); 42 for(i=0; i<nArg; i++){ 43 sqlite3_value *pIn = apVal[i]; 44 const char *z = (const char*)sqlite3_value_text(pIn); 45 Tcl_ListObjAppendElement(0, pScript, Tcl_NewStringObj(z, -1)); 46 } 47 48 if( TCL_OK==Tcl_EvalObjEx(interp, pScript, TCL_GLOBAL_ONLY) ){ 49 const char *z = Tcl_GetStringResult(interp); 50 sqlite3_result_text(pCtx, z, -1, SQLITE_TRANSIENT); 51 }else{ 52 Tcl_BackgroundError(interp); 53 } 54 55 Tcl_DecrRefCount(pScript); 56 } 57 58 59 static int SQLITE_TCLAPI test_sqlite3rbu_cmd( 60 ClientData clientData, 61 Tcl_Interp *interp, 62 int objc, 63 Tcl_Obj *CONST objv[] 64 ){ 65 int ret = TCL_OK; 66 sqlite3rbu *pRbu = (sqlite3rbu*)clientData; 67 struct RbuCmd { 68 const char *zName; 69 int nArg; 70 const char *zUsage; 71 } aCmd[] = { 72 {"step", 2, ""}, /* 0 */ 73 {"close", 2, ""}, /* 1 */ 74 {"create_rbu_delta", 2, ""}, /* 2 */ 75 {"savestate", 2, ""}, /* 3 */ 76 {"dbMain_eval", 3, "SQL"}, /* 4 */ 77 {"bp_progress", 2, ""}, /* 5 */ 78 {"db", 3, "RBU"}, /* 6 */ 79 {"state", 2, ""}, /* 7 */ 80 {"progress", 2, ""}, /* 8 */ 81 {"close_no_error", 2, ""}, /* 9 */ 82 {"temp_size_limit", 3, "LIMIT"}, /* 10 */ 83 {"temp_size", 2, ""}, /* 11 */ 84 {0,0,0} 85 }; 86 int iCmd; 87 88 if( objc<2 ){ 89 Tcl_WrongNumArgs(interp, 1, objv, "METHOD"); 90 return TCL_ERROR; 91 } 92 ret = Tcl_GetIndexFromObjStruct( 93 interp, objv[1], aCmd, sizeof(aCmd[0]), "method", 0, &iCmd 94 ); 95 if( ret ) return TCL_ERROR; 96 if( objc!=aCmd[iCmd].nArg ){ 97 Tcl_WrongNumArgs(interp, 1, objv, aCmd[iCmd].zUsage); 98 return TCL_ERROR; 99 } 100 101 switch( iCmd ){ 102 case 0: /* step */ { 103 int rc = sqlite3rbu_step(pRbu); 104 Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1)); 105 break; 106 } 107 108 case 9: /* close_no_error */ 109 case 1: /* close */ { 110 char *zErrmsg = 0; 111 int rc; 112 Tcl_DeleteCommand(interp, Tcl_GetString(objv[0])); 113 if( iCmd==1 ){ 114 rc = sqlite3rbu_close(pRbu, &zErrmsg); 115 }else{ 116 rc = sqlite3rbu_close(pRbu, 0); 117 } 118 if( rc==SQLITE_OK || rc==SQLITE_DONE ){ 119 Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1)); 120 assert( zErrmsg==0 ); 121 }else{ 122 Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1)); 123 if( zErrmsg ){ 124 Tcl_AppendResult(interp, " - ", zErrmsg, 0); 125 sqlite3_free(zErrmsg); 126 } 127 ret = TCL_ERROR; 128 } 129 break; 130 } 131 132 case 2: /* create_rbu_delta */ { 133 sqlite3 *db = sqlite3rbu_db(pRbu, 0); 134 int rc = sqlite3_create_function( 135 db, "rbu_delta", -1, SQLITE_UTF8, (void*)interp, test_rbu_delta, 0, 0 136 ); 137 Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1)); 138 ret = (rc==SQLITE_OK ? TCL_OK : TCL_ERROR); 139 break; 140 } 141 142 case 3: /* savestate */ { 143 int rc = sqlite3rbu_savestate(pRbu); 144 Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1)); 145 ret = (rc==SQLITE_OK ? TCL_OK : TCL_ERROR); 146 break; 147 } 148 149 case 4: /* dbMain_eval */ { 150 sqlite3 *db = sqlite3rbu_db(pRbu, 0); 151 int rc = sqlite3_exec(db, Tcl_GetString(objv[2]), 0, 0, 0); 152 if( rc!=SQLITE_OK ){ 153 Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3_errmsg(db), -1)); 154 ret = TCL_ERROR; 155 } 156 break; 157 } 158 159 case 5: /* bp_progress */ { 160 int one, two; 161 Tcl_Obj *pObj; 162 sqlite3rbu_bp_progress(pRbu, &one, &two); 163 164 pObj = Tcl_NewObj(); 165 Tcl_ListObjAppendElement(interp, pObj, Tcl_NewIntObj(one)); 166 Tcl_ListObjAppendElement(interp, pObj, Tcl_NewIntObj(two)); 167 Tcl_SetObjResult(interp, pObj); 168 break; 169 } 170 171 case 6: /* db */ { 172 int bArg; 173 if( Tcl_GetBooleanFromObj(interp, objv[2], &bArg) ){ 174 ret = TCL_ERROR; 175 }else{ 176 char zBuf[50]; 177 sqlite3 *db = sqlite3rbu_db(pRbu, bArg); 178 if( sqlite3TestMakePointerStr(interp, zBuf, (void*)db) ){ 179 ret = TCL_ERROR; 180 }else{ 181 Tcl_SetResult(interp, zBuf, TCL_VOLATILE); 182 } 183 } 184 break; 185 } 186 case 7: /* state */ { 187 const char *aRes[] = { 0, "oal", "move", "checkpoint", "done", "error" }; 188 int eState = sqlite3rbu_state(pRbu); 189 assert( eState>0 && eState<=5 ); 190 Tcl_SetResult(interp, (char*)aRes[eState], TCL_STATIC); 191 break; 192 } 193 case 8: /* progress */ { 194 sqlite3_int64 nStep = sqlite3rbu_progress(pRbu); 195 Tcl_SetObjResult(interp, Tcl_NewWideIntObj(nStep)); 196 break; 197 } 198 199 case 10: /* temp_size_limit */ { 200 sqlite3_int64 nLimit; 201 if( Tcl_GetWideIntFromObj(interp, objv[2], &nLimit) ){ 202 ret = TCL_ERROR; 203 }else{ 204 nLimit = sqlite3rbu_temp_size_limit(pRbu, nLimit); 205 Tcl_SetObjResult(interp, Tcl_NewWideIntObj(nLimit)); 206 } 207 break; 208 } 209 case 11: /* temp_size */ { 210 sqlite3_int64 sz = sqlite3rbu_temp_size(pRbu); 211 Tcl_SetObjResult(interp, Tcl_NewWideIntObj(sz)); 212 break; 213 } 214 215 default: /* seems unlikely */ 216 assert( !"cannot happen" ); 217 break; 218 } 219 220 return ret; 221 } 222 223 /* 224 ** Tclcmd: sqlite3rbu CMD <target-db> <rbu-db> ?<state-db>? 225 */ 226 static int SQLITE_TCLAPI test_sqlite3rbu( 227 ClientData clientData, 228 Tcl_Interp *interp, 229 int objc, 230 Tcl_Obj *CONST objv[] 231 ){ 232 sqlite3rbu *pRbu = 0; 233 const char *zCmd; 234 const char *zTarget; 235 const char *zRbu; 236 const char *zStateDb = 0; 237 238 if( objc!=4 && objc!=5 ){ 239 Tcl_WrongNumArgs(interp, 1, objv, "NAME TARGET-DB RBU-DB ?STATE-DB?"); 240 return TCL_ERROR; 241 } 242 zCmd = Tcl_GetString(objv[1]); 243 zTarget = Tcl_GetString(objv[2]); 244 zRbu = Tcl_GetString(objv[3]); 245 if( objc==5 ) zStateDb = Tcl_GetString(objv[4]); 246 247 pRbu = sqlite3rbu_open(zTarget, zRbu, zStateDb); 248 Tcl_CreateObjCommand(interp, zCmd, test_sqlite3rbu_cmd, (ClientData)pRbu, 0); 249 Tcl_SetObjResult(interp, objv[1]); 250 return TCL_OK; 251 } 252 253 /* 254 ** Tclcmd: sqlite3rbu_vacuum CMD <target-db> <state-db> 255 */ 256 static int SQLITE_TCLAPI test_sqlite3rbu_vacuum( 257 ClientData clientData, 258 Tcl_Interp *interp, 259 int objc, 260 Tcl_Obj *CONST objv[] 261 ){ 262 sqlite3rbu *pRbu = 0; 263 const char *zCmd; 264 const char *zTarget; 265 const char *zStateDb = 0; 266 267 if( objc!=3 && objc!=4 ){ 268 Tcl_WrongNumArgs(interp, 1, objv, "NAME TARGET-DB ?STATE-DB?"); 269 return TCL_ERROR; 270 } 271 zCmd = Tcl_GetString(objv[1]); 272 zTarget = Tcl_GetString(objv[2]); 273 if( objc==4 ) zStateDb = Tcl_GetString(objv[3]); 274 275 pRbu = sqlite3rbu_vacuum(zTarget, zStateDb); 276 Tcl_CreateObjCommand(interp, zCmd, test_sqlite3rbu_cmd, (ClientData)pRbu, 0); 277 Tcl_SetObjResult(interp, objv[1]); 278 return TCL_OK; 279 } 280 281 /* 282 ** Tclcmd: sqlite3rbu_create_vfs ?-default? NAME PARENT 283 */ 284 static int SQLITE_TCLAPI test_sqlite3rbu_create_vfs( 285 ClientData clientData, 286 Tcl_Interp *interp, 287 int objc, 288 Tcl_Obj *CONST objv[] 289 ){ 290 const char *zName; 291 const char *zParent; 292 int rc; 293 294 if( objc!=3 && objc!=4 ){ 295 Tcl_WrongNumArgs(interp, 1, objv, "?-default? NAME PARENT"); 296 return TCL_ERROR; 297 } 298 299 zName = Tcl_GetString(objv[objc-2]); 300 zParent = Tcl_GetString(objv[objc-1]); 301 if( zParent[0]=='\0' ) zParent = 0; 302 303 rc = sqlite3rbu_create_vfs(zName, zParent); 304 if( rc!=SQLITE_OK ){ 305 Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1)); 306 return TCL_ERROR; 307 }else if( objc==4 ){ 308 sqlite3_vfs *pVfs = sqlite3_vfs_find(zName); 309 sqlite3_vfs_register(pVfs, 1); 310 } 311 312 Tcl_ResetResult(interp); 313 return TCL_OK; 314 } 315 316 /* 317 ** Tclcmd: sqlite3rbu_destroy_vfs NAME 318 */ 319 static int SQLITE_TCLAPI test_sqlite3rbu_destroy_vfs( 320 ClientData clientData, 321 Tcl_Interp *interp, 322 int objc, 323 Tcl_Obj *CONST objv[] 324 ){ 325 const char *zName; 326 327 if( objc!=2 ){ 328 Tcl_WrongNumArgs(interp, 1, objv, "NAME"); 329 return TCL_ERROR; 330 } 331 332 zName = Tcl_GetString(objv[1]); 333 sqlite3rbu_destroy_vfs(zName); 334 return TCL_OK; 335 } 336 337 /* 338 ** Tclcmd: sqlite3rbu_internal_test 339 */ 340 static int SQLITE_TCLAPI test_sqlite3rbu_internal_test( 341 ClientData clientData, 342 Tcl_Interp *interp, 343 int objc, 344 Tcl_Obj *CONST objv[] 345 ){ 346 sqlite3 *db; 347 348 if( objc!=1 ){ 349 Tcl_WrongNumArgs(interp, 1, objv, ""); 350 return TCL_ERROR; 351 } 352 353 db = sqlite3rbu_db(0, 0); 354 if( db!=0 ){ 355 Tcl_AppendResult(interp, "sqlite3rbu_db(0, 0)!=0", 0); 356 return TCL_ERROR; 357 } 358 359 return TCL_OK; 360 } 361 362 int SqliteRbu_Init(Tcl_Interp *interp){ 363 static struct { 364 char *zName; 365 Tcl_ObjCmdProc *xProc; 366 } aObjCmd[] = { 367 { "sqlite3rbu", test_sqlite3rbu }, 368 { "sqlite3rbu_vacuum", test_sqlite3rbu_vacuum }, 369 { "sqlite3rbu_create_vfs", test_sqlite3rbu_create_vfs }, 370 { "sqlite3rbu_destroy_vfs", test_sqlite3rbu_destroy_vfs }, 371 { "sqlite3rbu_internal_test", test_sqlite3rbu_internal_test }, 372 }; 373 int i; 374 for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){ 375 Tcl_CreateObjCommand(interp, aObjCmd[i].zName, aObjCmd[i].xProc, 0, 0); 376 } 377 return TCL_OK; 378 } 379 380 #else 381 #if defined(INCLUDE_SQLITE_TCL_H) 382 # include "sqlite_tcl.h" 383 #else 384 # include "tcl.h" 385 #endif 386 int SqliteRbu_Init(Tcl_Interp *interp){ return TCL_OK; } 387 #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_RBU) */ 388 #endif /* defined(SQLITE_TEST) */