/ Check-in [f20779a6]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Move tcl test code from sqlite3ota.c to new file ext/ota/test_ota.c.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | ota-update
Files: files | file ages | folders
SHA1: f20779a6e890ba73bfaa904cefcf3a029b01fed4
User & Date: dan 2015-02-16 06:27:37
Context
2015-02-16
11:48
Add further tests and fixes for ota. check-in: 62dc1fff user: dan tags: ota-update
06:27
Move tcl test code from sqlite3ota.c to new file ext/ota/test_ota.c. check-in: f20779a6 user: dan tags: ota-update
2015-02-14
18:58
Change the way the "incremental checkpoint" function of OTA works in order to reduce the effect on the SQLite core code. check-in: b64a11a7 user: dan tags: ota-update
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to ext/ota/sqlite3ota.c.

   512    512       pIter->azTblType = &azNew[nCol];
   513    513       pIter->aiSrcOrder = (int*)&pIter->azTblType[nCol];
   514    514       pIter->abTblPk = (u8*)&pIter->aiSrcOrder[nCol];
   515    515       pIter->abNotNull = (u8*)&pIter->abTblPk[nCol];
   516    516     }
   517    517   }
   518    518   
   519         -static char *otaStrndup(const char *zStr, int nStr, int *pRc){
          519  +static char *otaStrndup(const char *zStr, int *pRc){
   520    520     char *zRet = 0;
          521  +
   521    522     assert( *pRc==SQLITE_OK );
   522         -
   523    523     if( zStr ){
   524         -    int nCopy = nStr;
   525         -    if( nCopy<0 ) nCopy = strlen(zStr) + 1;
          524  +    int nCopy = strlen(zStr) + 1;
   526    525       zRet = (char*)sqlite3_malloc(nCopy);
   527    526       if( zRet ){
   528    527         memcpy(zRet, zStr, nCopy);
   529    528       }else{
   530    529         *pRc = SQLITE_NOMEM;
   531    530       }
   532    531     }
................................................................................
   693    692       if( p->rc==SQLITE_OK ){
   694    693         nCol = sqlite3_column_count(pStmt);
   695    694         otaAllocateIterArrays(p, pIter, nCol);
   696    695       }
   697    696       for(i=0; p->rc==SQLITE_OK && i<nCol; i++){
   698    697         const char *zName = (const char*)sqlite3_column_name(pStmt, i);
   699    698         if( sqlite3_strnicmp("ota_", zName, 4) ){
   700         -        char *zCopy = otaStrndup(zName, -1, &p->rc);
          699  +        char *zCopy = otaStrndup(zName, &p->rc);
   701    700           pIter->aiSrcOrder[pIter->nTblCol] = pIter->nTblCol;
   702    701           pIter->azTblCol[pIter->nTblCol++] = zCopy;
   703    702         }
   704    703         else if( 0==sqlite3_stricmp("ota_rowid", zName) ){
   705    704           bOtaRowid = 1;
   706    705         }
   707    706       }
................................................................................
   742    741           const char *zType = (const char*)sqlite3_column_text(pStmt, 2);
   743    742   
   744    743           if( i!=iOrder ){
   745    744             SWAP(int, pIter->aiSrcOrder[i], pIter->aiSrcOrder[iOrder]);
   746    745             SWAP(char*, pIter->azTblCol[i], pIter->azTblCol[iOrder]);
   747    746           }
   748    747   
   749         -        pIter->azTblType[iOrder] = otaStrndup(zType, -1, &p->rc);
          748  +        pIter->azTblType[iOrder] = otaStrndup(zType, &p->rc);
   750    749           pIter->abTblPk[iOrder] = (iPk!=0);
   751    750           pIter->abNotNull[iOrder] = (u8)bNotNull || (iPk!=0);
   752    751           iOrder++;
   753    752         }
   754    753       }
   755    754   
   756    755       rc2 = sqlite3_finalize(pStmt);
