/ Check-in [46119e8d]
Login

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

Overview
Comment:Fix some problems with OTA and empty target databases, or target databases with the wrong set of tables. Also add SQLITE_FCNTL_VFSNAME support to the OTA VFS.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | ota-update
Files: files | file ages | folders
SHA1:46119e8d8e391d8dea844352521b58415f7365b1
User & Date: dan 2015-03-05 16:21:20
Context
2015-03-09
13:24
Merge recent trunk enhancements into the ota-update branch. check-in: 5489cb68 user: drh tags: ota-update
2015-03-05
16:21
Fix some problems with OTA and empty target databases, or target databases with the wrong set of tables. Also add SQLITE_FCNTL_VFSNAME support to the OTA VFS. check-in: 46119e8d user: dan tags: ota-update
14:07
Add comments to sqlite3ota.h to make it clear that passing NULL in place of a parent VFS name to sqlite3ota_create_vfs() causes the new VFS to use the system default as its parent. check-in: 158c1a48 user: dan tags: ota-update
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to ext/ota/ota.c.

    40     40   "\n"
    41     41   , zArgv0);
    42     42     exit(1);
    43     43   }
    44     44   
    45     45   void report_default_vfs(){
    46     46     sqlite3_vfs *pVfs = sqlite3_vfs_find(0);
    47         -  fprintf(stdout, "using vfs \"%s\"\n", pVfs->zName);
           47  +  fprintf(stdout, "default vfs is \"%s\"\n", pVfs->zName);
           48  +}
           49  +
           50  +void report_ota_vfs(sqlite3ota *pOta){
           51  +  if( pOta ){
           52  +    sqlite3 *db = sqlite3ota_db(pOta, 0);
           53  +    char *zName = 0;
           54  +    sqlite3_file_control(db, "main", SQLITE_FCNTL_VFSNAME, &zName);
           55  +    if( zName ){
           56  +      fprintf(stdout, "using vfs \"%s\"\n", zName);
           57  +    }else{
           58  +      fprintf(stdout, "vfs name not available\n");
           59  +    }
           60  +    sqlite3_free(zName);
           61  +  }
    48     62   }
    49     63   
    50     64   int main(int argc, char **argv){
    51     65     int i;
    52     66     const char *zTarget;            /* Target database to apply OTA to */
    53     67     const char *zOta;               /* Database containing OTA */
    54     68     char *zErrmsg;                  /* Error message, if any */
................................................................................
    72     86     report_default_vfs();
    73     87   
    74     88     /* Open an OTA handle. If nStep is less than or equal to zero, call
    75     89     ** sqlite3ota_step() until either the OTA has been completely applied
    76     90     ** or an error occurs. Or, if nStep is greater than zero, call
    77     91     ** sqlite3ota_step() a maximum of nStep times.  */
    78     92     pOta = sqlite3ota_open(zTarget, zOta);
           93  +  report_ota_vfs(pOta);
    79     94     for(i=0; (nStep<=0 || i<nStep) && sqlite3ota_step(pOta)==SQLITE_OK; i++);
    80     95     nProgress = sqlite3ota_progress(pOta);
    81     96     rc = sqlite3ota_close(pOta, &zErrmsg);
    82     97   
    83     98     /* Let the user know what happened. */
    84     99     switch( rc ){
    85    100       case SQLITE_OK:

Changes to ext/ota/ota1.test.

   544    544          } {SQLITE_ERROR - invalid ota_control value}
   545    545   
   546    546          9 {
   547    547            CREATE TABLE t1(a, b PRIMARY KEY) WITHOUT ROWID;
   548    548            CREATE TABLE ota.data_t1(a, b, ota_control);
   549    549            INSERT INTO ota.data_t1 VALUES(1, 2, 2);
   550    550          } {SQLITE_ERROR - invalid ota_control value}
   551         -    
          551  +
          552  +       10 {
          553  +         CREATE TABLE t2(a, b);
          554  +         CREATE TABLE ota.data_t1(a, b, ota_control);
          555  +         INSERT INTO ota.data_t1 VALUES(1, 2, 2);
          556  +       } {SQLITE_ERROR - no such table: t1}
          557  +
          558  +       11 {
          559  +         CREATE TABLE ota.data_t2(a, b, ota_control);
          560  +         INSERT INTO ota.data_t2 VALUES(1, 2, 2);
          561  +       } {SQLITE_ERROR - no such table: t2}
          562  +
   552    563       } {
   553    564         reset_db
   554    565         forcedelete ota.db
   555    566         execsql { ATTACH 'ota.db' AS ota }
   556    567         execsql $schema
   557    568   
   558    569         do_test $tn3.6.$tn {
   559    570           list [catch { run_ota test.db ota.db } msg] $msg
   560    571         } [list 1 $error]
   561    572       }
   562    573     }
          574  +
          575  +  # Test that an OTA database containing no input tables is handled
          576  +  # correctly.
          577  +  reset_db
          578  +  forcedelete ota.db
          579  +  do_test $tn3.7 {
          580  +    list [catch { run_ota test.db ota.db } msg] $msg
          581  +  } {0 SQLITE_DONE}
   563    582   
   564    583     catch { db close }
   565    584     eval $destroy_vfs
   566    585   }
   567    586   
   568    587   
   569    588   finish_test
   570    589   

