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 |
Timelines: | family | ancestors | descendants | both | ota-update |
Files: | files | file ages | folders |
SHA1: |
46119e8d8e391d8dea844352521b5841 |
User & Date: | dan 2015-03-05 16:21:20.067 |
Context
2015-03-09
| ||
13:24 | Merge recent trunk enhancements into the ota-update branch. (check-in: 5489cb6892 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: 46119e8d8e 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: 158c1a4881 user: dan tags: ota-update) | |
Changes
Changes to ext/ota/ota.c.
︙ | ︙ | |||
40 41 42 43 44 45 46 | "\n" , zArgv0); exit(1); } void report_default_vfs(){ sqlite3_vfs *pVfs = sqlite3_vfs_find(0); | > > > > > > > > > | > > > > > | 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | "\n" , zArgv0); exit(1); } void report_default_vfs(){ sqlite3_vfs *pVfs = sqlite3_vfs_find(0); fprintf(stdout, "default vfs is \"%s\"\n", pVfs->zName); } void report_ota_vfs(sqlite3ota *pOta){ if( pOta ){ sqlite3 *db = sqlite3ota_db(pOta, 0); char *zName = 0; sqlite3_file_control(db, "main", SQLITE_FCNTL_VFSNAME, &zName); if( zName ){ fprintf(stdout, "using vfs \"%s\"\n", zName); }else{ fprintf(stdout, "vfs name not available\n"); } sqlite3_free(zName); } } int main(int argc, char **argv){ int i; const char *zTarget; /* Target database to apply OTA to */ const char *zOta; /* Database containing OTA */ char *zErrmsg; /* Error message, if any */ |
︙ | ︙ | |||
72 73 74 75 76 77 78 79 80 81 82 83 84 85 | report_default_vfs(); /* Open an OTA handle. If nStep is less than or equal to zero, call ** sqlite3ota_step() until either the OTA has been completely applied ** or an error occurs. Or, if nStep is greater than zero, call ** sqlite3ota_step() a maximum of nStep times. */ pOta = sqlite3ota_open(zTarget, zOta); for(i=0; (nStep<=0 || i<nStep) && sqlite3ota_step(pOta)==SQLITE_OK; i++); nProgress = sqlite3ota_progress(pOta); rc = sqlite3ota_close(pOta, &zErrmsg); /* Let the user know what happened. */ switch( rc ){ case SQLITE_OK: | > | 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 | report_default_vfs(); /* Open an OTA handle. If nStep is less than or equal to zero, call ** sqlite3ota_step() until either the OTA has been completely applied ** or an error occurs. Or, if nStep is greater than zero, call ** sqlite3ota_step() a maximum of nStep times. */ pOta = sqlite3ota_open(zTarget, zOta); report_ota_vfs(pOta); for(i=0; (nStep<=0 || i<nStep) && sqlite3ota_step(pOta)==SQLITE_OK; i++); nProgress = sqlite3ota_progress(pOta); rc = sqlite3ota_close(pOta, &zErrmsg); /* Let the user know what happened. */ switch( rc ){ case SQLITE_OK: |
︙ | ︙ |
Changes to ext/ota/ota1.test.
︙ | ︙ | |||
544 545 546 547 548 549 550 | } {SQLITE_ERROR - invalid ota_control value} 9 { CREATE TABLE t1(a, b PRIMARY KEY) WITHOUT ROWID; CREATE TABLE ota.data_t1(a, b, ota_control); INSERT INTO ota.data_t1 VALUES(1, 2, 2); } {SQLITE_ERROR - invalid ota_control value} | | > > > > > > > > > > > > > > > > > > > | 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 | } {SQLITE_ERROR - invalid ota_control value} 9 { CREATE TABLE t1(a, b PRIMARY KEY) WITHOUT ROWID; CREATE TABLE ota.data_t1(a, b, ota_control); INSERT INTO ota.data_t1 VALUES(1, 2, 2); } {SQLITE_ERROR - invalid ota_control value} 10 { CREATE TABLE t2(a, b); CREATE TABLE ota.data_t1(a, b, ota_control); INSERT INTO ota.data_t1 VALUES(1, 2, 2); } {SQLITE_ERROR - no such table: t1} 11 { CREATE TABLE ota.data_t2(a, b, ota_control); INSERT INTO ota.data_t2 VALUES(1, 2, 2); } {SQLITE_ERROR - no such table: t2} } { reset_db forcedelete ota.db execsql { ATTACH 'ota.db' AS ota } execsql $schema do_test $tn3.6.$tn { list [catch { run_ota test.db ota.db } msg] $msg } [list 1 $error] } } # Test that an OTA database containing no input tables is handled # correctly. reset_db forcedelete ota.db do_test $tn3.7 { list [catch { run_ota test.db ota.db } msg] $msg } {0 SQLITE_DONE} catch { db close } eval $destroy_vfs } finish_test |
︙ | ︙ |
Changes to ext/ota/sqlite3ota.c.
︙ | ︙ | |||
831 832 833 834 835 836 837 838 839 840 841 842 843 844 | int bOtaRowid = 0; /* If input table has column "ota_rowid" */ int iOrder = 0; int iTnum = 0; /* Figure out the type of table this step will deal with. */ assert( pIter->eType==0 ); otaTableType(p, pIter->zTbl, &pIter->eType, &iTnum, &pIter->iPkTnum); if( p->rc ) return p->rc; if( pIter->zIdx==0 ) pIter->iTnum = iTnum; assert( pIter->eType==OTA_PK_NONE || pIter->eType==OTA_PK_IPK || pIter->eType==OTA_PK_EXTERNAL || pIter->eType==OTA_PK_WITHOUT_ROWID || pIter->eType==OTA_PK_VTAB ); | > > > > | 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 | int bOtaRowid = 0; /* If input table has column "ota_rowid" */ int iOrder = 0; int iTnum = 0; /* Figure out the type of table this step will deal with. */ assert( pIter->eType==0 ); otaTableType(p, pIter->zTbl, &pIter->eType, &iTnum, &pIter->iPkTnum); if( p->rc==SQLITE_OK && pIter->eType==OTA_PK_NOTABLE ){ p->rc = SQLITE_ERROR; p->zErrmsg = sqlite3_mprintf("no such table: %s", pIter->zTbl); } if( p->rc ) return p->rc; if( pIter->zIdx==0 ) pIter->iTnum = iTnum; assert( pIter->eType==OTA_PK_NONE || pIter->eType==OTA_PK_IPK || pIter->eType==OTA_PK_EXTERNAL || pIter->eType==OTA_PK_WITHOUT_ROWID || pIter->eType==OTA_PK_VTAB ); |
︙ | ︙ | |||
2614 2615 2616 2617 2618 2619 2620 | /* Open transactions both databases. The *-oal file is opened or ** created at this point. */ p->rc = sqlite3_exec(p->dbMain, "BEGIN IMMEDIATE", 0, 0, &p->zErrmsg); if( p->rc==SQLITE_OK ){ p->rc = sqlite3_exec(p->dbOta, "BEGIN IMMEDIATE", 0, 0, &p->zErrmsg); } | < | > > > > > > > | 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 | /* Open transactions both databases. The *-oal file is opened or ** created at this point. */ p->rc = sqlite3_exec(p->dbMain, "BEGIN IMMEDIATE", 0, 0, &p->zErrmsg); if( p->rc==SQLITE_OK ){ p->rc = sqlite3_exec(p->dbOta, "BEGIN IMMEDIATE", 0, 0, &p->zErrmsg); } /* Point the object iterator at the first object */ if( p->rc==SQLITE_OK ){ p->rc = otaObjIterFirst(p, &p->objiter); } /* If the OTA database contains no data_xxx tables, declare the OTA ** update finished. */ if( p->rc==SQLITE_OK && p->objiter.zTbl==0 ){ p->rc = SQLITE_DONE; } if( p->rc==SQLITE_OK ){ otaSetupOal(p, pState); } }else if( p->eStage==OTA_STAGE_MOVE ){ /* no-op */ }else if( p->eStage==OTA_STAGE_CKPT ){ otaSetupCheckpoint(p, pState); }else if( p->eStage==OTA_STAGE_DONE ){ p->rc = SQLITE_DONE; }else{ |
︙ | ︙ | |||
2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 | /* ** File control method. For custom operations on an otaVfs-file. */ static int otaVfsFileControl(sqlite3_file *pFile, int op, void *pArg){ ota_file *p = (ota_file *)pFile; int (*xControl)(sqlite3_file*,int,void*) = p->pReal->pMethods->xFileControl; assert( p->openFlags & (SQLITE_OPEN_MAIN_DB|SQLITE_OPEN_TEMP_DB) ); if( op==SQLITE_FCNTL_OTA ){ | > < | 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 | /* ** File control method. For custom operations on an otaVfs-file. */ static int otaVfsFileControl(sqlite3_file *pFile, int op, void *pArg){ ota_file *p = (ota_file *)pFile; int (*xControl)(sqlite3_file*,int,void*) = p->pReal->pMethods->xFileControl; int rc; assert( p->openFlags & (SQLITE_OPEN_MAIN_DB|SQLITE_OPEN_TEMP_DB) ); if( op==SQLITE_FCNTL_OTA ){ sqlite3ota *pOta = (sqlite3ota*)pArg; /* First try to find another OTA vfs lower down in the vfs stack. If ** one is found, this vfs will operate in pass-through mode. The lower ** level vfs will do the special OTA handling. */ rc = xControl(p->pReal, op, pArg); |
︙ | ︙ | |||
2994 2995 2996 2997 2998 2999 3000 | p->pOta = pOta; if( p->pWalFd ) p->pWalFd->pOta = pOta; rc = SQLITE_OK; } } return rc; } | > | > > > > > > > > > | 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 | p->pOta = pOta; if( p->pWalFd ) p->pWalFd->pOta = pOta; rc = SQLITE_OK; } } return rc; } rc = xControl(p->pReal, op, pArg); if( rc==SQLITE_OK && op==SQLITE_FCNTL_VFSNAME ){ ota_vfs *pOtaVfs = p->pOtaVfs; char *zIn = *(char**)pArg; char *zOut = sqlite3_mprintf("ota(%s)/%z", pOtaVfs->base.zName, zIn); *(char**)pArg = zOut; if( zOut==0 ) rc = SQLITE_NOMEM; } return rc; } /* ** Return the sector-size in bytes for an otaVfs-file. */ static int otaVfsSectorSize(sqlite3_file *pFile){ ota_file *p = (ota_file *)pFile; |
︙ | ︙ |
Changes to ext/ota/sqlite3ota.h.
︙ | ︙ | |||
330 331 332 333 334 335 336 | ** the custom VFS must be explicitly created by the user before the OTA ** handle is opened. The OTA VFS should be installed so that the zipvfs ** VFS uses the OTA VFS, which in turn uses any other VFS layers in use ** (for example multiplexor) to access the file-system. For example, ** to assemble an OTA enabled VFS stack that uses both zipvfs and ** multiplexor (error checking omitted): ** | | | | | 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 | ** the custom VFS must be explicitly created by the user before the OTA ** handle is opened. The OTA VFS should be installed so that the zipvfs ** VFS uses the OTA VFS, which in turn uses any other VFS layers in use ** (for example multiplexor) to access the file-system. For example, ** to assemble an OTA enabled VFS stack that uses both zipvfs and ** multiplexor (error checking omitted): ** ** // Create a VFS named "multiplex" (not the default). ** sqlite3_multiplex_initialize(0, 0); ** ** // Create an ota VFS named "ota" that uses multiplexor. If the ** // second argument were replaced with NULL, the "ota" VFS would ** // access the file-system via the system default VFS, bypassing the ** // multiplexor. ** sqlite3ota_create_vfs("ota", "multiplex"); ** ** // Create a zipvfs VFS named "zipvfs" that uses ota. ** zipvfs_create_vfs_v3("zipvfs", "ota", 0, xCompressorAlgorithmDetector); ** ** // Make zipvfs the default VFS. ** sqlite3_vfs_register(sqlite3_vfs_find("zipvfs"), 1); ** |
︙ | ︙ |
Changes to main.mk.
︙ | ︙ | |||
684 685 686 687 688 689 690 | $(TCC) -o LogEst$(EXE) $(TOP)/tool/logest.c wordcount$(EXE): $(TOP)/test/wordcount.c sqlite3.c $(TCC) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -o wordcount$(EXE) \ $(TOP)/test/wordcount.c sqlite3.c speedtest1$(EXE): $(TOP)/test/speedtest1.c sqlite3.o | | | < | 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 | $(TCC) -o LogEst$(EXE) $(TOP)/tool/logest.c wordcount$(EXE): $(TOP)/test/wordcount.c sqlite3.c $(TCC) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -o wordcount$(EXE) \ $(TOP)/test/wordcount.c sqlite3.c speedtest1$(EXE): $(TOP)/test/speedtest1.c sqlite3.o $(TCC) -I. $(OTAFLAGS) -o speedtest1$(EXE) $(TOP)/test/speedtest1.c sqlite3.o $(THREADLIB) ota$(EXE): $(TOP)/ext/ota/ota.c $(TOP)/ext/ota/sqlite3ota.c sqlite3.o $(TCC) -I. -o ota$(EXE) $(TOP)/ext/ota/ota.c sqlite3.o \ $(THREADLIB) # This target will fail if the SQLite amalgamation contains any exported # symbols that do not begin with "sqlite3_". It is run as part of the # releasetest.tcl script. # checksymbols: sqlite3.o |
︙ | ︙ |
Changes to test/speedtest1.c.
︙ | ︙ | |||
38 39 40 41 42 43 44 45 46 47 48 49 50 51 | #include "sqlite3.h" #include <assert.h> #include <stdio.h> #include <stdlib.h> #include <stdarg.h> #include <string.h> #include <ctype.h> /* All global state is held in this structure */ static struct Global { sqlite3 *db; /* The open database connection */ sqlite3_stmt *pStmt; /* Current SQL statement */ sqlite3_int64 iStart; /* Start-time for the current test */ sqlite3_int64 iTotal; /* Total time */ | > > > > | 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | #include "sqlite3.h" #include <assert.h> #include <stdio.h> #include <stdlib.h> #include <stdarg.h> #include <string.h> #include <ctype.h> #ifdef SQLITE_ENABLE_OTA # include "sqlite3ota.h" #endif /* All global state is held in this structure */ static struct Global { sqlite3 *db; /* The open database connection */ sqlite3_stmt *pStmt; /* Current SQL statement */ sqlite3_int64 iStart; /* Start-time for the current test */ sqlite3_int64 iTotal; /* Total time */ |
︙ | ︙ | |||
530 531 532 533 534 535 536 | zNum[len+1] = 0; sqlite3_bind_text(g.pStmt, 1, zNum, len, SQLITE_STATIC); speedtest1_run(); } speedtest1_exec("COMMIT"); speedtest1_end_test(); | | | 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 | zNum[len+1] = 0; sqlite3_bind_text(g.pStmt, 1, zNum, len, SQLITE_STATIC); speedtest1_run(); } speedtest1_exec("COMMIT"); speedtest1_end_test(); n = 10; /* g.szTest/5; */ speedtest1_begin_test(145, "%d SELECTS w/ORDER BY and LIMIT, unindexed", n); speedtest1_exec("BEGIN"); speedtest1_prepare( "SELECT a, b, c FROM t1 WHERE c LIKE ?1\n" " ORDER BY a LIMIT 10; -- %d times", n ); for(i=1; i<=n; i++){ |
︙ | ︙ | |||
1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 | nLook = integerValue(argv[i+1]); szLook = integerValue(argv[i+2]); i += 2; }else if( strcmp(z,"nosync")==0 ){ noSync = 1; }else if( strcmp(z,"notnull")==0 ){ g.zNN = "NOT NULL"; }else if( strcmp(z,"pagesize")==0 ){ if( i>=argc-1 ) fatal_error("missing argument on %s\n", argv[i]); pageSize = integerValue(argv[++i]); }else if( strcmp(z,"pcache")==0 ){ if( i>=argc-2 ) fatal_error("missing arguments on %s\n", argv[i]); nPCache = integerValue(argv[i+1]); szPCache = integerValue(argv[i+2]); | > > > > > | 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 | nLook = integerValue(argv[i+1]); szLook = integerValue(argv[i+2]); i += 2; }else if( strcmp(z,"nosync")==0 ){ noSync = 1; }else if( strcmp(z,"notnull")==0 ){ g.zNN = "NOT NULL"; #ifdef SQLITE_ENABLE_OTA }else if( strcmp(z,"ota")==0 ){ sqlite3ota_create_vfs("ota", 0); sqlite3_vfs_register(sqlite3_vfs_find("ota"), 1); #endif }else if( strcmp(z,"pagesize")==0 ){ if( i>=argc-1 ) fatal_error("missing argument on %s\n", argv[i]); pageSize = integerValue(argv[++i]); }else if( strcmp(z,"pcache")==0 ){ if( i>=argc-2 ) fatal_error("missing arguments on %s\n", argv[i]); nPCache = integerValue(argv[i+1]); szPCache = integerValue(argv[i+2]); |
︙ | ︙ |