................................................................................
  1439   1438                 "END;",
  1440   1439                 zWrite, zTbl, zTbl, zCollist, zNewlist
  1441   1440             );
  1442   1441           }
  1443   1442         }
  1444   1443   
  1445   1444         /* Allocate space required for the zMask field. */
  1446         -      if( p->rc==SQLITE_OK ){
  1447         -        int nMask = pIter->nTblCol+1;
  1448         -        pIter->zMask = (char*)sqlite3_malloc(nMask);
  1449         -        if( pIter->zMask==0 ){
  1450         -          p->rc = SQLITE_NOMEM;
  1451         -        }else{
  1452         -          memset(pIter->zMask, 0, nMask);
  1453         -        }
  1454         -      }
         1445  +      pIter->zMask = (char*)otaMalloc(p, pIter->nTblCol+1);
  1455   1446   
  1456   1447         sqlite3_free(zWhere);
  1457   1448         sqlite3_free(zOldlist);
  1458   1449         sqlite3_free(zNewlist);
  1459   1450         sqlite3_free(zBindings);
  1460   1451       }
  1461   1452       sqlite3_free(zCollist);
................................................................................
  2038   2029   static OtaState *otaLoadState(sqlite3ota *p){
  2039   2030     const char *zSelect = "SELECT k, v FROM ota.ota_state";
  2040   2031     OtaState *pRet = 0;
  2041   2032     sqlite3_stmt *pStmt = 0;
  2042   2033     int rc;
  2043   2034     int rc2;
  2044   2035   
  2045         -  assert( p->rc==SQLITE_OK );
  2046         -  pRet = (OtaState*)sqlite3_malloc(sizeof(OtaState));
  2047         -  if( pRet==0 ){
  2048         -    rc = SQLITE_NOMEM;
  2049         -  }else{
  2050         -    memset(pRet, 0, sizeof(OtaState));
  2051         -    rc = prepareAndCollectError(p->db, &pStmt, &p->zErrmsg, zSelect);
  2052         -  }
         2036  +  pRet = (OtaState*)otaMalloc(p, sizeof(OtaState));
         2037  +  if( pRet==0 ) return 0;
  2053   2038   
         2039  +  rc = prepareAndCollectError(p->db, &pStmt, &p->zErrmsg, zSelect);
  2054   2040     while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
  2055   2041       switch( sqlite3_column_int(pStmt, 0) ){
  2056   2042         case OTA_STATE_STAGE:
  2057   2043           pRet->eStage = sqlite3_column_int(pStmt, 1);
  2058   2044           if( pRet->eStage!=OTA_STAGE_OAL
  2059   2045            && pRet->eStage!=OTA_STAGE_CKPT
  2060   2046           ){
  2061   2047             p->rc = SQLITE_CORRUPT;
  2062   2048           }
  2063   2049           break;
  2064   2050   
  2065   2051         case OTA_STATE_TBL:
  2066         -        pRet->zTbl = otaStrndup((char*)sqlite3_column_text(pStmt, 1), -1, &rc);
         2052  +        pRet->zTbl = otaStrndup((char*)sqlite3_column_text(pStmt, 1), &rc);
  2067   2053           break;
  2068   2054   
  2069   2055         case OTA_STATE_IDX:
  2070         -        pRet->zIdx = otaStrndup((char*)sqlite3_column_text(pStmt, 1), -1, &rc);
         2056  +        pRet->zIdx = otaStrndup((char*)sqlite3_column_text(pStmt, 1), &rc);
  2071   2057           break;
  2072   2058   
  2073   2059         case OTA_STATE_ROW:
  2074   2060           pRet->nRow = sqlite3_column_int(pStmt, 1);
  2075   2061           break;
  2076   2062   
  2077   2063         case OTA_STATE_PROGRESS:
................................................................................
  2750   2736         z += (n + 8 + 1);
  2751   2737         pFd->zWal = z;
  2752   2738       }
  2753   2739       else if( flags & SQLITE_OPEN_WAL ){
  2754   2740         ota_file *pDb = otaFindMaindb(pOtaVfs, zName);
  2755   2741         if( pDb ){
  2756   2742           if( pDb->pOta && pDb->pOta->eStage==OTA_STAGE_OAL ){
  2757         -          char *zCopy = otaStrndup(zName, -1, &rc);
         2743  +          char *zCopy = otaStrndup(zName, &rc);
  2758   2744             if( zCopy ){
  2759   2745               int nCopy = strlen(zCopy);
  2760   2746               zCopy[nCopy-3] = 'o';
  2761   2747               zOpen = (const char*)(pFd->zDel = zCopy);
  2762   2748             }
  2763   2749             pFd->pOta = pDb->pOta;
  2764   2750           }
................................................................................
  3021   3007       p->zVfsName = 0;
  3022   3008     }
  3023   3009   }
  3024   3010   
  3025   3011   
  3026   3012   /**************************************************************************/
  3027   3013   
  3028         -#ifdef SQLITE_TEST 
  3029         -
  3030         -#include <tcl.h>
  3031         -
  3032         -/* From main.c (apparently...) */
  3033         -extern const char *sqlite3ErrName(int);
  3034         -
  3035         -void test_ota_delta(sqlite3_context *pCtx, int nArg, sqlite3_value **apVal){
  3036         -  Tcl_Interp *interp = (Tcl_Interp*)sqlite3_user_data(pCtx);
  3037         -  Tcl_Obj *pScript;
  3038         -  int i;
  3039         -
  3040         -  pScript = Tcl_NewObj();
  3041         -  Tcl_IncrRefCount(pScript);
  3042         -  Tcl_ListObjAppendElement(0, pScript, Tcl_NewStringObj("ota_delta", -1));
  3043         -  for(i=0; i<nArg; i++){
  3044         -    sqlite3_value *pIn = apVal[i];
  3045         -    const char *z = (const char*)sqlite3_value_text(pIn);
  3046         -    Tcl_ListObjAppendElement(0, pScript, Tcl_NewStringObj(z, -1));
  3047         -  }
  3048         -
  3049         -  if( TCL_OK==Tcl_EvalObjEx(interp, pScript, TCL_GLOBAL_ONLY) ){
  3050         -    const char *z = Tcl_GetStringResult(interp);
  3051         -    sqlite3_result_text(pCtx, z, -1, SQLITE_TRANSIENT);
  3052         -  }else{
  3053         -    Tcl_BackgroundError(interp);
  3054         -  }
  3055         -
  3056         -  Tcl_DecrRefCount(pScript);
  3057         -}
  3058         -
  3059         -
  3060         -static int test_sqlite3ota_cmd(
  3061         -  ClientData clientData,
  3062         -  Tcl_Interp *interp,
  3063         -  int objc,
  3064         -  Tcl_Obj *CONST objv[]
  3065         -){
  3066         -  int ret = TCL_OK;
  3067         -  sqlite3ota *pOta = (sqlite3ota*)clientData;
  3068         -  const char *azMethod[] = { "step", "close", "create_ota_delta", 0 };
  3069         -  int iMethod;
  3070         -
  3071         -  if( objc!=2 ){
  3072         -    Tcl_WrongNumArgs(interp, 1, objv, "METHOD");
  3073         -    return TCL_ERROR;
  3074         -  }
  3075         -  if( Tcl_GetIndexFromObj(interp, objv[1], azMethod, "method", 0, &iMethod) ){
  3076         -    return TCL_ERROR;
  3077         -  }
  3078         -
  3079         -  switch( iMethod ){
  3080         -    case 0: /* step */ {
  3081         -      int rc = sqlite3ota_step(pOta);
  3082         -      Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
  3083         -      break;
  3084         -    }
  3085         -
  3086         -    case 1: /* close */ {
  3087         -      char *zErrmsg = 0;
  3088         -      int rc;
  3089         -      Tcl_DeleteCommand(interp, Tcl_GetString(objv[0]));
  3090         -      rc = sqlite3ota_close(pOta, &zErrmsg);
  3091         -      if( rc==SQLITE_OK || rc==SQLITE_DONE ){
  3092         -        Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
  3093         -        assert( zErrmsg==0 );
  3094         -      }else{
  3095         -        Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
  3096         -        if( zErrmsg ){
  3097         -          Tcl_AppendResult(interp, " - ", zErrmsg, 0);
  3098         -          sqlite3_free(zErrmsg);
  3099         -        }
  3100         -        ret = TCL_ERROR;
  3101         -      }
  3102         -      break;
  3103         -    }
  3104         -
  3105         -    case 2: /* create_ota_delta */ {
  3106         -      sqlite3 *db = sqlite3ota_db(pOta);
  3107         -      int rc = sqlite3_create_function(
  3108         -          db, "ota_delta", -1, SQLITE_UTF8, (void*)interp, test_ota_delta, 0, 0
  3109         -      );
  3110         -      Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
  3111         -      ret = (rc==SQLITE_OK ? TCL_OK : TCL_ERROR);
  3112         -      break;
  3113         -    }
  3114         -
  3115         -    default: /* seems unlikely */
  3116         -      assert( !"cannot happen" );
  3117         -      break;
  3118         -  }
  3119         -
  3120         -  return ret;
  3121         -}
  3122         -
  3123         -/*
  3124         -** Tclcmd: sqlite3ota CMD <target-db> <ota-db>
  3125         -*/
  3126         -static int test_sqlite3ota(
  3127         -  ClientData clientData,
  3128         -  Tcl_Interp *interp,
  3129         -  int objc,
  3130         -  Tcl_Obj *CONST objv[]
  3131         -){
  3132         -  sqlite3ota *pOta = 0;
  3133         -  const char *zCmd;
  3134         -  const char *zTarget;
  3135         -  const char *zOta;
  3136         -
  3137         -  if( objc!=4 ){
  3138         -    Tcl_WrongNumArgs(interp, 1, objv, "NAME TARGET-DB OTA-DB");
  3139         -    return TCL_ERROR;
  3140         -  }
  3141         -  zCmd = Tcl_GetString(objv[1]);
  3142         -  zTarget = Tcl_GetString(objv[2]);
  3143         -  zOta = Tcl_GetString(objv[3]);
  3144         -
  3145         -  pOta = sqlite3ota_open(zTarget, zOta);
  3146         -  Tcl_CreateObjCommand(interp, zCmd, test_sqlite3ota_cmd, (ClientData)pOta, 0);
  3147         -  Tcl_SetObjResult(interp, objv[1]);
  3148         -  return TCL_OK;
  3149         -}
  3150         -
  3151         -/*
  3152         -** Tclcmd: sqlite3ota_create_vfs ?-default? NAME PARENT
  3153         -*/
  3154         -static int test_sqlite3ota_create_vfs(
  3155         -  ClientData clientData,
  3156         -  Tcl_Interp *interp,
  3157         -  int objc,
  3158         -  Tcl_Obj *CONST objv[]
  3159         -){
  3160         -  const char *zName;
  3161         -  const char *zParent;
  3162         -  int rc;
  3163         -
  3164         -  if( objc!=3 && objc!=4 ){
  3165         -    Tcl_WrongNumArgs(interp, 1, objv, "?-default? NAME PARENT");
  3166         -    return TCL_ERROR;
  3167         -  }
  3168         -
  3169         -  zName = Tcl_GetString(objv[objc-2]);
  3170         -  zParent = Tcl_GetString(objv[objc-1]);
  3171         -  if( zParent[0]=='\0' ) zParent = 0;
  3172         -
  3173         -  rc = sqlite3ota_create_vfs(zName, zParent);
  3174         -  if( rc!=SQLITE_OK ){
  3175         -    Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
  3176         -    return TCL_ERROR;
  3177         -  }else if( objc==4 ){
  3178         -    sqlite3_vfs *pVfs = sqlite3_vfs_find(zName);
  3179         -    sqlite3_vfs_register(pVfs, 1);
  3180         -  }
  3181         -
  3182         -  Tcl_ResetResult(interp);
  3183         -  return TCL_OK;
  3184         -}
  3185         -
  3186         -/*
  3187         -** Tclcmd: sqlite3ota_destroy_vfs NAME
  3188         -*/
  3189         -static int test_sqlite3ota_destroy_vfs(
  3190         -  ClientData clientData,
  3191         -  Tcl_Interp *interp,
  3192         -  int objc,
  3193         -  Tcl_Obj *CONST objv[]
  3194         -){
  3195         -  const char *zName;
  3196         -
  3197         -  if( objc!=2 ){
  3198         -    Tcl_WrongNumArgs(interp, 1, objv, "NAME");
  3199         -    return TCL_ERROR;
  3200         -  }
  3201         -
  3202         -  zName = Tcl_GetString(objv[1]);
  3203         -  sqlite3ota_destroy_vfs(zName);
  3204         -  return TCL_OK;
  3205         -}
  3206         -
  3207         -
  3208         -int SqliteOta_Init(Tcl_Interp *interp){ 
  3209         -  static struct {
  3210         -     char *zName;
  3211         -     Tcl_ObjCmdProc *xProc;
  3212         -  } aObjCmd[] = {
  3213         -    { "sqlite3ota", test_sqlite3ota },
  3214         -    { "sqlite3ota_create_vfs", test_sqlite3ota_create_vfs },
  3215         -    { "sqlite3ota_destroy_vfs", test_sqlite3ota_destroy_vfs },
  3216         -  };
  3217         -  int i;
  3218         -  for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
  3219         -    Tcl_CreateObjCommand(interp, aObjCmd[i].zName, aObjCmd[i].xProc, 0, 0);
  3220         -  }
  3221         -  return TCL_OK;
  3222         -}
  3223         -#endif                  /* ifdef SQLITE_TEST */
  3224         -#else   /* !SQLITE_CORE || SQLITE_ENABLE_OTA */
  3225         -# ifdef SQLITE_TEST
  3226         -#include <tcl.h>
  3227         -int SqliteOta_Init(Tcl_Interp *interp){ return TCL_OK; }
  3228         -# endif
  3229         -#endif
         3014  +#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_OTA) */

