Add SQLITE_ENABLE_OTA pre-processor directives so that this branch may be compiled with or without OTA.

FossilOrigin-Name: 600cefdd4d29c1de4d107fa7ddeb76a18edce4f5
This commit is contained in:
dan 2014-11-22 09:09:50 +00:00
parent 841ed2b0f2
commit 7bf9ec1c26
14 changed files with 239 additions and 118 deletions

View File

@ -17,6 +17,8 @@
#include <unistd.h>
#include "sqlite3.h"
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_OTA)
#include "sqlite3ota.h"
@ -1662,12 +1664,18 @@ static int test_sqlite3ota(
return TCL_OK;
}
int SqliteOta_Init(Tcl_Interp *interp){
Tcl_CreateObjCommand(interp, "sqlite3ota", test_sqlite3ota, 0, 0);
return TCL_OK;
}
#endif /* ifdef SQLITE_TEST */
#else /* !SQLITE_CORE || SQLITE_ENABLE_OTA */
# ifdef SQLITE_TEST
#include <tcl.h>
int SqliteOta_Init(Tcl_Interp *interp){ return TCL_OK; }
# endif
#endif

View File

@ -1,5 +1,5 @@
C Merge\slatest\strunk\schanges\swith\sthis\sbranch.
D 2014-11-21T14:37:24.898
C Add\sSQLITE_ENABLE_OTA\spre-processor\sdirectives\sso\sthat\sthis\sbranch\smay\sbe\scompiled\swith\sor\swithout\sOTA.
D 2014-11-22T09:09:50.320
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in a226317fdf3f4c895fb3cfedc355b4d0868ce1fb
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@ -135,7 +135,7 @@ F ext/ota/ota7.test 1fe2c5761705374530e29f70c39693076028221a
F ext/ota/ota8.test cd70e63a0c29c45c0906692827deafa34638feda
F ext/ota/ota9.test d9ad30ccb4e08f878e382876fe67752309538af9
F ext/ota/otafault.test be02466863015a583cc0ceb6aca871a5e6f7a71b
F ext/ota/sqlite3ota.c 07ef7b72358ed422b69a10e4702ab131041e2896
F ext/ota/sqlite3ota.c accfada2ab182dc52225e7345f656520a4e8db22
F ext/ota/sqlite3ota.h 04577b00c456aacb99be9c8b55572a6e3ca9aa27
F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761
F ext/rtree/rtree.c 57bec53e1a677ab74217fe1f20a58c3a47261d6b
@ -209,7 +209,7 @@ F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d
F src/legacy.c ba1863ea58c4c840335a84ec276fc2b25e22bc4e
F src/lempar.c 7274c97d24bb46631e504332ccd3bd1b37841770
F src/loadext.c de741e66e5ddc1598d904d7289239696e40ed994
F src/main.c e2adfa1e7bef8b553a1e7c250cc02bcb109d15f2
F src/main.c cd819123ed552a15c37bd2fd5360db25015dc461
F src/malloc.c 740db54387204c9a2eb67c6d98e68b08e9ef4eab
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c faf615aafd8be74a71494dfa027c113ea5c6615f
@ -230,13 +230,13 @@ F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa
F src/os_unix.c fb587121840f690101336879adfa6d0b2cd0e8c7
F src/os_win.c a9e500dd963fb1f67d7860e58b5772abe6123862
F src/os_win.h 09e751b20bbc107ffbd46e13555dc73576d88e21
F src/pager.c c2a4795e65b5794248dadd7c8bb65a8d9145995e
F src/pager.c 9fe27a768be53dbe0a818ae10791dc36100a0e76
F src/pager.h c6157af66a9999797629968921133f67716f8f9f
F src/parse.y 5dfead8aed90cb0c7c1115898ee2266804daff45
F src/pcache.c ace1b67632deeaa84859b4c16c27711dfb7db3d4
F src/pcache.h b44658c9c932d203510279439d891a2a83e12ba8
F src/pcache1.c facbdd3ecc09c8f750089d941305694301328e98
F src/pragma.c 272b122a873fc756e999c319f8e81de55ef39d5c
F src/pragma.c 8e0087a5ae6e60ac9ed48df19025cb423e3c8c34
F src/prepare.c b7b7bf020bd4c962f7c8aed5a3c542c7dfe9f9c7
F src/printf.c 9e75a6a0b55bf61cfff7d7e19d89834a1b938236
F src/random.c ba2679f80ec82c4190062d756f22d0c358180696
@ -244,10 +244,10 @@ F src/resolve.c 4965007d6497b6a4d7a6d98751cc39712885f952
F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e
F src/select.c 428165951748151e87a15295b7357221433e311b
F src/shell.c bc28d5992109717c87804e2eb1a08a7c8cc7a2fd
F src/sqlite.h.in 972125a6b4ea1891d2428cc55302c71f0fb1adb3
F src/sqlite.h.in f60a24616a6a7e622266e723ed141f0c6131514e
F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad
F src/sqlite3ext.h 17d487c3c91b0b8c584a32fbeb393f6f795eea7d
F src/sqliteInt.h d96b5f3ee07d35b52aa54a279028105b33a9592c
F src/sqliteInt.h 32d7becef5cbd9a1118608921ec99f00f96c6e5d
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
F src/status.c 81712116e826b0089bb221b018929536b2b5406f
F src/table.c f142bba7903e93ca8d113a5b8877a108ad1a27dc
@ -266,7 +266,7 @@ F src/test_autoext.c dea8a01a7153b9adc97bd26161e4226329546e12
F src/test_backup.c 3875e899222b651e18b662f86e0e50daa946344e
F src/test_blob.c 1f2e3e25255b731c4fcf15ee7990d06347cb6c09
F src/test_btree.c 2e9978eca99a9a4bfa8cae949efb00886860a64f
F src/test_config.c 035c17a173937d019b8dfc1d524f9d3fc8123504
F src/test_config.c 7d50e35f5e94235863c9bac448f63b0d141119e5
F src/test_demovfs.c 69b2085076654ebc18014cbc6386f04409c959a9
F src/test_devsym.c e7498904e72ba7491d142d5c83b476c4e76993bc
F src/test_fs.c ced436e3d4b8e4681328409b8081051ce614e28f
@ -300,7 +300,7 @@ F src/test_vfstrace.c bab9594adc976cbe696ff3970728830b4c5ed698
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
F src/threads.c 6de09362b657f19ba83e5fa521ee715787ce9fee
F src/tokenize.c cc9016e5007fc5e76789079616d2f26741bcc689
F src/trigger.c eb921d1292aca83d515bde5881df71df91d962d6
F src/trigger.c 6dcdf46a21acf4d4e011c809b2c971e63f797a1a
F src/update.c 3c4ecc282accf12d39edb8d524cf089645e55a13
F src/utf.c fc6b889ba0779b7722634cdeaa25f1930d93820c
F src/util.c 3b627daa45c7308c1e36e3dbaa3f9ce7e5c7fa73
@ -310,12 +310,12 @@ F src/vdbe.h 6fc69d9c5e146302c56e163cb4b31d1ee64a18c3
F src/vdbeInt.h 9bb69ff2447c34b6ccc58b34ec35b615f86ead78
F src/vdbeapi.c 07acb615d1e4170e71fc1b0d087f3c53a1ad8e83
F src/vdbeaux.c 5ce4f414147a3bc3cbcf00ec57f2606c25791629
F src/vdbeblob.c 845c24601a4f107f4829725fa0c672b93b816bab
F src/vdbeblob.c 317c71482ed73b0966db2d1c4e20839be3e9fe79
F src/vdbemem.c 31d8eabb0cd78bfeab4e5124c7363c3e9e54db9f
F src/vdbesort.c 87f3923483113d1c95d84640becb4e4946f27d9a
F src/vdbetrace.c 7e4222955e07dd707a2f360c0eb73452be1cb010
F src/vtab.c 2a30791bbd7926b589401bd09c3abb33de563793
F src/wal.c e8fe2d73c40066872f97db5809ea62f285175825
F src/wal.c d5c581b635951cf5513ec9699d118b32323443f3
F src/wal.h 0d3ba0c3f1b4c25796cb213568a84b9f9063f465
F src/walker.c c253b95b4ee44b21c406e2a1052636c31ea27804
F src/where.c e275cb74731a3351a9da6ba8280bd5054db6192d
@ -777,7 +777,7 @@ F test/orderby5.test 8f08a54836d21fb7c70245360751aedd1c2286fb
F test/orderby6.test 8b38138ab0972588240b3fca0985d2e400432859
F test/orderby7.test 3d1383d52ade5b9eb3a173b3147fdd296f0202da
F test/oserror.test 50417780d0e0d7cd23cf12a8277bb44024765df3
F test/ota.test d81a211dfbdf9fe02b5ad50c86f8a5df924391f5
F test/ota.test 3a8d97cbf8f7210dc6a638797c4e4cd674036927
F test/ovfl.test 4f7ca651cba5c059a12d8c67dddd49bec5747799
F test/pager1.test 1acbdb14c5952a72dd43129cabdbf69aaa3ed1fa
F test/pager2.test 67b8f40ae98112bcdba1f2b2d03ea83266418c71
@ -1200,7 +1200,7 @@ F tool/logest.c eef612f8adf4d0993dafed0416064cf50d5d33c6
F tool/mkautoconfamal.sh 5dc5010e2e748a9e1bba67baca5956a2c2deda7b
F tool/mkkeywordhash.c dfff09dbbfaf950e89af294f48f902181b144670
F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e
F tool/mkpragmatab.tcl 22c85e67987ad7d2e8789c48506ec95b99a90c08
F tool/mkpragmatab.tcl 7c9f48bfe61ba0e4018868bf34b2450026c24ae1
F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97
F tool/mksqlite3c-noext.tcl 88a1e3b0c769773fb7a9ebb363ffc603a4ac21d8
F tool/mksqlite3c.tcl e72c0c97fe1a105fa9616483e652949be2199fe6
@ -1236,7 +1236,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
P 14139542b68fbf01632a1b149cd6fca4bb01efa6 b1e6c02f8b9a2afaa12ac15a33e3f698c3be27d6
R 0115f003ae5ca012270e27f3f42f3f8e
P 7ef44c5b5bd30bcc4ef59ed172b9ce9ac6a843f6
R a969a1e9314cd2ef179f3839efd0b8ec
U dan
Z 7ed6e391881cc7d739c6ad1cb9d3b777
Z bba2f4cd69d571c58d439710133b8bb2