Changes to ext/ota/sqlite3ota.c.

   831    831       int bOtaRowid = 0;            /* If input table has column "ota_rowid" */
   832    832       int iOrder = 0;
   833    833       int iTnum = 0;
   834    834   
   835    835       /* Figure out the type of table this step will deal with. */
   836    836       assert( pIter->eType==0 );
   837    837       otaTableType(p, pIter->zTbl, &pIter->eType, &iTnum, &pIter->iPkTnum);
          838  +    if( p->rc==SQLITE_OK && pIter->eType==OTA_PK_NOTABLE ){
          839  +      p->rc = SQLITE_ERROR;
          840  +      p->zErrmsg = sqlite3_mprintf("no such table: %s", pIter->zTbl);
          841  +    }
   838    842       if( p->rc ) return p->rc;
   839    843       if( pIter->zIdx==0 ) pIter->iTnum = iTnum;
   840    844   
   841    845       assert( pIter->eType==OTA_PK_NONE || pIter->eType==OTA_PK_IPK 
   842    846            || pIter->eType==OTA_PK_EXTERNAL || pIter->eType==OTA_PK_WITHOUT_ROWID
   843    847            || pIter->eType==OTA_PK_VTAB
   844    848       );
................................................................................
  2614   2618   
  2615   2619           /* Open transactions both databases. The *-oal file is opened or
  2616   2620           ** created at this point. */
  2617   2621           p->rc = sqlite3_exec(p->dbMain, "BEGIN IMMEDIATE", 0, 0, &p->zErrmsg);
  2618   2622           if( p->rc==SQLITE_OK ){
  2619   2623             p->rc = sqlite3_exec(p->dbOta, "BEGIN IMMEDIATE", 0, 0, &p->zErrmsg);
  2620   2624           }
  2621         -        assert( p->rc!=SQLITE_OK || p->pTargetFd->pWalFd );
  2622   2625     
  2623   2626           /* Point the object iterator at the first object */
  2624   2627           if( p->rc==SQLITE_OK ){
  2625   2628             p->rc = otaObjIterFirst(p, &p->objiter);
  2626   2629           }
  2627         -  
         2630  +
         2631  +        /* If the OTA database contains no data_xxx tables, declare the OTA
         2632  +        ** update finished.  */
         2633  +        if( p->rc==SQLITE_OK && p->objiter.zTbl==0 ){
         2634  +          p->rc = SQLITE_DONE;
         2635  +        }
         2636  +
  2628   2637           if( p->rc==SQLITE_OK ){
  2629   2638             otaSetupOal(p, pState);
  2630   2639           }
         2640  +
  2631   2641         }else if( p->eStage==OTA_STAGE_MOVE ){
  2632   2642           /* no-op */
  2633   2643         }else if( p->eStage==OTA_STAGE_CKPT ){
  2634   2644           otaSetupCheckpoint(p, pState);
  2635   2645         }else if( p->eStage==OTA_STAGE_DONE ){
  2636   2646           p->rc = SQLITE_DONE;
  2637   2647         }else{
................................................................................
  2966   2976   
  2967   2977   /*
  2968   2978   ** File control method. For custom operations on an otaVfs-file.
  2969   2979   */
  2970   2980   static int otaVfsFileControl(sqlite3_file *pFile, int op, void *pArg){
  2971   2981     ota_file *p = (ota_file *)pFile;
  2972   2982     int (*xControl)(sqlite3_file*,int,void*) = p->pReal->pMethods->xFileControl;
         2983  +  int rc;
  2973   2984   
  2974   2985     assert( p->openFlags & (SQLITE_OPEN_MAIN_DB|SQLITE_OPEN_TEMP_DB) );
  2975   2986     if( op==SQLITE_FCNTL_OTA ){
  2976         -    int rc;
  2977   2987       sqlite3ota *pOta = (sqlite3ota*)pArg;
  2978   2988   
  2979   2989       /* First try to find another OTA vfs lower down in the vfs stack. If
  2980   2990       ** one is found, this vfs will operate in pass-through mode. The lower
  2981   2991       ** level vfs will do the special OTA handling.  */
  2982   2992       rc = xControl(p->pReal, op, pArg);
  2983   2993   
................................................................................
  2994   3004           p->pOta = pOta;
  2995   3005           if( p->pWalFd ) p->pWalFd->pOta = pOta;
  2996   3006           rc = SQLITE_OK;
  2997   3007         }
  2998   3008       }
  2999   3009       return rc;
  3000   3010     }
  3001         -  return xControl(p->pReal, op, pArg);
         3011  +
         3012  +  rc = xControl(p->pReal, op, pArg);
         3013  +  if( rc==SQLITE_OK && op==SQLITE_FCNTL_VFSNAME ){
         3014  +    ota_vfs *pOtaVfs = p->pOtaVfs;
         3015  +    char *zIn = *(char**)pArg;
         3016  +    char *zOut = sqlite3_mprintf("ota(%s)/%z", pOtaVfs->base.zName, zIn);
         3017  +    *(char**)pArg = zOut;
         3018  +    if( zOut==0 ) rc = SQLITE_NOMEM;
         3019  +  }
         3020  +
         3021  +  return rc;
  3002   3022   }
  3003   3023   
  3004   3024   /*
  3005   3025   ** Return the sector-size in bytes for an otaVfs-file.
  3006   3026   */
  3007   3027   static int otaVfsSectorSize(sqlite3_file *pFile){
  3008   3028     ota_file *p = (ota_file *)pFile;

Changes to ext/ota/sqlite3ota.h.

   330    330   ** the custom VFS must be explicitly created by the user before the OTA
   331    331   ** handle is opened. The OTA VFS should be installed so that the zipvfs
   332    332   ** VFS uses the OTA VFS, which in turn uses any other VFS layers in use 
   333    333   ** (for example multiplexor) to access the file-system. For example,
   334    334   ** to assemble an OTA enabled VFS stack that uses both zipvfs and 
   335    335   ** multiplexor (error checking omitted):
   336    336   **
   337         -**     // Create a VFS named "multiplexor" (not the default).
   338         -**     sqlite3_multiplex_initialize("multiplexor", 0);
          337  +**     // Create a VFS named "multiplex" (not the default).
          338  +**     sqlite3_multiplex_initialize(0, 0);
   339    339   **
   340    340   **     // Create an ota VFS named "ota" that uses multiplexor. If the
   341    341   **     // second argument were replaced with NULL, the "ota" VFS would
   342    342   **     // access the file-system via the system default VFS, bypassing the
   343    343   **     // multiplexor.
   344         -**     sqlite3ota_create_vfs("ota", "multiplexor");
          344  +**     sqlite3ota_create_vfs("ota", "multiplex");
   345    345   **
   346    346   **     // Create a zipvfs VFS named "zipvfs" that uses ota.
   347    347   **     zipvfs_create_vfs_v3("zipvfs", "ota", 0, xCompressorAlgorithmDetector);
   348    348   **
   349    349   **     // Make zipvfs the default VFS.
   350    350   **     sqlite3_vfs_register(sqlite3_vfs_find("zipvfs"), 1);
   351    351   **

Changes to main.mk.

   684    684   	$(TCC) -o LogEst$(EXE) $(TOP)/tool/logest.c
   685    685   
   686    686   wordcount$(EXE):	$(TOP)/test/wordcount.c sqlite3.c
   687    687   	$(TCC) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -o wordcount$(EXE) \
   688    688   		$(TOP)/test/wordcount.c sqlite3.c
   689    689   
   690    690   speedtest1$(EXE):	$(TOP)/test/speedtest1.c sqlite3.o
   691         -	$(TCC) -I. -o speedtest1$(EXE) $(TOP)/test/speedtest1.c sqlite3.o $(THREADLIB)
          691  +	$(TCC) -I. $(OTAFLAGS) -o speedtest1$(EXE) $(TOP)/test/speedtest1.c sqlite3.o $(THREADLIB) 
   692    692   
   693    693   ota$(EXE): $(TOP)/ext/ota/ota.c $(TOP)/ext/ota/sqlite3ota.c sqlite3.o 
   694         -	$(TCC) -I. -o ota$(EXE) \
   695         -	  $(TOP)/ext/ota/ota.c $(TOP)/ext/ota/sqlite3ota.c sqlite3.o \
          694  +	$(TCC) -I. -o ota$(EXE) $(TOP)/ext/ota/ota.c sqlite3.o \
   696    695   	  $(THREADLIB)
   697    696   
   698    697   # This target will fail if the SQLite amalgamation contains any exported
   699    698   # symbols that do not begin with "sqlite3_". It is run as part of the
   700    699   # releasetest.tcl script.
   701    700   #
   702    701   checksymbols: sqlite3.o

Changes to test/speedtest1.c.

    38     38   #include "sqlite3.h"
    39     39   #include <assert.h>
    40     40   #include <stdio.h>
    41     41   #include <stdlib.h>
    42     42   #include <stdarg.h>
    43     43   #include <string.h>
    44     44   #include <ctype.h>
           45  +
           46  +#ifdef SQLITE_ENABLE_OTA
           47  +# include "sqlite3ota.h"
           48  +#endif
    45     49   
    46     50   /* All global state is held in this structure */
    47     51   static struct Global {
    48     52     sqlite3 *db;               /* The open database connection */
    49     53     sqlite3_stmt *pStmt;       /* Current SQL statement */
    50     54     sqlite3_int64 iStart;      /* Start-time for the current test */
    51     55     sqlite3_int64 iTotal;      /* Total time */
................................................................................
   530    534       zNum[len+1] = 0;
   531    535       sqlite3_bind_text(g.pStmt, 1, zNum, len, SQLITE_STATIC);
   532    536       speedtest1_run();
   533    537     }
   534    538     speedtest1_exec("COMMIT");
   535    539     speedtest1_end_test();
   536    540   
   537         -  n = 10; //g.szTest/5;
          541  +  n = 10; /* g.szTest/5; */
   538    542     speedtest1_begin_test(145, "%d SELECTS w/ORDER BY and LIMIT, unindexed", n);
   539    543     speedtest1_exec("BEGIN");
   540    544     speedtest1_prepare(
   541    545       "SELECT a, b, c FROM t1 WHERE c LIKE ?1\n"
   542    546       " ORDER BY a LIMIT 10; -- %d times", n
   543    547     );
   544    548     for(i=1; i<=n; i++){
................................................................................
  1200   1204           nLook = integerValue(argv[i+1]);
  1201   1205           szLook = integerValue(argv[i+2]);
  1202   1206           i += 2;
  1203   1207         }else if( strcmp(z,"nosync")==0 ){
  1204   1208           noSync = 1;
  1205   1209         }else if( strcmp(z,"notnull")==0 ){
  1206   1210           g.zNN = "NOT NULL";
         1211  +#ifdef SQLITE_ENABLE_OTA
         1212  +      }else if( strcmp(z,"ota")==0 ){
         1213  +        sqlite3ota_create_vfs("ota", 0);
         1214  +        sqlite3_vfs_register(sqlite3_vfs_find("ota"), 1);
         1215  +#endif
  1207   1216         }else if( strcmp(z,"pagesize")==0 ){
  1208   1217           if( i>=argc-1 ) fatal_error("missing argument on %s\n", argv[i]);
  1209   1218           pageSize = integerValue(argv[++i]);
  1210   1219         }else if( strcmp(z,"pcache")==0 ){
  1211   1220           if( i>=argc-2 ) fatal_error("missing arguments on %s\n", argv[i]);
  1212   1221           nPCache = integerValue(argv[i+1]);
  1213   1222           szPCache = integerValue(argv[i+2]);