Added ext/ota/test_ota.c.

            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_OTA)
           18  +
           19  +#include "sqlite3ota.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_ota_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("ota_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_sqlite3ota_cmd(
           52  +  ClientData clientData,
           53  +  Tcl_Interp *interp,
           54  +  int objc,
           55  +  Tcl_Obj *CONST objv[]
           56  +){
           57  +  int ret = TCL_OK;
           58  +  sqlite3ota *pOta = (sqlite3ota*)clientData;
           59  +  const char *azMethod[] = { "step", "close", "create_ota_delta", 0 };
           60  +  int iMethod;
           61  +
           62  +  if( objc!=2 ){
           63  +    Tcl_WrongNumArgs(interp, 1, objv, "METHOD");
           64  +    return TCL_ERROR;
           65  +  }
           66  +  if( Tcl_GetIndexFromObj(interp, objv[1], azMethod, "method", 0, &iMethod) ){
           67  +    return TCL_ERROR;
           68  +  }
           69  +
           70  +  switch( iMethod ){
           71  +    case 0: /* step */ {
           72  +      int rc = sqlite3ota_step(pOta);
           73  +      Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
           74  +      break;
           75  +    }
           76  +
           77  +    case 1: /* close */ {
           78  +      char *zErrmsg = 0;
           79  +      int rc;
           80  +      Tcl_DeleteCommand(interp, Tcl_GetString(objv[0]));
           81  +      rc = sqlite3ota_close(pOta, &zErrmsg);
           82  +      if( rc==SQLITE_OK || rc==SQLITE_DONE ){
           83  +        Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
           84  +        assert( zErrmsg==0 );
           85  +      }else{
           86  +        Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
           87  +        if( zErrmsg ){
           88  +          Tcl_AppendResult(interp, " - ", zErrmsg, 0);
           89  +          sqlite3_free(zErrmsg);
           90  +        }
           91  +        ret = TCL_ERROR;
           92  +      }
           93  +      break;
           94  +    }
           95  +
           96  +    case 2: /* create_ota_delta */ {
           97  +      sqlite3 *db = sqlite3ota_db(pOta);
           98  +      int rc = sqlite3_create_function(
           99  +          db, "ota_delta", -1, SQLITE_UTF8, (void*)interp, test_ota_delta, 0, 0
          100  +      );
          101  +      Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
          102  +      ret = (rc==SQLITE_OK ? TCL_OK : TCL_ERROR);
          103  +      break;
          104  +    }
          105  +
          106  +    default: /* seems unlikely */
          107  +      assert( !"cannot happen" );
          108  +      break;
          109  +  }
          110  +
          111  +  return ret;
          112  +}
          113  +
          114  +/*
          115  +** Tclcmd: sqlite3ota CMD <target-db> <ota-db>
          116  +*/
          117  +static int test_sqlite3ota(
          118  +  ClientData clientData,
          119  +  Tcl_Interp *interp,
          120  +  int objc,
          121  +  Tcl_Obj *CONST objv[]
          122  +){
          123  +  sqlite3ota *pOta = 0;
          124  +  const char *zCmd;
          125  +  const char *zTarget;
          126  +  const char *zOta;
          127  +
          128  +  if( objc!=4 ){
          129  +    Tcl_WrongNumArgs(interp, 1, objv, "NAME TARGET-DB OTA-DB");
          130  +    return TCL_ERROR;
          131  +  }
          132  +  zCmd = Tcl_GetString(objv[1]);
          133  +  zTarget = Tcl_GetString(objv[2]);
          134  +  zOta = Tcl_GetString(objv[3]);
          135  +
          136  +  pOta = sqlite3ota_open(zTarget, zOta);
          137  +  Tcl_CreateObjCommand(interp, zCmd, test_sqlite3ota_cmd, (ClientData)pOta, 0);
          138  +  Tcl_SetObjResult(interp, objv[1]);
          139  +  return TCL_OK;
          140  +}
          141  +
          142  +/*
          143  +** Tclcmd: sqlite3ota_create_vfs ?-default? NAME PARENT
          144  +*/
          145  +static int test_sqlite3ota_create_vfs(
          146  +  ClientData clientData,
          147  +  Tcl_Interp *interp,
          148  +  int objc,
          149  +  Tcl_Obj *CONST objv[]
          150  +){
          151  +  const char *zName;
          152  +  const char *zParent;
          153  +  int rc;
          154  +
          155  +  if( objc!=3 && objc!=4 ){
          156  +    Tcl_WrongNumArgs(interp, 1, objv, "?-default? NAME PARENT");
          157  +    return TCL_ERROR;
          158  +  }
          159  +
          160  +  zName = Tcl_GetString(objv[objc-2]);
          161  +  zParent = Tcl_GetString(objv[objc-1]);
          162  +  if( zParent[0]=='\0' ) zParent = 0;
          163  +
          164  +  rc = sqlite3ota_create_vfs(zName, zParent);
          165  +  if( rc!=SQLITE_OK ){
          166  +    Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
          167  +    return TCL_ERROR;
          168  +  }else if( objc==4 ){
          169  +    sqlite3_vfs *pVfs = sqlite3_vfs_find(zName);
          170  +    sqlite3_vfs_register(pVfs, 1);
          171  +  }
          172  +
          173  +  Tcl_ResetResult(interp);
          174  +  return TCL_OK;
          175  +}
          176  +
          177  +/*
          178  +** Tclcmd: sqlite3ota_destroy_vfs NAME
          179  +*/
          180  +static int test_sqlite3ota_destroy_vfs(
          181  +  ClientData clientData,
          182  +  Tcl_Interp *interp,
          183  +  int objc,
          184  +  Tcl_Obj *CONST objv[]
          185  +){
          186  +  const char *zName;
          187  +
          188  +  if( objc!=2 ){
          189  +    Tcl_WrongNumArgs(interp, 1, objv, "NAME");
          190  +    return TCL_ERROR;
          191  +  }
          192  +
          193  +  zName = Tcl_GetString(objv[1]);
          194  +  sqlite3ota_destroy_vfs(zName);
          195  +  return TCL_OK;
          196  +}
          197  +
          198  +
          199  +int SqliteOta_Init(Tcl_Interp *interp){ 
          200  +  static struct {
          201  +     char *zName;
          202  +     Tcl_ObjCmdProc *xProc;
          203  +  } aObjCmd[] = {
          204  +    { "sqlite3ota", test_sqlite3ota },
          205  +    { "sqlite3ota_create_vfs", test_sqlite3ota_create_vfs },
          206  +    { "sqlite3ota_destroy_vfs", test_sqlite3ota_destroy_vfs },
          207  +  };
          208  +  int i;
          209  +  for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
          210  +    Tcl_CreateObjCommand(interp, aObjCmd[i].zName, aObjCmd[i].xProc, 0, 0);
          211  +  }
          212  +  return TCL_OK;
          213  +}
          214  +
          215  +#else
          216  +#include <tcl.h>
          217  +int SqliteOta_Init(Tcl_Interp *interp){ return TCL_OK; }
          218  +#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_OTA) */
          219  +#endif /* defined(SQLITE_TEST) */
          220  +