View File

@ -1 +1 @@
7ef44c5b5bd30bcc4ef59ed172b9ce9ac6a843f6
600cefdd4d29c1de4d107fa7ddeb76a18edce4f5

View File

@ -1960,6 +1960,7 @@ int sqlite3_wal_checkpoint_v2(
#endif
}
#ifdef SQLITE_ENABLE_OTA
/*
** Open an incremental checkpoint handle.
*/
@ -1984,6 +1985,7 @@ int sqlite3_ckpt_open(
sqlite3_mutex_leave(db->mutex);
return rc;
}
#endif /* SQLITE_ENABLE_OTA */
/*

View File

@ -642,7 +642,9 @@ struct Pager {
u8 noLock; /* Do not lock (except in WAL mode) */
u8 readOnly; /* True for a read-only database */
u8 memDb; /* True to inhibit all file I/O */
#ifdef SQLITE_ENABLE_OTA
u8 otaMode; /* Non-zero if in ota_mode */
#endif
/**************************************************************************
** The following block contains those class members that change during
@ -716,6 +718,16 @@ struct Pager {
#endif
};
/*
** Return the value of the pager otaMode flag (0, 1 or 2). Or, if
** SQLITE_ENABLE_OTA is not defined, return constant value 0.
*/
#ifdef SQLITE_ENABLE_OTA
# define PagerOtaMode(pPager) ((pPager)->otaMode)
#else
# define PagerOtaMode(pPager) 0
#endif
/*
** Indexes for use with Pager.aStat[]. The Pager.aStat[] array contains
** the values accessed by passing SQLITE_DBSTATUS_CACHE_HIT, CACHE_MISS
@ -2029,7 +2041,7 @@ static int pager_end_transaction(Pager *pPager, int hasMaster, int bCommit){
if( rc==SQLITE_NOTFOUND ) rc = SQLITE_OK;
}
if( !pPager->exclusiveMode && !pPager->otaMode
if( !pPager->exclusiveMode && !PagerOtaMode(pPager)
&& (!pagerUseWal(pPager) || sqlite3WalExclusiveMode(pPager->pWal, 0))
){
rc2 = pagerUnlockDb(pPager, SHARED_LOCK);
@ -3985,7 +3997,7 @@ int sqlite3PagerClose(Pager *pPager){
pPager->exclusiveMode = 0;
#ifndef SQLITE_OMIT_WAL
sqlite3WalClose(pPager->pWal,
pPager->ckptSyncFlags, pPager->pageSize, (pPager->otaMode?0:pTmp)
pPager->ckptSyncFlags, pPager->pageSize, (PagerOtaMode(pPager)?0:pTmp)
);
pPager->pWal = 0;
#endif
@ -5191,7 +5203,7 @@ int sqlite3PagerSharedLock(Pager *pPager){
** mode. Otherwise, the following function call is a no-op.
*/
rc = pagerOpenWalIfPresent(pPager);
if( rc==SQLITE_OK && pPager->otaMode ){
if( rc==SQLITE_OK && PagerOtaMode(pPager) ){
int nWal = sqlite3Strlen30(pPager->zWal);
pPager->zWal[nWal-3] = 'o';
rc = pagerOpenWalInternal(pPager, 0);
@ -5205,13 +5217,15 @@ int sqlite3PagerSharedLock(Pager *pPager){
if( pagerUseWal(pPager) ){
assert( rc==SQLITE_OK );
rc = pagerBeginReadTransaction(pPager);
if( rc==SQLITE_OK && pPager->otaMode==1 ){
if( rc==SQLITE_OK && PagerOtaMode(pPager)==1 ){
rc = sqlite3WalCheckSalt(pPager->pWal, pPager->fd);
if( rc!=SQLITE_OK ){
sqlite3WalClose(pPager->pWal, 0, 0, 0);
pPager->pWal = 0;
}else{
#ifdef SQLITE_ENABLE_OTA
pPager->otaMode = 2;
#endif
}
}
}
@ -7105,7 +7119,7 @@ void sqlite3PagerClearCache(Pager *pPager){
*/
int sqlite3PagerCheckpoint(Pager *pPager, int eMode, int *pnLog, int *pnCkpt){
int rc = SQLITE_OK;
if( pPager->pWal && pPager->otaMode==0 ){
if( pPager->pWal && PagerOtaMode(pPager)==0 ){
rc = sqlite3WalCheckpoint(pPager->pWal, eMode,
pPager->xBusyHandler, pPager->pBusyHandlerArg,
pPager->ckptSyncFlags, pPager->pageSize, (u8 *)pPager->pTmpSpace,
@ -7172,7 +7186,7 @@ static int pagerOpenWal(Pager *pPager){
*/
if( rc==SQLITE_OK ){
rc = sqlite3WalOpen(pPager->pVfs,
pPager->fd, pPager->zWal, pPager->exclusiveMode || pPager->otaMode,
pPager->fd, pPager->zWal, pPager->exclusiveMode || PagerOtaMode(pPager),
pPager->journalSizeLimit, &pPager->pWal
);
}
@ -7181,6 +7195,14 @@ static int pagerOpenWal(Pager *pPager){
return rc;
}
/*
** Open the WAL file if it is not open. If it is already open, set *pbOpen
** to 1 before returning. Return SQLITE_OK if successful, or an SQLite error
** code otherwise.
**
** The difference between this function and sqlite3PagerOpenWal() is that
** PagerOpenWal() does not open the WAL file if the pager is in OTA mode.
*/
static int pagerOpenWalInternal(
Pager *pPager, /* Pager object */
int *pbOpen /* OUT: Set to true if call is a no-op */
@ -7230,7 +7252,7 @@ int sqlite3PagerOpenWal(
Pager *pPager, /* Pager object */
int *pbOpen /* OUT: Set to true if call is a no-op */
){
if( pPager->otaMode ) return SQLITE_CANTOPEN;
if( PagerOtaMode(pPager) ) return SQLITE_CANTOPEN_BKPT;
return pagerOpenWalInternal(pPager, pbOpen);
}
@ -7287,7 +7309,7 @@ int sqlite3PagerCloseWal(Pager *pPager){
** of pseudo-random data.
*/
void sqlite3PagerWalSalt(Pager *pPager, u32 *aSalt){
if( pPager->otaMode ){
if( PagerOtaMode(pPager) ){
memcpy(aSalt, pPager->dbFileVers, 8);
}else{
sqlite3_randomness(8, aSalt);
@ -7310,6 +7332,7 @@ int sqlite3PagerWalFramesize(Pager *pPager){
}
#endif
#ifdef SQLITE_ENABLE_OTA
/*
** Set or clear the "OTA mode" flag.
*/
@ -7341,5 +7364,6 @@ int sqlite3PagerWalCheckpointStart(
);
}
}
#endif /* !SQLITE_ENABLE_OTA */
#endif /* SQLITE_OMIT_DISKIO */

View File

@ -310,10 +310,12 @@ static const struct sPragmaNames {
/* ePragFlag: */ 0,
/* iArg: */ 0 },
#endif
#if defined(SQLITE_ENABLE_OTA)
{ /* zName: */ "ota_mode",
/* ePragTyp: */ PragTyp_FLAG,
/* ePragFlag: */ 0,
/* iArg: */ SQLITE_OtaMode },
#endif
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
{ /* zName: */ "page_count",
/* ePragTyp: */ PragTyp_PAGE_COUNT,
@ -324,10 +326,12 @@ static const struct sPragmaNames {
/* ePragFlag: */ 0,
/* iArg: */ 0 },
#endif
#if defined(SQLITE_ENABLE_OTA)
{ /* zName: */ "pager_ota_mode",
/* ePragTyp: */ PragTyp_PAGER_OTA_MODE,
/* ePragFlag: */ 0,
/* iArg: */ 0 },
#endif
#if defined(SQLITE_DEBUG)
{ /* zName: */ "parser_trace",
/* ePragTyp: */ PragTyp_PARSER_TRACE,
@ -481,7 +485,7 @@ static const struct sPragmaNames {
/* iArg: */ SQLITE_WriteSchema|SQLITE_RecoveryMode },
#endif
};
/* Number of pragmas: 59 on by default, 72 total. */
/* Number of pragmas: 57 on by default, 72 total. */
/* End of the automatically generated pragma table.
***************************************************************************/
@ -896,6 +900,7 @@ void sqlite3Pragma(
** Other clients see a rollback-mode database on which the pager_ota_mode
** client is holding a SHARED lock.
*/
#ifdef SQLITE_ENABLE_OTA
case PragTyp_PAGER_OTA_MODE: {
Btree *pBt = pDb->pBt;
assert( pBt!=0 );
@ -916,6 +921,7 @@ void sqlite3Pragma(
}
break;
}
#endif /* SQLITE_ENABLE_OTA */
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
/*

View File

@ -7445,62 +7445,6 @@ int sqlite3_vtab_on_conflict(sqlite3 *);
/* #define SQLITE_ABORT 4 // Also an error code */
#define SQLITE_REPLACE 5
/*
** Allocate a statement handle that may be used to write directly to an
** index b-tree. This allows the user to create a corrupt database. Once
** the statement handle is allocated, it may be used with the same APIs
** as any statement handle created with sqlite3_prepare().
**
** The statement writes to the index specified by parameter zIndex, which
** must be in the "main" database. If argument bDelete is false, then each
** time the statement is sqlite3_step()ed, an entry is inserted into the
** b-tree index. If it is true, then an entry may be deleted (or may not, if
** the specified key is not found) each time the statement is
** sqlite3_step()ed.
**
** If statement compilation is successful, *ppStmt is set to point to the
** new statement handle and SQLITE_OK is returned. Otherwise, if an error
** occurs, *ppStmt is set to NULL and an error code returned. An error
** message may be left in the database handle in this case.
**
** If statement compilation succeeds, output variable *pnCol is set to the
** total number of columns in the index, including the primary key columns
** at the end. Variable *paiCol is set to point to an array *pnCol entries
** in size. Each entry is the table column index, numbered from zero from left
** to right, of the corresponding index column. For example, if:
**
** CREATE TABLE t1(a, b, c, d);
** CREATE INDEX i1 ON t1(b, c);
**
** then *pnCol is 3 and *paiCol points to an array containing {1, 2, -1}.
** If table t1 had an explicit INTEGER PRIMARY KEY, then the "-1" in the
** *paiCol array would be replaced by its column index. Or if:
**
** CREATE TABLE t2(a, b, c, d, PRIMARY KEY(d, c)) WITHOUT ROWID;
** CREATE INDEX i2 ON t2(a);
**
** then (*pnCol) is 3 and *paiCol points to an array containing {0, 3, 2}.
**
** The lifetime of the array is the same as that of the statement handle -
** it is automatically freed when the statement handle is passed to
** sqlite3_finalize().
**
** The statement has (*pnCol) SQL variables that values may be bound to.
** They correspond to the values used to create the index key that is
** inserted or deleted when the statement is stepped.
**
** If the index is a UNIQUE index, the usual checking and error codes apply
** to insert operations.
*/
int sqlite3_index_writer(
sqlite3 *db,
int bDelete, /* Zero for insert, non-zero for delete */
const char *zIndex, /* Index to write to */
sqlite3_stmt**, /* OUT: New statement handle */
const char ***pazColl, /* OUT: Collation sequences for each column */
int **paiCol, int *pnCol /* OUT: See above */
);
/*
** CAPI3REF: Prepared Statement Scan Status Opcodes
** KEYWORDS: {scanstatus options}
@ -7594,6 +7538,66 @@ SQLITE_EXPERIMENTAL int sqlite3_stmt_scanstatus(
*/
SQLITE_EXPERIMENTAL void sqlite3_stmt_scanstatus_reset(sqlite3_stmt*);
/*
** Allocate a statement handle that may be used to write directly to an
** index b-tree. This allows the user to create a corrupt database. Once
** the statement handle is allocated, it may be used with the same APIs
** as any statement handle created with sqlite3_prepare().
**
** The statement writes to the index specified by parameter zIndex, which
** must be in the "main" database. If argument bDelete is false, then each
** time the statement is sqlite3_step()ed, an entry is inserted into the
** b-tree index. If it is true, then an entry may be deleted (or may not, if
** the specified key is not found) each time the statement is
** sqlite3_step()ed.
**
** If statement compilation is successful, *ppStmt is set to point to the
** new statement handle and SQLITE_OK is returned. Otherwise, if an error
** occurs, *ppStmt is set to NULL and an error code returned. An error
** message may be left in the database handle in this case.
**
** If statement compilation succeeds, output variable *pnCol is set to the
** total number of columns in the index, including the primary key columns
** at the end. Variable *paiCol is set to point to an array *pnCol entries
** in size. Each entry is the table column index, numbered from zero from left
** to right, of the corresponding index column. For example, if:
**
** CREATE TABLE t1(a, b, c, d);
** CREATE INDEX i1 ON t1(b, c);
**
** then *pnCol is 3 and *paiCol points to an array containing {1, 2, -1}.
** If table t1 had an explicit INTEGER PRIMARY KEY, then the "-1" in the
** *paiCol array would be replaced by its column index. Or if:
**
** CREATE TABLE t2(a, b, c, d, PRIMARY KEY(d, c)) WITHOUT ROWID;
** CREATE INDEX i2 ON t2(a);
**
** then (*pnCol) is 3 and *paiCol points to an array containing {0, 3, 2}.
**
** The lifetime of the array is the same as that of the statement handle -
** it is automatically freed when the statement handle is passed to
** sqlite3_finalize().
**
** The statement has (*pnCol) SQL variables that values may be bound to.
** They correspond to the values used to create the index key that is
** inserted or deleted when the statement is stepped.
**
** If the index is a UNIQUE index, the usual checking and error codes apply
** to insert operations.
**
** This API is only available if SQLITE_ENABLE_OTA is defined at compile
** time. It is intended for use by the OTA extension only. As such, it is
** subject to change or removal at any point.
*/
int sqlite3_index_writer(
sqlite3 *db,
int bDelete, /* Zero for insert, non-zero for delete */
const char *zIndex, /* Index to write to */
sqlite3_stmt**, /* OUT: New statement handle */
const char ***pazColl, /* OUT: Collation sequence for each column */
int **paiCol, int *pnCol /* OUT: See above */
);
/*
** Incremental checkpoint API.
**
@ -7622,9 +7626,13 @@ SQLITE_EXPERIMENTAL void sqlite3_stmt_scanstatus_reset(sqlite3_stmt*);
** The contents of this buffer may be passed to a later call to
** sqlite3_ckpt_open() to restart the checkpoint. The second output variable
** is set to the size of the buffer in bytes.
**
** These APIs are only available if SQLITE_ENABLE_OTA is defined at compile
** time. They are intended for use by the OTA extension only. As such, they
** are subject to change or removal at any point.
*/
typedef struct sqlite3_ckpt sqlite3_ckpt;
int sqlite3_ckpt_open(sqlite3*, unsigned char *a, int n, sqlite3_ckpt **ppCkpt);
int sqlite3_ckpt_open(sqlite3*, unsigned char*, int n, sqlite3_ckpt **ppCkpt);
int sqlite3_ckpt_step(sqlite3_ckpt*);
int sqlite3_ckpt_close(sqlite3_ckpt*, unsigned char **pa, int *pn);

View File

@ -1196,8 +1196,11 @@ struct sqlite3 {
#define SQLITE_QueryOnly 0x02000000 /* Disable database changes */
#define SQLITE_VdbeEQP 0x04000000 /* Debug EXPLAIN QUERY PLAN */
#define SQLITE_OtaMode 0x08000000 /* True in "ota mode" */
#ifdef SQLITE_ENABLE_OTA
# define SQLITE_OtaMode 0x08000000 /* True in "ota mode" */
#else
# define SQLITE_OtaMode 0x00000000
#endif
/*
** Bits of the sqlite3.dbOptFlags field that are used by the

View File

@ -430,6 +430,12 @@ Tcl_SetVar2(interp, "sqlite_options", "mergesort", "1", TCL_GLOBAL_ONLY);
Tcl_SetVar2(interp, "sqlite_options", "or_opt", "1", TCL_GLOBAL_ONLY);
#endif
#ifdef SQLITE_ENABLE_OTA
Tcl_SetVar2(interp, "sqlite_options", "ota", "1", TCL_GLOBAL_ONLY);
#else
Tcl_SetVar2(interp, "sqlite_options", "ota", "0", TCL_GLOBAL_ONLY);
#endif
#ifdef SQLITE_OMIT_PAGER_PRAGMAS
Tcl_SetVar2(interp, "sqlite_options", "pager_pragmas", "0", TCL_GLOBAL_ONLY);
#else

View File

@ -50,7 +50,7 @@ void sqlite3DeleteTriggerStep(sqlite3 *db, TriggerStep *pTriggerStep){
Trigger *sqlite3TriggerList(Parse *pParse, Table *pTab){
Schema * const pTmpSchema = pParse->db->aDb[1].pSchema;
Trigger *pList = 0; /* List of triggers to return */
int bOta = !!(pParse->db->flags & SQLITE_OtaMode);
const int bOta = !!(pParse->db->flags & SQLITE_OtaMode);
if( pParse->disableTriggers ){
return 0;

View File

@ -467,6 +467,11 @@ int sqlite3_blob_reopen(sqlite3_blob *pBlob, sqlite3_int64 iRow){
return rc;
}
#ifdef SQLITE_ENABLE_OTA
/*
** Allocate and populate the output arrays returned by the
** sqlite3_index_writer() function.
*/
static int indexWriterOutputVars(
sqlite3 *db,
Index *pIdx,
@ -529,7 +534,10 @@ static int indexWriterOutputVars(
return SQLITE_OK;
}
/*
** Prepare and return an SQL statement handle that can be used to write
** directly to an index b-tree.
*/
int sqlite3_index_writer(
sqlite3 *db,
int bDelete,
@ -634,5 +642,6 @@ index_writer_out:
sqlite3_mutex_leave(db->mutex);
return rc;
}
#endif /* SQLITE_ENABLE_OTA */
#endif /* #ifndef SQLITE_OMIT_INCRBLOB */

107
src/wal.c
View File

@ -483,7 +483,14 @@ struct WalIterator {
};
/*
** walCheckpoint
** An object of the following type is used to store state information for
** an ongoing checkpoint operation. For normal checkpoints, the instance
** is allocated on the stack by the walCheckpoint() function. For the special
** incremental checkpoints performed by OTA clients, it is allocated in
** heap memory by sqlite3WalCheckpointStart().
**
** See the implementations of walCheckpointStart(), walCheckpointStep() and
** walCheckpointFinalize() for further details.
*/
typedef struct WalCkpt WalCkpt;
struct WalCkpt {
@ -1642,8 +1649,15 @@ static int walPagesize(Wal *pWal){
return (pWal->hdr.szPage&0xfe00) + ((pWal->hdr.szPage&0x0001)<<16);
}
/*
** Initialize the contents of the WalCkpt object indicated by the final
** argument and begin a checkpoint operation. The CKPT lock must already
** be held when this function is called.
**
** Return SQLITE_OK if successful or an error code otherwise.
*/
static int walCheckpointStart(
Wal *pWal,
Wal *pWal, /* Wal connection */
u8 *aBuf, /* Page-sized temporary buffer */
int nBuf, /* Size of aBuf[] in bytes */
int (*xBusy)(void*), /* Function to call when busy (or NULL) */
@ -1655,7 +1669,6 @@ static int walCheckpointStart(
int i; /* Iterator variable */
memset(p, 0, sizeof(WalCkpt));
if( pWal->hdr.mxFrame && walPagesize(pWal)!=nBuf ){
return SQLITE_CORRUPT_BKPT;
}
@ -1729,6 +1742,12 @@ static int walCheckpointStart(
return rc;
}
/*
** Attempt to copy the next frame from the wal file to the database file. If
** there are no more frames to copy to the database file return SQLITE_DONE.
** If the frame is successfully copied, return SQLITE_OK. Or, if an error
** occurs, return an SQLite error code.
*/
static int walCheckpointStep(WalCkpt *p){
u32 iDbpage = 0; /* Next database page to write */
u32 iFrame = 0; /* Wal frame containing data for iDbpage */
@ -1760,6 +1779,16 @@ static int walCheckpointStep(WalCkpt *p){
return rc;
}
/*
** The current round of checkpointing work using the object indicated by
** the only argument is now finished. If no error occcurred, this function
** saves the results to shared memory (i.e. updates the WalCkptInfo.nBackfill
** variable), and truncates and syncs the database file as required.
**
** All dynamic resources currently held by the WalCkpt object are released.
** It is the responsibility of the caller to delete the WalCkpt itself if
** required.
*/
static int walCheckpointFinalize(WalCkpt *p){
if( p->pIter ){
int rc = p->rc;
@ -1780,9 +1809,15 @@ static int walCheckpointFinalize(WalCkpt *p){
p->pInfo->nBackfill = p->mxSafeFrame;
}
p->rc = rc;
}else if( rc==SQLITE_OK && p->sync_flags ){
/* If work was not completed, but no error has occured. */
p->rc = sqlite3OsSync(pWal->pDbFd, p->sync_flags);
}else{
#ifdef SQLITE_ENABLE_OTA
if( rc==SQLITE_OK && p->sync_flags ){
/* If work was not completed, but no error has occured. */
p->rc = sqlite3OsSync(pWal->pDbFd, p->sync_flags);
}
#else
assert( rc!=SQLITE_OK );
#endif
}
/* Release the reader lock held while backfilling */
@ -1846,7 +1881,6 @@ static int walCheckpoint(
/* Step the checkpoint object until it reports something other than
** SQLITE_OK. */
while( SQLITE_OK==(rc = walCheckpointStep(&sC)) );
if( rc==SQLITE_DONE ) rc = SQLITE_OK;
rc = walCheckpointFinalize(&sC);
/* If this is an SQLITE_CHECKPOINT_RESTART operation, and the entire wal
@ -1893,8 +1927,8 @@ static void walLimitSize(Wal *pWal, i64 nMax){
/*
** Close a connection to a log file.
**
** If parameter zBuf is not NULL, attempt to obtain an exclusive lock
** and run a checkpoint.
** If parameter zBuf is not NULL, also attempt to obtain an exclusive
** lock and run a checkpoint.
*/
int sqlite3WalClose(
Wal *pWal, /* Wal to close */
@ -1914,7 +1948,10 @@ int sqlite3WalClose(
**
** The EXCLUSIVE lock is not released before returning.
*/
if( zBuf ){
#ifdef SQLITE_ENABLE_OTA
if( zBuf ) /* In non-OTA builds, zBuf is always non-NULL */
#endif
{
rc = sqlite3OsLock(pWal->pDbFd, SQLITE_LOCK_EXCLUSIVE);
if( rc==SQLITE_OK ){
if( pWal->exclusiveMode==WAL_NORMAL_MODE ){
@ -3071,6 +3108,11 @@ int sqlite3WalCheckpoint(
return (rc==SQLITE_OK && eMode!=eMode2 ? SQLITE_BUSY : rc);
}
#ifdef SQLITE_ENABLE_OTA
/*
** Step the checkpoint object passed as the first argument.
*/
int sqlite3_ckpt_step(sqlite3_ckpt *pCkpt){
int rc;
WalCkpt *p = (WalCkpt*)pCkpt;
@ -3080,6 +3122,14 @@ int sqlite3_ckpt_step(sqlite3_ckpt *pCkpt){
return rc;
}
/*
** Close the checkpoint object passed as the first argument. If the checkpoint
** was completed, zero the two output variables. Otherwise, set *paState to
** point to a buffer containing data that may be passed to a subsequent
** call to ckpt_open() to resume the checkpoint. In this case *pnState is
** set to the size of the buffer in bytes. The buffer should be eventually
** freed by the caller using sqlite3_free().
*/
int sqlite3_ckpt_close(sqlite3_ckpt *pCkpt, u8 **paState, int *pnState){
int rc;
WalCkpt *p = (WalCkpt*)pCkpt;
@ -3192,6 +3242,25 @@ int sqlite3WalCheckpointStart(
return rc;
}
/*
** Unless the wal file is empty, check that the 8 bytes of salt stored in
** the wal header are identical to those in the buffer indicated by the
** second argument. If they are not, return SQLITE_BUSY_SNAPSHOT. Otherwise,
** if the buffers match or the WAL file is empty, return SQLITE_OK.
*/
int sqlite3WalCheckSalt(Wal *pWal, sqlite3_file *pFd){
int rc = SQLITE_OK;
if( pWal->hdr.mxFrame>0 ){
u8 aData[16];
rc = sqlite3OsRead(pFd, aData, sizeof(aData), 24);
if( rc==SQLITE_OK && memcmp(pWal->hdr.aSalt, aData, 8) ){
rc = SQLITE_BUSY_SNAPSHOT;
}
}
return rc;
}
#endif /* SQLITE_ENABLE_OTA */
/* Return the value to pass to a sqlite3_wal_hook callback, the
** number of frames in the WAL at the point of the last commit since
** sqlite3WalCallback() was called. If no commits have occurred since
@ -3276,24 +3345,6 @@ int sqlite3WalHeapMemory(Wal *pWal){
return (pWal && pWal->exclusiveMode==WAL_HEAPMEMORY_MODE );
}
/*
** Unless the wal file is empty, check that the 8 bytes of salt stored in
** the wal header are identical to those in the buffer indicated by the
** second argument. If they are not, return SQLITE_BUSY_SNAPSHOT. Otherwise,
** if the buffers match or the WAL file is empty, return SQLITE_OK.
*/
int sqlite3WalCheckSalt(Wal *pWal, sqlite3_file *pFd){
int rc = SQLITE_OK;
if( pWal->hdr.mxFrame>0 ){
u8 aData[16];
rc = sqlite3OsRead(pFd, aData, sizeof(aData), 24);
if( rc==SQLITE_OK && memcmp(pWal->hdr.aSalt, aData, 8) ){
rc = SQLITE_BUSY_SNAPSHOT;
}
}
return rc;
}
#ifdef SQLITE_ENABLE_ZIPVFS
/*
** If the argument is not NULL, it points to a Wal object that holds a

View File

@ -11,6 +11,8 @@
set testdir [file dirname $argv0]
source $testdir/permutations.test
run_test_suite ota
ifcapable !ota { finish_test ; return }
run_test_suite ota
finish_test

View File

@ -298,10 +298,12 @@ set pragma_def {
NAME: threads
NAME: pager_ota_mode
IF: defined(SQLITE_ENABLE_OTA)
NAME: ota_mode
TYPE: FLAG
ARG: SQLITE_OtaMode
IF: defined(SQLITE_ENABLE_OTA)
}
fconfigure stdout -translation lf
set name {}