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) */