Changes to main.mk.

    61     61            fts3_write.o func.o global.o hash.o \
    62     62            icu.o insert.o journal.o legacy.o loadext.o \
    63     63            main.o malloc.o mem0.o mem1.o mem2.o mem3.o mem5.o \
    64     64            memjournal.o \
    65     65            mutex.o mutex_noop.o mutex_unix.o mutex_w32.o \
    66     66            notify.o opcodes.o os.o os_unix.o os_win.o \
    67     67            pager.o pcache.o pcache1.o pragma.o prepare.o printf.o \
    68         -         random.o resolve.o rowset.o rtree.o select.o status.o \
           68  +         random.o resolve.o rowset.o rtree.o select.o sqlite3ota.o status.o \
    69     69            table.o threads.o tokenize.o trigger.o \
    70     70            update.o userauth.o util.o vacuum.o \
    71     71            vdbeapi.o vdbeaux.o vdbeblob.o vdbemem.o vdbesort.o \
    72     72   	 vdbetrace.o wal.o walker.o where.o utf.o vtab.o
    73     73   
    74     74   
    75     75   
................................................................................
   337    337     parse.c \
   338    338     $(TOP)/ext/fts3/fts3.c \
   339    339     $(TOP)/ext/fts3/fts3_aux.c \
   340    340     $(TOP)/ext/fts3/fts3_expr.c \
   341    341     $(TOP)/ext/fts3/fts3_tokenizer.c \
   342    342     $(TOP)/ext/fts3/fts3_write.c \
   343    343     $(TOP)/ext/async/sqlite3async.c \
   344         -  $(TOP)/ext/ota/sqlite3ota.c
          344  +  $(TOP)/ext/ota/test_ota.c
   345    345   
   346    346   # Header files used by all library source files.
   347    347   #
   348    348   HDR = \
   349    349      $(TOP)/src/btree.h \
   350    350      $(TOP)/src/btreeInt.h \
   351    351      $(TOP)/src/hash.h \
................................................................................
   570    570   	$(TCCX) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_write.c
   571    571   
   572    572   rtree.o:	$(TOP)/ext/rtree/rtree.c $(HDR) $(EXTHDR)
   573    573   	$(TCCX) -DSQLITE_CORE -c $(TOP)/ext/rtree/rtree.c
   574    574   
   575    575   userauth.o:	$(TOP)/ext/userauth/userauth.c $(HDR) $(EXTHDR)
   576    576   	$(TCCX) -DSQLITE_CORE -c $(TOP)/ext/userauth/userauth.c
          577  +
          578  +sqlite3ota.o:	$(TOP)/ext/ota/sqlite3ota.c $(HDR) $(EXTHDR)
          579  +	$(TCCX) -DSQLITE_CORE -c $(TOP)/ext/ota/sqlite3ota.c
   577    580   
   578    581   
   579    582   # Rules for building test programs and for running tests
   580    583   #
   581    584   tclsqlite3:	$(TOP)/src/tclsqlite.c libsqlite3.a
   582    585   	$(TCCX) $(TCL_FLAGS) -DTCLSH=1 -o tclsqlite3 \
   583    586   		$(TOP)/src/tclsqlite.c libsqlite3.a $(LIBTCL) $(THREADLIB)