1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-07-29 08:01:23 +03:00

Merge all changes in the latest 3.8.11 beta into the sessions branch.

Changes include the rename of OTA to RBU, the WITHOUT-ROWID-OR-Skipscan fix,
and improvements to pcache1.

FossilOrigin-Name: 7f0ee77062d2fcb014942c7c62c163ccc801f21b
This commit is contained in:
drh
2015-07-23 21:59:58 +00:00
58 changed files with 1839 additions and 1747 deletions

View File

@ -351,8 +351,8 @@ SRC += \
$(TOP)/ext/session/sqlite3session.c \ $(TOP)/ext/session/sqlite3session.c \
$(TOP)/ext/session/sqlite3session.h $(TOP)/ext/session/sqlite3session.h
SRC += \ SRC += \
$(TOP)/ext/ota/sqlite3ota.h \ $(TOP)/ext/rbu/sqlite3rbu.h \
$(TOP)/ext/ota/sqlite3ota.c $(TOP)/ext/rbu/sqlite3rbu.c
# Generated source code files # Generated source code files
# #
@ -410,7 +410,7 @@ TESTSRC = \
$(TOP)/ext/fts3/fts3_term.c \ $(TOP)/ext/fts3/fts3_term.c \
$(TOP)/ext/fts3/fts3_test.c \ $(TOP)/ext/fts3/fts3_test.c \
$(TOP)/ext/session/test_session.c \ $(TOP)/ext/session/test_session.c \
$(TOP)/ext/ota/test_ota.c $(TOP)/ext/rbu/test_rbu.c
# Statically linked extensions # Statically linked extensions
# #
@ -1203,10 +1203,10 @@ clean:
rm -f fuzzershell fuzzershell.exe rm -f fuzzershell fuzzershell.exe
rm -f fuzzcheck fuzzcheck.exe rm -f fuzzcheck fuzzcheck.exe
rm -f sqldiff sqldiff.exe rm -f sqldiff sqldiff.exe
rm -f fts5.c fts5.h fts5parse.* rm -f fts5.* fts5parse.*
distclean: clean distclean: clean
rm -f config.log config.status libtool Makefile sqlite3.pc rm -f config.h config.log config.status libtool Makefile sqlite3.pc
# #
# Windows section # Windows section

View File

@ -1020,8 +1020,8 @@ SRC4 = \
$(TOP)\ext\rtree\rtree.c \ $(TOP)\ext\rtree\rtree.c \
$(TOP)\ext\session\sqlite3session.h \ $(TOP)\ext\session\sqlite3session.h \
$(TOP)\ext\session\sqlite3session.c \ $(TOP)\ext\session\sqlite3session.c \
$(TOP)\ext\ota\sqlite3ota.h \ $(TOP)\ext\rbu\sqlite3rbu.h \
$(TOP)\ext\ota\sqlite3ota.c $(TOP)\ext\rbu\sqlite3rbu.c
# Generated source code files # Generated source code files
@ -1083,7 +1083,7 @@ TESTSRC = \
$(TOP)\ext\fts3\fts3_term.c \ $(TOP)\ext\fts3\fts3_term.c \
$(TOP)\ext\fts3\fts3_test.c \ $(TOP)\ext\fts3\fts3_test.c \
$(TOP)\ext\session\test_session.c \ $(TOP)\ext\session\test_session.c \
$(TOP)\ext\ota\test_ota.c $(TOP)\ext\rbu\test_rbu.c
# Statically linked extensions # Statically linked extensions
# #
@ -1866,7 +1866,7 @@ clean:
del /Q sqlite3_analyzer.exe sqlite3_analyzer.c 2>NUL del /Q sqlite3_analyzer.exe sqlite3_analyzer.c 2>NUL
del /Q sqlite-*-output.vsix 2>NUL del /Q sqlite-*-output.vsix 2>NUL
del /Q fuzzershell.exe fuzzcheck.exe sqldiff.exe 2>NUL del /Q fuzzershell.exe fuzzcheck.exe sqldiff.exe 2>NUL
del /Q fts5.c fts5.h fts5parse.* 2>NUL del /Q fts5.* fts5parse.* 2>NUL
# Dynamic link library section. # Dynamic link library section.
# #

View File

@ -348,7 +348,7 @@ clean:
distclean: clean distclean: clean
-rm -f *.tab.c -rm -f *.tab.c
-rm -f $(CONFIG_CLEAN_FILES) -rm -f $(CONFIG_CLEAN_FILES)
-rm -f config.cache config.log config.status -rm -f config.h config.cache config.log config.status
#======================================================================== #========================================================================
# Install binary object libraries. On Windows this includes both .dll and # Install binary object libraries. On Windows this includes both .dll and

View File

@ -255,7 +255,7 @@ static void fts5SnippetFunction(
int iCol; /* 1st argument to snippet() */ int iCol; /* 1st argument to snippet() */
const char *zEllips; /* 4th argument to snippet() */ const char *zEllips; /* 4th argument to snippet() */
int nToken; /* 5th argument to snippet() */ int nToken; /* 5th argument to snippet() */
int nInst; /* Number of instance matches this row */ int nInst = 0; /* Number of instance matches this row */
int i; /* Used to iterate through instances */ int i; /* Used to iterate through instances */
int nPhrase; /* Number of phrases in query */ int nPhrase; /* Number of phrases in query */
unsigned char *aSeen; /* Array of "seen instance" flags */ unsigned char *aSeen; /* Array of "seen instance" flags */
@ -263,7 +263,7 @@ static void fts5SnippetFunction(
int iBestStart = 0; /* First token of best snippet */ int iBestStart = 0; /* First token of best snippet */
int iBestLast; /* Last token of best snippet */ int iBestLast; /* Last token of best snippet */
int nBestScore = 0; /* Score of best snippet */ int nBestScore = 0; /* Score of best snippet */
int nColSize; /* Total size of iBestCol in tokens */ int nColSize = 0; /* Total size of iBestCol in tokens */
if( nVal!=5 ){ if( nVal!=5 ){
const char *zErr = "wrong number of arguments to function snippet()"; const char *zErr = "wrong number of arguments to function snippet()";
@ -407,8 +407,8 @@ static int fts5Bm25GetData(
p = pApi->xGetAuxdata(pFts, 0); p = pApi->xGetAuxdata(pFts, 0);
if( p==0 ){ if( p==0 ){
int nPhrase; /* Number of phrases in query */ int nPhrase; /* Number of phrases in query */
sqlite3_int64 nRow; /* Number of rows in table */ sqlite3_int64 nRow = 0; /* Number of rows in table */
sqlite3_int64 nToken; /* Number of tokens in table */ sqlite3_int64 nToken = 0; /* Number of tokens in table */
int nByte; /* Bytes of space to allocate */ int nByte; /* Bytes of space to allocate */
int i; int i;
@ -481,9 +481,9 @@ static void fts5Bm25Function(
double score = 0.0; /* SQL function return value */ double score = 0.0; /* SQL function return value */
Fts5Bm25Data *pData; /* Values allocated/calculated once only */ Fts5Bm25Data *pData; /* Values allocated/calculated once only */
int i; /* Iterator variable */ int i; /* Iterator variable */
int nInst; /* Value returned by xInstCount() */ int nInst = 0; /* Value returned by xInstCount() */
double D; /* Total number of tokens in row */ double D = 0.0; /* Total number of tokens in row */
double *aFreq; /* Array of phrase freq. for current row */ double *aFreq = 0; /* Array of phrase freq. for current row */
/* Calculate the phrase frequency (symbol "f(qi,D)" in the documentation) /* Calculate the phrase frequency (symbol "f(qi,D)" in the documentation)
** for each phrase in the query for the current row. */ ** for each phrase in the query for the current row. */

View File

@ -83,7 +83,7 @@ struct Fts5ExprPhrase {
Fts5ExprNode *pNode; /* FTS5_STRING node this phrase is part of */ Fts5ExprNode *pNode; /* FTS5_STRING node this phrase is part of */
Fts5Buffer poslist; /* Current position list */ Fts5Buffer poslist; /* Current position list */
int nTerm; /* Number of entries in aTerm[] */ int nTerm; /* Number of entries in aTerm[] */
Fts5ExprTerm aTerm[0]; /* Terms that make up this phrase */ Fts5ExprTerm aTerm[1]; /* Terms that make up this phrase */
}; };
/* /*
@ -104,7 +104,7 @@ struct Fts5ExprNearset {
int nNear; /* NEAR parameter */ int nNear; /* NEAR parameter */
Fts5ExprColset *pColset; /* Columns to search (NULL -> all columns) */ Fts5ExprColset *pColset; /* Columns to search (NULL -> all columns) */
int nPhrase; /* Number of entries in aPhrase[] array */ int nPhrase; /* Number of entries in aPhrase[] array */
Fts5ExprPhrase *apPhrase[0]; /* Array of phrase pointers */ Fts5ExprPhrase *apPhrase[1]; /* Array of phrase pointers */
}; };

View File

@ -66,9 +66,16 @@ struct Fts5HashEntry {
int iCol; /* Column of last value written */ int iCol; /* Column of last value written */
int iPos; /* Position of last value written */ int iPos; /* Position of last value written */
i64 iRowid; /* Rowid of last value written */ i64 iRowid; /* Rowid of last value written */
char zKey[0]; /* Nul-terminated entry key */ char zKey[8]; /* Nul-terminated entry key */
}; };
/*
** Size of Fts5HashEntry without the zKey[] array.
*/
#define FTS5_HASHENTRYSIZE (sizeof(Fts5HashEntry)-8)
/* /*
** Allocate a new hash table. ** Allocate a new hash table.
*/ */
@ -220,7 +227,7 @@ int sqlite3Fts5HashWrite(
/* If an existing hash entry cannot be found, create a new one. */ /* If an existing hash entry cannot be found, create a new one. */
if( p==0 ){ if( p==0 ){
int nByte = sizeof(Fts5HashEntry) + (nToken+1) + 1 + 64; int nByte = FTS5_HASHENTRYSIZE + (nToken+1) + 1 + 64;
if( nByte<128 ) nByte = 128; if( nByte<128 ) nByte = 128;
if( (pHash->nEntry*2)>=pHash->nSlot ){ if( (pHash->nEntry*2)>=pHash->nSlot ){
@ -231,13 +238,13 @@ int sqlite3Fts5HashWrite(
p = (Fts5HashEntry*)sqlite3_malloc(nByte); p = (Fts5HashEntry*)sqlite3_malloc(nByte);
if( !p ) return SQLITE_NOMEM; if( !p ) return SQLITE_NOMEM;
memset(p, 0, sizeof(Fts5HashEntry)); memset(p, 0, FTS5_HASHENTRYSIZE);
p->nAlloc = nByte; p->nAlloc = nByte;
p->zKey[0] = bByte; p->zKey[0] = bByte;
memcpy(&p->zKey[1], pToken, nToken); memcpy(&p->zKey[1], pToken, nToken);
assert( iHash==fts5HashKey(pHash->nSlot, p->zKey, nToken+1) ); assert( iHash==fts5HashKey(pHash->nSlot, p->zKey, nToken+1) );
p->zKey[nToken+1] = '\0'; p->zKey[nToken+1] = '\0';
p->nData = nToken+1 + 1 + sizeof(Fts5HashEntry); p->nData = nToken+1 + 1 + FTS5_HASHENTRYSIZE;
p->nData += sqlite3Fts5PutVarint(&((u8*)p)[p->nData], iRowid); p->nData += sqlite3Fts5PutVarint(&((u8*)p)[p->nData], iRowid);
p->iSzPoslist = p->nData; p->iSzPoslist = p->nData;
p->nData += 1; p->nData += 1;
@ -417,7 +424,7 @@ int sqlite3Fts5HashQuery(
if( p ){ if( p ){
fts5HashAddPoslistSize(p); fts5HashAddPoslistSize(p);
*ppDoclist = (const u8*)&p->zKey[nTerm+1]; *ppDoclist = (const u8*)&p->zKey[nTerm+1];
*pnDoclist = p->nData - (sizeof(*p) + nTerm + 1); *pnDoclist = p->nData - (FTS5_HASHENTRYSIZE + nTerm + 1);
}else{ }else{
*ppDoclist = 0; *ppDoclist = 0;
*pnDoclist = 0; *pnDoclist = 0;
@ -454,7 +461,7 @@ void sqlite3Fts5HashScanEntry(
fts5HashAddPoslistSize(p); fts5HashAddPoslistSize(p);
*pzTerm = p->zKey; *pzTerm = p->zKey;
*ppDoclist = (const u8*)&p->zKey[nTerm+1]; *ppDoclist = (const u8*)&p->zKey[nTerm+1];
*pnDoclist = p->nData - (sizeof(*p) + nTerm + 1); *pnDoclist = p->nData - (FTS5_HASHENTRYSIZE + nTerm + 1);
}else{ }else{
*pzTerm = 0; *pzTerm = 0;
*ppDoclist = 0; *ppDoclist = 0;

View File

@ -368,7 +368,7 @@ struct Fts5Structure {
u64 nWriteCounter; /* Total leaves written to level 0 */ u64 nWriteCounter; /* Total leaves written to level 0 */
int nSegment; /* Total segments in this structure */ int nSegment; /* Total segments in this structure */
int nLevel; /* Number of levels in this index */ int nLevel; /* Number of levels in this index */
Fts5StructureLevel aLevel[0]; /* Array of nLevel level objects */ Fts5StructureLevel aLevel[1]; /* Array of nLevel level objects */
}; };
/* /*
@ -738,7 +738,7 @@ static Fts5Data *fts5DataReadOrBuffer(
if( rc==SQLITE_ERROR ) rc = FTS5_CORRUPT; if( rc==SQLITE_ERROR ) rc = FTS5_CORRUPT;
if( rc==SQLITE_OK ){ if( rc==SQLITE_OK ){
u8 *aOut; /* Read blob data into this buffer */ u8 *aOut = 0; /* Read blob data into this buffer */
int nByte = sqlite3_blob_bytes(p->pReader); int nByte = sqlite3_blob_bytes(p->pReader);
if( pBuf ){ if( pBuf ){
fts5BufferSize(pBuf, MAX(nByte, p->pConfig->pgsz) + 20); fts5BufferSize(pBuf, MAX(nByte, p->pConfig->pgsz) + 20);
@ -929,7 +929,7 @@ static int fts5StructureDecode(
i += fts5GetVarint32(&pData[i], nSegment); i += fts5GetVarint32(&pData[i], nSegment);
nByte = ( nByte = (
sizeof(Fts5Structure) + /* Main structure */ sizeof(Fts5Structure) + /* Main structure */
sizeof(Fts5StructureLevel) * (nLevel) /* aLevel[] array */ sizeof(Fts5StructureLevel) * (nLevel-1) /* aLevel[] array */
); );
pRet = (Fts5Structure*)sqlite3Fts5MallocZero(&rc, nByte); pRet = (Fts5Structure*)sqlite3Fts5MallocZero(&rc, nByte);
@ -1198,7 +1198,7 @@ static void fts5StructurePromote(
if( p->rc==SQLITE_OK ){ if( p->rc==SQLITE_OK ){
int iTst; int iTst;
int iPromote = -1; int iPromote = -1;
int szPromote; /* Promote anything this size or smaller */ int szPromote = 0; /* Promote anything this size or smaller */
Fts5StructureSegment *pSeg; /* Segment just written */ Fts5StructureSegment *pSeg; /* Segment just written */
int szSeg; /* Size of segment just written */ int szSeg; /* Size of segment just written */
@ -1863,8 +1863,8 @@ static void fts5SegIterNext(
} }
}else if( pIter->pSeg==0 ){ }else if( pIter->pSeg==0 ){
const u8 *pList = 0; const u8 *pList = 0;
const char *zTerm; const char *zTerm = 0;
int nList; int nList = 0;
if( 0==(pIter->flags & FTS5_SEGITER_ONETERM) ){ if( 0==(pIter->flags & FTS5_SEGITER_ONETERM) ){
sqlite3Fts5HashScanNext(p->pHash); sqlite3Fts5HashScanNext(p->pHash);
sqlite3Fts5HashScanEntry(p->pHash, &zTerm, &pList, &nList); sqlite3Fts5HashScanEntry(p->pHash, &zTerm, &pList, &nList);
@ -2215,7 +2215,6 @@ static void fts5LeafSeek(
while( 1 ){ while( 1 ){
int i; int i;
int nCmp; int nCmp;
i64 rowid;
/* Figure out how many new bytes are in this term */ /* Figure out how many new bytes are in this term */
fts5IndexGetVarint32(a, iOff, nNew); fts5IndexGetVarint32(a, iOff, nNew);
@ -2324,7 +2323,6 @@ static void fts5SegIterSeekInit(
int h; int h;
int bGe = (flags & FTS5INDEX_QUERY_SCAN); int bGe = (flags & FTS5INDEX_QUERY_SCAN);
int bDlidx = 0; /* True if there is a doclist-index */ int bDlidx = 0; /* True if there is a doclist-index */
Fts5Data *pLeaf;
static int nCall = 0; static int nCall = 0;
nCall++; nCall++;
@ -3072,7 +3070,7 @@ static void fts5ChunkIterate(
** returned in this case. ** returned in this case.
*/ */
static int fts5AllocateSegid(Fts5Index *p, Fts5Structure *pStruct){ static int fts5AllocateSegid(Fts5Index *p, Fts5Structure *pStruct){
u32 iSegid = 0; int iSegid = 0;
if( p->rc==SQLITE_OK ){ if( p->rc==SQLITE_OK ){
if( pStruct->nSegment>=FTS5_MAX_SEGMENT ){ if( pStruct->nSegment>=FTS5_MAX_SEGMENT ){
@ -3081,8 +3079,7 @@ static int fts5AllocateSegid(Fts5Index *p, Fts5Structure *pStruct){
while( iSegid==0 ){ while( iSegid==0 ){
int iLvl, iSeg; int iLvl, iSeg;
sqlite3_randomness(sizeof(u32), (void*)&iSegid); sqlite3_randomness(sizeof(u32), (void*)&iSegid);
iSegid = (iSegid % ((1 << FTS5_DATA_ID_B) - 2)) + 1; iSegid = iSegid & ((1 << FTS5_DATA_ID_B)-1);
assert( iSegid>0 && iSegid<=65535 );
for(iLvl=0; iLvl<pStruct->nLevel; iLvl++){ for(iLvl=0; iLvl<pStruct->nLevel; iLvl++){
for(iSeg=0; iSeg<pStruct->aLevel[iLvl].nSeg; iSeg++){ for(iSeg=0; iSeg<pStruct->aLevel[iLvl].nSeg; iSeg++){
if( iSegid==pStruct->aLevel[iLvl].aSeg[iSeg].iSegid ){ if( iSegid==pStruct->aLevel[iLvl].aSeg[iSeg].iSegid ){
@ -3094,7 +3091,7 @@ static int fts5AllocateSegid(Fts5Index *p, Fts5Structure *pStruct){
} }
} }
return (int)iSegid; return iSegid;
} }
/* /*

View File

@ -145,7 +145,7 @@ struct Fts5Sorter {
i64 iRowid; /* Current rowid */ i64 iRowid; /* Current rowid */
const u8 *aPoslist; /* Position lists for current row */ const u8 *aPoslist; /* Position lists for current row */
int nIdx; /* Number of entries in aIdx[] */ int nIdx; /* Number of entries in aIdx[] */
int aIdx[0]; /* Offsets into aPoslist for current row */ int aIdx[1]; /* Offsets into aPoslist for current row */
}; };
@ -361,7 +361,7 @@ static int fts5InitVtab(
Fts5Global *pGlobal = (Fts5Global*)pAux; Fts5Global *pGlobal = (Fts5Global*)pAux;
const char **azConfig = (const char**)argv; const char **azConfig = (const char**)argv;
int rc = SQLITE_OK; /* Return code */ int rc = SQLITE_OK; /* Return code */
Fts5Config *pConfig; /* Results of parsing argc/argv */ Fts5Config *pConfig = 0; /* Results of parsing argc/argv */
Fts5Table *pTab = 0; /* New virtual table object */ Fts5Table *pTab = 0; /* New virtual table object */
/* Allocate the new vtab object and parse the configuration */ /* Allocate the new vtab object and parse the configuration */
@ -756,7 +756,7 @@ static int fts5CursorReseek(Fts5Cursor *pCsr, int *pbSkip){
*/ */
static int fts5NextMethod(sqlite3_vtab_cursor *pCursor){ static int fts5NextMethod(sqlite3_vtab_cursor *pCursor){
Fts5Cursor *pCsr = (Fts5Cursor*)pCursor; Fts5Cursor *pCsr = (Fts5Cursor*)pCursor;
int rc; int rc = SQLITE_OK;
assert( (pCsr->ePlan<2)== assert( (pCsr->ePlan<2)==
(pCsr->ePlan==FTS5_PLAN_MATCH || pCsr->ePlan==FTS5_PLAN_SOURCE) (pCsr->ePlan==FTS5_PLAN_MATCH || pCsr->ePlan==FTS5_PLAN_SOURCE)
@ -808,7 +808,7 @@ static int fts5CursorFirstSorted(Fts5Table *pTab, Fts5Cursor *pCsr, int bDesc){
const char *zRankArgs = pCsr->zRankArgs; const char *zRankArgs = pCsr->zRankArgs;
nPhrase = sqlite3Fts5ExprPhraseCount(pCsr->pExpr); nPhrase = sqlite3Fts5ExprPhraseCount(pCsr->pExpr);
nByte = sizeof(Fts5Sorter) + sizeof(int) * nPhrase; nByte = sizeof(Fts5Sorter) + sizeof(int) * (nPhrase-1);
pSorter = (Fts5Sorter*)sqlite3_malloc(nByte); pSorter = (Fts5Sorter*)sqlite3_malloc(nByte);
if( pSorter==0 ) return SQLITE_NOMEM; if( pSorter==0 ) return SQLITE_NOMEM;
memset(pSorter, 0, nByte); memset(pSorter, 0, nByte);

View File

@ -501,7 +501,7 @@ static int fts5StorageSaveTotals(Fts5Storage *p){
int sqlite3Fts5StorageDelete(Fts5Storage *p, i64 iDel){ int sqlite3Fts5StorageDelete(Fts5Storage *p, i64 iDel){
Fts5Config *pConfig = p->pConfig; Fts5Config *pConfig = p->pConfig;
int rc; int rc;
sqlite3_stmt *pDel; sqlite3_stmt *pDel = 0;
rc = fts5StorageLoadTotals(p, 1); rc = fts5StorageLoadTotals(p, 1);
@ -545,7 +545,7 @@ int sqlite3Fts5StorageSpecialDelete(
){ ){
Fts5Config *pConfig = p->pConfig; Fts5Config *pConfig = p->pConfig;
int rc; int rc;
sqlite3_stmt *pDel; sqlite3_stmt *pDel = 0;
assert( pConfig->eContent!=FTS5_CONTENT_NORMAL ); assert( pConfig->eContent!=FTS5_CONTENT_NORMAL );
rc = fts5StorageLoadTotals(p, 1); rc = fts5StorageLoadTotals(p, 1);
@ -719,7 +719,7 @@ int sqlite3Fts5StorageInsert(
){ ){
Fts5Config *pConfig = p->pConfig; Fts5Config *pConfig = p->pConfig;
int rc = SQLITE_OK; /* Return code */ int rc = SQLITE_OK; /* Return code */
sqlite3_stmt *pInsert; /* Statement used to write %_content table */ sqlite3_stmt *pInsert = 0; /* Statement used to write %_content table */
int eStmt = 0; /* Type of statement used on %_content */ int eStmt = 0; /* Type of statement used on %_content */
int i; /* Counter variable */ int i; /* Counter variable */
Fts5InsertCtx ctx; /* Tokenization callback context object */ Fts5InsertCtx ctx; /* Tokenization callback context object */

View File

@ -10,11 +10,11 @@
** **
************************************************************************* *************************************************************************
** **
** This file contains a command-line application that uses the OTA ** This file contains a command-line application that uses the RBU
** extension. See the usage() function below for an explanation. ** extension. See the usage() function below for an explanation.
*/ */
#include "sqlite3ota.h" #include "sqlite3rbu.h"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -24,18 +24,18 @@
*/ */
void usage(const char *zArgv0){ void usage(const char *zArgv0){
fprintf(stderr, fprintf(stderr,
"Usage: %s [-step NSTEP] TARGET-DB OTA-DB\n" "Usage: %s [-step NSTEP] TARGET-DB RBU-DB\n"
"\n" "\n"
" Argument OTA-DB must be an OTA database containing an update suitable for\n" " Argument RBU-DB must be an RBU database containing an update suitable for\n"
" target database TARGET-DB. If NSTEP is set to less than or equal to zero\n" " target database TARGET-DB. If NSTEP is set to less than or equal to zero\n"
" (the default value), this program attempts to apply the entire update to\n" " (the default value), this program attempts to apply the entire update to\n"
" the target database.\n" " the target database.\n"
"\n" "\n"
" If NSTEP is greater than zero, then a maximum of NSTEP calls are made\n" " If NSTEP is greater than zero, then a maximum of NSTEP calls are made\n"
" to sqlite3ota_step(). If the OTA update has not been completely applied\n" " to sqlite3rbu_step(). If the RBU update has not been completely applied\n"
" after the NSTEP'th call is made, the state is saved in the database OTA-DB\n" " after the NSTEP'th call is made, the state is saved in the database RBU-DB\n"
" and the program exits. Subsequent invocations of this (or any other OTA)\n" " and the program exits. Subsequent invocations of this (or any other RBU)\n"
" application will use this state to resume applying the OTA update to the\n" " application will use this state to resume applying the RBU update to the\n"
" target db.\n" " target db.\n"
"\n" "\n"
, zArgv0); , zArgv0);
@ -47,8 +47,8 @@ void report_default_vfs(){
fprintf(stdout, "default vfs is \"%s\"\n", pVfs->zName); fprintf(stdout, "default vfs is \"%s\"\n", pVfs->zName);
} }
void report_ota_vfs(sqlite3ota *pOta){ void report_rbu_vfs(sqlite3rbu *pRbu){
sqlite3 *db = sqlite3ota_db(pOta, 0); sqlite3 *db = sqlite3rbu_db(pRbu, 0);
if( db ){ if( db ){
char *zName = 0; char *zName = 0;
sqlite3_file_control(db, "main", SQLITE_FCNTL_VFSNAME, &zName); sqlite3_file_control(db, "main", SQLITE_FCNTL_VFSNAME, &zName);
@ -63,16 +63,16 @@ void report_ota_vfs(sqlite3ota *pOta){
int main(int argc, char **argv){ int main(int argc, char **argv){
int i; int i;
const char *zTarget; /* Target database to apply OTA to */ const char *zTarget; /* Target database to apply RBU to */
const char *zOta; /* Database containing OTA */ const char *zRbu; /* Database containing RBU */
char *zErrmsg; /* Error message, if any */ char *zErrmsg; /* Error message, if any */
sqlite3ota *pOta; /* OTA handle */ sqlite3rbu *pRbu; /* RBU handle */
int nStep = 0; /* Maximum number of step() calls */ int nStep = 0; /* Maximum number of step() calls */
int rc; int rc;
sqlite3_int64 nProgress = 0; sqlite3_int64 nProgress = 0;
/* Process command line arguments. Following this block local variables /* Process command line arguments. Following this block local variables
** zTarget, zOta and nStep are all set. */ ** zTarget, zRbu and nStep are all set. */
if( argc==5 ){ if( argc==5 ){
int nArg1 = strlen(argv[1]); int nArg1 = strlen(argv[1]);
if( nArg1>5 || nArg1<2 || memcmp("-step", argv[1], nArg1) ) usage(argv[0]); if( nArg1>5 || nArg1<2 || memcmp("-step", argv[1], nArg1) ) usage(argv[0]);
@ -81,32 +81,32 @@ int main(int argc, char **argv){
usage(argv[0]); usage(argv[0]);
} }
zTarget = argv[argc-2]; zTarget = argv[argc-2];
zOta = argv[argc-1]; zRbu = argv[argc-1];
report_default_vfs(); report_default_vfs();
/* Open an OTA handle. If nStep is less than or equal to zero, call /* Open an RBU handle. If nStep is less than or equal to zero, call
** sqlite3ota_step() until either the OTA has been completely applied ** sqlite3rbu_step() until either the RBU has been completely applied
** or an error occurs. Or, if nStep is greater than zero, call ** or an error occurs. Or, if nStep is greater than zero, call
** sqlite3ota_step() a maximum of nStep times. */ ** sqlite3rbu_step() a maximum of nStep times. */
pOta = sqlite3ota_open(zTarget, zOta, 0); pRbu = sqlite3rbu_open(zTarget, zRbu, 0);
report_ota_vfs(pOta); report_rbu_vfs(pRbu);
for(i=0; (nStep<=0 || i<nStep) && sqlite3ota_step(pOta)==SQLITE_OK; i++); for(i=0; (nStep<=0 || i<nStep) && sqlite3rbu_step(pRbu)==SQLITE_OK; i++);
nProgress = sqlite3ota_progress(pOta); nProgress = sqlite3rbu_progress(pRbu);
rc = sqlite3ota_close(pOta, &zErrmsg); rc = sqlite3rbu_close(pRbu, &zErrmsg);
/* Let the user know what happened. */ /* Let the user know what happened. */
switch( rc ){ switch( rc ){
case SQLITE_OK: case SQLITE_OK:
fprintf(stdout, fprintf(stdout,
"SQLITE_OK: ota update incomplete (%lld operations so far)\n", "SQLITE_OK: rbu update incomplete (%lld operations so far)\n",
nProgress nProgress
); );
break; break;
case SQLITE_DONE: case SQLITE_DONE:
fprintf(stdout, fprintf(stdout,
"SQLITE_DONE: ota update completed (%lld operations)\n", "SQLITE_DONE: rbu update completed (%lld operations)\n",
nProgress nProgress
); );
break; break;

View File

@ -14,128 +14,128 @@ if {![info exists testdir]} {
set testdir [file join [file dirname [info script]] .. .. test] set testdir [file join [file dirname [info script]] .. .. test]
} }
source $testdir/tester.tcl source $testdir/tester.tcl
set ::testprefix ota1 set ::testprefix rbu1
db close db close
sqlite3_shutdown sqlite3_shutdown
sqlite3_config_uri 1 sqlite3_config_uri 1
# Create a simple OTA database. That expects to write to a table: # Create a simple RBU database. That expects to write to a table:
# #
# CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c); # CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
# #
proc create_ota1 {filename} { proc create_rbu1 {filename} {
forcedelete $filename forcedelete $filename
sqlite3 ota1 $filename sqlite3 rbu1 $filename
ota1 eval { rbu1 eval {
CREATE TABLE data_t1(a, b, c, ota_control); CREATE TABLE data_t1(a, b, c, rbu_control);
INSERT INTO data_t1 VALUES(1, 2, 3, 0); INSERT INTO data_t1 VALUES(1, 2, 3, 0);
INSERT INTO data_t1 VALUES(2, 'two', 'three', 0); INSERT INTO data_t1 VALUES(2, 'two', 'three', 0);
INSERT INTO data_t1 VALUES(3, NULL, 8.2, 0); INSERT INTO data_t1 VALUES(3, NULL, 8.2, 0);
} }
ota1 close rbu1 close
return $filename return $filename
} }
# Create a simple OTA database. That expects to write to a table: # Create a simple RBU database. That expects to write to a table:
# #
# CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c); # CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
# #
# This OTA includes both insert and delete operations. # This RBU includes both insert and delete operations.
# #
proc create_ota4 {filename} { proc create_rbu4 {filename} {
forcedelete $filename forcedelete $filename
sqlite3 ota1 $filename sqlite3 rbu1 $filename
ota1 eval { rbu1 eval {
CREATE TABLE data_t1(a, b, c, ota_control); CREATE TABLE data_t1(a, b, c, rbu_control);
INSERT INTO data_t1 VALUES(1, 2, 3, 0); INSERT INTO data_t1 VALUES(1, 2, 3, 0);
INSERT INTO data_t1 VALUES(2, NULL, 5, 1); INSERT INTO data_t1 VALUES(2, NULL, 5, 1);
INSERT INTO data_t1 VALUES(3, 8, 9, 0); INSERT INTO data_t1 VALUES(3, 8, 9, 0);
INSERT INTO data_t1 VALUES(4, NULL, 11, 1); INSERT INTO data_t1 VALUES(4, NULL, 11, 1);
} }
ota1 close rbu1 close
return $filename return $filename
} }
# #
# Create a simple OTA database. That expects to write to a table: # Create a simple RBU database. That expects to write to a table:
# #
# CREATE TABLE t1(c, b, '(a)' INTEGER PRIMARY KEY); # CREATE TABLE t1(c, b, '(a)' INTEGER PRIMARY KEY);
# #
# This OTA includes both insert and delete operations. # This RBU includes both insert and delete operations.
# #
proc create_ota4b {filename} { proc create_rbu4b {filename} {
forcedelete $filename forcedelete $filename
sqlite3 ota1 $filename sqlite3 rbu1 $filename
ota1 eval { rbu1 eval {
CREATE TABLE data_t1(c, b, '(a)', ota_control); CREATE TABLE data_t1(c, b, '(a)', rbu_control);
INSERT INTO data_t1 VALUES(3, 2, 1, 0); INSERT INTO data_t1 VALUES(3, 2, 1, 0);
INSERT INTO data_t1 VALUES(5, NULL, 2, 1); INSERT INTO data_t1 VALUES(5, NULL, 2, 1);
INSERT INTO data_t1 VALUES(9, 8, 3, 0); INSERT INTO data_t1 VALUES(9, 8, 3, 0);
INSERT INTO data_t1 VALUES(11, NULL, 4, 1); INSERT INTO data_t1 VALUES(11, NULL, 4, 1);
} }
ota1 close rbu1 close
return $filename return $filename
} }
# Create a simple OTA database. That expects to write to a table: # Create a simple RBU database. That expects to write to a table:
# #
# CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c, d); # CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c, d);
# #
# This OTA includes update statements. # This RBU includes update statements.
# #
proc create_ota5 {filename} { proc create_rbu5 {filename} {
forcedelete $filename forcedelete $filename
sqlite3 ota5 $filename sqlite3 rbu5 $filename
ota5 eval { rbu5 eval {
CREATE TABLE data_t1(a, b, c, d, ota_control); CREATE TABLE data_t1(a, b, c, d, rbu_control);
INSERT INTO data_t1 VALUES(1, NULL, NULL, 5, '...x'); -- SET d = 5 INSERT INTO data_t1 VALUES(1, NULL, NULL, 5, '...x'); -- SET d = 5
INSERT INTO data_t1 VALUES(2, NULL, 10, 5, '..xx'); -- SET c=10, d = 5 INSERT INTO data_t1 VALUES(2, NULL, 10, 5, '..xx'); -- SET c=10, d = 5
INSERT INTO data_t1 VALUES(3, 11, NULL, NULL, '.x..'); -- SET b=11 INSERT INTO data_t1 VALUES(3, 11, NULL, NULL, '.x..'); -- SET b=11
} }
ota5 close rbu5 close
return $filename return $filename
} }
# Run the OTA in file $ota on target database $target until completion. # Run the RBU in file $rbu on target database $target until completion.
# #
proc run_ota {target ota} { proc run_rbu {target rbu} {
sqlite3ota ota $target $ota sqlite3rbu rbu $target $rbu
while 1 { while 1 {
set rc [ota step] set rc [rbu step]
if {$rc!="SQLITE_OK"} break if {$rc!="SQLITE_OK"} break
} }
ota close rbu close
} }
proc step_ota {target ota} { proc step_rbu {target rbu} {
while 1 { while 1 {
sqlite3ota ota $target $ota sqlite3rbu rbu $target $rbu
set rc [ota step] set rc [rbu step]
ota close rbu close
if {$rc != "SQLITE_OK"} break if {$rc != "SQLITE_OK"} break
} }
set rc set rc
} }
# Same as [step_ota], except using a URI to open the target db. # Same as [step_rbu], except using a URI to open the target db.
# #
proc step_ota_uri {target ota} { proc step_rbu_uri {target rbu} {
while 1 { while 1 {
sqlite3ota ota file:$target?xyz=&abc=123 $ota sqlite3rbu rbu file:$target?xyz=&abc=123 $rbu
set rc [ota step] set rc [rbu step]
ota close rbu close
if {$rc != "SQLITE_OK"} break if {$rc != "SQLITE_OK"} break
} }
set rc set rc
} }
# Same as [step_ota], except using an external state database - "state.db" # Same as [step_rbu], except using an external state database - "state.db"
# #
proc step_ota_state {target ota} { proc step_rbu_state {target rbu} {
while 1 { while 1 {
sqlite3ota ota $target $ota state.db sqlite3rbu rbu $target $rbu state.db
set rc [ota step] set rc [rbu step]
ota close rbu close
if {$rc != "SQLITE_OK"} break if {$rc != "SQLITE_OK"} break
} }
set rc set rc
@ -151,17 +151,17 @@ proc dbfilecksum {file} {
foreach {tn3 create_vfs destroy_vfs} { foreach {tn3 create_vfs destroy_vfs} {
1 {} {} 1 {} {}
2 { 2 {
sqlite3ota_create_vfs -default myota "" sqlite3rbu_create_vfs -default myrbu ""
} { } {
sqlite3ota_destroy_vfs myota sqlite3rbu_destroy_vfs myrbu
} }
} { } {
eval $create_vfs eval $create_vfs
foreach {tn2 cmd} { foreach {tn2 cmd} {
1 run_ota 1 run_rbu
2 step_ota 3 step_ota_uri 4 step_ota_state 2 step_rbu 3 step_rbu_uri 4 step_rbu_state
} { } {
foreach {tn schema} { foreach {tn schema} {
1 { 1 {
@ -240,12 +240,12 @@ foreach {tn3 create_vfs destroy_vfs} {
} { } {
reset_db reset_db
execsql $schema execsql $schema
create_ota1 ota.db create_rbu1 rbu.db
set check [dbfilecksum ota.db] set check [dbfilecksum rbu.db]
forcedelete state.db forcedelete state.db
do_test $tn3.1.$tn2.$tn.1 { do_test $tn3.1.$tn2.$tn.1 {
$cmd test.db ota.db $cmd test.db rbu.db
} {SQLITE_DONE} } {SQLITE_DONE}
do_execsql_test $tn3.1.$tn2.$tn.2 { SELECT * FROM t1 ORDER BY a ASC } { do_execsql_test $tn3.1.$tn2.$tn.2 { SELECT * FROM t1 ORDER BY a ASC } {
@ -266,51 +266,51 @@ foreach {tn3 create_vfs destroy_vfs} {
do_execsql_test $tn3.1.$tn2.$tn.5 { PRAGMA integrity_check } ok do_execsql_test $tn3.1.$tn2.$tn.5 { PRAGMA integrity_check } ok
if {$cmd=="step_ota_state"} { if {$cmd=="step_rbu_state"} {
do_test $tn3.1.$tn2.$tn.6 { file exists state.db } 1 do_test $tn3.1.$tn2.$tn.6 { file exists state.db } 1
do_test $tn3.1.$tn2.$tn.7 { expr {$check == [dbfilecksum ota.db]} } 1 do_test $tn3.1.$tn2.$tn.7 { expr {$check == [dbfilecksum rbu.db]} } 1
} else { } else {
do_test $tn3.1.$tn2.$tn.8 { file exists state.db } 0 do_test $tn3.1.$tn2.$tn.8 { file exists state.db } 0
do_test $tn3.1.$tn2.$tn.9 { expr {$check == [dbfilecksum ota.db]} } 0 do_test $tn3.1.$tn2.$tn.9 { expr {$check == [dbfilecksum rbu.db]} } 0
} }
} }
} }
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
# Check that an OTA cannot be applied to a table that has no PK. # Check that an RBU cannot be applied to a table that has no PK.
# #
# UPDATE: At one point OTA required that all tables featured either # UPDATE: At one point RBU required that all tables featured either
# explicit IPK columns or were declared WITHOUT ROWID. This has been # explicit IPK columns or were declared WITHOUT ROWID. This has been
# relaxed so that external PRIMARY KEYs on tables with automatic rowids # relaxed so that external PRIMARY KEYs on tables with automatic rowids
# are now allowed. # are now allowed.
# #
# UPDATE 2: Tables without any PRIMARY KEY declaration are now allowed. # UPDATE 2: Tables without any PRIMARY KEY declaration are now allowed.
# However the input table must feature an "ota_rowid" column. # However the input table must feature an "rbu_rowid" column.
# #
reset_db reset_db
create_ota1 ota.db create_rbu1 rbu.db
do_execsql_test $tn3.2.1 { CREATE TABLE t1(a, b, c) } do_execsql_test $tn3.2.1 { CREATE TABLE t1(a, b, c) }
do_test $tn3.2.2 { do_test $tn3.2.2 {
sqlite3ota ota test.db ota.db sqlite3rbu rbu test.db rbu.db
ota step rbu step
} {SQLITE_ERROR} } {SQLITE_ERROR}
do_test $tn3.2.3 { do_test $tn3.2.3 {
list [catch { ota close } msg] $msg list [catch { rbu close } msg] $msg
} {1 {SQLITE_ERROR - table data_t1 requires ota_rowid column}} } {1 {SQLITE_ERROR - table data_t1 requires rbu_rowid column}}
reset_db reset_db
do_execsql_test $tn3.2.4 { CREATE TABLE t1(a PRIMARY KEY, b, c) } do_execsql_test $tn3.2.4 { CREATE TABLE t1(a PRIMARY KEY, b, c) }
do_test $tn3.2.5 { do_test $tn3.2.5 {
sqlite3ota ota test.db ota.db sqlite3rbu rbu test.db rbu.db
ota step rbu step
} {SQLITE_OK} } {SQLITE_OK}
do_test $tn3.2.6 { do_test $tn3.2.6 {
list [catch { ota close } msg] $msg list [catch { rbu close } msg] $msg
} {0 SQLITE_OK} } {0 SQLITE_OK}
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
# Check that if a UNIQUE constraint is violated the current and all # Check that if a UNIQUE constraint is violated the current and all
# subsequent [ota step] calls return SQLITE_CONSTRAINT. And that the OTA # subsequent [rbu step] calls return SQLITE_CONSTRAINT. And that the RBU
# transaction is rolled back by the [ota close] that deletes the ota # transaction is rolled back by the [rbu close] that deletes the rbu
# handle. # handle.
# #
foreach {tn errcode errmsg schema} { foreach {tn errcode errmsg schema} {
@ -340,16 +340,16 @@ foreach {tn3 create_vfs destroy_vfs} {
set cksum [dbcksum db main] set cksum [dbcksum db main]
do_test $tn3.3.$tn.1 { do_test $tn3.3.$tn.1 {
create_ota1 ota.db create_rbu1 rbu.db
sqlite3ota ota test.db ota.db sqlite3rbu rbu test.db rbu.db
while {[set res [ota step]]=="SQLITE_OK"} {} while {[set res [rbu step]]=="SQLITE_OK"} {}
set res set res
} $errcode } $errcode
do_test $tn3.3.$tn.2 { ota step } $errcode do_test $tn3.3.$tn.2 { rbu step } $errcode
do_test $tn3.3.$tn.3 { do_test $tn3.3.$tn.3 {
list [catch { ota close } msg] $msg list [catch { rbu close } msg] $msg
} [list 1 "$errcode - $errmsg"] } [list 1 "$errcode - $errmsg"]
do_test $tn3.3.$tn.4 { dbcksum db main } $cksum do_test $tn3.3.$tn.4 { dbcksum db main } $cksum
@ -357,7 +357,7 @@ foreach {tn3 create_vfs destroy_vfs} {
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
# #
foreach {tn2 cmd} {1 run_ota 2 step_ota 3 step_ota_state } { foreach {tn2 cmd} {1 run_rbu 2 step_rbu 3 step_rbu_state } {
foreach {tn schema} { foreach {tn schema} {
1 { 1 {
CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c); CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
@ -406,12 +406,12 @@ foreach {tn3 create_vfs destroy_vfs} {
INSERT INTO t1 VALUES(6, 'hello', 'xyz'); INSERT INTO t1 VALUES(6, 'hello', 'xyz');
} }
create_ota4 ota.db create_rbu4 rbu.db
set check [dbfilecksum ota.db] set check [dbfilecksum rbu.db]
forcedelete state.db forcedelete state.db
do_test $tn3.4.$tn2.$tn.1 { do_test $tn3.4.$tn2.$tn.1 {
$cmd test.db ota.db $cmd test.db rbu.db
} {SQLITE_DONE} } {SQLITE_DONE}
do_execsql_test $tn3.4.$tn2.$tn.2 { do_execsql_test $tn3.4.$tn2.$tn.2 {
@ -424,17 +424,17 @@ foreach {tn3 create_vfs destroy_vfs} {
do_execsql_test $tn3.4.$tn2.$tn.3 { PRAGMA integrity_check } ok do_execsql_test $tn3.4.$tn2.$tn.3 { PRAGMA integrity_check } ok
if {$cmd=="step_ota_state"} { if {$cmd=="step_rbu_state"} {
do_test $tn3.4.$tn2.$tn.4 { file exists state.db } 1 do_test $tn3.4.$tn2.$tn.4 { file exists state.db } 1
do_test $tn3.4.$tn2.$tn.5 { expr {$check == [dbfilecksum ota.db]} } 1 do_test $tn3.4.$tn2.$tn.5 { expr {$check == [dbfilecksum rbu.db]} } 1
} else { } else {
do_test $tn3.4.$tn2.$tn.6 { file exists state.db } 0 do_test $tn3.4.$tn2.$tn.6 { file exists state.db } 0
do_test $tn3.4.$tn2.$tn.7 { expr {$check == [dbfilecksum ota.db]} } 0 do_test $tn3.4.$tn2.$tn.7 { expr {$check == [dbfilecksum rbu.db]} } 0
} }
} }
} }
foreach {tn2 cmd} {1 run_ota 2 step_ota 3 step_ota_state} { foreach {tn2 cmd} {1 run_rbu 2 step_rbu 3 step_rbu_state} {
foreach {tn schema} { foreach {tn schema} {
1 { 1 {
CREATE TABLE t1(c, b, '(a)' INTEGER PRIMARY KEY); CREATE TABLE t1(c, b, '(a)' INTEGER PRIMARY KEY);
@ -455,12 +455,12 @@ foreach {tn3 create_vfs destroy_vfs} {
INSERT INTO t1('(a)', b, c) VALUES(6, 'hello', 'xyz'); INSERT INTO t1('(a)', b, c) VALUES(6, 'hello', 'xyz');
} }
create_ota4b ota.db create_rbu4b rbu.db
set check [dbfilecksum ota.db] set check [dbfilecksum rbu.db]
forcedelete state.db forcedelete state.db
do_test $tn3.5.$tn2.$tn.1 { do_test $tn3.5.$tn2.$tn.1 {
$cmd test.db ota.db $cmd test.db rbu.db
} {SQLITE_DONE} } {SQLITE_DONE}
do_execsql_test $tn3.5.$tn2.$tn.2 { do_execsql_test $tn3.5.$tn2.$tn.2 {
@ -473,19 +473,19 @@ foreach {tn3 create_vfs destroy_vfs} {
do_execsql_test $tn3.4.$tn2.$tn.3 { PRAGMA integrity_check } ok do_execsql_test $tn3.4.$tn2.$tn.3 { PRAGMA integrity_check } ok
if {$cmd=="step_ota_state"} { if {$cmd=="step_rbu_state"} {
do_test $tn3.5.$tn2.$tn.4 { file exists state.db } 1 do_test $tn3.5.$tn2.$tn.4 { file exists state.db } 1
do_test $tn3.5.$tn2.$tn.5 { expr {$check == [dbfilecksum ota.db]} } 1 do_test $tn3.5.$tn2.$tn.5 { expr {$check == [dbfilecksum rbu.db]} } 1
} else { } else {
do_test $tn3.5.$tn2.$tn.6 { file exists state.db } 0 do_test $tn3.5.$tn2.$tn.6 { file exists state.db } 0
do_test $tn3.5.$tn2.$tn.7 { expr {$check == [dbfilecksum ota.db]} } 0 do_test $tn3.5.$tn2.$tn.7 { expr {$check == [dbfilecksum rbu.db]} } 0
} }
} }
} }
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
# #
foreach {tn2 cmd} {1 run_ota 2 step_ota 3 step_ota_state} { foreach {tn2 cmd} {1 run_rbu 2 step_rbu 3 step_rbu_state} {
foreach {tn schema} { foreach {tn schema} {
1 { 1 {
CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c, d); CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c, d);
@ -526,12 +526,12 @@ foreach {tn3 create_vfs destroy_vfs} {
INSERT INTO t1 VALUES(3, 8, 9, 10); INSERT INTO t1 VALUES(3, 8, 9, 10);
} }
create_ota5 ota.db create_rbu5 rbu.db
set check [dbfilecksum ota.db] set check [dbfilecksum rbu.db]
forcedelete state.db forcedelete state.db
do_test $tn3.5.$tn2.$tn.1 { do_test $tn3.5.$tn2.$tn.1 {
$cmd test.db ota.db $cmd test.db rbu.db
} {SQLITE_DONE} } {SQLITE_DONE}
do_execsql_test $tn3.5.$tn2.$tn.2 { do_execsql_test $tn3.5.$tn2.$tn.2 {
@ -544,12 +544,12 @@ foreach {tn3 create_vfs destroy_vfs} {
do_execsql_test $tn3.6.$tn2.$tn.3 { PRAGMA integrity_check } ok do_execsql_test $tn3.6.$tn2.$tn.3 { PRAGMA integrity_check } ok
if {$cmd=="step_ota_state"} { if {$cmd=="step_rbu_state"} {
do_test $tn3.6.$tn2.$tn.4 { file exists state.db } 1 do_test $tn3.6.$tn2.$tn.4 { file exists state.db } 1
do_test $tn3.6.$tn2.$tn.5 { expr {$check == [dbfilecksum ota.db]} } 1 do_test $tn3.6.$tn2.$tn.5 { expr {$check == [dbfilecksum rbu.db]} } 1
} else { } else {
do_test $tn3.6.$tn2.$tn.6 { file exists state.db } 0 do_test $tn3.6.$tn2.$tn.6 { file exists state.db } 0
do_test $tn3.6.$tn2.$tn.7 { expr {$check == [dbfilecksum ota.db]} } 0 do_test $tn3.6.$tn2.$tn.7 { expr {$check == [dbfilecksum rbu.db]} } 0
} }
} }
} }
@ -557,9 +557,9 @@ foreach {tn3 create_vfs destroy_vfs} {
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
# Test some error cases: # Test some error cases:
# #
# * A virtual table with no ota_rowid column. # * A virtual table with no rbu_rowid column.
# * A no-PK table with no ota_rowid column. # * A no-PK table with no rbu_rowid column.
# * A PK table with an ota_rowid column. # * A PK table with an rbu_rowid column.
# #
# 6: An update string of the wrong length # 6: An update string of the wrong length
# #
@ -567,88 +567,88 @@ foreach {tn3 create_vfs destroy_vfs} {
foreach {tn schema error} { foreach {tn schema error} {
1 { 1 {
CREATE TABLE t1(a, b); CREATE TABLE t1(a, b);
CREATE TABLE ota.data_t1(a, b, ota_control); CREATE TABLE rbu.data_t1(a, b, rbu_control);
} {SQLITE_ERROR - table data_t1 requires ota_rowid column} } {SQLITE_ERROR - table data_t1 requires rbu_rowid column}
2 { 2 {
CREATE VIRTUAL TABLE t1 USING fts4(a, b); CREATE VIRTUAL TABLE t1 USING fts4(a, b);
CREATE TABLE ota.data_t1(a, b, ota_control); CREATE TABLE rbu.data_t1(a, b, rbu_control);
} {SQLITE_ERROR - table data_t1 requires ota_rowid column} } {SQLITE_ERROR - table data_t1 requires rbu_rowid column}
3 { 3 {
CREATE TABLE t1(a PRIMARY KEY, b); CREATE TABLE t1(a PRIMARY KEY, b);
CREATE TABLE ota.data_t1(a, b, ota_rowid, ota_control); CREATE TABLE rbu.data_t1(a, b, rbu_rowid, rbu_control);
} {SQLITE_ERROR - table data_t1 may not have ota_rowid column} } {SQLITE_ERROR - table data_t1 may not have rbu_rowid column}
4 { 4 {
CREATE TABLE t1(a INTEGER PRIMARY KEY, b); CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
CREATE TABLE ota.data_t1(a, b, ota_rowid, ota_control); CREATE TABLE rbu.data_t1(a, b, rbu_rowid, rbu_control);
} {SQLITE_ERROR - table data_t1 may not have ota_rowid column} } {SQLITE_ERROR - table data_t1 may not have rbu_rowid column}
5 { 5 {
CREATE TABLE t1(a, b PRIMARY KEY) WITHOUT ROWID; CREATE TABLE t1(a, b PRIMARY KEY) WITHOUT ROWID;
CREATE TABLE ota.data_t1(a, b, ota_rowid, ota_control); CREATE TABLE rbu.data_t1(a, b, rbu_rowid, rbu_control);
} {SQLITE_ERROR - table data_t1 may not have ota_rowid column} } {SQLITE_ERROR - table data_t1 may not have rbu_rowid column}
6 { 6 {
CREATE TABLE t1(a, b PRIMARY KEY) WITHOUT ROWID; CREATE TABLE t1(a, b PRIMARY KEY) WITHOUT ROWID;
CREATE TABLE ota.data_t1(a, b, ota_control); CREATE TABLE rbu.data_t1(a, b, rbu_control);
INSERT INTO ota.data_t1 VALUES(1, 2, 'x.x'); INSERT INTO rbu.data_t1 VALUES(1, 2, 'x.x');
} {SQLITE_ERROR - invalid ota_control value} } {SQLITE_ERROR - invalid rbu_control value}
7 { 7 {
CREATE TABLE t1(a, b PRIMARY KEY) WITHOUT ROWID; CREATE TABLE t1(a, b PRIMARY KEY) WITHOUT ROWID;
CREATE TABLE ota.data_t1(a, b, ota_control); CREATE TABLE rbu.data_t1(a, b, rbu_control);
INSERT INTO ota.data_t1 VALUES(1, 2, NULL); INSERT INTO rbu.data_t1 VALUES(1, 2, NULL);
} {SQLITE_ERROR - invalid ota_control value} } {SQLITE_ERROR - invalid rbu_control value}
8 { 8 {
CREATE TABLE t1(a, b PRIMARY KEY) WITHOUT ROWID; CREATE TABLE t1(a, b PRIMARY KEY) WITHOUT ROWID;
CREATE TABLE ota.data_t1(a, b, ota_control); CREATE TABLE rbu.data_t1(a, b, rbu_control);
INSERT INTO ota.data_t1 VALUES(1, 2, 4); INSERT INTO rbu.data_t1 VALUES(1, 2, 4);
} {SQLITE_ERROR - invalid ota_control value} } {SQLITE_ERROR - invalid rbu_control value}
9 { 9 {
CREATE TABLE t1(a, b PRIMARY KEY) WITHOUT ROWID; CREATE TABLE t1(a, b PRIMARY KEY) WITHOUT ROWID;
CREATE TABLE ota.data_t1(a, b, ota_control); CREATE TABLE rbu.data_t1(a, b, rbu_control);
INSERT INTO ota.data_t1 VALUES(1, 2, 2); INSERT INTO rbu.data_t1 VALUES(1, 2, 2);
} {SQLITE_ERROR - invalid ota_control value} } {SQLITE_ERROR - invalid rbu_control value}
10 { 10 {
CREATE TABLE t2(a, b); CREATE TABLE t2(a, b);
CREATE TABLE ota.data_t1(a, b, ota_control); CREATE TABLE rbu.data_t1(a, b, rbu_control);
INSERT INTO ota.data_t1 VALUES(1, 2, 2); INSERT INTO rbu.data_t1 VALUES(1, 2, 2);
} {SQLITE_ERROR - no such table: t1} } {SQLITE_ERROR - no such table: t1}
11 { 11 {
CREATE TABLE ota.data_t2(a, b, ota_control); CREATE TABLE rbu.data_t2(a, b, rbu_control);
INSERT INTO ota.data_t2 VALUES(1, 2, 2); INSERT INTO rbu.data_t2 VALUES(1, 2, 2);
} {SQLITE_ERROR - no such table: t2} } {SQLITE_ERROR - no such table: t2}
} { } {
reset_db reset_db
forcedelete ota.db forcedelete rbu.db
execsql { ATTACH 'ota.db' AS ota } execsql { ATTACH 'rbu.db' AS rbu }
execsql $schema execsql $schema
do_test $tn3.7.$tn { do_test $tn3.7.$tn {
list [catch { run_ota test.db ota.db } msg] $msg list [catch { run_rbu test.db rbu.db } msg] $msg
} [list 1 $error] } [list 1 $error]
} }
} }
# Test that an OTA database containing no input tables is handled # Test that an RBU database containing no input tables is handled
# correctly. # correctly.
reset_db reset_db
forcedelete ota.db forcedelete rbu.db
do_test $tn3.8 { do_test $tn3.8 {
list [catch { run_ota test.db ota.db } msg] $msg list [catch { run_rbu test.db rbu.db } msg] $msg
} {0 SQLITE_DONE} } {0 SQLITE_DONE}
# Test that OTA can update indexes containing NULL values. # Test that RBU can update indexes containing NULL values.
# #
reset_db reset_db
forcedelete ota.db forcedelete rbu.db
do_execsql_test $tn3.9.1 { do_execsql_test $tn3.9.1 {
CREATE TABLE t1(a PRIMARY KEY, b, c); CREATE TABLE t1(a PRIMARY KEY, b, c);
CREATE INDEX i1 ON t1(b, c); CREATE INDEX i1 ON t1(b, c);
@ -656,14 +656,14 @@ foreach {tn3 create_vfs destroy_vfs} {
INSERT INTO t1 VALUES(2, NULL, 2); INSERT INTO t1 VALUES(2, NULL, 2);
INSERT INTO t1 VALUES(3, NULL, NULL); INSERT INTO t1 VALUES(3, NULL, NULL);
ATTACH 'ota.db' AS ota; ATTACH 'rbu.db' AS rbu;
CREATE TABLE ota.data_t1(a, b, c, ota_control); CREATE TABLE rbu.data_t1(a, b, c, rbu_control);
INSERT INTO data_t1 VALUES(1, NULL, NULL, 1); INSERT INTO data_t1 VALUES(1, NULL, NULL, 1);
INSERT INTO data_t1 VALUES(3, NULL, NULL, 1); INSERT INTO data_t1 VALUES(3, NULL, NULL, 1);
} {} } {}
do_test $tn3.9.2 { do_test $tn3.9.2 {
list [catch { run_ota test.db ota.db } msg] $msg list [catch { run_rbu test.db rbu.db } msg] $msg
} {0 SQLITE_DONE} } {0 SQLITE_DONE}
do_execsql_test $tn3.9.3 { do_execsql_test $tn3.9.3 {

View File

@ -14,7 +14,7 @@ if {![info exists testdir]} {
set testdir [file join [file dirname [info script]] .. .. test] set testdir [file join [file dirname [info script]] .. .. test]
} }
source $testdir/tester.tcl source $testdir/tester.tcl
set ::testprefix ota10 set ::testprefix rbu10
#-------------------------------------------------------------------- #--------------------------------------------------------------------
@ -26,19 +26,19 @@ do_execsql_test 1.0 {
INSERT INTO t1 VALUES(1, 'b', 'c'); INSERT INTO t1 VALUES(1, 'b', 'c');
} }
proc apply_ota {sql} { proc apply_rbu {sql} {
forcedelete ota.db forcedelete rbu.db
sqlite3 db2 ota.db sqlite3 db2 rbu.db
db2 eval $sql db2 eval $sql
db2 close db2 close
sqlite3ota ota test.db ota.db sqlite3rbu rbu test.db rbu.db
while { [ota step]=="SQLITE_OK" } {} while { [rbu step]=="SQLITE_OK" } {}
ota close rbu close
} }
do_test 1.1 { do_test 1.1 {
apply_ota { apply_rbu {
CREATE TABLE data_t1(a, c, b, ota_control); CREATE TABLE data_t1(a, c, b, rbu_control);
INSERT INTO data_t1 VALUES(1, 'xxx', NULL, '.x.'); INSERT INTO data_t1 VALUES(1, 'xxx', NULL, '.x.');
} }
db eval { SELECT * FROM t1 } db eval { SELECT * FROM t1 }
@ -53,8 +53,8 @@ ifcapable fts3 {
CREATE VIRTUAL TABLE ft USING fts4(a, b, languageid='langid'); CREATE VIRTUAL TABLE ft USING fts4(a, b, languageid='langid');
} }
do_test 2.1 { do_test 2.1 {
apply_ota { apply_rbu {
CREATE TABLE data_ft(a, b, ota_rowid, langid, ota_control); CREATE TABLE data_ft(a, b, rbu_rowid, langid, rbu_control);
INSERT INTO data_ft VALUES('a', 'b', 22, 1, 0); -- insert INSERT INTO data_ft VALUES('a', 'b', 22, 1, 0); -- insert
INSERT INTO data_ft VALUES('a', 'b', 23, 10, 0); -- insert INSERT INTO data_ft VALUES('a', 'b', 23, 10, 0); -- insert
INSERT INTO data_ft VALUES('a', 'b', 24, 100, 0); -- insert INSERT INTO data_ft VALUES('a', 'b', 24, 100, 0); -- insert
@ -70,8 +70,8 @@ ifcapable fts3 {
# defaults to 0. # defaults to 0.
# #
do_test 2.2 { do_test 2.2 {
apply_ota { apply_rbu {
CREATE TABLE data_ft(a, b, ota_rowid, ota_control); CREATE TABLE data_ft(a, b, rbu_rowid, rbu_control);
INSERT INTO data_ft VALUES('a', 'b', 25, 0); -- insert INSERT INTO data_ft VALUES('a', 'b', 25, 0); -- insert
} }
db eval { SELECT a, b, rowid, langid FROM ft } db eval { SELECT a, b, rowid, langid FROM ft }
@ -85,8 +85,8 @@ ifcapable fts3 {
# Update langid. # Update langid.
# #
do_test 2.3 { do_test 2.3 {
apply_ota { apply_rbu {
CREATE TABLE data_ft(a, b, ota_rowid, langid, ota_control); CREATE TABLE data_ft(a, b, rbu_rowid, langid, rbu_control);
INSERT INTO data_ft VALUES(NULL, NULL, 23, 50, '..x'); INSERT INTO data_ft VALUES(NULL, NULL, 23, 50, '..x');
INSERT INTO data_ft VALUES(NULL, NULL, 25, 500, '..x'); INSERT INTO data_ft VALUES(NULL, NULL, 25, 500, '..x');
} }
@ -101,7 +101,7 @@ ifcapable fts3 {
#-------------------------------------------------------------------- #--------------------------------------------------------------------
# Test that if writing a hidden virtual table column is an error, # Test that if writing a hidden virtual table column is an error,
# attempting to do so via ota is also an error. # attempting to do so via rbu is also an error.
# #
ifcapable fts3 { ifcapable fts3 {
do_execsql_test 3.0 { do_execsql_test 3.0 {
@ -109,8 +109,8 @@ ifcapable fts3 {
} }
do_test 3.1 { do_test 3.1 {
list [catch { list [catch {
apply_ota { apply_rbu {
CREATE TABLE data_xt(a, xt, ota_rowid, ota_control); CREATE TABLE data_xt(a, xt, rbu_rowid, rbu_control);
INSERT INTO data_xt VALUES('a', 'b', 1, 0); INSERT INTO data_xt VALUES('a', 'b', 1, 0);
} }
} msg] $msg } msg] $msg
@ -119,7 +119,7 @@ ifcapable fts3 {
#-------------------------------------------------------------------- #--------------------------------------------------------------------
# Test that it is not possible to violate a NOT NULL constraint by # Test that it is not possible to violate a NOT NULL constraint by
# applying an OTA update. # applying an RBU update.
# #
do_execsql_test 4.1 { do_execsql_test 4.1 {
CREATE TABLE t2(a INTEGER NOT NULL, b TEXT NOT NULL, c PRIMARY KEY); CREATE TABLE t2(a INTEGER NOT NULL, b TEXT NOT NULL, c PRIMARY KEY);
@ -131,7 +131,7 @@ do_execsql_test 4.1 {
INSERT INTO t4 VALUES(10, 10); INSERT INTO t4 VALUES(10, 10);
} }
foreach {tn error ota} { foreach {tn error rbu} {
2 {SQLITE_CONSTRAINT - NOT NULL constraint failed: t2.a} { 2 {SQLITE_CONSTRAINT - NOT NULL constraint failed: t2.a} {
INSERT INTO data_t2 VALUES(NULL, 'abc', 1, 0); INSERT INTO data_t2 VALUES(NULL, 'abc', 1, 0);
} }
@ -163,24 +163,24 @@ foreach {tn error ota} {
INSERT INTO data_t3 VALUES(1, 'abc', 'text', 0); INSERT INTO data_t3 VALUES(1, 'abc', 'text', 0);
} }
} { } {
set ota " set rbu "
CREATE TABLE data_t2(a, b, c, ota_control); CREATE TABLE data_t2(a, b, c, rbu_control);
CREATE TABLE data_t3(a, b, c, ota_control); CREATE TABLE data_t3(a, b, c, rbu_control);
CREATE TABLE data_t4(a, b, ota_control); CREATE TABLE data_t4(a, b, rbu_control);
$ota $rbu
" "
do_test 4.2.$tn { do_test 4.2.$tn {
list [catch { apply_ota $ota } msg] $msg list [catch { apply_rbu $rbu } msg] $msg
} [list 1 $error] } [list 1 $error]
} }
do_test 4.3 { do_test 4.3 {
set ota { set rbu {
CREATE TABLE data_t3(a, b, c, ota_control); CREATE TABLE data_t3(a, b, c, rbu_control);
INSERT INTO data_t3 VALUES(1, 'abc', '5', 0); INSERT INTO data_t3 VALUES(1, 'abc', '5', 0);
INSERT INTO data_t3 VALUES(1, 'abc', '-6.0', 0); INSERT INTO data_t3 VALUES(1, 'abc', '-6.0', 0);
} }
list [catch { apply_ota $ota } msg] $msg list [catch { apply_rbu $rbu } msg] $msg
} {0 SQLITE_DONE} } {0 SQLITE_DONE}

View File

@ -14,17 +14,17 @@ if {![info exists testdir]} {
set testdir [file join [file dirname [info script]] .. .. test] set testdir [file join [file dirname [info script]] .. .. test]
} }
source $testdir/tester.tcl source $testdir/tester.tcl
set ::testprefix ota11 set ::testprefix rbu11
#-------------------------------------------------------------------- #--------------------------------------------------------------------
# Test that the xAccess() method of an ota vfs handles queries other # Test that the xAccess() method of an rbu vfs handles queries other
# than SQLITE_ACCESS_EXISTS correctly. The test code below causes # than SQLITE_ACCESS_EXISTS correctly. The test code below causes
# SQLite to call xAccess(SQLITE_ACCESS_READWRITE) on the directory # SQLite to call xAccess(SQLITE_ACCESS_READWRITE) on the directory
# path argument passed to "PRAGMA temp_store_directory". # path argument passed to "PRAGMA temp_store_directory".
# #
do_test 1.1 { do_test 1.1 {
sqlite3ota_create_vfs -default ota "" sqlite3rbu_create_vfs -default rbu ""
reset_db reset_db
catchsql { PRAGMA temp_store_directory = '/no/such/directory' } catchsql { PRAGMA temp_store_directory = '/no/such/directory' }
} {1 {not a writable directory}} } {1 {not a writable directory}}
@ -39,11 +39,11 @@ do_test 1.3 {
do_test 1.4 { do_test 1.4 {
db close db close
sqlite3ota_destroy_vfs ota sqlite3rbu_destroy_vfs rbu
} {} } {}
#-------------------------------------------------------------------- #--------------------------------------------------------------------
# Try to trick ota into operating on a database opened in wal mode. # Try to trick rbu into operating on a database opened in wal mode.
# #
reset_db reset_db
do_execsql_test 2.1 { do_execsql_test 2.1 {
@ -57,10 +57,10 @@ do_test 2.2 {
db_save db_save
db close db close
forcedelete ota.db forcedelete rbu.db
sqlite3 dbo ota.db sqlite3 dbo rbu.db
dbo eval { dbo eval {
CREATE TABLE data_t1(a, b, c, ota_control); CREATE TABLE data_t1(a, b, c, rbu_control);
INSERT INTO data_t1 VALUES(4, 5, 6, 0); INSERT INTO data_t1 VALUES(4, 5, 6, 0);
INSERT INTO data_t1 VALUES(7, 8, 9, 0); INSERT INTO data_t1 VALUES(7, 8, 9, 0);
} }
@ -72,12 +72,12 @@ do_test 2.2 {
} {1} } {1}
do_test 2.3 { do_test 2.3 {
sqlite3ota ota test.db ota.db sqlite3rbu rbu test.db rbu.db
ota step rbu step
} {SQLITE_ERROR} } {SQLITE_ERROR}
do_test 2.4 { do_test 2.4 {
list [catch {ota close} msg] $msg list [catch {rbu close} msg] $msg
} {1 {SQLITE_ERROR - cannot update wal mode database}} } {1 {SQLITE_ERROR - cannot update wal mode database}}
#-------------------------------------------------------------------- #--------------------------------------------------------------------
@ -94,26 +94,26 @@ do_execsql_test 3.1 {
db close db close
do_test 3.2 { do_test 3.2 {
forcedelete ota.db forcedelete rbu.db
sqlite3 dbo ota.db sqlite3 dbo rbu.db
dbo eval { dbo eval {
CREATE TABLE "data_(t1)"(a, b, c, ota_control); CREATE TABLE "data_(t1)"(a, b, c, rbu_control);
INSERT INTO "data_(t1)" VALUES(4, 8, 9, 0); INSERT INTO "data_(t1)" VALUES(4, 8, 9, 0);
} }
dbo close dbo close
sqlite3ota ota test.db ota.db sqlite3rbu rbu test.db rbu.db
ota step rbu step
ota step rbu step
} {SQLITE_CONSTRAINT} } {SQLITE_CONSTRAINT}
do_test 3.3 { do_test 3.3 {
list [catch {ota close} msg] $msg list [catch {rbu close} msg] $msg
} {1 {SQLITE_CONSTRAINT - UNIQUE constraint failed: (t1).a}} } {1 {SQLITE_CONSTRAINT - UNIQUE constraint failed: (t1).a}}
#-------------------------------------------------------------------- #--------------------------------------------------------------------
# Check that once an OTA update has been applied, attempting to apply # Check that once an RBU update has been applied, attempting to apply
# it a second time is a no-op (as the state stored in the OTA database is # it a second time is a no-op (as the state stored in the RBU database is
# "all steps completed"). # "all steps completed").
# #
reset_db reset_db
@ -125,74 +125,74 @@ do_execsql_test 4.1 {
db close db close
do_test 4.2 { do_test 4.2 {
forcedelete ota.db forcedelete rbu.db
sqlite3 dbo ota.db sqlite3 dbo rbu.db
dbo eval { dbo eval {
CREATE TABLE "data_(t1)"(a, b, c, ota_control); CREATE TABLE "data_(t1)"(a, b, c, rbu_control);
INSERT INTO "data_(t1)" VALUES(7, 8, 9, 0); INSERT INTO "data_(t1)" VALUES(7, 8, 9, 0);
INSERT INTO "data_(t1)" VALUES(1, 2, 3, 1); INSERT INTO "data_(t1)" VALUES(1, 2, 3, 1);
} }
dbo close dbo close
sqlite3ota ota test.db ota.db sqlite3rbu rbu test.db rbu.db
while {[ota step]=="SQLITE_OK"} { } while {[rbu step]=="SQLITE_OK"} { }
ota close rbu close
} {SQLITE_DONE} } {SQLITE_DONE}
do_test 4.3 { do_test 4.3 {
sqlite3ota ota test.db ota.db sqlite3rbu rbu test.db rbu.db
ota step rbu step
} {SQLITE_DONE} } {SQLITE_DONE}
do_test 4.4 { do_test 4.4 {
ota close rbu close
} {SQLITE_DONE} } {SQLITE_DONE}
do_test 4.5.1 { do_test 4.5.1 {
sqlite3 dbo ota.db sqlite3 dbo rbu.db
dbo eval { INSERT INTO ota_state VALUES(100, 100) } dbo eval { INSERT INTO rbu_state VALUES(100, 100) }
dbo close dbo close
sqlite3ota ota test.db ota.db sqlite3rbu rbu test.db rbu.db
ota step rbu step
} {SQLITE_CORRUPT} } {SQLITE_CORRUPT}
do_test 4.5.2 { do_test 4.5.2 {
list [catch {ota close} msg] $msg list [catch {rbu close} msg] $msg
} {1 SQLITE_CORRUPT} } {1 SQLITE_CORRUPT}
do_test 4.5.3 { do_test 4.5.3 {
sqlite3 dbo ota.db sqlite3 dbo rbu.db
dbo eval { DELETE FROM ota_state WHERE k = 100 } dbo eval { DELETE FROM rbu_state WHERE k = 100 }
dbo close dbo close
} {} } {}
# Also, check that an invalid state value in the ota_state table is # Also, check that an invalid state value in the rbu_state table is
# detected and reported as corruption. # detected and reported as corruption.
do_test 4.6.1 { do_test 4.6.1 {
sqlite3 dbo ota.db sqlite3 dbo rbu.db
dbo eval { UPDATE ota_state SET v = v*-1 WHERE k = 1 } dbo eval { UPDATE rbu_state SET v = v*-1 WHERE k = 1 }
dbo close dbo close
sqlite3ota ota test.db ota.db sqlite3rbu rbu test.db rbu.db
ota step rbu step
} {SQLITE_CORRUPT} } {SQLITE_CORRUPT}
do_test 4.6.2 { do_test 4.6.2 {
list [catch {ota close} msg] $msg list [catch {rbu close} msg] $msg
} {1 SQLITE_CORRUPT} } {1 SQLITE_CORRUPT}
do_test 4.6.3 { do_test 4.6.3 {
sqlite3 dbo ota.db sqlite3 dbo rbu.db
dbo eval { UPDATE ota_state SET v = v*-1 WHERE k = 1 } dbo eval { UPDATE rbu_state SET v = v*-1 WHERE k = 1 }
dbo close dbo close
} {} } {}
do_test 4.7.1 { do_test 4.7.1 {
sqlite3 dbo ota.db sqlite3 dbo rbu.db
dbo eval { UPDATE ota_state SET v = 1 WHERE k = 1 } dbo eval { UPDATE rbu_state SET v = 1 WHERE k = 1 }
dbo eval { UPDATE ota_state SET v = 'nosuchtable' WHERE k = 2 } dbo eval { UPDATE rbu_state SET v = 'nosuchtable' WHERE k = 2 }
dbo close dbo close
sqlite3ota ota test.db ota.db sqlite3rbu rbu test.db rbu.db
ota step rbu step
} {SQLITE_ERROR} } {SQLITE_ERROR}
do_test 4.7.2 { do_test 4.7.2 {
list [catch {ota close} msg] $msg list [catch {rbu close} msg] $msg
} {1 {SQLITE_ERROR - ota_state mismatch error}} } {1 {SQLITE_ERROR - rbu_state mismatch error}}
finish_test finish_test

View File

@ -15,7 +15,7 @@ if {![info exists testdir]} {
} }
source $testdir/tester.tcl source $testdir/tester.tcl
source $testdir/lock_common.tcl source $testdir/lock_common.tcl
set ::testprefix ota12 set ::testprefix rbu12
set setup_sql { set setup_sql {
DROP TABLE IF EXISTS xx; DROP TABLE IF EXISTS xx;
@ -24,34 +24,34 @@ set setup_sql {
INSERT INTO xx VALUES(1, 2, 3); INSERT INTO xx VALUES(1, 2, 3);
CREATE TABLE xy(a, b, c PRIMARY KEY); CREATE TABLE xy(a, b, c PRIMARY KEY);
ATTACH 'ota.db' AS ota; ATTACH 'rbu.db' AS rbu;
DROP TABLE IF EXISTS data_xx; DROP TABLE IF EXISTS data_xx;
CREATE TABLE ota.data_xx(a, b, c, ota_control); CREATE TABLE rbu.data_xx(a, b, c, rbu_control);
INSERT INTO data_xx VALUES(4, 5, 6, 0); INSERT INTO data_xx VALUES(4, 5, 6, 0);
INSERT INTO data_xx VALUES(7, 8, 9, 0); INSERT INTO data_xx VALUES(7, 8, 9, 0);
CREATE TABLE ota.data_xy(a, b, c, ota_control); CREATE TABLE rbu.data_xy(a, b, c, rbu_control);
INSERT INTO data_xy VALUES(10, 11, 12, 0); INSERT INTO data_xy VALUES(10, 11, 12, 0);
DETACH ota; DETACH rbu;
} }
do_multiclient_test tn { do_multiclient_test tn {
# Initialize a target (test.db) and ota (ota.db) database. # Initialize a target (test.db) and rbu (rbu.db) database.
# #
forcedelete ota.db forcedelete rbu.db
sql1 $setup_sql sql1 $setup_sql
# Using connection 2, open a read transaction on the target database. # Using connection 2, open a read transaction on the target database.
# OTA will still be able to generate "test.db-oal", but it will not be # RBU will still be able to generate "test.db-oal", but it will not be
# able to rename it to "test.db-wal". # able to rename it to "test.db-wal".
# #
do_test 1.$tn.1 { do_test 1.$tn.1 {
sql2 { BEGIN; SELECT * FROM xx; } sql2 { BEGIN; SELECT * FROM xx; }
} {1 2 3} } {1 2 3}
do_test 1.$tn.2 { do_test 1.$tn.2 {
sqlite3ota ota test.db ota.db sqlite3rbu rbu test.db rbu.db
while 1 { while 1 {
set res [ota step] set res [rbu step]
if {$res!="SQLITE_OK"} break if {$res!="SQLITE_OK"} break
} }
set res set res
@ -64,119 +64,119 @@ do_multiclient_test tn {
} {0 1} } {0 1}
do_test 1.$tn.6 { sql2 COMMIT } {} do_test 1.$tn.6 { sql2 COMMIT } {}
# The ota object that hit the SQLITE_BUSY error above cannot be reused. # The rbu object that hit the SQLITE_BUSY error above cannot be reused.
# It is stuck in a permanent SQLITE_BUSY state at this point. # It is stuck in a permanent SQLITE_BUSY state at this point.
# #
do_test 1.$tn.7 { ota step } {SQLITE_BUSY} do_test 1.$tn.7 { rbu step } {SQLITE_BUSY}
do_test 1.$tn.8 { do_test 1.$tn.8 {
list [catch { ota close } msg] $msg list [catch { rbu close } msg] $msg
} {1 SQLITE_BUSY} } {1 SQLITE_BUSY}
do_test 1.$tn.9.1 { sql2 { BEGIN EXCLUSIVE } } {} do_test 1.$tn.9.1 { sql2 { BEGIN EXCLUSIVE } } {}
do_test 1.$tn.9.2 { do_test 1.$tn.9.2 {
sqlite3ota ota test.db ota.db sqlite3rbu rbu test.db rbu.db
ota step rbu step
} {SQLITE_BUSY} } {SQLITE_BUSY}
do_test 1.$tn.9.3 { do_test 1.$tn.9.3 {
list [catch { ota close } msg] $msg list [catch { rbu close } msg] $msg
} {1 {SQLITE_BUSY - database is locked}} } {1 {SQLITE_BUSY - database is locked}}
do_test 1.$tn.9.4 { sql2 COMMIT } {} do_test 1.$tn.9.4 { sql2 COMMIT } {}
sqlite3ota ota test.db ota.db sqlite3rbu rbu test.db rbu.db
do_test 1.$tn.10.1 { sql2 { BEGIN EXCLUSIVE } } {} do_test 1.$tn.10.1 { sql2 { BEGIN EXCLUSIVE } } {}
do_test 1.$tn.10.2 { do_test 1.$tn.10.2 {
ota step rbu step
} {SQLITE_BUSY} } {SQLITE_BUSY}
do_test 1.$tn.10.3 { do_test 1.$tn.10.3 {
list [catch { ota close } msg] $msg list [catch { rbu close } msg] $msg
} {1 SQLITE_BUSY} } {1 SQLITE_BUSY}
do_test 1.$tn.10.4 { sql2 COMMIT } {} do_test 1.$tn.10.4 { sql2 COMMIT } {}
# A new ota object can finish the work though. # A new rbu object can finish the work though.
# #
do_test 1.$tn.11 { do_test 1.$tn.11 {
sqlite3ota ota test.db ota.db sqlite3rbu rbu test.db rbu.db
ota step rbu step
} {SQLITE_OK} } {SQLITE_OK}
do_test 1.$tn.12 { do_test 1.$tn.12 {
list [file exists test.db-wal] [file exists test.db-oal] list [file exists test.db-wal] [file exists test.db-oal]
} {1 0} } {1 0}
do_test 1.$tn.13 { do_test 1.$tn.13 {
while 1 { while 1 {
set res [ota step] set res [rbu step]
if {$res!="SQLITE_OK"} break if {$res!="SQLITE_OK"} break
} }
set res set res
} {SQLITE_DONE} } {SQLITE_DONE}
do_test 1.$tn.14 { do_test 1.$tn.14 {
ota close rbu close
} {SQLITE_DONE} } {SQLITE_DONE}
} }
do_multiclient_test tn { do_multiclient_test tn {
# Initialize a target (test.db) and ota (ota.db) database. # Initialize a target (test.db) and rbu (rbu.db) database.
# #
forcedelete ota.db forcedelete rbu.db
sql1 $setup_sql sql1 $setup_sql
do_test 2.$tn.1 { do_test 2.$tn.1 {
sqlite3ota ota test.db ota.db sqlite3rbu rbu test.db rbu.db
while {[file exists test.db-wal]==0} { while {[file exists test.db-wal]==0} {
if {[ota step]!="SQLITE_OK"} {error "problem here...."} if {[rbu step]!="SQLITE_OK"} {error "problem here...."}
} }
ota close rbu close
} {SQLITE_OK} } {SQLITE_OK}
do_test 2.$tn.2 { sql2 { BEGIN IMMEDIATE } } {} do_test 2.$tn.2 { sql2 { BEGIN IMMEDIATE } } {}
do_test 2.$tn.3 { do_test 2.$tn.3 {
sqlite3ota ota test.db ota.db sqlite3rbu rbu test.db rbu.db
ota step rbu step
} {SQLITE_BUSY} } {SQLITE_BUSY}
do_test 2.$tn.4 { list [catch { ota close } msg] $msg } {1 SQLITE_BUSY} do_test 2.$tn.4 { list [catch { rbu close } msg] $msg } {1 SQLITE_BUSY}
do_test 2.$tn.5 { do_test 2.$tn.5 {
sql2 { SELECT * FROM xx ; COMMIT } sql2 { SELECT * FROM xx ; COMMIT }
} {1 2 3 4 5 6 7 8 9} } {1 2 3 4 5 6 7 8 9}
do_test 2.$tn.6 { do_test 2.$tn.6 {
sqlite3ota ota test.db ota.db sqlite3rbu rbu test.db rbu.db
ota step rbu step
ota close rbu close
} {SQLITE_OK} } {SQLITE_OK}
do_test 2.$tn.7 { sql2 { BEGIN EXCLUSIVE } } {} do_test 2.$tn.7 { sql2 { BEGIN EXCLUSIVE } } {}
do_test 2.$tn.8 { do_test 2.$tn.8 {
sqlite3ota ota test.db ota.db sqlite3rbu rbu test.db rbu.db
ota step rbu step
} {SQLITE_BUSY} } {SQLITE_BUSY}
do_test 2.$tn.9 { list [catch { ota close } msg] $msg } {1 SQLITE_BUSY} do_test 2.$tn.9 { list [catch { rbu close } msg] $msg } {1 SQLITE_BUSY}
do_test 2.$tn.10 { do_test 2.$tn.10 {
sql2 { SELECT * FROM xx ; COMMIT } sql2 { SELECT * FROM xx ; COMMIT }
} {1 2 3 4 5 6 7 8 9} } {1 2 3 4 5 6 7 8 9}
do_test 2.$tn.11 { do_test 2.$tn.11 {
sqlite3ota ota test.db ota.db sqlite3rbu rbu test.db rbu.db
while {[ota step]=="SQLITE_OK"} {} while {[rbu step]=="SQLITE_OK"} {}
ota close rbu close
} {SQLITE_DONE} } {SQLITE_DONE}
} }
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
# Test that "PRAGMA data_version" works when an OTA client writes the # Test that "PRAGMA data_version" works when an RBU client writes the
# database. # database.
# #
do_multiclient_test tn { do_multiclient_test tn {
# Initialize a target (test.db) and ota (ota.db) database. # Initialize a target (test.db) and rbu (rbu.db) database.
# #
forcedelete ota.db forcedelete rbu.db
sql1 $setup_sql sql1 $setup_sql
# Check the initial database contains table "xx" with a single row. # Check the initial database contains table "xx" with a single row.
@ -195,17 +195,17 @@ do_multiclient_test tn {
list [sql1 {PRAGMA data_version}] [sql2 {PRAGMA data_version}] list [sql1 {PRAGMA data_version}] [sql2 {PRAGMA data_version}]
} [list $V1 $V2] } [list $V1 $V2]
# Start stepping the OTA. From the point of view of [db1] and [db2], the # Start stepping the RBU. From the point of view of [db1] and [db2], the
# data-version values remain unchanged until the database contents are # data-version values remain unchanged until the database contents are
# modified. At which point the values are incremented. # modified. At which point the values are incremented.
# #
sqlite3ota ota test.db ota.db sqlite3rbu rbu test.db rbu.db
set x 0 set x 0
while {[db one {SELECT count(*) FROM xx}]==1} { while {[db one {SELECT count(*) FROM xx}]==1} {
do_test 2.$tn.3.[incr x] { do_test 2.$tn.3.[incr x] {
list [sql1 {PRAGMA data_version}] [sql2 {PRAGMA data_version}] list [sql1 {PRAGMA data_version}] [sql2 {PRAGMA data_version}]
} [list $V1 $V2] } [list $V1 $V2]
ota step rbu step
} }
do_test 2.$tn.5.1 { expr {$V1 < [sql1 {PRAGMA data_version}]} } 1 do_test 2.$tn.5.1 { expr {$V1 < [sql1 {PRAGMA data_version}]} } 1
do_test 2.$tn.5.2 { expr {$V2 < [sql2 {PRAGMA data_version}]} } 1 do_test 2.$tn.5.2 { expr {$V2 < [sql2 {PRAGMA data_version}]} } 1
@ -219,11 +219,11 @@ do_multiclient_test tn {
set V1 [sql1 {PRAGMA data_version}] set V1 [sql1 {PRAGMA data_version}]
set V2 [sql2 {PRAGMA data_version}] set V2 [sql2 {PRAGMA data_version}]
# Finish applying the OTA (i.e. do the incremental checkpoint). Check that # Finish applying the RBU (i.e. do the incremental checkpoint). Check that
# this does not cause the data-version values to change. # this does not cause the data-version values to change.
# #
while {[ota step]=="SQLITE_OK"} { } while {[rbu step]=="SQLITE_OK"} { }
ota close rbu close
do_test 2.$tn.6 { do_test 2.$tn.6 {
list [sql1 {PRAGMA data_version}] [sql2 {PRAGMA data_version}] list [sql1 {PRAGMA data_version}] [sql2 {PRAGMA data_version}]

View File

@ -9,8 +9,8 @@
# #
#*********************************************************************** #***********************************************************************
# #
# Test an OTA update that features lots of different ota_control strings # Test an RBU update that features lots of different rbu_control strings
# for UPDATE statements. This tests OTA's internal UPDATE statement cache. # for UPDATE statements. This tests RBU's internal UPDATE statement cache.
# #
if {![info exists testdir]} { if {![info exists testdir]} {
@ -18,7 +18,7 @@ if {![info exists testdir]} {
} }
source $testdir/tester.tcl source $testdir/tester.tcl
source $testdir/lock_common.tcl source $testdir/lock_common.tcl
set ::testprefix ota13 set ::testprefix rbu13
do_execsql_test 1.0 { do_execsql_test 1.0 {
CREATE TABLE t1(a PRIMARY KEY, b, c, d, e, f, g, h); CREATE TABLE t1(a PRIMARY KEY, b, c, d, e, f, g, h);
@ -26,10 +26,10 @@ do_execsql_test 1.0 {
INSERT INTO t1 SELECT i, 0, 0, 0, 0, 0, 0, 0 FROM ii; INSERT INTO t1 SELECT i, 0, 0, 0, 0, 0, 0, 0 FROM ii;
} }
forcedelete ota.db forcedelete rbu.db
do_execsql_test 1.1 { do_execsql_test 1.1 {
ATTACH 'ota.db' AS ota; ATTACH 'rbu.db' AS rbu;
CREATE TABLE ota.data_t1(a, b, c, d, e, f, g, h, ota_control); CREATE TABLE rbu.data_t1(a, b, c, d, e, f, g, h, rbu_control);
} }
do_test 1.2 { do_test 1.2 {
@ -47,12 +47,12 @@ do_test 1.2 {
} {} } {}
do_test 1.3 { do_test 1.3 {
sqlite3ota ota test.db ota.db sqlite3rbu rbu test.db rbu.db
while 1 { while 1 {
set rc [ota step] set rc [rbu step]
if {$rc!="SQLITE_OK"} break if {$rc!="SQLITE_OK"} break
} }
ota close rbu close
} {SQLITE_DONE} } {SQLITE_DONE}
do_execsql_test 1.4 { do_execsql_test 1.4 {

View File

@ -14,25 +14,25 @@ if {![info exists testdir]} {
set testdir [file join [file dirname [info script]] .. .. test] set testdir [file join [file dirname [info script]] .. .. test]
} }
source $testdir/tester.tcl source $testdir/tester.tcl
set ::testprefix ota3 set ::testprefix rbu3
# Run the OTA in file $ota on target database $target until completion. # Run the RBU in file $rbu on target database $target until completion.
# #
proc run_ota {target ota} { proc run_rbu {target rbu} {
sqlite3ota ota $target $ota sqlite3rbu rbu $target $rbu
while { [ota step]=="SQLITE_OK" } {} while { [rbu step]=="SQLITE_OK" } {}
ota close rbu close
} }
forcedelete test.db-oal ota.db forcedelete test.db-oal rbu.db
db close db close
sqlite3_shutdown sqlite3_shutdown
sqlite3_config_uri 1 sqlite3_config_uri 1
reset_db reset_db
#-------------------------------------------------------------------- #--------------------------------------------------------------------
# Test that for an OTA to be applied, no corruption results if the # Test that for an RBU to be applied, no corruption results if the
# affinities on the source and target table do not match. # affinities on the source and target table do not match.
# #
do_execsql_test 1.0 { do_execsql_test 1.0 {
@ -41,14 +41,14 @@ do_execsql_test 1.0 {
} {} } {}
do_test 1.1 { do_test 1.1 {
sqlite3 db2 ota.db sqlite3 db2 rbu.db
db2 eval { db2 eval {
CREATE TABLE data_x1(a, b, c, ota_control); CREATE TABLE data_x1(a, b, c, rbu_control);
INSERT INTO data_x1 VALUES(1, '123', '123', 0); INSERT INTO data_x1 VALUES(1, '123', '123', 0);
INSERT INTO data_x1 VALUES(2, 123, 123, 0); INSERT INTO data_x1 VALUES(2, 123, 123, 0);
} }
db2 close db2 close
run_ota test.db ota.db run_rbu test.db rbu.db
} {SQLITE_DONE} } {SQLITE_DONE}
do_execsql_test 1.2 { do_execsql_test 1.2 {
@ -59,7 +59,7 @@ do_execsql_test 1.2 {
# Test that NULL values may not be inserted into INTEGER PRIMARY KEY # Test that NULL values may not be inserted into INTEGER PRIMARY KEY
# columns. # columns.
# #
forcedelete ota.db forcedelete rbu.db
reset_db reset_db
do_execsql_test 2.0 { do_execsql_test 2.0 {
@ -67,23 +67,23 @@ do_execsql_test 2.0 {
CREATE INDEX i1 ON x1(b, c); CREATE INDEX i1 ON x1(b, c);
} {} } {}
foreach {tn otadb} { foreach {tn rbudb} {
1 { 1 {
CREATE TABLE data_x1(a, b, c, ota_control); CREATE TABLE data_x1(a, b, c, rbu_control);
INSERT INTO data_x1 VALUES(NULL, 'a', 'b', 0); INSERT INTO data_x1 VALUES(NULL, 'a', 'b', 0);
} }
2 { 2 {
CREATE TABLE data_x1(c, b, a, ota_control); CREATE TABLE data_x1(c, b, a, rbu_control);
INSERT INTO data_x1 VALUES('b', 'a', NULL, 0); INSERT INTO data_x1 VALUES('b', 'a', NULL, 0);
} }
} { } {
do_test 2.$tn.1 { do_test 2.$tn.1 {
forcedelete ota.db forcedelete rbu.db
sqlite3 db2 ota.db sqlite3 db2 rbu.db
db2 eval $otadb db2 eval $rbudb
db2 close db2 close
list [catch { run_ota test.db ota.db } msg] $msg list [catch { run_rbu test.db rbu.db } msg] $msg
} {1 {SQLITE_MISMATCH - datatype mismatch}} } {1 {SQLITE_MISMATCH - datatype mismatch}}
do_execsql_test 2.1.2 { do_execsql_test 2.1.2 {
@ -94,7 +94,7 @@ foreach {tn otadb} {
#-------------------------------------------------------------------- #--------------------------------------------------------------------
# Test that missing columns are detected. # Test that missing columns are detected.
# #
forcedelete ota.db forcedelete rbu.db
reset_db reset_db
do_execsql_test 2.0 { do_execsql_test 2.0 {
@ -103,13 +103,13 @@ do_execsql_test 2.0 {
} {} } {}
do_test 2.1 { do_test 2.1 {
sqlite3 db2 ota.db sqlite3 db2 rbu.db
db2 eval { db2 eval {
CREATE TABLE data_x1(a, b, ota_control); CREATE TABLE data_x1(a, b, rbu_control);
INSERT INTO data_x1 VALUES(1, 'a', 0); INSERT INTO data_x1 VALUES(1, 'a', 0);
} }
db2 close db2 close
list [catch { run_ota test.db ota.db } msg] $msg list [catch { run_rbu test.db rbu.db } msg] $msg
} {1 {SQLITE_ERROR - column missing from data_x1: c}} } {1 {SQLITE_ERROR - column missing from data_x1: c}}
do_execsql_test 2.2 { do_execsql_test 2.2 {
@ -124,14 +124,14 @@ do_execsql_test 2.3 {
} {} } {}
do_test 2.4 { do_test 2.4 {
forcedelete ota.db forcedelete rbu.db
sqlite3 db2 ota.db sqlite3 db2 rbu.db
db2 eval { db2 eval {
CREATE TABLE data_x2(a, b, c, d, ota_control); CREATE TABLE data_x2(a, b, c, d, rbu_control);
INSERT INTO data_x2 VALUES(1, 'a', 2, 3, 0); INSERT INTO data_x2 VALUES(1, 'a', 2, 3, 0);
} }
db2 close db2 close
list [catch { run_ota test.db ota.db } msg] $msg list [catch { run_rbu test.db rbu.db } msg] $msg
} {1 SQLITE_ERROR} } {1 SQLITE_ERROR}
do_execsql_test 2.5 { do_execsql_test 2.5 {
@ -140,48 +140,48 @@ do_execsql_test 2.5 {
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
# Test that sqlite3ota_create_vfs() returns an error if the requested # Test that sqlite3rbu_create_vfs() returns an error if the requested
# parent VFS is unknown. # parent VFS is unknown.
# #
# And that nothing disasterous happens if a VFS name passed to # And that nothing disasterous happens if a VFS name passed to
# sqlite3ota_destroy_vfs() is unknown or not an OTA vfs. # sqlite3rbu_destroy_vfs() is unknown or not an RBU vfs.
# #
do_test 3.1 { do_test 3.1 {
list [catch {sqlite3ota_create_vfs xyz nosuchparent} msg] $msg list [catch {sqlite3rbu_create_vfs xyz nosuchparent} msg] $msg
} {1 SQLITE_NOTFOUND} } {1 SQLITE_NOTFOUND}
do_test 3.2 { do_test 3.2 {
sqlite3ota_destroy_vfs nosuchvfs sqlite3rbu_destroy_vfs nosuchvfs
sqlite3ota_destroy_vfs unix sqlite3rbu_destroy_vfs unix
sqlite3ota_destroy_vfs win32 sqlite3rbu_destroy_vfs win32
} {} } {}
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
# Test that it is an error to specify an explicit VFS that does not # Test that it is an error to specify an explicit VFS that does not
# include ota VFS functionality. # include rbu VFS functionality.
# #
do_test 4.1 { do_test 4.1 {
testvfs tvfs testvfs tvfs
sqlite3ota ota file:test.db?vfs=tvfs ota.db sqlite3rbu rbu file:test.db?vfs=tvfs rbu.db
list [catch { ota step } msg] $msg list [catch { rbu step } msg] $msg
} {0 SQLITE_ERROR} } {0 SQLITE_ERROR}
do_test 4.2 { do_test 4.2 {
list [catch { ota close } msg] $msg list [catch { rbu close } msg] $msg
} {1 {SQLITE_ERROR - ota vfs not found}} } {1 {SQLITE_ERROR - rbu vfs not found}}
tvfs delete tvfs delete
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
# Test a large ota update to ensure that wal_autocheckpoint does not get # Test a large rbu update to ensure that wal_autocheckpoint does not get
# in the way. # in the way.
# #
forcedelete ota.db forcedelete rbu.db
reset_db reset_db
do_execsql_test 5.1 { do_execsql_test 5.1 {
CREATE TABLE x1(a, b, c, PRIMARY KEY(a)) WITHOUT ROWID; CREATE TABLE x1(a, b, c, PRIMARY KEY(a)) WITHOUT ROWID;
CREATE INDEX i1 ON x1(a); CREATE INDEX i1 ON x1(a);
ATTACH 'ota.db' AS ota; ATTACH 'rbu.db' AS rbu;
CREATE TABLE ota.data_x1(a, b, c, ota_control); CREATE TABLE rbu.data_x1(a, b, c, rbu_control);
WITH s(a, b, c) AS ( WITH s(a, b, c) AS (
SELECT randomblob(300), randomblob(300), 1 SELECT randomblob(300), randomblob(300), 1
UNION ALL UNION ALL
@ -191,16 +191,16 @@ do_execsql_test 5.1 {
} }
do_test 5.2 { do_test 5.2 {
sqlite3ota ota test.db ota.db sqlite3rbu rbu test.db rbu.db
while {[ota step]=="SQLITE_OK" && [file exists test.db-wal]==0} {} while {[rbu step]=="SQLITE_OK" && [file exists test.db-wal]==0} {}
ota close rbu close
} {SQLITE_OK} } {SQLITE_OK}
do_test 5.3 { do_test 5.3 {
expr {[file size test.db-wal] > (1024 * 1200)} expr {[file size test.db-wal] > (1024 * 1200)}
} 1 } 1
do_test 6.1 { sqlite3ota_internal_test } {} do_test 6.1 { sqlite3rbu_internal_test } {}
finish_test finish_test

View File

@ -9,33 +9,33 @@
# #
#*********************************************************************** #***********************************************************************
# #
# Test some properties of the pager_ota_mode and ota_mode pragmas. # Test some properties of the pager_rbu_mode and rbu_mode pragmas.
# #
if {![info exists testdir]} { if {![info exists testdir]} {
set testdir [file join [file dirname [info script]] .. .. test] set testdir [file join [file dirname [info script]] .. .. test]
} }
source $testdir/tester.tcl source $testdir/tester.tcl
set ::testprefix ota5 set ::testprefix rbu5
# Run the OTA in file $ota on target database $target until completion. # Run the RBU in file $rbu on target database $target until completion.
# #
proc run_ota {target ota} { proc run_rbu {target rbu} {
sqlite3ota ota $target $ota sqlite3rbu rbu $target $rbu
while { [ota step]=="SQLITE_OK" } {} while { [rbu step]=="SQLITE_OK" } {}
ota close rbu close
} }
# Run the OTA in file $ota on target database $target one step at a # Run the RBU in file $rbu on target database $target one step at a
# time until completion. # time until completion.
# #
proc step_ota {target ota} { proc step_rbu {target rbu} {
while 1 { while 1 {
sqlite3ota ota $target $ota sqlite3rbu rbu $target $rbu
set rc [ota step] set rc [rbu step]
ota close rbu close
if {$rc != "SQLITE_OK"} break if {$rc != "SQLITE_OK"} break
} }
set rc set rc
@ -99,31 +99,31 @@ proc ucontrol {args} {
# Argument $target is the name of an SQLite database file. $sql is an SQL # Argument $target is the name of an SQLite database file. $sql is an SQL
# script containing INSERT, UPDATE and DELETE statements to execute against # script containing INSERT, UPDATE and DELETE statements to execute against
# it. This command creates an OTA update database in file $ota that has # it. This command creates an RBU update database in file $rbu that has
# the same effect as the script. The target database is not modified by # the same effect as the script. The target database is not modified by
# this command. # this command.
# #
proc generate_ota_db {target ota sql} { proc generate_rbu_db {target rbu sql} {
forcedelete $ota forcedelete $rbu
forcecopy $target copy.db forcecopy $target copy.db
# Evaluate the SQL script to modify the contents of copy.db. # Evaluate the SQL script to modify the contents of copy.db.
# #
sqlite3 dbOta copy.db sqlite3 dbRbu copy.db
dbOta eval $sql dbRbu eval $sql
dbOta function ucontrol ucontrol dbRbu function ucontrol ucontrol
# Evaluate the SQL script to modify the contents of copy.db. # Evaluate the SQL script to modify the contents of copy.db.
set ret [datacksum dbOta] set ret [datacksum dbRbu]
dbOta eval { ATTACH $ota AS ota } dbRbu eval { ATTACH $rbu AS rbu }
dbOta eval { ATTACH $target AS orig } dbRbu eval { ATTACH $target AS orig }
dbOta eval { SELECT name AS tbl FROM sqlite_master WHERE type = 'table' } { dbRbu eval { SELECT name AS tbl FROM sqlite_master WHERE type = 'table' } {
set pk [pkcols dbOta $tbl] set pk [pkcols dbRbu $tbl]
set cols [allcols dbOta $tbl] set cols [allcols dbRbu $tbl]
# A WHERE clause to test that the PK columns match. # A WHERE clause to test that the PK columns match.
# #
@ -138,25 +138,25 @@ proc generate_ota_db {target ota sql} {
set ucontrol "ucontrol([join $where2 ,])" set ucontrol "ucontrol([join $where2 ,])"
set where2 [join $where2 " AND "] set where2 [join $where2 " AND "]
# Create a data_xxx table in the OTA update database. # Create a data_xxx table in the RBU update database.
dbOta eval " dbRbu eval "
CREATE TABLE ota.data_$tbl AS SELECT *, '' AS ota_control CREATE TABLE rbu.data_$tbl AS SELECT *, '' AS rbu_control
FROM main.$tbl LIMIT 0 FROM main.$tbl LIMIT 0
" "
# Find all new rows INSERTed by the script. # Find all new rows INSERTed by the script.
dbOta eval " dbRbu eval "
INSERT INTO ota.data_$tbl INSERT INTO rbu.data_$tbl
SELECT *, 0 AS ota_control FROM main.$tbl SELECT *, 0 AS rbu_control FROM main.$tbl
WHERE NOT EXISTS ( WHERE NOT EXISTS (
SELECT 1 FROM orig.$tbl WHERE $where SELECT 1 FROM orig.$tbl WHERE $where
) )
" "
# Find all old rows DELETEd by the script. # Find all old rows DELETEd by the script.
dbOta eval " dbRbu eval "
INSERT INTO ota.data_$tbl INSERT INTO rbu.data_$tbl
SELECT *, 1 AS ota_control FROM orig.$tbl SELECT *, 1 AS rbu_control FROM orig.$tbl
WHERE NOT EXISTS ( WHERE NOT EXISTS (
SELECT 1 FROM main.$tbl WHERE $where SELECT 1 FROM main.$tbl WHERE $where
) )
@ -166,16 +166,16 @@ proc generate_ota_db {target ota sql} {
set origcols [list] set origcols [list]
foreach c $cols { lappend origcols "main.$tbl.$c" } foreach c $cols { lappend origcols "main.$tbl.$c" }
set origcols [join $origcols ,] set origcols [join $origcols ,]
dbOta eval " dbRbu eval "
INSERT INTO ota.data_$tbl INSERT INTO rbu.data_$tbl
SELECT $origcols, $ucontrol AS ota_control SELECT $origcols, $ucontrol AS rbu_control
FROM orig.$tbl, main.$tbl FROM orig.$tbl, main.$tbl
WHERE $where AND NOT ($where2) WHERE $where AND NOT ($where2)
" "
} }
dbOta close dbRbu close
forcedelete copy.db forcedelete copy.db
return $ret return $ret
@ -197,7 +197,7 @@ do_execsql_test 1.0 {
} }
db close db close
set cksum [generate_ota_db test.db ota.db { set cksum [generate_rbu_db test.db rbu.db {
INSERT INTO t1 VALUES(4, 8, 12); INSERT INTO t1 VALUES(4, 8, 12);
DELETE FROM t1 WHERE a = 2; DELETE FROM t1 WHERE a = 2;
UPDATE t1 SET c = 15 WHERE a=3; UPDATE t1 SET c = 15 WHERE a=3;
@ -217,13 +217,13 @@ foreach {tn idx} {
} { } {
foreach cmd {run step} { foreach cmd {run step} {
forcecopy test.db test.db2 forcecopy test.db test.db2
forcecopy ota.db ota.db2 forcecopy rbu.db rbu.db2
sqlite3 db test.db2 sqlite3 db test.db2
db eval $idx db eval $idx
do_test 1.$tn.$cmd.1 { do_test 1.$tn.$cmd.1 {
${cmd}_ota test.db2 ota.db2 ${cmd}_rbu test.db2 rbu.db2
datacksum db datacksum db
} $cksum } $cksum
@ -265,7 +265,7 @@ do_execsql_test 2.0 {
} }
db close db close
set cksum [generate_ota_db test.db ota.db { set cksum [generate_rbu_db test.db rbu.db {
INSERT INTO t2 VALUES(222916.23,'idh',X'472C517405',X'E3',X'7C4F31824669'); INSERT INTO t2 VALUES(222916.23,'idh',X'472C517405',X'E3',X'7C4F31824669');
INSERT INTO t2 VALUES('xcndjwafcoxwxizoktd',-319567.21,NULL,-720906.43,-577170); INSERT INTO t2 VALUES('xcndjwafcoxwxizoktd',-319567.21,NULL,-720906.43,-577170);
INSERT INTO t2 VALUES(376369.99,-536058,'yoaiurfqupdscwc',X'29EC8A2542EC3953E9',-740485.22); INSERT INTO t2 VALUES(376369.99,-536058,'yoaiurfqupdscwc',X'29EC8A2542EC3953E9',-740485.22);
@ -305,13 +305,13 @@ foreach {tn idx} {
} { } {
foreach cmd {run step} { foreach cmd {run step} {
forcecopy test.db test.db2 forcecopy test.db test.db2
forcecopy ota.db ota.db2 forcecopy rbu.db rbu.db2
sqlite3 db test.db2 sqlite3 db test.db2
db eval $idx db eval $idx
do_test 2.$tn.$cmd.1 { do_test 2.$tn.$cmd.1 {
${cmd}_ota test.db2 ota.db2 ${cmd}_rbu test.db2 rbu.db2
datacksum db datacksum db
} $cksum } $cksum

View File

@ -9,15 +9,15 @@
# #
#*********************************************************************** #***********************************************************************
# #
# This file contains tests for the OTA module. Specifically, it tests the # This file contains tests for the RBU module. Specifically, it tests the
# outcome of some other client writing to the database while an OTA update # outcome of some other client writing to the database while an RBU update
# is being applied. # is being applied.
if {![info exists testdir]} { if {![info exists testdir]} {
set testdir [file join [file dirname [info script]] .. .. test] set testdir [file join [file dirname [info script]] .. .. test]
} }
source $testdir/tester.tcl source $testdir/tester.tcl
set ::testprefix ota6 set ::testprefix rbu6
proc setup_test {} { proc setup_test {} {
reset_db reset_db
@ -28,17 +28,17 @@ proc setup_test {} {
} }
db close db close
forcedelete ota.db forcedelete rbu.db
sqlite3 ota ota.db sqlite3 rbu rbu.db
ota eval { rbu eval {
CREATE TABLE data_t1(a, b, ota_control); CREATE TABLE data_t1(a, b, rbu_control);
CREATE TABLE data_t2(a, b, ota_control); CREATE TABLE data_t2(a, b, rbu_control);
CREATE TABLE data_t3(a, b, ota_control); CREATE TABLE data_t3(a, b, rbu_control);
INSERT INTO data_t1 VALUES(1, 't1', 0); INSERT INTO data_t1 VALUES(1, 't1', 0);
INSERT INTO data_t2 VALUES(2, 't2', 0); INSERT INTO data_t2 VALUES(2, 't2', 0);
INSERT INTO data_t3 VALUES(3, 't3', 0); INSERT INTO data_t3 VALUES(3, 't3', 0);
} }
ota close rbu close
} }
# Test the outcome of some other client writing the db while the *-oal # Test the outcome of some other client writing the db while the *-oal
@ -48,49 +48,49 @@ proc setup_test {} {
for {set nStep 1} {$nStep < 8} {incr nStep} { for {set nStep 1} {$nStep < 8} {incr nStep} {
do_test 1.$nStep.1 { do_test 1.$nStep.1 {
setup_test setup_test
sqlite3ota ota test.db ota.db sqlite3rbu rbu test.db rbu.db
for {set i 0} {$i<$nStep} {incr i} {ota step} for {set i 0} {$i<$nStep} {incr i} {rbu step}
ota close rbu close
sqlite3 db test.db sqlite3 db test.db
execsql { INSERT INTO t1 VALUES(5, 'hello') } execsql { INSERT INTO t1 VALUES(5, 'hello') }
sqlite3ota ota test.db ota.db sqlite3rbu rbu test.db rbu.db
ota step rbu step
} {SQLITE_BUSY} } {SQLITE_BUSY}
do_test 1.$nStep.2 { do_test 1.$nStep.2 {
ota step rbu step
} {SQLITE_BUSY} } {SQLITE_BUSY}
do_test 1.$nStep.3 { do_test 1.$nStep.3 {
list [file exists test.db-oal] [file exists test.db-wal] list [file exists test.db-oal] [file exists test.db-wal]
} {1 0} } {1 0}
do_test 1.$nStep.4 { do_test 1.$nStep.4 {
list [catch { ota close } msg] $msg list [catch { rbu close } msg] $msg
} {1 {SQLITE_BUSY - database modified during ota update}} } {1 {SQLITE_BUSY - database modified during rbu update}}
} }
# Test the outcome of some other client writing the db after the *-oal # Test the outcome of some other client writing the db after the *-oal
# file has been copied to the *-wal path. Once this has happened, any # file has been copied to the *-wal path. Once this has happened, any
# other client writing to the db causes OTA to consider its job finished. # other client writing to the db causes RBU to consider its job finished.
# #
for {set nStep 8} {$nStep < 20} {incr nStep} { for {set nStep 8} {$nStep < 20} {incr nStep} {
do_test 1.$nStep.1 { do_test 1.$nStep.1 {
setup_test setup_test
sqlite3ota ota test.db ota.db sqlite3rbu rbu test.db rbu.db
for {set i 0} {$i<$nStep} {incr i} {ota step} for {set i 0} {$i<$nStep} {incr i} {rbu step}
ota close rbu close
sqlite3 db test.db sqlite3 db test.db
execsql { INSERT INTO t1 VALUES(5, 'hello') } execsql { INSERT INTO t1 VALUES(5, 'hello') }
sqlite3ota ota test.db ota.db sqlite3rbu rbu test.db rbu.db
ota step rbu step
} {SQLITE_DONE} } {SQLITE_DONE}
do_test 1.$nStep.2 { do_test 1.$nStep.2 {
ota step rbu step
} {SQLITE_DONE} } {SQLITE_DONE}
do_test 1.$nStep.3 { do_test 1.$nStep.3 {
file exists test.db-oal file exists test.db-oal
} {0} } {0}
do_test 1.$nStep.4 { do_test 1.$nStep.4 {
list [catch { ota close } msg] $msg list [catch { rbu close } msg] $msg
} {0 SQLITE_DONE} } {0 SQLITE_DONE}
do_execsql_test 1.$nStep.5 { do_execsql_test 1.$nStep.5 {

View File

@ -9,7 +9,7 @@
# #
#*********************************************************************** #***********************************************************************
# #
# This file contains tests for the OTA module. # This file contains tests for the RBU module.
# #
@ -17,12 +17,12 @@ if {![info exists testdir]} {
set testdir [file join [file dirname [info script]] .. .. test] set testdir [file join [file dirname [info script]] .. .. test]
} }
source $testdir/tester.tcl source $testdir/tester.tcl
set ::testprefix ota7 set ::testprefix rbu7
# Test index: # Test index:
# #
# 1.*: That affinities are correctly applied to values within the # 1.*: That affinities are correctly applied to values within the
# OTA database. # RBU database.
# #
# 2.*: Tests for multi-column primary keys. # 2.*: Tests for multi-column primary keys.
# #
@ -34,19 +34,19 @@ do_test 1.0 {
INSERT INTO t1 VALUES(2, 'def'); INSERT INTO t1 VALUES(2, 'def');
} }
forcedelete ota.db forcedelete rbu.db
sqlite3 ota ota.db sqlite3 rbu rbu.db
ota eval { rbu eval {
CREATE TABLE data_t1(a, b, ota_control); CREATE TABLE data_t1(a, b, rbu_control);
INSERT INTO data_t1 VALUES('1', NULL, 1); INSERT INTO data_t1 VALUES('1', NULL, 1);
} }
ota close rbu close
} {} } {}
do_test 1.1 { do_test 1.1 {
sqlite3ota ota test.db ota.db sqlite3rbu rbu test.db rbu.db
while { [ota step]=="SQLITE_OK" } {} while { [rbu step]=="SQLITE_OK" } {}
ota close rbu close
} {SQLITE_DONE} } {SQLITE_DONE}
sqlite3 db test.db sqlite3 db test.db
@ -72,24 +72,24 @@ foreach {tn tbl} {
} }
do_test 2.$tn.2 { do_test 2.$tn.2 {
forcedelete ota.db forcedelete rbu.db
sqlite3 ota ota.db sqlite3 rbu rbu.db
execsql { execsql {
CREATE TABLE data_t1(a, b, c, ota_control); CREATE TABLE data_t1(a, b, c, rbu_control);
INSERT INTO data_t1 VALUES(3, 1, 'e', 0); INSERT INTO data_t1 VALUES(3, 1, 'e', 0);
INSERT INTO data_t1 VALUES(3, 2, 'f', 0); INSERT INTO data_t1 VALUES(3, 2, 'f', 0);
INSERT INTO data_t1 VALUES(1, 2, NULL, 1); INSERT INTO data_t1 VALUES(1, 2, NULL, 1);
INSERT INTO data_t1 VALUES(2, 1, 'X', '..x'); INSERT INTO data_t1 VALUES(2, 1, 'X', '..x');
} ota } rbu
ota close rbu close
} {} } {}
do_test 2.$tn.3 { do_test 2.$tn.3 {
set rc "SQLITE_OK" set rc "SQLITE_OK"
while {$rc == "SQLITE_OK"} { while {$rc == "SQLITE_OK"} {
sqlite3ota ota test.db ota.db sqlite3rbu rbu test.db rbu.db
ota step rbu step
set rc [ota close] set rc [rbu close]
} }
set rc set rc
} {SQLITE_DONE} } {SQLITE_DONE}

View File

@ -9,14 +9,14 @@
# #
#*********************************************************************** #***********************************************************************
# #
# Test the ota_delta() feature. # Test the rbu_delta() feature.
# #
if {![info exists testdir]} { if {![info exists testdir]} {
set testdir [file join [file dirname [info script]] .. .. test] set testdir [file join [file dirname [info script]] .. .. test]
} }
source $testdir/tester.tcl source $testdir/tester.tcl
set ::testprefix ota8 set ::testprefix rbu8
do_execsql_test 1.0 { do_execsql_test 1.0 {
CREATE TABLE t1(x, y PRIMARY KEY, z); CREATE TABLE t1(x, y PRIMARY KEY, z);
@ -27,10 +27,10 @@ do_execsql_test 1.0 {
} }
do_test 1.1 { do_test 1.1 {
forcedelete ota.db forcedelete rbu.db
sqlite3 db2 ota.db sqlite3 db2 rbu.db
db2 eval { db2 eval {
CREATE TABLE data_t1(x, y, z, ota_control); CREATE TABLE data_t1(x, y, z, rbu_control);
INSERT INTO data_t1 VALUES('a', 1, '_i' , 'x.d'); INSERT INTO data_t1 VALUES('a', 1, '_i' , 'x.d');
INSERT INTO data_t1 VALUES('b', 2, 2 , '..x'); INSERT INTO data_t1 VALUES('b', 2, 2 , '..x');
INSERT INTO data_t1 VALUES('_iii', 3, '-III' , 'd.d'); INSERT INTO data_t1 VALUES('_iii', 3, '-III' , 'd.d');
@ -39,26 +39,26 @@ do_test 1.1 {
} {} } {}
do_test 1.2.1 { do_test 1.2.1 {
sqlite3ota ota test.db ota.db sqlite3rbu rbu test.db rbu.db
ota step rbu step
} {SQLITE_ERROR} } {SQLITE_ERROR}
do_test 1.2.2 { do_test 1.2.2 {
list [catch {ota close} msg] $msg list [catch {rbu close} msg] $msg
} {1 {SQLITE_ERROR - no such function: ota_delta}} } {1 {SQLITE_ERROR - no such function: rbu_delta}}
proc ota_delta {orig new} { proc rbu_delta {orig new} {
return "${orig}${new}" return "${orig}${new}"
} }
do_test 1.3.1 { do_test 1.3.1 {
while 1 { while 1 {
sqlite3ota ota test.db ota.db sqlite3rbu rbu test.db rbu.db
ota create_ota_delta rbu create_rbu_delta
set rc [ota step] set rc [rbu step]
if {$rc != "SQLITE_OK"} break if {$rc != "SQLITE_OK"} break
ota close rbu close
} }
ota close rbu close
} {SQLITE_DONE} } {SQLITE_DONE}
do_execsql_test 1.3.2 { do_execsql_test 1.3.2 {

View File

@ -9,14 +9,14 @@
# #
#*********************************************************************** #***********************************************************************
# #
# Test OTA with virtual tables. And tables with no PRIMARY KEY declarations. # Test RBU with virtual tables. And tables with no PRIMARY KEY declarations.
# #
if {![info exists testdir]} { if {![info exists testdir]} {
set testdir [file join [file dirname [info script]] .. .. test] set testdir [file join [file dirname [info script]] .. .. test]
} }
source $testdir/tester.tcl source $testdir/tester.tcl
set ::testprefix ota9 set ::testprefix rbu9
ifcapable !fts3 { ifcapable !fts3 {
finish_test finish_test
@ -31,10 +31,10 @@ do_execsql_test 1.1 {
} }
do_test 1.1 { do_test 1.1 {
forcedelete ota.db forcedelete rbu.db
sqlite3 db2 ota.db sqlite3 db2 rbu.db
db2 eval { db2 eval {
CREATE TABLE data_f1(ota_rowid, a, b, c, ota_control); CREATE TABLE data_f1(rbu_rowid, a, b, c, rbu_control);
INSERT INTO data_f1 VALUES(14, 'x', 'y', 'z', 0); -- INSERT INSERT INTO data_f1 VALUES(14, 'x', 'y', 'z', 0); -- INSERT
INSERT INTO data_f1 VALUES(11, NULL, NULL, NULL, 1); -- DELETE INSERT INTO data_f1 VALUES(11, NULL, NULL, NULL, 1); -- DELETE
INSERT INTO data_f1 VALUES(13, NULL, NULL, 'X', '..x'); -- UPDATE INSERT INTO data_f1 VALUES(13, NULL, NULL, 'X', '..x'); -- UPDATE
@ -44,12 +44,12 @@ do_test 1.1 {
do_test 1.2.1 { do_test 1.2.1 {
while 1 { while 1 {
sqlite3ota ota test.db ota.db sqlite3rbu rbu test.db rbu.db
set rc [ota step] set rc [rbu step]
if {$rc != "SQLITE_OK"} break if {$rc != "SQLITE_OK"} break
ota close rbu close
} }
ota close rbu close
} {SQLITE_DONE} } {SQLITE_DONE}
do_execsql_test 1.2.2 { SELECT rowid, * FROM f1 } { do_execsql_test 1.2.2 { SELECT rowid, * FROM f1 } {
@ -64,12 +64,12 @@ integrity_check 1.2.4
# Tables with no PK declaration. # Tables with no PK declaration.
# #
# Run the OTA in file $ota on target database $target until completion. # Run the RBU in file $rbu on target database $target until completion.
# #
proc run_ota {target ota} { proc run_rbu {target rbu} {
sqlite3ota ota $target $ota sqlite3rbu rbu $target $rbu
while { [ota step]=="SQLITE_OK" } {} while { [rbu step]=="SQLITE_OK" } {}
ota close rbu close
} }
foreach {tn idx} { foreach {tn idx} {
@ -96,10 +96,10 @@ foreach {tn idx} {
db eval $idx db eval $idx
do_test 2.$tn.2 { do_test 2.$tn.2 {
forcedelete ota.db forcedelete rbu.db
sqlite3 db2 ota.db sqlite3 db2 rbu.db
db2 eval { db2 eval {
CREATE TABLE data_t1(ota_rowid, a, b, c, ota_control); CREATE TABLE data_t1(rbu_rowid, a, b, c, rbu_control);
INSERT INTO data_t1 VALUES(3, 'x', 'y', 'z', 0); INSERT INTO data_t1 VALUES(3, 'x', 'y', 'z', 0);
INSERT INTO data_t1 VALUES(NULL, 'X', 'Y', 'Z', 0); INSERT INTO data_t1 VALUES(NULL, 'X', 'Y', 'Z', 0);
INSERT INTO data_t1 VALUES('1', NULL, NULL, NULL, 1); INSERT INTO data_t1 VALUES('1', NULL, NULL, NULL, 1);
@ -108,7 +108,7 @@ foreach {tn idx} {
db2 close db2 close
} {} } {}
run_ota test.db ota.db run_rbu test.db rbu.db
do_execsql_test 2.$tn.3 { do_execsql_test 2.$tn.3 {
SELECT rowid, a, b, c FROM t1 ORDER BY rowid; SELECT rowid, a, b, c FROM t1 ORDER BY rowid;

View File

@ -9,22 +9,22 @@
# #
#*********************************************************************** #***********************************************************************
# #
# This file contains tests for the OTA module. More specifically, it # This file contains tests for the RBU module. More specifically, it
# contains tests to ensure that it is an error to attempt to update # contains tests to ensure that it is an error to attempt to update
# a wal mode database via OTA. # a wal mode database via RBU.
# #
if {![info exists testdir]} { if {![info exists testdir]} {
set testdir [file join [file dirname [info script]] .. .. test] set testdir [file join [file dirname [info script]] .. .. test]
} }
source $testdir/tester.tcl source $testdir/tester.tcl
set ::testprefix otaA set ::testprefix rbuA
set db_sql { set db_sql {
CREATE TABLE t1(a PRIMARY KEY, b, c); CREATE TABLE t1(a PRIMARY KEY, b, c);
} }
set ota_sql { set rbu_sql {
CREATE TABLE data_t1(a, b, c, ota_control); CREATE TABLE data_t1(a, b, c, rbu_control);
INSERT INTO data_t1 VALUES(1, 2, 3, 0); INSERT INTO data_t1 VALUES(1, 2, 3, 0);
INSERT INTO data_t1 VALUES(4, 5, 6, 0); INSERT INTO data_t1 VALUES(4, 5, 6, 0);
INSERT INTO data_t1 VALUES(7, 8, 9, 0); INSERT INTO data_t1 VALUES(7, 8, 9, 0);
@ -32,38 +32,38 @@ set ota_sql {
do_test 1.0 { do_test 1.0 {
db close db close
forcedelete test.db ota.db forcedelete test.db rbu.db
sqlite3 db test.db sqlite3 db test.db
db eval $db_sql db eval $db_sql
db eval { PRAGMA journal_mode = wal } db eval { PRAGMA journal_mode = wal }
db close db close
sqlite3 db ota.db sqlite3 db rbu.db
db eval $ota_sql db eval $rbu_sql
db close db close
sqlite3ota ota test.db ota.db sqlite3rbu rbu test.db rbu.db
ota step rbu step
} {SQLITE_ERROR} } {SQLITE_ERROR}
do_test 1.1 { do_test 1.1 {
list [catch { ota close } msg] $msg list [catch { rbu close } msg] $msg
} {1 {SQLITE_ERROR - cannot update wal mode database}} } {1 {SQLITE_ERROR - cannot update wal mode database}}
do_test 2.0 { do_test 2.0 {
forcedelete test.db ota.db forcedelete test.db rbu.db
sqlite3 db test.db sqlite3 db test.db
db eval $db_sql db eval $db_sql
db close db close
sqlite3 db ota.db sqlite3 db rbu.db
db eval $ota_sql db eval $rbu_sql
db close db close
sqlite3ota ota test.db ota.db sqlite3rbu rbu test.db rbu.db
ota step rbu step
ota close rbu close
} {SQLITE_OK} } {SQLITE_OK}
do_test 2.1 { do_test 2.1 {
@ -71,12 +71,12 @@ do_test 2.1 {
db eval {PRAGMA journal_mode = wal} db eval {PRAGMA journal_mode = wal}
db close db close
breakpoint breakpoint
sqlite3ota ota test.db ota.db sqlite3rbu rbu test.db rbu.db
ota step rbu step
} {SQLITE_ERROR} } {SQLITE_ERROR}
do_test 2.2 { do_test 2.2 {
list [catch { ota close } msg] $msg list [catch { rbu close } msg] $msg
} {1 {SQLITE_ERROR - cannot update wal mode database}} } {1 {SQLITE_ERROR - cannot update wal mode database}}

View File

@ -14,16 +14,16 @@ if {![info exists testdir]} {
set testdir [file join [file dirname [info script]] .. .. test] set testdir [file join [file dirname [info script]] .. .. test]
} }
source $testdir/tester.tcl source $testdir/tester.tcl
set ::testprefix otacrash set ::testprefix rbucrash
db close db close
forcedelete test.db-oal ota.db forcedelete test.db-oal rbu.db
sqlite3_shutdown sqlite3_shutdown
sqlite3_config_uri 1 sqlite3_config_uri 1
reset_db reset_db
# Set up a target database and an ota update database. The target # Set up a target database and an rbu update database. The target
# db is the usual "test.db", the ota db is "test.db2". # db is the usual "test.db", the rbu db is "test.db2".
# #
forcedelete test.db2 forcedelete test.db2
do_execsql_test 1.0 { do_execsql_test 1.0 {
@ -32,8 +32,8 @@ do_execsql_test 1.0 {
INSERT INTO t1 VALUES(4, 5, 6); INSERT INTO t1 VALUES(4, 5, 6);
INSERT INTO t1 VALUES(7, 8, 9); INSERT INTO t1 VALUES(7, 8, 9);
ATTACH 'test.db2' AS ota; ATTACH 'test.db2' AS rbu;
CREATE TABLE ota.data_t1(a, b, c, ota_control); CREATE TABLE rbu.data_t1(a, b, c, rbu_control);
INSERT INTO data_t1 VALUES(10, 11, 12, 0); INSERT INTO data_t1 VALUES(10, 11, 12, 0);
INSERT INTO data_t1 VALUES(13, 14, 15, 0); INSERT INTO data_t1 VALUES(13, 14, 15, 0);
INSERT INTO data_t1 VALUES(4, NULL, NULL, 1); INSERT INTO data_t1 VALUES(4, NULL, NULL, 1);
@ -42,63 +42,63 @@ do_execsql_test 1.0 {
db_save_and_close db_save_and_close
# Determine the number of steps in applying the ota update to the test # Determine the number of steps in applying the rbu update to the test
# target database created above. Set $::ota_num_steps accordingly # target database created above. Set $::rbu_num_steps accordingly
# #
# Check that the same number of steps are required to apply the ota # Check that the same number of steps are required to apply the rbu
# update using many calls to sqlite3ota_step() on a single ota handle # update using many calls to sqlite3rbu_step() on a single rbu handle
# as required to apply it using a series of ota handles, on each of # as required to apply it using a series of rbu handles, on each of
# which sqlite3ota_step() is called once. # which sqlite3rbu_step() is called once.
# #
do_test 1.1 { do_test 1.1 {
db_restore db_restore
sqlite3ota ota test.db test.db2 sqlite3rbu rbu test.db test.db2
breakpoint breakpoint
set nStep 0 set nStep 0
while {[ota step]=="SQLITE_OK"} { incr nStep } while {[rbu step]=="SQLITE_OK"} { incr nStep }
ota close rbu close
} {SQLITE_DONE} } {SQLITE_DONE}
set ota_num_steps $nStep set rbu_num_steps $nStep
do_test 1.2 { do_test 1.2 {
db_restore db_restore
set nStep 0 set nStep 0
while {1} { while {1} {
sqlite3ota ota test.db test.db2 sqlite3rbu rbu test.db test.db2
ota step rbu step
if {[ota close]=="SQLITE_DONE"} break if {[rbu close]=="SQLITE_DONE"} break
incr nStep incr nStep
} }
set nStep set nStep
} $ota_num_steps } $rbu_num_steps
# Run one or more tests using the target (test.db) and ota (test.db2) # Run one or more tests using the target (test.db) and rbu (test.db2)
# databases created above. As follows: # databases created above. As follows:
# #
# 1. This process starts the ota update and calls sqlite3ota_step() # 1. This process starts the rbu update and calls sqlite3rbu_step()
# $nPre times. Then closes the ota update handle. # $nPre times. Then closes the rbu update handle.
# #
# 2. A second process resumes the ota update and attempts to call # 2. A second process resumes the rbu update and attempts to call
# sqlite3ota_step() $nStep times before closing the handle. A # sqlite3rbu_step() $nStep times before closing the handle. A
# crash is simulated during each xSync() of file test.db2. # crash is simulated during each xSync() of file test.db2.
# #
# 3. This process attempts to resume the ota update from whatever # 3. This process attempts to resume the rbu update from whatever
# state it was left in by step (2). Test that it is successful # state it was left in by step (2). Test that it is successful
# in doing so and that the final target database is as expected. # in doing so and that the final target database is as expected.
# #
# In total (nSync+1) tests are run, where nSync is the number of times # In total (nSync+1) tests are run, where nSync is the number of times
# xSync() is called on test.db2. # xSync() is called on test.db2.
# #
proc do_ota_crash_test {tn nPre nStep} { proc do_rbu_crash_test {tn nPre nStep} {
set script [subst -nocommands { set script [subst -nocommands {
sqlite3ota ota test.db file:test.db2?vfs=crash sqlite3rbu rbu test.db file:test.db2?vfs=crash
set i 0 set i 0
while {[set i] < $nStep} { while {[set i] < $nStep} {
if {[ota step]!="SQLITE_OK"} break if {[rbu step]!="SQLITE_OK"} break
incr i incr i
} }
ota close rbu close
}] }]
set bDone 0 set bDone 0
@ -107,12 +107,12 @@ proc do_ota_crash_test {tn nPre nStep} {
db_restore db_restore
if {$nPre>0} { if {$nPre>0} {
sqlite3ota ota test.db file:test.db2 sqlite3rbu rbu test.db file:test.db2
set i 0 set i 0
for {set i 0} {$i < $nPre} {incr i} { for {set i 0} {$i < $nPre} {incr i} {
if {[ota step]!="SQLITE_OK"} break if {[rbu step]!="SQLITE_OK"} break
} }
ota close rbu close
} }
set res [ set res [
@ -126,9 +126,9 @@ proc do_ota_crash_test {tn nPre nStep} {
error "unexected catchsql result: $res" error "unexected catchsql result: $res"
} }
sqlite3ota ota test.db test.db2 sqlite3rbu rbu test.db test.db2
while {[ota step]=="SQLITE_OK"} {} while {[rbu step]=="SQLITE_OK"} {}
ota close rbu close
sqlite3 db test.db sqlite3 db test.db
do_execsql_test $tn.delay=$iDelay { do_execsql_test $tn.delay=$iDelay {
@ -139,9 +139,9 @@ proc do_ota_crash_test {tn nPre nStep} {
} }
} }
for {set nPre 0} {$nPre < $ota_num_steps} {incr nPre} { for {set nPre 0} {$nPre < $rbu_num_steps} {incr nPre} {
for {set is 1} {$is <= ($ota_num_steps - $nPre)} {incr is} { for {set is 1} {$is <= ($rbu_num_steps - $nPre)} {incr is} {
do_ota_crash_test 2.pre=$nPre.step=$is $nPre $is do_rbu_crash_test 2.pre=$nPre.step=$is $nPre $is
} }
} }

View File

@ -15,7 +15,7 @@ if {![info exists testdir]} {
} }
source $testdir/tester.tcl source $testdir/tester.tcl
source $testdir/malloc_common.tcl source $testdir/malloc_common.tcl
set ::testprefix otafault set ::testprefix rbufault
proc copy_if_exists {src target} { proc copy_if_exists {src target} {
if {[file exists $src]} { if {[file exists $src]} {
@ -33,7 +33,7 @@ foreach {tn2 setup sql expect} {
INSERT INTO t1 VALUES(2, 2, 2); INSERT INTO t1 VALUES(2, 2, 2);
INSERT INTO t1 VALUES(3, 3, 3); INSERT INTO t1 VALUES(3, 3, 3);
CREATE TABLE ota.data_t1(a, b, c, ota_control); CREATE TABLE rbu.data_t1(a, b, c, rbu_control);
INSERT INTO data_t1 VALUES(2, NULL, NULL, 1); INSERT INTO data_t1 VALUES(2, NULL, NULL, 1);
INSERT INTO data_t1 VALUES(3, 'three', NULL, '.x.'); INSERT INTO data_t1 VALUES(3, 'three', NULL, '.x.');
INSERT INTO data_t1 VALUES(4, 4, 4, 0); INSERT INTO data_t1 VALUES(4, 4, 4, 0);
@ -48,7 +48,7 @@ foreach {tn2 setup sql expect} {
INSERT INTO t2 VALUES('b', 'b', 'b'); INSERT INTO t2 VALUES('b', 'b', 'b');
INSERT INTO t2 VALUES('c', 'c', 'c'); INSERT INTO t2 VALUES('c', 'c', 'c');
CREATE TABLE ota.data_t2(a, b, c, ota_control); CREATE TABLE rbu.data_t2(a, b, c, rbu_control);
INSERT INTO data_t2 VALUES('b', NULL, NULL, 1); INSERT INTO data_t2 VALUES('b', NULL, NULL, 1);
INSERT INTO data_t2 VALUES('c', 'see', NULL, '.x.'); INSERT INTO data_t2 VALUES('c', 'see', NULL, '.x.');
INSERT INTO data_t2 VALUES('d', 'd', 'd', 0); INSERT INTO data_t2 VALUES('d', 'd', 'd', 0);
@ -62,8 +62,8 @@ foreach {tn2 setup sql expect} {
CREATE INDEX t1cb ON t1(c, b); CREATE INDEX t1cb ON t1(c, b);
CREATE INDEX t2cb ON t2(c, b); CREATE INDEX t2cb ON t2(c, b);
CREATE TABLE ota.data_t1(a, b, c, ota_control); CREATE TABLE rbu.data_t1(a, b, c, rbu_control);
CREATE TABLE ota.data_t2(a, b, c, ota_control); CREATE TABLE rbu.data_t2(a, b, c, rbu_control);
INSERT INTO data_t1 VALUES(1, 2, 3, 0); INSERT INTO data_t1 VALUES(1, 2, 3, 0);
INSERT INTO data_t2 VALUES(4, 5, 6, 0); INSERT INTO data_t2 VALUES(4, 5, 6, 0);
} { } {
@ -76,7 +76,7 @@ foreach {tn2 setup sql expect} {
INSERT INTO t1 VALUES('A', 'B', 'C'); INSERT INTO t1 VALUES('A', 'B', 'C');
INSERT INTO t1 VALUES('D', 'E', 'F'); INSERT INTO t1 VALUES('D', 'E', 'F');
CREATE TABLE ota.data_t1(a, b, c, ota_control); CREATE TABLE rbu.data_t1(a, b, c, rbu_control);
INSERT INTO data_t1 VALUES('D', NULL, NULL, 1); INSERT INTO data_t1 VALUES('D', NULL, NULL, 1);
INSERT INTO data_t1 VALUES('A', 'Z', NULL, '.x.'); INSERT INTO data_t1 VALUES('A', 'Z', NULL, '.x.');
INSERT INTO data_t1 VALUES('G', 'H', 'I', 0); INSERT INTO data_t1 VALUES('G', 'H', 'I', 0);
@ -88,7 +88,7 @@ foreach {tn2 setup sql expect} {
CREATE TABLE t1(a, b, c); CREATE TABLE t1(a, b, c);
CREATE INDEX t1c ON t1(c, b); CREATE INDEX t1c ON t1(c, b);
CREATE TABLE ota.data_t1(a, b, c, ota_rowid, ota_control); CREATE TABLE rbu.data_t1(a, b, c, rbu_rowid, rbu_control);
INSERT INTO data_t1 VALUES('a', 'b', 'c', 1, 0); INSERT INTO data_t1 VALUES('a', 'b', 'c', 1, 0);
INSERT INTO data_t1 VALUES('d', 'e', 'f', '2', 0); INSERT INTO data_t1 VALUES('d', 'e', 'f', '2', 0);
} { } {
@ -97,17 +97,17 @@ foreach {tn2 setup sql expect} {
} { } {
catch {db close} catch {db close}
forcedelete ota.db test.db forcedelete rbu.db test.db
sqlite3 db test.db sqlite3 db test.db
execsql { execsql {
PRAGMA encoding = utf16; PRAGMA encoding = utf16;
ATTACH 'ota.db' AS ota; ATTACH 'rbu.db' AS rbu;
} }
execsql $setup execsql $setup
db close db close
forcecopy test.db test.db.bak forcecopy test.db test.db.bak
forcecopy ota.db ota.db.bak forcecopy rbu.db rbu.db.bak
foreach {tn f reslist} { foreach {tn f reslist} {
1 oom-tra* { 1 oom-tra* {
@ -126,8 +126,8 @@ foreach {tn2 setup sql expect} {
{1 SQLITE_IOERR_READ} {1 SQLITE_IOERR_READ}
{1 SQLITE_IOERR_FSYNC} {1 SQLITE_IOERR_FSYNC}
{1 {SQLITE_ERROR - SQL logic error or missing database}} {1 {SQLITE_ERROR - SQL logic error or missing database}}
{1 {SQLITE_ERROR - unable to open database: ota.db}} {1 {SQLITE_ERROR - unable to open database: rbu.db}}
{1 {SQLITE_IOERR - unable to open database: ota.db}} {1 {SQLITE_IOERR - unable to open database: rbu.db}}
} }
3 shmerr-* { 3 shmerr-* {
@ -145,13 +145,13 @@ foreach {tn2 setup sql expect} {
do_faultsim_test 2.$tn2 -faults $::f -prep { do_faultsim_test 2.$tn2 -faults $::f -prep {
catch { db close } catch { db close }
forcedelete test.db-journal test.db-wal ota.db-journal ota.db-wal forcedelete test.db-journal test.db-wal rbu.db-journal rbu.db-wal
forcecopy test.db.bak test.db forcecopy test.db.bak test.db
forcecopy ota.db.bak ota.db forcecopy rbu.db.bak rbu.db
} -body { } -body {
sqlite3ota ota test.db ota.db sqlite3rbu rbu test.db rbu.db
while {[ota step]=="SQLITE_OK"} {} while {[rbu step]=="SQLITE_OK"} {}
ota close rbu close
} -test { } -test {
faultsim_test_result {*}$::reslist faultsim_test_result {*}$::reslist
if {$testrc==0} { if {$testrc==0} {
@ -176,46 +176,46 @@ foreach {tn2 setup sql expect} {
for {set iStep 0} {$iStep<=21} {incr iStep} { for {set iStep 0} {$iStep<=21} {incr iStep} {
forcedelete test.db-journal test.db-wal ota.db-journal ota.db-wal forcedelete test.db-journal test.db-wal rbu.db-journal rbu.db-wal
copy_if_exists test.db.bak test.db copy_if_exists test.db.bak test.db
copy_if_exists ota.db.bak ota.db copy_if_exists rbu.db.bak rbu.db
sqlite3ota ota test.db ota.db sqlite3rbu rbu test.db rbu.db
for {set x 0} {$x < $::iStep} {incr x} { ota step } for {set x 0} {$x < $::iStep} {incr x} { rbu step }
ota close rbu close
# sqlite3 x ota.db ; puts "XYZ [x eval { SELECT * FROM ota_state } ]" ; x close # sqlite3 x rbu.db ; puts "XYZ [x eval { SELECT * FROM rbu_state } ]" ; x close
copy_if_exists test.db test.db.bak.2 copy_if_exists test.db test.db.bak.2
copy_if_exists test.db-wal test.db.bak.2-wal copy_if_exists test.db-wal test.db.bak.2-wal
copy_if_exists test.db-oal test.db.bak.2-oal copy_if_exists test.db-oal test.db.bak.2-oal
copy_if_exists ota.db ota.db.bak.2 copy_if_exists rbu.db rbu.db.bak.2
do_faultsim_test 3.$tn.$iStep -faults $::f -prep { do_faultsim_test 3.$tn.$iStep -faults $::f -prep {
catch { db close } catch { db close }
forcedelete test.db-journal test.db-wal ota.db-journal ota.db-wal forcedelete test.db-journal test.db-wal rbu.db-journal rbu.db-wal
copy_if_exists test.db.bak.2 test.db copy_if_exists test.db.bak.2 test.db
copy_if_exists test.db.bak.2-wal test.db-wal copy_if_exists test.db.bak.2-wal test.db-wal
copy_if_exists test.db.bak.2-oal test.db-oal copy_if_exists test.db.bak.2-oal test.db-oal
copy_if_exists ota.db.bak.2 ota.db copy_if_exists rbu.db.bak.2 rbu.db
} -body { } -body {
sqlite3ota ota test.db ota.db sqlite3rbu rbu test.db rbu.db
ota step rbu step
ota close rbu close
} -test { } -test {
if {$testresult=="SQLITE_OK"} {set testresult "SQLITE_DONE"} if {$testresult=="SQLITE_OK"} {set testresult "SQLITE_DONE"}
faultsim_test_result {*}$::reslist faultsim_test_result {*}$::reslist
if {$testrc==0} { if {$testrc==0} {
# No error occurred. If the OTA has not already been fully applied, # No error occurred. If the RBU has not already been fully applied,
# apply the rest of it now. Then ensure that the final state of the # apply the rest of it now. Then ensure that the final state of the
# target db is as expected. And that "PRAGMA integrity_check" # target db is as expected. And that "PRAGMA integrity_check"
# passes. # passes.
sqlite3ota ota test.db ota.db sqlite3rbu rbu test.db rbu.db
while {[ota step] == "SQLITE_OK"} {} while {[rbu step] == "SQLITE_OK"} {}
ota close rbu close
sqlite3 db test.db sqlite3 db test.db
faultsim_integrity_check faultsim_integrity_check

View File

@ -15,33 +15,33 @@ if {![info exists testdir]} {
} }
source $testdir/tester.tcl source $testdir/tester.tcl
source $testdir/malloc_common.tcl source $testdir/malloc_common.tcl
set ::testprefix otafault2 set ::testprefix rbufault2
forcedelete ota.db forcedelete rbu.db
do_execsql_test 1.0 { do_execsql_test 1.0 {
CREATE TABLE target(x UNIQUE, y, z, PRIMARY KEY(y)); CREATE TABLE target(x UNIQUE, y, z, PRIMARY KEY(y));
INSERT INTO target VALUES(1, 2, 3); INSERT INTO target VALUES(1, 2, 3);
INSERT INTO target VALUES(4, 5, 6); INSERT INTO target VALUES(4, 5, 6);
ATTACH 'ota.db' AS ota; ATTACH 'rbu.db' AS rbu;
CREATE TABLE ota.data_target(x, y, z, ota_control); CREATE TABLE rbu.data_target(x, y, z, rbu_control);
INSERT INTO data_target VALUES(7, 8, 9, 0); INSERT INTO data_target VALUES(7, 8, 9, 0);
INSERT INTO data_target VALUES(1, 11, 12, 0); INSERT INTO data_target VALUES(1, 11, 12, 0);
DETACH ota; DETACH rbu;
} }
db close db close
forcecopy test.db test.db-bak forcecopy test.db test.db-bak
forcecopy ota.db ota.db-bak forcecopy rbu.db rbu.db-bak
do_faultsim_test 1 -faults oom* -prep { do_faultsim_test 1 -faults oom* -prep {
forcecopy test.db-bak test.db forcecopy test.db-bak test.db
forcecopy ota.db-bak ota.db forcecopy rbu.db-bak rbu.db
forcedelete test.db-oal test.db-wal ota.db-journal forcedelete test.db-oal test.db-wal rbu.db-journal
sqlite3ota ota test.db ota.db sqlite3rbu rbu test.db rbu.db
} -body { } -body {
while {[ota step]=="SQLITE_OK"} { } while {[rbu step]=="SQLITE_OK"} { }
ota close rbu close
} -test { } -test {
faultsim_test_result \ faultsim_test_result \
{1 {SQLITE_CONSTRAINT - UNIQUE constraint failed: target.x}} \ {1 {SQLITE_CONSTRAINT - UNIQUE constraint failed: target.x}} \

File diff suppressed because it is too large Load Diff

View File

@ -10,7 +10,7 @@
** **
************************************************************************* *************************************************************************
** **
** This file contains the public interface for the OTA extension. ** This file contains the public interface for the RBU extension.
*/ */
/* /*
@ -47,14 +47,14 @@
** to read from the original database snapshot. In other words, partially ** to read from the original database snapshot. In other words, partially
** applied transactions are not visible to other clients. ** applied transactions are not visible to other clients.
** **
** "OTA" stands for "Over The Air" update. As in a large database update ** "RBU" stands for "Over The Air" update. As in a large database update
** transmitted via a wireless network to a mobile device. A transaction ** transmitted via a wireless network to a mobile device. A transaction
** applied using this extension is hence refered to as an "OTA update". ** applied using this extension is hence refered to as an "RBU update".
** **
** **
** LIMITATIONS ** LIMITATIONS
** **
** An "OTA update" transaction is subject to the following limitations: ** An "RBU update" transaction is subject to the following limitations:
** **
** * The transaction must consist of INSERT, UPDATE and DELETE operations ** * The transaction must consist of INSERT, UPDATE and DELETE operations
** only. ** only.
@ -79,41 +79,41 @@
** **
** PREPARATION ** PREPARATION
** **
** An "OTA update" is stored as a separate SQLite database. A database ** An "RBU update" is stored as a separate SQLite database. A database
** containing an OTA update is an "OTA database". For each table in the ** containing an RBU update is an "RBU database". For each table in the
** target database to be updated, the OTA database should contain a table ** target database to be updated, the RBU database should contain a table
** named "data_<target name>" containing the same set of columns as the ** named "data_<target name>" containing the same set of columns as the
** target table, and one more - "ota_control". The data_% table should ** target table, and one more - "rbu_control". The data_% table should
** have no PRIMARY KEY or UNIQUE constraints, but each column should have ** have no PRIMARY KEY or UNIQUE constraints, but each column should have
** the same type as the corresponding column in the target database. ** the same type as the corresponding column in the target database.
** The "ota_control" column should have no type at all. For example, if ** The "rbu_control" column should have no type at all. For example, if
** the target database contains: ** the target database contains:
** **
** CREATE TABLE t1(a INTEGER PRIMARY KEY, b TEXT, c UNIQUE); ** CREATE TABLE t1(a INTEGER PRIMARY KEY, b TEXT, c UNIQUE);
** **
** Then the OTA database should contain: ** Then the RBU database should contain:
** **
** CREATE TABLE data_t1(a INTEGER, b TEXT, c, ota_control); ** CREATE TABLE data_t1(a INTEGER, b TEXT, c, rbu_control);
** **
** The order of the columns in the data_% table does not matter. ** The order of the columns in the data_% table does not matter.
** **
** If the target database table is a virtual table or a table that has no ** If the target database table is a virtual table or a table that has no
** PRIMARY KEY declaration, the data_% table must also contain a column ** PRIMARY KEY declaration, the data_% table must also contain a column
** named "ota_rowid". This column is mapped to the tables implicit primary ** named "rbu_rowid". This column is mapped to the tables implicit primary
** key column - "rowid". Virtual tables for which the "rowid" column does ** key column - "rowid". Virtual tables for which the "rowid" column does
** not function like a primary key value cannot be updated using OTA. For ** not function like a primary key value cannot be updated using RBU. For
** example, if the target db contains either of the following: ** example, if the target db contains either of the following:
** **
** CREATE VIRTUAL TABLE x1 USING fts3(a, b); ** CREATE VIRTUAL TABLE x1 USING fts3(a, b);
** CREATE TABLE x1(a, b) ** CREATE TABLE x1(a, b)
** **
** then the OTA database should contain: ** then the RBU database should contain:
** **
** CREATE TABLE data_x1(a, b, ota_rowid, ota_control); ** CREATE TABLE data_x1(a, b, rbu_rowid, rbu_control);
** **
** All non-hidden columns (i.e. all columns matched by "SELECT *") of the ** All non-hidden columns (i.e. all columns matched by "SELECT *") of the
** target table must be present in the input table. For virtual tables, ** target table must be present in the input table. For virtual tables,
** hidden columns are optional - they are updated by OTA if present in ** hidden columns are optional - they are updated by RBU if present in
** the input table, or not otherwise. For example, to write to an fts4 ** the input table, or not otherwise. For example, to write to an fts4
** table with a hidden languageid column such as: ** table with a hidden languageid column such as:
** **
@ -121,12 +121,12 @@
** **
** Either of the following input table schemas may be used: ** Either of the following input table schemas may be used:
** **
** CREATE TABLE data_ft1(a, b, langid, ota_rowid, ota_control); ** CREATE TABLE data_ft1(a, b, langid, rbu_rowid, rbu_control);
** CREATE TABLE data_ft1(a, b, ota_rowid, ota_control); ** CREATE TABLE data_ft1(a, b, rbu_rowid, rbu_control);
** **
** For each row to INSERT into the target database as part of the OTA ** For each row to INSERT into the target database as part of the RBU
** update, the corresponding data_% table should contain a single record ** update, the corresponding data_% table should contain a single record
** with the "ota_control" column set to contain integer value 0. The ** with the "rbu_control" column set to contain integer value 0. The
** other columns should be set to the values that make up the new record ** other columns should be set to the values that make up the new record
** to insert. ** to insert.
** **
@ -134,54 +134,54 @@
** possible to insert a NULL value into the IPK column. Attempting to ** possible to insert a NULL value into the IPK column. Attempting to
** do so results in an SQLITE_MISMATCH error. ** do so results in an SQLITE_MISMATCH error.
** **
** For each row to DELETE from the target database as part of the OTA ** For each row to DELETE from the target database as part of the RBU
** update, the corresponding data_% table should contain a single record ** update, the corresponding data_% table should contain a single record
** with the "ota_control" column set to contain integer value 1. The ** with the "rbu_control" column set to contain integer value 1. The
** real primary key values of the row to delete should be stored in the ** real primary key values of the row to delete should be stored in the
** corresponding columns of the data_% table. The values stored in the ** corresponding columns of the data_% table. The values stored in the
** other columns are not used. ** other columns are not used.
** **
** For each row to UPDATE from the target database as part of the OTA ** For each row to UPDATE from the target database as part of the RBU
** update, the corresponding data_% table should contain a single record ** update, the corresponding data_% table should contain a single record
** with the "ota_control" column set to contain a value of type text. ** with the "rbu_control" column set to contain a value of type text.
** The real primary key values identifying the row to update should be ** The real primary key values identifying the row to update should be
** stored in the corresponding columns of the data_% table row, as should ** stored in the corresponding columns of the data_% table row, as should
** the new values of all columns being update. The text value in the ** the new values of all columns being update. The text value in the
** "ota_control" column must contain the same number of characters as ** "rbu_control" column must contain the same number of characters as
** there are columns in the target database table, and must consist entirely ** there are columns in the target database table, and must consist entirely
** of 'x' and '.' characters (or in some special cases 'd' - see below). For ** of 'x' and '.' characters (or in some special cases 'd' - see below). For
** each column that is being updated, the corresponding character is set to ** each column that is being updated, the corresponding character is set to
** 'x'. For those that remain as they are, the corresponding character of the ** 'x'. For those that remain as they are, the corresponding character of the
** ota_control value should be set to '.'. For example, given the tables ** rbu_control value should be set to '.'. For example, given the tables
** above, the update statement: ** above, the update statement:
** **
** UPDATE t1 SET c = 'usa' WHERE a = 4; ** UPDATE t1 SET c = 'usa' WHERE a = 4;
** **
** is represented by the data_t1 row created by: ** is represented by the data_t1 row created by:
** **
** INSERT INTO data_t1(a, b, c, ota_control) VALUES(4, NULL, 'usa', '..x'); ** INSERT INTO data_t1(a, b, c, rbu_control) VALUES(4, NULL, 'usa', '..x');
** **
** Instead of an 'x' character, characters of the ota_control value specified ** Instead of an 'x' character, characters of the rbu_control value specified
** for UPDATEs may also be set to 'd'. In this case, instead of updating the ** for UPDATEs may also be set to 'd'. In this case, instead of updating the
** target table with the value stored in the corresponding data_% column, the ** target table with the value stored in the corresponding data_% column, the
** user-defined SQL function "ota_delta()" is invoked and the result stored in ** user-defined SQL function "rbu_delta()" is invoked and the result stored in
** the target table column. ota_delta() is invoked with two arguments - the ** the target table column. rbu_delta() is invoked with two arguments - the
** original value currently stored in the target table column and the ** original value currently stored in the target table column and the
** value specified in the data_xxx table. ** value specified in the data_xxx table.
** **
** For example, this row: ** For example, this row:
** **
** INSERT INTO data_t1(a, b, c, ota_control) VALUES(4, NULL, 'usa', '..d'); ** INSERT INTO data_t1(a, b, c, rbu_control) VALUES(4, NULL, 'usa', '..d');
** **
** is similar to an UPDATE statement such as: ** is similar to an UPDATE statement such as:
** **
** UPDATE t1 SET c = ota_delta(c, 'usa') WHERE a = 4; ** UPDATE t1 SET c = rbu_delta(c, 'usa') WHERE a = 4;
** **
** If the target database table is a virtual table or a table with no PRIMARY ** If the target database table is a virtual table or a table with no PRIMARY
** KEY, the ota_control value should not include a character corresponding ** KEY, the rbu_control value should not include a character corresponding
** to the ota_rowid value. For example, this: ** to the rbu_rowid value. For example, this:
** **
** INSERT INTO data_ft1(a, b, ota_rowid, ota_control) ** INSERT INTO data_ft1(a, b, rbu_rowid, rbu_control)
** VALUES(NULL, 'usa', 12, '.x'); ** VALUES(NULL, 'usa', 12, '.x');
** **
** causes a result similar to: ** causes a result similar to:
@ -189,7 +189,7 @@
** UPDATE ft1 SET b = 'usa' WHERE rowid = 12; ** UPDATE ft1 SET b = 'usa' WHERE rowid = 12;
** **
** The data_xxx tables themselves should have no PRIMARY KEY declarations. ** The data_xxx tables themselves should have no PRIMARY KEY declarations.
** However, OTA is more efficient if reading the rows in from each data_xxx ** However, RBU is more efficient if reading the rows in from each data_xxx
** table in "rowid" order is roughly the same as reading them sorted by ** table in "rowid" order is roughly the same as reading them sorted by
** the PRIMARY KEY of the corresponding target database table. In other ** the PRIMARY KEY of the corresponding target database table. In other
** words, rows should be sorted using the destination table PRIMARY KEY ** words, rows should be sorted using the destination table PRIMARY KEY
@ -197,107 +197,107 @@
** **
** USAGE ** USAGE
** **
** The API declared below allows an application to apply an OTA update ** The API declared below allows an application to apply an RBU update
** stored on disk to an existing target database. Essentially, the ** stored on disk to an existing target database. Essentially, the
** application: ** application:
** **
** 1) Opens an OTA handle using the sqlite3ota_open() function. ** 1) Opens an RBU handle using the sqlite3rbu_open() function.
** **
** 2) Registers any required virtual table modules with the database ** 2) Registers any required virtual table modules with the database
** handle returned by sqlite3ota_db(). Also, if required, register ** handle returned by sqlite3rbu_db(). Also, if required, register
** the ota_delta() implementation. ** the rbu_delta() implementation.
** **
** 3) Calls the sqlite3ota_step() function one or more times on ** 3) Calls the sqlite3rbu_step() function one or more times on
** the new handle. Each call to sqlite3ota_step() performs a single ** the new handle. Each call to sqlite3rbu_step() performs a single
** b-tree operation, so thousands of calls may be required to apply ** b-tree operation, so thousands of calls may be required to apply
** a complete update. ** a complete update.
** **
** 4) Calls sqlite3ota_close() to close the OTA update handle. If ** 4) Calls sqlite3rbu_close() to close the RBU update handle. If
** sqlite3ota_step() has been called enough times to completely ** sqlite3rbu_step() has been called enough times to completely
** apply the update to the target database, then the OTA database ** apply the update to the target database, then the RBU database
** is marked as fully applied. Otherwise, the state of the OTA ** is marked as fully applied. Otherwise, the state of the RBU
** update application is saved in the OTA database for later ** update application is saved in the RBU database for later
** resumption. ** resumption.
** **
** See comments below for more detail on APIs. ** See comments below for more detail on APIs.
** **
** If an update is only partially applied to the target database by the ** If an update is only partially applied to the target database by the
** time sqlite3ota_close() is called, various state information is saved ** time sqlite3rbu_close() is called, various state information is saved
** within the OTA database. This allows subsequent processes to automatically ** within the RBU database. This allows subsequent processes to automatically
** resume the OTA update from where it left off. ** resume the RBU update from where it left off.
** **
** To remove all OTA extension state information, returning an OTA database ** To remove all RBU extension state information, returning an RBU database
** to its original contents, it is sufficient to drop all tables that begin ** to its original contents, it is sufficient to drop all tables that begin
** with the prefix "ota_" ** with the prefix "rbu_"
** **
** DATABASE LOCKING ** DATABASE LOCKING
** **
** An OTA update may not be applied to a database in WAL mode. Attempting ** An RBU update may not be applied to a database in WAL mode. Attempting
** to do so is an error (SQLITE_ERROR). ** to do so is an error (SQLITE_ERROR).
** **
** While an OTA handle is open, a SHARED lock may be held on the target ** While an RBU handle is open, a SHARED lock may be held on the target
** database file. This means it is possible for other clients to read the ** database file. This means it is possible for other clients to read the
** database, but not to write it. ** database, but not to write it.
** **
** If an OTA update is started and then suspended before it is completed, ** If an RBU update is started and then suspended before it is completed,
** then an external client writes to the database, then attempting to resume ** then an external client writes to the database, then attempting to resume
** the suspended OTA update is also an error (SQLITE_BUSY). ** the suspended RBU update is also an error (SQLITE_BUSY).
*/ */
#ifndef _SQLITE3OTA_H #ifndef _SQLITE3RBU_H
#define _SQLITE3OTA_H #define _SQLITE3RBU_H
#include "sqlite3.h" /* Required for error code definitions */ #include "sqlite3.h" /* Required for error code definitions */
typedef struct sqlite3ota sqlite3ota; typedef struct sqlite3rbu sqlite3rbu;
/* /*
** Open an OTA handle. ** Open an RBU handle.
** **
** Argument zTarget is the path to the target database. Argument zOta is ** Argument zTarget is the path to the target database. Argument zRbu is
** the path to the OTA database. Each call to this function must be matched ** the path to the RBU database. Each call to this function must be matched
** by a call to sqlite3ota_close(). When opening the databases, OTA passes ** by a call to sqlite3rbu_close(). When opening the databases, RBU passes
** the SQLITE_CONFIG_URI flag to sqlite3_open_v2(). So if either zTarget ** the SQLITE_CONFIG_URI flag to sqlite3_open_v2(). So if either zTarget
** or zOta begin with "file:", it will be interpreted as an SQLite ** or zRbu begin with "file:", it will be interpreted as an SQLite
** database URI, not a regular file name. ** database URI, not a regular file name.
** **
** If the zState argument is passed a NULL value, the OTA extension stores ** If the zState argument is passed a NULL value, the RBU extension stores
** the current state of the update (how many rows have been updated, which ** the current state of the update (how many rows have been updated, which
** indexes are yet to be updated etc.) within the OTA database itself. This ** indexes are yet to be updated etc.) within the RBU database itself. This
** can be convenient, as it means that the OTA application does not need to ** can be convenient, as it means that the RBU application does not need to
** organize removing a separate state file after the update is concluded. ** organize removing a separate state file after the update is concluded.
** Or, if zState is non-NULL, it must be a path to a database file in which ** Or, if zState is non-NULL, it must be a path to a database file in which
** the OTA extension can store the state of the update. ** the RBU extension can store the state of the update.
** **
** When resuming an OTA update, the zState argument must be passed the same ** When resuming an RBU update, the zState argument must be passed the same
** value as when the OTA update was started. ** value as when the RBU update was started.
** **
** Once the OTA update is finished, the OTA extension does not ** Once the RBU update is finished, the RBU extension does not
** automatically remove any zState database file, even if it created it. ** automatically remove any zState database file, even if it created it.
** **
** By default, OTA uses the default VFS to access the files on disk. To ** By default, RBU uses the default VFS to access the files on disk. To
** use a VFS other than the default, an SQLite "file:" URI containing a ** use a VFS other than the default, an SQLite "file:" URI containing a
** "vfs=..." option may be passed as the zTarget option. ** "vfs=..." option may be passed as the zTarget option.
** **
** IMPORTANT NOTE FOR ZIPVFS USERS: The OTA extension works with all of ** IMPORTANT NOTE FOR ZIPVFS USERS: The RBU extension works with all of
** SQLite's built-in VFSs, including the multiplexor VFS. However it does ** SQLite's built-in VFSs, including the multiplexor VFS. However it does
** not work out of the box with zipvfs. Refer to the comment describing ** not work out of the box with zipvfs. Refer to the comment describing
** the zipvfs_create_vfs() API below for details on using OTA with zipvfs. ** the zipvfs_create_vfs() API below for details on using RBU with zipvfs.
*/ */
sqlite3ota *sqlite3ota_open( sqlite3rbu *sqlite3rbu_open(
const char *zTarget, const char *zTarget,
const char *zOta, const char *zRbu,
const char *zState const char *zState
); );
/* /*
** Internally, each OTA connection uses a separate SQLite database ** Internally, each RBU connection uses a separate SQLite database
** connection to access the target and ota update databases. This ** connection to access the target and rbu update databases. This
** API allows the application direct access to these database handles. ** API allows the application direct access to these database handles.
** **
** The first argument passed to this function must be a valid, open, OTA ** The first argument passed to this function must be a valid, open, RBU
** handle. The second argument should be passed zero to access the target ** handle. The second argument should be passed zero to access the target
** database handle, or non-zero to access the ota update database handle. ** database handle, or non-zero to access the rbu update database handle.
** Accessing the underlying database handles may be useful in the ** Accessing the underlying database handles may be useful in the
** following scenarios: ** following scenarios:
** **
@ -305,44 +305,44 @@ sqlite3ota *sqlite3ota_open(
** call sqlite3_create_module() on the target database handle to ** call sqlite3_create_module() on the target database handle to
** register the required virtual table implementations. ** register the required virtual table implementations.
** **
** * If the data_xxx tables in the OTA source database are virtual ** * If the data_xxx tables in the RBU source database are virtual
** tables, the application may need to call sqlite3_create_module() on ** tables, the application may need to call sqlite3_create_module() on
** the ota update db handle to any required virtual table ** the rbu update db handle to any required virtual table
** implementations. ** implementations.
** **
** * If the application uses the "ota_delta()" feature described above, ** * If the application uses the "rbu_delta()" feature described above,
** it must use sqlite3_create_function() or similar to register the ** it must use sqlite3_create_function() or similar to register the
** ota_delta() implementation with the target database handle. ** rbu_delta() implementation with the target database handle.
** **
** If an error has occurred, either while opening or stepping the OTA object, ** If an error has occurred, either while opening or stepping the RBU object,
** this function may return NULL. The error code and message may be collected ** this function may return NULL. The error code and message may be collected
** when sqlite3ota_close() is called. ** when sqlite3rbu_close() is called.
*/ */
sqlite3 *sqlite3ota_db(sqlite3ota*, int bOta); sqlite3 *sqlite3rbu_db(sqlite3rbu*, int bRbu);
/* /*
** Do some work towards applying the OTA update to the target db. ** Do some work towards applying the RBU update to the target db.
** **
** Return SQLITE_DONE if the update has been completely applied, or ** Return SQLITE_DONE if the update has been completely applied, or
** SQLITE_OK if no error occurs but there remains work to do to apply ** SQLITE_OK if no error occurs but there remains work to do to apply
** the OTA update. If an error does occur, some other error code is ** the RBU update. If an error does occur, some other error code is
** returned. ** returned.
** **
** Once a call to sqlite3ota_step() has returned a value other than ** Once a call to sqlite3rbu_step() has returned a value other than
** SQLITE_OK, all subsequent calls on the same OTA handle are no-ops ** SQLITE_OK, all subsequent calls on the same RBU handle are no-ops
** that immediately return the same value. ** that immediately return the same value.
*/ */
int sqlite3ota_step(sqlite3ota *pOta); int sqlite3rbu_step(sqlite3rbu *pRbu);
/* /*
** Close an OTA handle. ** Close an RBU handle.
** **
** If the OTA update has been completely applied, mark the OTA database ** If the RBU update has been completely applied, mark the RBU database
** as fully applied. Otherwise, assuming no error has occurred, save the ** as fully applied. Otherwise, assuming no error has occurred, save the
** current state of the OTA update appliation to the OTA database. ** current state of the RBU update appliation to the RBU database.
** **
** If an error has already occurred as part of an sqlite3ota_step() ** If an error has already occurred as part of an sqlite3rbu_step()
** or sqlite3ota_open() call, or if one occurs within this function, an ** or sqlite3rbu_open() call, or if one occurs within this function, an
** SQLite error code is returned. Additionally, *pzErrmsg may be set to ** SQLite error code is returned. Additionally, *pzErrmsg may be set to
** point to a buffer containing a utf-8 formatted English language error ** point to a buffer containing a utf-8 formatted English language error
** message. It is the responsibility of the caller to eventually free any ** message. It is the responsibility of the caller to eventually free any
@ -352,68 +352,67 @@ int sqlite3ota_step(sqlite3ota *pOta);
** update has been partially applied, or SQLITE_DONE if it has been ** update has been partially applied, or SQLITE_DONE if it has been
** completely applied. ** completely applied.
*/ */
int sqlite3ota_close(sqlite3ota *pOta, char **pzErrmsg); int sqlite3rbu_close(sqlite3rbu *pRbu, char **pzErrmsg);
/* /*
** Return the total number of key-value operations (inserts, deletes or ** Return the total number of key-value operations (inserts, deletes or
** updates) that have been performed on the target database since the ** updates) that have been performed on the target database since the
** current OTA update was started. ** current RBU update was started.
*/ */
sqlite3_int64 sqlite3ota_progress(sqlite3ota *pOta); sqlite3_int64 sqlite3rbu_progress(sqlite3rbu *pRbu);
/* /*
** Create an OTA VFS named zName that accesses the underlying file-system ** Create an RBU VFS named zName that accesses the underlying file-system
** via existing VFS zParent. Or, if the zParent parameter is passed NULL, ** via existing VFS zParent. Or, if the zParent parameter is passed NULL,
** then the new OTA VFS uses the default system VFS to access the file-system. ** then the new RBU VFS uses the default system VFS to access the file-system.
** The new object is registered as a non-default VFS with SQLite before ** The new object is registered as a non-default VFS with SQLite before
** returning. ** returning.
** **
** Part of the OTA implementation uses a custom VFS object. Usually, this ** Part of the RBU implementation uses a custom VFS object. Usually, this
** object is created and deleted automatically by OTA. ** object is created and deleted automatically by RBU.
** **
** The exception is for applications that also use zipvfs. In this case, ** The exception is for applications that also use zipvfs. In this case,
** the custom VFS must be explicitly created by the user before the OTA ** the custom VFS must be explicitly created by the user before the RBU
** handle is opened. The OTA VFS should be installed so that the zipvfs ** handle is opened. The RBU VFS should be installed so that the zipvfs
** VFS uses the OTA VFS, which in turn uses any other VFS layers in use ** VFS uses the RBU VFS, which in turn uses any other VFS layers in use
** (for example multiplexor) to access the file-system. For example, ** (for example multiplexor) to access the file-system. For example,
** to assemble an OTA enabled VFS stack that uses both zipvfs and ** to assemble an RBU enabled VFS stack that uses both zipvfs and
** multiplexor (error checking omitted): ** multiplexor (error checking omitted):
** **
** // Create a VFS named "multiplex" (not the default). ** // Create a VFS named "multiplex" (not the default).
** sqlite3_multiplex_initialize(0, 0); ** sqlite3_multiplex_initialize(0, 0);
** **
** // Create an ota VFS named "ota" that uses multiplexor. If the ** // Create an rbu VFS named "rbu" that uses multiplexor. If the
** // second argument were replaced with NULL, the "ota" VFS would ** // second argument were replaced with NULL, the "rbu" VFS would
** // access the file-system via the system default VFS, bypassing the ** // access the file-system via the system default VFS, bypassing the
** // multiplexor. ** // multiplexor.
** sqlite3ota_create_vfs("ota", "multiplex"); ** sqlite3rbu_create_vfs("rbu", "multiplex");
** **
** // Create a zipvfs VFS named "zipvfs" that uses ota. ** // Create a zipvfs VFS named "zipvfs" that uses rbu.
** zipvfs_create_vfs_v3("zipvfs", "ota", 0, xCompressorAlgorithmDetector); ** zipvfs_create_vfs_v3("zipvfs", "rbu", 0, xCompressorAlgorithmDetector);
** **
** // Make zipvfs the default VFS. ** // Make zipvfs the default VFS.
** sqlite3_vfs_register(sqlite3_vfs_find("zipvfs"), 1); ** sqlite3_vfs_register(sqlite3_vfs_find("zipvfs"), 1);
** **
** Because the default VFS created above includes a OTA functionality, it ** Because the default VFS created above includes a RBU functionality, it
** may be used by OTA clients. Attempting to use OTA with a zipvfs VFS stack ** may be used by RBU clients. Attempting to use RBU with a zipvfs VFS stack
** that does not include the OTA layer results in an error. ** that does not include the RBU layer results in an error.
** **
** The overhead of adding the "ota" VFS to the system is negligible for ** The overhead of adding the "rbu" VFS to the system is negligible for
** non-OTA users. There is no harm in an application accessing the ** non-RBU users. There is no harm in an application accessing the
** file-system via "ota" all the time, even if it only uses OTA functionality ** file-system via "rbu" all the time, even if it only uses RBU functionality
** occasionally. ** occasionally.
*/ */
int sqlite3ota_create_vfs(const char *zName, const char *zParent); int sqlite3rbu_create_vfs(const char *zName, const char *zParent);
/* /*
** Deregister and destroy an OTA vfs created by an earlier call to ** Deregister and destroy an RBU vfs created by an earlier call to
** sqlite3ota_create_vfs(). ** sqlite3rbu_create_vfs().
** **
** VFS objects are not reference counted. If a VFS object is destroyed ** VFS objects are not reference counted. If a VFS object is destroyed
** before all database handles that use it have been closed, the results ** before all database handles that use it have been closed, the results
** are undefined. ** are undefined.
*/ */
void sqlite3ota_destroy_vfs(const char *zName); void sqlite3rbu_destroy_vfs(const char *zName);
#endif /* _SQLITE3OTA_H */
#endif /* _SQLITE3RBU_H */

View File

@ -14,23 +14,23 @@
#include "sqlite3.h" #include "sqlite3.h"
#if defined(SQLITE_TEST) #if defined(SQLITE_TEST)
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_OTA) #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_RBU)
#include "sqlite3ota.h" #include "sqlite3rbu.h"
#include <tcl.h> #include <tcl.h>
#include <assert.h> #include <assert.h>
/* From main.c (apparently...) */ /* From main.c (apparently...) */
extern const char *sqlite3ErrName(int); extern const char *sqlite3ErrName(int);
void test_ota_delta(sqlite3_context *pCtx, int nArg, sqlite3_value **apVal){ void test_rbu_delta(sqlite3_context *pCtx, int nArg, sqlite3_value **apVal){
Tcl_Interp *interp = (Tcl_Interp*)sqlite3_user_data(pCtx); Tcl_Interp *interp = (Tcl_Interp*)sqlite3_user_data(pCtx);
Tcl_Obj *pScript; Tcl_Obj *pScript;
int i; int i;
pScript = Tcl_NewObj(); pScript = Tcl_NewObj();
Tcl_IncrRefCount(pScript); Tcl_IncrRefCount(pScript);
Tcl_ListObjAppendElement(0, pScript, Tcl_NewStringObj("ota_delta", -1)); Tcl_ListObjAppendElement(0, pScript, Tcl_NewStringObj("rbu_delta", -1));
for(i=0; i<nArg; i++){ for(i=0; i<nArg; i++){
sqlite3_value *pIn = apVal[i]; sqlite3_value *pIn = apVal[i];
const char *z = (const char*)sqlite3_value_text(pIn); const char *z = (const char*)sqlite3_value_text(pIn);
@ -48,15 +48,15 @@ void test_ota_delta(sqlite3_context *pCtx, int nArg, sqlite3_value **apVal){
} }
static int test_sqlite3ota_cmd( static int test_sqlite3rbu_cmd(
ClientData clientData, ClientData clientData,
Tcl_Interp *interp, Tcl_Interp *interp,
int objc, int objc,
Tcl_Obj *CONST objv[] Tcl_Obj *CONST objv[]
){ ){
int ret = TCL_OK; int ret = TCL_OK;
sqlite3ota *pOta = (sqlite3ota*)clientData; sqlite3rbu *pRbu = (sqlite3rbu*)clientData;
const char *azMethod[] = { "step", "close", "create_ota_delta", 0 }; const char *azMethod[] = { "step", "close", "create_rbu_delta", 0 };
int iMethod; int iMethod;
if( objc!=2 ){ if( objc!=2 ){
@ -69,7 +69,7 @@ static int test_sqlite3ota_cmd(
switch( iMethod ){ switch( iMethod ){
case 0: /* step */ { case 0: /* step */ {
int rc = sqlite3ota_step(pOta); int rc = sqlite3rbu_step(pRbu);
Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1)); Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
break; break;
} }
@ -78,7 +78,7 @@ static int test_sqlite3ota_cmd(
char *zErrmsg = 0; char *zErrmsg = 0;
int rc; int rc;
Tcl_DeleteCommand(interp, Tcl_GetString(objv[0])); Tcl_DeleteCommand(interp, Tcl_GetString(objv[0]));
rc = sqlite3ota_close(pOta, &zErrmsg); rc = sqlite3rbu_close(pRbu, &zErrmsg);
if( rc==SQLITE_OK || rc==SQLITE_DONE ){ if( rc==SQLITE_OK || rc==SQLITE_DONE ){
Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1)); Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
assert( zErrmsg==0 ); assert( zErrmsg==0 );
@ -93,10 +93,10 @@ static int test_sqlite3ota_cmd(
break; break;
} }
case 2: /* create_ota_delta */ { case 2: /* create_rbu_delta */ {
sqlite3 *db = sqlite3ota_db(pOta, 0); sqlite3 *db = sqlite3rbu_db(pRbu, 0);
int rc = sqlite3_create_function( int rc = sqlite3_create_function(
db, "ota_delta", -1, SQLITE_UTF8, (void*)interp, test_ota_delta, 0, 0 db, "rbu_delta", -1, SQLITE_UTF8, (void*)interp, test_rbu_delta, 0, 0
); );
Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1)); Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
ret = (rc==SQLITE_OK ? TCL_OK : TCL_ERROR); ret = (rc==SQLITE_OK ? TCL_OK : TCL_ERROR);
@ -112,39 +112,39 @@ static int test_sqlite3ota_cmd(
} }
/* /*
** Tclcmd: sqlite3ota CMD <target-db> <ota-db> ?<state-db>? ** Tclcmd: sqlite3rbu CMD <target-db> <rbu-db> ?<state-db>?
*/ */
static int test_sqlite3ota( static int test_sqlite3rbu(
ClientData clientData, ClientData clientData,
Tcl_Interp *interp, Tcl_Interp *interp,
int objc, int objc,
Tcl_Obj *CONST objv[] Tcl_Obj *CONST objv[]
){ ){
sqlite3ota *pOta = 0; sqlite3rbu *pRbu = 0;
const char *zCmd; const char *zCmd;
const char *zTarget; const char *zTarget;
const char *zOta; const char *zRbu;
const char *zStateDb = 0; const char *zStateDb = 0;
if( objc!=4 && objc!=5 ){ if( objc!=4 && objc!=5 ){
Tcl_WrongNumArgs(interp, 1, objv, "NAME TARGET-DB OTA-DB ?STATE-DB?"); Tcl_WrongNumArgs(interp, 1, objv, "NAME TARGET-DB RBU-DB ?STATE-DB?");
return TCL_ERROR; return TCL_ERROR;
} }
zCmd = Tcl_GetString(objv[1]); zCmd = Tcl_GetString(objv[1]);
zTarget = Tcl_GetString(objv[2]); zTarget = Tcl_GetString(objv[2]);
zOta = Tcl_GetString(objv[3]); zRbu = Tcl_GetString(objv[3]);
if( objc==5 ) zStateDb = Tcl_GetString(objv[4]); if( objc==5 ) zStateDb = Tcl_GetString(objv[4]);
pOta = sqlite3ota_open(zTarget, zOta, zStateDb); pRbu = sqlite3rbu_open(zTarget, zRbu, zStateDb);
Tcl_CreateObjCommand(interp, zCmd, test_sqlite3ota_cmd, (ClientData)pOta, 0); Tcl_CreateObjCommand(interp, zCmd, test_sqlite3rbu_cmd, (ClientData)pRbu, 0);
Tcl_SetObjResult(interp, objv[1]); Tcl_SetObjResult(interp, objv[1]);
return TCL_OK; return TCL_OK;
} }
/* /*
** Tclcmd: sqlite3ota_create_vfs ?-default? NAME PARENT ** Tclcmd: sqlite3rbu_create_vfs ?-default? NAME PARENT
*/ */
static int test_sqlite3ota_create_vfs( static int test_sqlite3rbu_create_vfs(
ClientData clientData, ClientData clientData,
Tcl_Interp *interp, Tcl_Interp *interp,
int objc, int objc,
@ -163,7 +163,7 @@ static int test_sqlite3ota_create_vfs(
zParent = Tcl_GetString(objv[objc-1]); zParent = Tcl_GetString(objv[objc-1]);
if( zParent[0]=='\0' ) zParent = 0; if( zParent[0]=='\0' ) zParent = 0;
rc = sqlite3ota_create_vfs(zName, zParent); rc = sqlite3rbu_create_vfs(zName, zParent);
if( rc!=SQLITE_OK ){ if( rc!=SQLITE_OK ){
Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1)); Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
return TCL_ERROR; return TCL_ERROR;
@ -177,9 +177,9 @@ static int test_sqlite3ota_create_vfs(
} }
/* /*
** Tclcmd: sqlite3ota_destroy_vfs NAME ** Tclcmd: sqlite3rbu_destroy_vfs NAME
*/ */
static int test_sqlite3ota_destroy_vfs( static int test_sqlite3rbu_destroy_vfs(
ClientData clientData, ClientData clientData,
Tcl_Interp *interp, Tcl_Interp *interp,
int objc, int objc,
@ -193,14 +193,14 @@ static int test_sqlite3ota_destroy_vfs(
} }
zName = Tcl_GetString(objv[1]); zName = Tcl_GetString(objv[1]);
sqlite3ota_destroy_vfs(zName); sqlite3rbu_destroy_vfs(zName);
return TCL_OK; return TCL_OK;
} }
/* /*
** Tclcmd: sqlite3ota_internal_test ** Tclcmd: sqlite3rbu_internal_test
*/ */
static int test_sqlite3ota_internal_test( static int test_sqlite3rbu_internal_test(
ClientData clientData, ClientData clientData,
Tcl_Interp *interp, Tcl_Interp *interp,
int objc, int objc,
@ -213,24 +213,24 @@ static int test_sqlite3ota_internal_test(
return TCL_ERROR; return TCL_ERROR;
} }
db = sqlite3ota_db(0, 0); db = sqlite3rbu_db(0, 0);
if( db!=0 ){ if( db!=0 ){
Tcl_AppendResult(interp, "sqlite3ota_db(0, 0)!=0", 0); Tcl_AppendResult(interp, "sqlite3rbu_db(0, 0)!=0", 0);
return TCL_ERROR; return TCL_ERROR;
} }
return TCL_OK; return TCL_OK;
} }
int SqliteOta_Init(Tcl_Interp *interp){ int SqliteRbu_Init(Tcl_Interp *interp){
static struct { static struct {
char *zName; char *zName;
Tcl_ObjCmdProc *xProc; Tcl_ObjCmdProc *xProc;
} aObjCmd[] = { } aObjCmd[] = {
{ "sqlite3ota", test_sqlite3ota }, { "sqlite3rbu", test_sqlite3rbu },
{ "sqlite3ota_create_vfs", test_sqlite3ota_create_vfs }, { "sqlite3rbu_create_vfs", test_sqlite3rbu_create_vfs },
{ "sqlite3ota_destroy_vfs", test_sqlite3ota_destroy_vfs }, { "sqlite3rbu_destroy_vfs", test_sqlite3rbu_destroy_vfs },
{ "sqlite3ota_internal_test", test_sqlite3ota_internal_test }, { "sqlite3rbu_internal_test", test_sqlite3rbu_internal_test },
}; };
int i; int i;
for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){ for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
@ -241,7 +241,6 @@ int SqliteOta_Init(Tcl_Interp *interp){
#else #else
#include <tcl.h> #include <tcl.h>
int SqliteOta_Init(Tcl_Interp *interp){ return TCL_OK; } int SqliteRbu_Init(Tcl_Interp *interp){ return TCL_OK; }
#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_OTA) */ #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_RBU) */
#endif /* defined(SQLITE_TEST) */ #endif /* defined(SQLITE_TEST) */

18
main.mk
View File

@ -66,7 +66,7 @@ LIBOBJ+= vdbe.o parse.o \
mutex.o mutex_noop.o mutex_unix.o mutex_w32.o \ mutex.o mutex_noop.o mutex_unix.o mutex_w32.o \
notify.o opcodes.o os.o os_unix.o os_win.o \ notify.o opcodes.o os.o os_unix.o os_win.o \
pager.o pcache.o pcache1.o pragma.o prepare.o printf.o \ pager.o pcache.o pcache1.o pragma.o prepare.o printf.o \
random.o resolve.o rowset.o rtree.o select.o sqlite3ota.o status.o \ random.o resolve.o rowset.o rtree.o select.o sqlite3rbu.o status.o \
table.o threads.o tokenize.o treeview.o trigger.o \ table.o threads.o tokenize.o treeview.o trigger.o \
update.o userauth.o util.o vacuum.o \ update.o userauth.o util.o vacuum.o \
vdbeapi.o vdbeaux.o vdbeblob.o vdbemem.o vdbesort.o \ vdbeapi.o vdbeaux.o vdbeblob.o vdbemem.o vdbesort.o \
@ -233,8 +233,8 @@ SRC += \
$(TOP)/ext/userauth/sqlite3userauth.h $(TOP)/ext/userauth/sqlite3userauth.h
SRC += \ SRC += \
$(TOP)/ext/ota/sqlite3ota.c \ $(TOP)/ext/rbu/sqlite3rbu.c \
$(TOP)/ext/ota/sqlite3ota.h $(TOP)/ext/rbu/sqlite3rbu.h
# Generated source code files # Generated source code files
@ -253,7 +253,7 @@ SRC += \
TESTSRC = \ TESTSRC = \
$(TOP)/ext/fts3/fts3_term.c \ $(TOP)/ext/fts3/fts3_term.c \
$(TOP)/ext/fts3/fts3_test.c \ $(TOP)/ext/fts3/fts3_test.c \
$(TOP)/ext/ota/test_ota.c \ $(TOP)/ext/rbu/test_rbu.c \
$(TOP)/src/test1.c \ $(TOP)/src/test1.c \
$(TOP)/src/test2.c \ $(TOP)/src/test2.c \
$(TOP)/src/test3.c \ $(TOP)/src/test3.c \
@ -679,8 +679,8 @@ userauth.o: $(TOP)/ext/userauth/userauth.c $(HDR) $(EXTHDR)
sqlite3session.o: $(TOP)/ext/session/sqlite3session.c $(HDR) $(EXTHDR) sqlite3session.o: $(TOP)/ext/session/sqlite3session.c $(HDR) $(EXTHDR)
$(TCCX) -DSQLITE_CORE -c $(TOP)/ext/session/sqlite3session.c $(TCCX) -DSQLITE_CORE -c $(TOP)/ext/session/sqlite3session.c
sqlite3ota.o: $(TOP)/ext/ota/sqlite3ota.c $(HDR) $(EXTHDR) sqlite3rbu.o: $(TOP)/ext/rbu/sqlite3rbu.c $(HDR) $(EXTHDR)
$(TCCX) -DSQLITE_CORE -c $(TOP)/ext/ota/sqlite3ota.c $(TCCX) -DSQLITE_CORE -c $(TOP)/ext/rbu/sqlite3rbu.c
# Rules for building test programs and for running tests # Rules for building test programs and for running tests
# #
@ -829,8 +829,8 @@ wordcount$(EXE): $(TOP)/test/wordcount.c sqlite3.c
speedtest1$(EXE): $(TOP)/test/speedtest1.c sqlite3.o speedtest1$(EXE): $(TOP)/test/speedtest1.c sqlite3.o
$(TCC) -I. $(OTAFLAGS) -o speedtest1$(EXE) $(TOP)/test/speedtest1.c sqlite3.o $(THREADLIB) $(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 rbu$(EXE): $(TOP)/ext/rbu/rbu.c $(TOP)/ext/rbu/sqlite3rbu.c sqlite3.o
$(TCC) -I. -o ota$(EXE) $(TOP)/ext/ota/ota.c sqlite3.o \ $(TCC) -I. -o rbu$(EXE) $(TOP)/ext/rbu/rbu.c sqlite3.o \
$(THREADLIB) $(THREADLIB)
loadfts: $(TOP)/tool/loadfts.c libsqlite3.a loadfts: $(TOP)/tool/loadfts.c libsqlite3.a
@ -888,4 +888,4 @@ clean:
rm -f fuzzershell fuzzershell.exe rm -f fuzzershell fuzzershell.exe
rm -f fuzzcheck fuzzcheck.exe rm -f fuzzcheck fuzzcheck.exe
rm -f sqldiff sqldiff.exe rm -f sqldiff sqldiff.exe
rm -f fts5.c fts5.h fts5parse.* rm -f fts5.* fts5parse.*

122
manifest
View File

@ -1,9 +1,9 @@
C Merge\strunk\schanges,\sincluding\sthe\saddition\sof\sFTS5\sand\spcache1\sperformance\nenhancements. C Merge\sall\schanges\sin\sthe\slatest\s3.8.11\sbeta\sinto\sthe\ssessions\sbranch.\nChanges\sinclude\sthe\srename\sof\sOTA\sto\sRBU,\sthe\sWITHOUT-ROWID-OR-Skipscan\sfix,\nand\simprovements\sto\spcache1.
D 2015-07-14T15:39:22.594 D 2015-07-23T21:59:58.899
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in 82cd7996d31d7b0a9a80a6c247ad9fd9b41223af F Makefile.in e4e700c7c1764b1e731e2747dc9121e63eb951fc
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
F Makefile.msc 69a5df1f8764b991cb1a269825538258f9097c4c F Makefile.msc bbb9d41e71f6b32ea5eb12dfec06302f7f6de70a
F Makefile.vxworks e1b65dea203f054e71653415bd8f96dcaed47858 F Makefile.vxworks e1b65dea203f054e71653415bd8f96dcaed47858
F README.md 8ecc12493ff9f820cdea6520a9016001cb2e59b7 F README.md 8ecc12493ff9f820cdea6520a9016001cb2e59b7
F VERSION ce0ae95abd7121c534f6917c1c8f2b70d9acd4db F VERSION ce0ae95abd7121c534f6917c1c8f2b70d9acd4db
@ -23,7 +23,7 @@ F autoconf/depcomp 0b26f101e3bc9fd1ff0be1da9fb4a82371142f92 x
F autoconf/install-sh 06ee6336e63bb845c8439d777c32eb2eccc4fbf1 x F autoconf/install-sh 06ee6336e63bb845c8439d777c32eb2eccc4fbf1 x
F autoconf/ltmain.sh 7a658a24028f02331c1d2446562758083c5eadd1 F autoconf/ltmain.sh 7a658a24028f02331c1d2446562758083c5eadd1
F autoconf/missing d7c9981a81af13370d4ed152b24c0a82b7028585 x F autoconf/missing d7c9981a81af13370d4ed152b24c0a82b7028585 x
F autoconf/tea/Makefile.in d55bcc63832caf0309c2ff80358756116618cfca F autoconf/tea/Makefile.in b438a7020446c8a8156e8d97c8914a04833da6fd
F autoconf/tea/README 3e9a3c060f29a44344ab50aec506f4db903fb873 F autoconf/tea/README 3e9a3c060f29a44344ab50aec506f4db903fb873
F autoconf/tea/aclocal.m4 52c47aac44ce0ddb1f918b6993e8beb8eee88f43 F autoconf/tea/aclocal.m4 52c47aac44ce0ddb1f918b6993e8beb8eee88f43
F autoconf/tea/configure.ac 93d43c79e936fb16556e22498177d7e8571efa04 F autoconf/tea/configure.ac 93d43c79e936fb16556e22498177d7e8571efa04
@ -107,14 +107,14 @@ F ext/fts3/unicode/parseunicode.tcl da577d1384810fb4e2b209bf3313074353193e95
F ext/fts5/extract_api_docs.tcl 06583c935f89075ea0b32f85efa5dd7619fcbd03 F ext/fts5/extract_api_docs.tcl 06583c935f89075ea0b32f85efa5dd7619fcbd03
F ext/fts5/fts5.h 81d1a92fc2b4bd477af7e4e0b38b456f3e199fba F ext/fts5/fts5.h 81d1a92fc2b4bd477af7e4e0b38b456f3e199fba
F ext/fts5/fts5Int.h 8d9bce1847a10df2e4ed9492ea4f3868276748fb F ext/fts5/fts5Int.h 8d9bce1847a10df2e4ed9492ea4f3868276748fb
F ext/fts5/fts5_aux.c 7cd0e2858171dacf505fea4e2e84ee6126854c3d F ext/fts5/fts5_aux.c 044cb176a815f4388308738437f6e130aa384fb0
F ext/fts5/fts5_buffer.c 80f9ba4431848cb857e3d2158f5280093dcd8015 F ext/fts5/fts5_buffer.c 80f9ba4431848cb857e3d2158f5280093dcd8015
F ext/fts5/fts5_config.c b2456e9625bca41c51d54c363e369c6356895c90 F ext/fts5/fts5_config.c b2456e9625bca41c51d54c363e369c6356895c90
F ext/fts5/fts5_expr.c d2e148345639c5a5583e0daa39a639bf298ae6a7 F ext/fts5/fts5_expr.c ac0614f843cf5c80a85c4c6aa44bbede62a51bb2
F ext/fts5/fts5_hash.c 219f4edd72e5cf95b19c33f1058809a18fad5229 F ext/fts5/fts5_hash.c ff07722c73587c12781213133edbdb22cd156378
F ext/fts5/fts5_index.c 1a1fd996dfe2d632df1dd00689553bc0d205497d F ext/fts5/fts5_index.c d6ad9293280f39c56343ef5035b0475ff2a6be12
F ext/fts5/fts5_main.c 2e43726b3ef40b3d5efc0adc7c279d857b1c74fe F ext/fts5/fts5_main.c 0de7ba81488d2c502c8e794eaf7983d468e4c6e9
F ext/fts5/fts5_storage.c 4cae85b5287b159d9d98174a4e70adf872b0930a F ext/fts5/fts5_storage.c 1c35a38a564ee9cadcbd7ae0b13a806bdda722bd
F ext/fts5/fts5_tcl.c 85eb4e0d0fefa9420b78151496ad4599a1783e20 F ext/fts5/fts5_tcl.c 85eb4e0d0fefa9420b78151496ad4599a1783e20
F ext/fts5/fts5_tokenize.c 30f97a8c74683797b4cd233790444fbefb3b0708 F ext/fts5/fts5_tokenize.c 30f97a8c74683797b4cd233790444fbefb3b0708
F ext/fts5/fts5_unicode2.c 78273fbd588d1d9bd0a7e4e0ccc9207348bae33c F ext/fts5/fts5_unicode2.c 78273fbd588d1d9bd0a7e4e0ccc9207348bae33c
@ -200,25 +200,25 @@ F ext/misc/totype.c 4a167594e791abeed95e0a8db028822b5e8fe512
F ext/misc/vfslog.c fe40fab5c077a40477f7e5eba994309ecac6cc95 F ext/misc/vfslog.c fe40fab5c077a40477f7e5eba994309ecac6cc95
F ext/misc/vtshim.c babb0dc2bf116029e3e7c9a618b8a1377045303e F ext/misc/vtshim.c babb0dc2bf116029e3e7c9a618b8a1377045303e
F ext/misc/wholenumber.c 784b12543d60702ebdd47da936e278aa03076212 F ext/misc/wholenumber.c 784b12543d60702ebdd47da936e278aa03076212
F ext/ota/ota.c 3a849c3b0a4ad6e63125668be9f67be03621216e F ext/rbu/rbu.c e04e7baea76b6dd719a4f290f8a58166efc8d234 w ext/ota/ota.c
F ext/ota/ota1.test abdcbe746db4c7f7b51e842b576cacb33eef28f5 F ext/rbu/rbu1.test 57601977588603e82700a43c279bd55282ffa482 w ext/ota/ota1.test
F ext/ota/ota10.test 85e0f6e7964db5007590c1b299e75211ed4240d4 F ext/rbu/rbu10.test 046b0980041d30700464a800bbf6733ed2df515d w ext/ota/ota10.test
F ext/ota/ota11.test 2f606cd2b4af260a86b549e91b9f395450fc75cb F ext/rbu/rbu11.test 9bc68c2d3dbeb1720153626e3bd0466dcc017702 w ext/ota/ota11.test
F ext/ota/ota12.test e4c0b9a14255ffbe04d241fc15da2c65b3c06846 F ext/rbu/rbu12.test bde22ed0004dd5d1888c72a84ae407e574aeae16 w ext/ota/ota12.test
F ext/ota/ota13.test f7a3d73fa5d3fabf2755b569f125fce7390a874c F ext/rbu/rbu13.test 462ff799c4afedc3ef8a47ff818c0ffbf14ae4f2 w ext/ota/ota13.test
F ext/ota/ota3.test 3fe3521fbdce32d0e4e116a60999c3cba47712c5 F ext/rbu/rbu3.test 8bd4c6b87367c358981b6a47dc3d654fa60bff90 w ext/ota/ota3.test
F ext/ota/ota5.test ad0799daf8923ddebffe75ae8c5504ca90b7fadb F ext/rbu/rbu5.test 2e24fee3e615aecd99bbdd46967935a641e866f7 w ext/ota/ota5.test
F ext/ota/ota6.test 3bde7f69a894748b27206b6753462ec3b75b6bb6 F ext/rbu/rbu6.test 32e8ed60631b6facdb6366bd2b5f5f25245e7edb w ext/ota/ota6.test
F ext/ota/ota7.test 1fe2c5761705374530e29f70c39693076028221a F ext/rbu/rbu7.test fd025d5ba440fcfe151fbb0e3835e1e7fe964fa1 w ext/ota/ota7.test
F ext/ota/ota8.test cd70e63a0c29c45c0906692827deafa34638feda F ext/rbu/rbu8.test 3bbf2c35d71a843c463efe93946f14ad10c3ede0 w ext/ota/ota8.test
F ext/ota/ota9.test d3eee95dd836824d07a22e5efcdb7bf6e869358b F ext/rbu/rbu9.test 0806d1772c9f4981774ff028de6656e4183082af w ext/ota/ota9.test
F ext/ota/otaA.test ab67f7f53670b81c750dcc946c5b704f51c429a4 F ext/rbu/rbuA.test c1a7b3e2d926b8f8448bb3b4ae787e314ee4b2b3 w ext/ota/otaA.test
F ext/ota/otacrash.test 8346192b2d46cbe7787d5d65904d81d3262a3cbf F ext/rbu/rbucrash.test 8d2ed5d4b05fef6c00c2a6b5f7ead71fa172a695 w ext/ota/otacrash.test
F ext/ota/otafault.test 8c43586c2b96ca16bbce00b5d7e7d67316126db8 F ext/rbu/rbufault.test cc0be8d5d392d98b0c2d6a51be377ea989250a89 w ext/ota/otafault.test
F ext/ota/otafault2.test fa202a98ca221faec318f3e5c5f39485b1256561 F ext/rbu/rbufault2.test 9a7f19edd6ea35c4c9f807d8a3db0a03a5670c06 w ext/ota/otafault2.test
F ext/ota/sqlite3ota.c 21575d86eac30482a9bfbb2a531f433015e0e03c F ext/rbu/sqlite3rbu.c d37e1ca2d13e439cb3df7cd9d98db90458f21433 w ext/ota/sqlite3ota.c
F ext/ota/sqlite3ota.h 00028de37eede471ff1947d455cc3f33d3a911c6 F ext/rbu/sqlite3rbu.h 27dc1bdc18df6c9bfa3bd7d7b011699ed619d6f6 w ext/ota/sqlite3ota.h
F ext/ota/test_ota.c a876f88550d7d59a3ef62d4c1a5c04c4c2f1ebe1 F ext/rbu/test_rbu.c f99698956cc9158d6bf865e461e2d15876538ac1 w ext/ota/test_ota.c
F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761 F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761
F ext/rtree/rtree.c 0f9b595bd0debcbedf1d7a63d0e0678d619e6c9c F ext/rtree/rtree.c 0f9b595bd0debcbedf1d7a63d0e0678d619e6c9c
F ext/rtree/rtree.h 834dbcb82dc85b2481cde6a07cdadfddc99e9b9e F ext/rtree/rtree.h 834dbcb82dc85b2481cde6a07cdadfddc99e9b9e
@ -267,7 +267,7 @@ F ext/userauth/userauth.c 5fa3bdb492f481bbc1709fc83c91ebd13460c69e
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60 F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60
F main.mk c4250d110d0275a9903f12788346f1dc795275bf F main.mk 7e9671e3b41d23a454398e8ab5b1fa5a05bd6df6
F mkopcodec.awk c2ff431854d702cdd2d779c9c0d1f58fa16fa4ea F mkopcodec.awk c2ff431854d702cdd2d779c9c0d1f58fa16fa4ea
F mkopcodeh.awk 0e7f04a8eb90f92259e47d80110e4e98d7ce337a F mkopcodeh.awk 0e7f04a8eb90f92259e47d80110e4e98d7ce337a
F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83 F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83
@ -288,14 +288,14 @@ F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240
F src/backup.c 4d9134dc988a87838c06056c89c0e8c4700a0452 F src/backup.c 4d9134dc988a87838c06056c89c0e8c4700a0452
F src/bitvec.c d1f21d7d91690747881f03940584f4cc548c9d3d F src/bitvec.c d1f21d7d91690747881f03940584f4cc548c9d3d
F src/btmutex.c 45a968cc85afed9b5e6cf55bf1f42f8d18107f79 F src/btmutex.c 45a968cc85afed9b5e6cf55bf1f42f8d18107f79
F src/btree.c 781deff0d5af639e8dd4f83ec963cc3bbf8cffc2 F src/btree.c f48b3ef91676c06a90a8832987ecef6b94c931ee
F src/btree.h 969adc948e89e449220ff0ff724c94bb2a52e9f1 F src/btree.h 969adc948e89e449220ff0ff724c94bb2a52e9f1
F src/btreeInt.h 2ad754dd4528baa8d0946a593cc373b890bf859e F src/btreeInt.h 2ad754dd4528baa8d0946a593cc373b890bf859e
F src/build.c b3f15255d5b16e42dafeaa638fd4f8a47c94ed70 F src/build.c b3f15255d5b16e42dafeaa638fd4f8a47c94ed70
F src/callback.c 7b44ce59674338ad48b0e84e7b72f935ea4f68b0 F src/callback.c 7b44ce59674338ad48b0e84e7b72f935ea4f68b0
F src/complete.c addcd8160b081131005d5bc2d34adf20c1c5c92f F src/complete.c addcd8160b081131005d5bc2d34adf20c1c5c92f
F src/ctime.c 5a0b735dc95604766f5dac73973658eef782ee8b F src/ctime.c 5a0b735dc95604766f5dac73973658eef782ee8b
F src/date.c e4d50b3283696836ec1036b695ead9a19e37a5ac F src/date.c 8ec787fed4929d8ccdf6b1bc360fccc3e1d2ca58
F src/dbstat.c f402e77e25089c6003d0c60b3233b9b3947d599a F src/dbstat.c f402e77e25089c6003d0c60b3233b9b3947d599a
F src/delete.c b998fbc3c55e8331a5f40aa7ff80972254de8de1 F src/delete.c b998fbc3c55e8331a5f40aa7ff80972254de8de1
F src/expr.c c5c58e4d01c7ceb2266791d8d877f1b23a88e316 F src/expr.c c5c58e4d01c7ceb2266791d8d877f1b23a88e316
@ -311,7 +311,7 @@ F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d
F src/legacy.c ba1863ea58c4c840335a84ec276fc2b25e22bc4e F src/legacy.c ba1863ea58c4c840335a84ec276fc2b25e22bc4e
F src/lempar.c 92bafa308607dd985ca389a788cd9e0a2b608712 F src/lempar.c 92bafa308607dd985ca389a788cd9e0a2b608712
F src/loadext.c e722f4b832f923744788365df5fb8515c0bc8a47 F src/loadext.c e722f4b832f923744788365df5fb8515c0bc8a47
F src/main.c 5e170f7c4872c272d733572a99628e47fe92ab43 F src/main.c 6dd8bf94f181925a50a1f494042e50a64d5ecaca
F src/malloc.c 19461e159bccf0e2cf06a50e867963d0a7b124a8 F src/malloc.c 19461e159bccf0e2cf06a50e867963d0a7b124a8
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c abe6ee469b6c5a35c7f22bfeb9c9bac664a1c987 F src/mem1.c abe6ee469b6c5a35c7f22bfeb9c9bac664a1c987
@ -338,25 +338,25 @@ F src/pager.h 6d435f563b3f7fcae4b84433b76a6ac2730036e2
F src/parse.y 6d60dda8f8d418b6dc034f1fbccd816c459983a8 F src/parse.y 6d60dda8f8d418b6dc034f1fbccd816c459983a8
F src/pcache.c cde06aa50962595e412d497e22fd2e07878ba1f0 F src/pcache.c cde06aa50962595e412d497e22fd2e07878ba1f0
F src/pcache.h 9968603796240cdf83da7e7bef76edf90619cea9 F src/pcache.h 9968603796240cdf83da7e7bef76edf90619cea9
F src/pcache1.c 3f4c87cf913f2de8189026d9a5223ddaf55eaf6b F src/pcache1.c d08939800abf3031bd0affd5a13fbc4d7ba3fb68
F src/pragma.c c1f4d012ea9f6b1ce52d341b2cd0ad72d560afd7 F src/pragma.c e52084b37a08a88f258830518461e94627af2621
F src/pragma.h b8632d7cdda7b25323fa580e3e558a4f0d4502cc F src/pragma.h 631a91c8b0e6ca8f051a1d8a4a0da4150e04620a
F src/prepare.c 82e5db1013846a819f198336fed72c44c974e7b1 F src/prepare.c 82e5db1013846a819f198336fed72c44c974e7b1
F src/printf.c db11b5960105ee661dcac690f2ae6276e49bf251 F src/printf.c 2bc439ff20a4aad0e0ad50a37a67b5eae7d20edc
F src/random.c ba2679f80ec82c4190062d756f22d0c358180696 F src/random.c ba2679f80ec82c4190062d756f22d0c358180696
F src/resolve.c 2d47554370de8de6dd5be060cef9559eec315005 F src/resolve.c 2d47554370de8de6dd5be060cef9559eec315005
F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e
F src/select.c d3c04f01549317afbe02455c4ca9465100e9c5fe F src/select.c 57ef3d98c4400b93eea318813be41b2af2da2217
F src/shell.c e4ad9031072a6d679b2c69a780014d30db62dc7f F src/shell.c e4ad9031072a6d679b2c69a780014d30db62dc7f
F src/sqlite.h.in 84aac470adebde08e319c200f892664c6e976692 F src/sqlite.h.in 814992bc580544d632965a5480f8dc76eee331ed
F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad
F src/sqlite3ext.h be1a718b7d2ce40ceba725ae92c8eb5f18003066 F src/sqlite3ext.h be1a718b7d2ce40ceba725ae92c8eb5f18003066
F src/sqliteInt.h f5d9aa5d0cb0c89af4030c5b5b0ff93d5ef1e9a3 F src/sqliteInt.h cdc9b0c2dc12273c60603eb6c4157dd998603039
F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46 F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46
F src/status.c f266ad8a2892d659b74f0f50cb6a88b6e7c12179 F src/status.c f266ad8a2892d659b74f0f50cb6a88b6e7c12179
F src/table.c 51b46b2a62d1b3a959633d593b89bab5e2c9155e F src/table.c 51b46b2a62d1b3a959633d593b89bab5e2c9155e
F src/tclsqlite.c 6cfb538d12565aba52840709721a02dd99806f1c F src/tclsqlite.c e2344bee0d192397f555a24ef3fab26f2ed93bcc
F src/test1.c e055ab594a48d25720ed31daa5eced1163544488 F src/test1.c 375d7bd56d9f806095deb91a3dafe61bd0e367c8
F src/test2.c 577961fe48961b2f2e5c8b56ee50c3f459d3359d F src/test2.c 577961fe48961b2f2e5c8b56ee50c3f459d3359d
F src/test3.c 64d2afdd68feac1bb5e2ffb8226c8c639f798622 F src/test3.c 64d2afdd68feac1bb5e2ffb8226c8c639f798622
F src/test4.c d168f83cc78d02e8d35567bb5630e40dcd85ac1e F src/test4.c d168f83cc78d02e8d35567bb5630e40dcd85ac1e
@ -370,7 +370,7 @@ F src/test_autoext.c dea8a01a7153b9adc97bd26161e4226329546e12
F src/test_backup.c 2e6e6a081870150f20c526a2e9d0d29cda47d803 F src/test_backup.c 2e6e6a081870150f20c526a2e9d0d29cda47d803
F src/test_blob.c e5a7a81d61a780da79101aeb1e60d300af169e07 F src/test_blob.c e5a7a81d61a780da79101aeb1e60d300af169e07
F src/test_btree.c 2e9978eca99a9a4bfa8cae949efb00886860a64f F src/test_btree.c 2e9978eca99a9a4bfa8cae949efb00886860a64f
F src/test_config.c c15d03e834c4bda571e689a0fefb106a288450a4 F src/test_config.c 548c99a1a91fd89fe2c94ee08017884091e3d6f0
F src/test_demovfs.c 0de72c2c89551629f58486fde5734b7d90758852 F src/test_demovfs.c 0de72c2c89551629f58486fde5734b7d90758852
F src/test_devsym.c e7498904e72ba7491d142d5c83b476c4e76993bc F src/test_devsym.c e7498904e72ba7491d142d5c83b476c4e76993bc
F src/test_fs.c ced436e3d4b8e4681328409b8081051ce614e28f F src/test_fs.c ced436e3d4b8e4681328409b8081051ce614e28f
@ -420,12 +420,12 @@ F src/vdbesort.c f5009e7a35e3065635d8918b9a31f498a499976b
F src/vdbetrace.c 8befe829faff6d9e6f6e4dee5a7d3f85cc85f1a0 F src/vdbetrace.c 8befe829faff6d9e6f6e4dee5a7d3f85cc85f1a0
F src/vtab.c 082b35a25a26e3d36f365ca8cd73c1922532f05e F src/vtab.c 082b35a25a26e3d36f365ca8cd73c1922532f05e
F src/vxworks.h c18586c8edc1bddbc15c004fa16aeb1e1342b4fb F src/vxworks.h c18586c8edc1bddbc15c004fa16aeb1e1342b4fb
F src/wal.c ce2cb2d06faab54d1bce3e739bec79e063dd9113 F src/wal.c 6fb6b68969e4692593c2552c4e7bff5882de2cb8
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4 F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
F src/walker.c c253b95b4ee44b21c406e2a1052636c31ea27804 F src/walker.c c253b95b4ee44b21c406e2a1052636c31ea27804
F src/where.c 909eba3b6db984eb2adfbca9de2c237ee7056adb F src/where.c 909eba3b6db984eb2adfbca9de2c237ee7056adb
F src/whereInt.h 5f87e3c4b0551747d119730dfebddd3c54f04047 F src/whereInt.h 5f87e3c4b0551747d119730dfebddd3c54f04047
F src/wherecode.c 0669481cabaf5caf934b6bb825df15bc57f60d40 F src/wherecode.c 5da5049224f12db314931ae7e0919b4914a2a0b1
F src/whereexpr.c 9ce1c9cfedbf80c93c7d899497025ec8256ce652 F src/whereexpr.c 9ce1c9cfedbf80c93c7d899497025ec8256ce652
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd
@ -751,7 +751,7 @@ F test/func5.test cdd224400bc3e48d891827cc913a57051a426fa4
F test/fuzz-oss1.test 4912e528ec9cf2f42134456933659d371c9e0d74 F test/fuzz-oss1.test 4912e528ec9cf2f42134456933659d371c9e0d74
F test/fuzz.test 96083052bf5765e4518c1ba686ce2bab785670d1 F test/fuzz.test 96083052bf5765e4518c1ba686ce2bab785670d1
F test/fuzz2.test 76dc35b32b6d6f965259508508abce75a6c4d7e1 F test/fuzz2.test 76dc35b32b6d6f965259508508abce75a6c4d7e1
F test/fuzz3.test efd384b896c647b61a2c1848ba70d42aad60a7b3 F test/fuzz3.test 0d13010d1c13003a3aa57dda2f69b6b71ccac46e
F test/fuzz_common.tcl a87dfbb88c2a6b08a38e9a070dabd129e617b45b F test/fuzz_common.tcl a87dfbb88c2a6b08a38e9a070dabd129e617b45b
F test/fuzz_malloc.test 328f70aaca63adf29b4c6f06505ed0cf57ca7c26 F test/fuzz_malloc.test 328f70aaca63adf29b4c6f06505ed0cf57ca7c26
F test/fuzzcheck.c b973b06b500e6fc052d7059257cdf70df1f3a986 F test/fuzzcheck.c b973b06b500e6fc052d7059257cdf70df1f3a986
@ -842,7 +842,7 @@ F test/make-where7.tcl 05c16b5d4f5d6512881dfec560cb793915932ef9
F test/malloc.test 21c213365f2cca95ab2d7dc078dc8525f96065f8 F test/malloc.test 21c213365f2cca95ab2d7dc078dc8525f96065f8
F test/malloc3.test e3b32c724b5a124b57cb0ed177f675249ad0c66a F test/malloc3.test e3b32c724b5a124b57cb0ed177f675249ad0c66a
F test/malloc4.test 957337613002b7058a85116493a262f679f3a261 F test/malloc4.test 957337613002b7058a85116493a262f679f3a261
F test/malloc5.test e9a9116f80ab6b7a9ca258876c6f3dedb08cb08b F test/malloc5.test 4e87e596a28908c034eb5777fc33dd921bb44fc3
F test/malloc6.test 2f039d9821927eacae43e1831f815e157659a151 F test/malloc6.test 2f039d9821927eacae43e1831f815e157659a151
F test/malloc7.test 7c68a32942858bc715284856c5507446bba88c3a F test/malloc7.test 7c68a32942858bc715284856c5507446bba88c3a
F test/malloc8.test 9b7a3f8cb9cf0b12fff566e80a980b1767bd961d F test/malloc8.test 9b7a3f8cb9cf0b12fff566e80a980b1767bd961d
@ -908,7 +908,6 @@ F test/orderby6.test 8b38138ab0972588240b3fca0985d2e400432859
F test/orderby7.test 3d1383d52ade5b9eb3a173b3147fdd296f0202da F test/orderby7.test 3d1383d52ade5b9eb3a173b3147fdd296f0202da
F test/orderby8.test 23ef1a5d72bd3adcc2f65561c654295d1b8047bd F test/orderby8.test 23ef1a5d72bd3adcc2f65561c654295d1b8047bd
F test/oserror.test 14fec2796c2b6fe431c7823750e8a18a761176d7 F test/oserror.test 14fec2796c2b6fe431c7823750e8a18a761176d7
F test/ota.test 3a8d97cbf8f7210dc6a638797c4e4cd674036927
F test/ovfl.test 4f7ca651cba5c059a12d8c67dddd49bec5747799 F test/ovfl.test 4f7ca651cba5c059a12d8c67dddd49bec5747799
F test/pager1.test 1acbdb14c5952a72dd43129cabdbf69aaa3ed1fa F test/pager1.test 1acbdb14c5952a72dd43129cabdbf69aaa3ed1fa
F test/pager2.test 67b8f40ae98112bcdba1f2b2d03ea83266418c71 F test/pager2.test 67b8f40ae98112bcdba1f2b2d03ea83266418c71
@ -919,10 +918,10 @@ F test/pagerfault2.test caf4c7facb914fd3b03a17b31ae2b180c8d6ca1f
F test/pagerfault3.test 1003fcda009bf48a8e22a516e193b6ef0dd1bbd8 F test/pagerfault3.test 1003fcda009bf48a8e22a516e193b6ef0dd1bbd8
F test/pageropt.test 6b8f6a123a5572c195ad4ae40f2987007923bbd6 F test/pageropt.test 6b8f6a123a5572c195ad4ae40f2987007923bbd6
F test/pagesize.test 5769fc62d8c890a83a503f67d47508dfdc543305 F test/pagesize.test 5769fc62d8c890a83a503f67d47508dfdc543305
F test/pcache.test b09104b03160aca0d968d99e8cd2c5b1921a993d F test/pcache.test c8acbedd3b6fd0f9a7ca887a83b11d24a007972b
F test/pcache2.test ec3ae192f444ee6a0a80d1fd80d99695d884bfb3 F test/pcache2.test c70d92547550136ba6f818e6a44fe246d2738604
F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff
F test/permutations.test 1a49f543ec7f0e075ca24eae3bda7f75bb00634b F test/permutations.test dacb0a4094fbf20fc8b5c0e6d40fb5a985836b19
F test/pragma.test be7195f0aa72bdb8a512133e9640ac40f15b57a2 F test/pragma.test be7195f0aa72bdb8a512133e9640ac40f15b57a2
F test/pragma2.test f624a496a95ee878e81e59961eade66d5c00c028 F test/pragma2.test f624a496a95ee878e81e59961eade66d5c00c028
F test/pragma3.test 6f849ccffeee7e496d2f2b5e74152306c0b8757c F test/pragma3.test 6f849ccffeee7e496d2f2b5e74152306c0b8757c
@ -938,10 +937,11 @@ F test/quota2.test 7dc12e08b11cbc4c16c9ba2aa2e040ea8d8ab4b8
F test/quote.test 215897dbe8de1a6f701265836d6601cc6ed103e6 F test/quote.test 215897dbe8de1a6f701265836d6601cc6ed103e6
F test/randexpr1.tcl 40dec52119ed3a2b8b2a773bce24b63a3a746459 F test/randexpr1.tcl 40dec52119ed3a2b8b2a773bce24b63a3a746459
F test/randexpr1.test eda062a97e60f9c38ae8d806b03b0ddf23d796df F test/randexpr1.test eda062a97e60f9c38ae8d806b03b0ddf23d796df
F test/rbu.test 168573d353cd0fd10196b87b0caa322c144ef736 w test/ota.test
F test/rdonly.test 64e2696c322e3538df0b1ed624e21f9a23ed9ff8 F test/rdonly.test 64e2696c322e3538df0b1ed624e21f9a23ed9ff8
F test/regexp1.test 497ea812f264d12b6198d6e50a76be4a1973a9d8 F test/regexp1.test 497ea812f264d12b6198d6e50a76be4a1973a9d8
F test/reindex.test 44edd3966b474468b823d481eafef0c305022254 F test/reindex.test 44edd3966b474468b823d481eafef0c305022254
F test/releasetest.tcl 2aaffa548a8f8d10053b20bcf68a1b5a01081e51 F test/releasetest.tcl 8eb718bca8bca71c0c0145384f9915bb7e53fca3
F test/resolver01.test f4022acafda7f4d40eca94dbf16bc5fc4ac30ceb F test/resolver01.test f4022acafda7f4d40eca94dbf16bc5fc4ac30ceb
F test/rollback.test 458fe73eb3ffdfdf9f6ba3e9b7350a6220414dea F test/rollback.test 458fe73eb3ffdfdf9f6ba3e9b7350a6220414dea
F test/rollback2.test fc14cf6d1a2b250d2735ef16124b971bce152f14 F test/rollback2.test fc14cf6d1a2b250d2735ef16124b971bce152f14
@ -1005,7 +1005,7 @@ F test/shortread1.test bb591ef20f0fd9ed26d0d12e80eee6d7ac8897a3
F test/show_speedtest1_rtree.tcl 32e6c5f073d7426148a6936a0408f4b5b169aba5 F test/show_speedtest1_rtree.tcl 32e6c5f073d7426148a6936a0408f4b5b169aba5
F test/shrink.test 06deac10d591186017466ce67d10645150bfdeec F test/shrink.test 06deac10d591186017466ce67d10645150bfdeec
F test/sidedelete.test f0ad71abe6233e3b153100f3b8d679b19a488329 F test/sidedelete.test f0ad71abe6233e3b153100f3b8d679b19a488329
F test/skipscan1.test 2ddfe5d168462170c4487f534e2a99fb006b2076 F test/skipscan1.test d37a75b4be4eb9dedeb69b4f38b1d0a74b5021d7
F test/skipscan2.test d1d1450952b7275f0b0a3a981f0230532743951a F test/skipscan2.test d1d1450952b7275f0b0a3a981f0230532743951a
F test/skipscan3.test ec5bab3f81c7038b43450e7b3062e04a198bdbb5 F test/skipscan3.test ec5bab3f81c7038b43450e7b3062e04a198bdbb5
F test/skipscan5.test 67817a4b6857c47e0e33ba3e506da6f23ef68de2 F test/skipscan5.test 67817a4b6857c47e0e33ba3e506da6f23ef68de2
@ -1026,7 +1026,7 @@ F test/speed3.test d32043614c08c53eafdc80f33191d5bd9b920523
F test/speed4.test abc0ad3399dcf9703abed2fff8705e4f8e416715 F test/speed4.test abc0ad3399dcf9703abed2fff8705e4f8e416715
F test/speed4p.explain 6b5f104ebeb34a038b2f714150f51d01143e59aa F test/speed4p.explain 6b5f104ebeb34a038b2f714150f51d01143e59aa
F test/speed4p.test 0e51908951677de5a969b723e03a27a1c45db38b F test/speed4p.test 0e51908951677de5a969b723e03a27a1c45db38b
F test/speedtest1.c 54f211994e2fb5b3f7c5c82137378f46ca89aae8 F test/speedtest1.c 857439869d1cb4db35e1c720ee9c2756eb9ea2a0
F test/spellfix.test 0597065ff57042df1f138e6a2611ae19c2698135 F test/spellfix.test 0597065ff57042df1f138e6a2611ae19c2698135
F test/sqldiff1.test 8f6bc7c6a5b3585d350d779c6078869ba402f8f5 F test/sqldiff1.test 8f6bc7c6a5b3585d350d779c6078869ba402f8f5
F test/sqllimits1.test e05786eaed7950ff6a2d00031d001d8a26131e68 F test/sqllimits1.test e05786eaed7950ff6a2d00031d001d8a26131e68
@ -1347,10 +1347,10 @@ F tool/logest.c eef612f8adf4d0993dafed0416064cf50d5d33c6
F tool/mkautoconfamal.sh d1a2da0e15b2ed33d60af35c7e9d483f13a8eb9f F tool/mkautoconfamal.sh d1a2da0e15b2ed33d60af35c7e9d483f13a8eb9f
F tool/mkkeywordhash.c dfff09dbbfaf950e89af294f48f902181b144670 F tool/mkkeywordhash.c dfff09dbbfaf950e89af294f48f902181b144670
F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e
F tool/mkpragmatab.tcl 40c287d3f929ece67da6e9e7c49885789960accf F tool/mkpragmatab.tcl 84af2b180484323a2ea22a2279e8bd9e3e1e492e
F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97 F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97
F tool/mksqlite3c-noext.tcl 69bae8ce4aa52d2ff82d4a8a856bf283ec035b2e F tool/mksqlite3c-noext.tcl 87240b09c20042999b41d5fabe091b7111287835
F tool/mksqlite3c.tcl 12444ca6af8600db9fa08cbd134705f2f758387e F tool/mksqlite3c.tcl 038ed0aee939e6207c462727088a08d0bdf49a8c
F tool/mksqlite3h.tcl 96d92fcac21c6037d9db20c7cb2e06b534b550ac F tool/mksqlite3h.tcl 96d92fcac21c6037d9db20c7cb2e06b534b550ac
F tool/mksqlite3internalh.tcl eb994013e833359137eb53a55acdad0b5ae1049b F tool/mksqlite3internalh.tcl eb994013e833359137eb53a55acdad0b5ae1049b
F tool/mkvsix.tcl 3b58b9398f91c7dbf18d49eb87cefeee9efdbce1 F tool/mkvsix.tcl 3b58b9398f91c7dbf18d49eb87cefeee9efdbce1
@ -1385,7 +1385,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
P 85ca4409bdca7aee801e9fba1c49a87fabbf2064 202479aa0a62067343e724487960b8a039e2e978 P db4cbefb8674c6cfff27c1e918741de1885c845c 017c5019e1ce042025d4f327e50ec50af49f9fa4
R 582a57d0946e0ad5287c5fb6b7d3efee R 9260e9fdfb3bce3b7e0f7ced18f40623
U drh U drh
Z a3ed5c85e5c2e63374f7522fd856797b Z 699bda1d1e2b37f0ec4352c1a5a3ac67

View File

@ -1 +1 @@
db4cbefb8674c6cfff27c1e918741de1885c845c 7f0ee77062d2fcb014942c7c62c163ccc801f21b

View File

@ -8959,7 +8959,7 @@ static int checkTreePage(
const char *saved_zPfx = pCheck->zPfx; const char *saved_zPfx = pCheck->zPfx;
int saved_v1 = pCheck->v1; int saved_v1 = pCheck->v1;
int saved_v2 = pCheck->v2; int saved_v2 = pCheck->v2;
u8 savedIsInit; u8 savedIsInit = 0;
/* Check that the page exists /* Check that the page exists
*/ */

View File

@ -355,7 +355,7 @@ static void computeYMD(DateTime *p){
A = Z + 1 + A - (A/4); A = Z + 1 + A - (A/4);
B = A + 1524; B = A + 1524;
C = (int)((B - 122.1)/365.25); C = (int)((B - 122.1)/365.25);
D = (36525*C)/100; D = (36525*(C&32767))/100;
E = (int)((B-D)/30.6001); E = (int)((B-D)/30.6001);
X1 = (int)(30.6001*E); X1 = (int)(30.6001*E);
p->D = B - D - X1; p->D = B - D - X1;

View File

@ -642,6 +642,7 @@ int sqlite3_config(int op, ...){
** the lookaside memory. ** the lookaside memory.
*/ */
static int setupLookaside(sqlite3 *db, void *pBuf, int sz, int cnt){ static int setupLookaside(sqlite3 *db, void *pBuf, int sz, int cnt){
#ifndef SQLITE_OMIT_LOOKASIDE
void *pStart; void *pStart;
if( db->lookaside.nOut ){ if( db->lookaside.nOut ){
return SQLITE_BUSY; return SQLITE_BUSY;
@ -692,6 +693,7 @@ static int setupLookaside(sqlite3 *db, void *pBuf, int sz, int cnt){
db->lookaside.bEnabled = 0; db->lookaside.bEnabled = 0;
db->lookaside.bMalloced = 0; db->lookaside.bMalloced = 0;
} }
#endif /* SQLITE_OMIT_LOOKASIDE */
return SQLITE_OK; return SQLITE_OK;
} }

View File

@ -191,6 +191,7 @@ static SQLITE_WSD struct PCacheGlobal {
*/ */
int isInit; /* True if initialized */ int isInit; /* True if initialized */
int separateCache; /* Use a new PGroup for each PCache */ int separateCache; /* Use a new PGroup for each PCache */
int nInitPage; /* Initial bulk allocation size */
int szSlot; /* Size of each free slot */ int szSlot; /* Size of each free slot */
int nSlot; /* The number of pcache slots */ int nSlot; /* The number of pcache slots */
int nReserve; /* Try to keep nFreeSlot above this */ int nReserve; /* Try to keep nFreeSlot above this */
@ -259,6 +260,43 @@ void sqlite3PCacheBufferSetup(void *pBuf, int sz, int n){
} }
} }
/*
** Try to initialize the pCache->pFree and pCache->pBulk fields. Return
** true if pCache->pFree ends up containing one or more free pages.
*/
static int pcache1InitBulk(PCache1 *pCache){
i64 szBulk;
char *zBulk;
if( pcache1.nInitPage==0 ) return 0;
/* Do not bother with a bulk allocation if the cache size very small */
if( pCache->nMax<3 ) return 0;
sqlite3BeginBenignMalloc();
if( pcache1.nInitPage>0 ){
szBulk = pCache->szAlloc * (i64)pcache1.nInitPage;
}else{
szBulk = -1024 * (i64)pcache1.nInitPage;
}
if( szBulk > pCache->szAlloc*(i64)pCache->nMax ){
szBulk = pCache->szAlloc*pCache->nMax;
}
zBulk = pCache->pBulk = sqlite3Malloc( szBulk );
sqlite3EndBenignMalloc();
if( zBulk ){
int nBulk = sqlite3MallocSize(zBulk)/pCache->szAlloc;
int i;
for(i=0; i<nBulk; i++){
PgHdr1 *pX = (PgHdr1*)&zBulk[pCache->szPage];
pX->page.pBuf = zBulk;
pX->page.pExtra = &pX[1];
pX->isBulkLocal = 1;
pX->pNext = pCache->pFree;
pCache->pFree = pX;
zBulk += pCache->szAlloc;
}
}
return pCache->pFree!=0;
}
/* /*
** Malloc function used within this file to allocate space from the buffer ** Malloc function used within this file to allocate space from the buffer
** configured using sqlite3_config(SQLITE_CONFIG_PAGECACHE) option. If no ** configured using sqlite3_config(SQLITE_CONFIG_PAGECACHE) option. If no
@ -359,7 +397,7 @@ static PgHdr1 *pcache1AllocPage(PCache1 *pCache){
void *pPg; void *pPg;
assert( sqlite3_mutex_held(pCache->pGroup->mutex) ); assert( sqlite3_mutex_held(pCache->pGroup->mutex) );
if( pCache->pFree ){ if( pCache->pFree || (pCache->nPage==0 && pcache1InitBulk(pCache)) ){
p = pCache->pFree; p = pCache->pFree;
pCache->pFree = p->pNext; pCache->pFree = p->pNext;
p->pNext = 0; p->pNext = 0;
@ -563,7 +601,8 @@ static void pcache1RemoveFromHash(PgHdr1 *pPage, int freeFlag){
** If there are currently more than nMaxPage pages allocated, try ** If there are currently more than nMaxPage pages allocated, try
** to recycle pages to reduce the number allocated to nMaxPage. ** to recycle pages to reduce the number allocated to nMaxPage.
*/ */
static void pcache1EnforceMaxPage(PGroup *pGroup){ static void pcache1EnforceMaxPage(PCache1 *pCache){
PGroup *pGroup = pCache->pGroup;
assert( sqlite3_mutex_held(pGroup->mutex) ); assert( sqlite3_mutex_held(pGroup->mutex) );
while( pGroup->nCurrentPage>pGroup->nMaxPage && pGroup->pLruTail ){ while( pGroup->nCurrentPage>pGroup->nMaxPage && pGroup->pLruTail ){
PgHdr1 *p = pGroup->pLruTail; PgHdr1 *p = pGroup->pLruTail;
@ -572,6 +611,10 @@ static void pcache1EnforceMaxPage(PGroup *pGroup){
pcache1PinPage(p); pcache1PinPage(p);
pcache1RemoveFromHash(p, 1); pcache1RemoveFromHash(p, 1);
} }
if( pCache->nPage==0 && pCache->pBulk ){
sqlite3_free(pCache->pBulk);
pCache->pBulk = pCache->pFree = 0;
}
} }
/* /*
@ -647,6 +690,14 @@ static int pcache1Init(void *NotUsed){
pcache1.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_PMEM); pcache1.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_PMEM);
} }
#endif #endif
if( pcache1.separateCache
&& sqlite3GlobalConfig.nPage!=0
&& sqlite3GlobalConfig.pPage==0
){
pcache1.nInitPage = sqlite3GlobalConfig.nPage;
}else{
pcache1.nInitPage = 0;
}
pcache1.grp.mxPinned = 10; pcache1.grp.mxPinned = 10;
pcache1.isInit = 1; pcache1.isInit = 1;
return SQLITE_OK; return SQLITE_OK;
@ -701,36 +752,6 @@ static sqlite3_pcache *pcache1Create(int szPage, int szExtra, int bPurgeable){
pGroup->mxPinned = pGroup->nMaxPage + 10 - pGroup->nMinPage; pGroup->mxPinned = pGroup->nMaxPage + 10 - pGroup->nMinPage;
} }
pcache1LeaveMutex(pGroup); pcache1LeaveMutex(pGroup);
/* Try to initialize the local bulk pagecache line allocation if using
** separate caches and if nPage!=0 */
if( pcache1.separateCache
&& sqlite3GlobalConfig.nPage!=0
&& sqlite3GlobalConfig.pPage==0
){
int szBulk;
char *zBulk;
sqlite3BeginBenignMalloc();
if( sqlite3GlobalConfig.nPage>0 ){
szBulk = pCache->szAlloc * sqlite3GlobalConfig.nPage;
}else{
szBulk = -1024*sqlite3GlobalConfig.nPage;
}
zBulk = pCache->pBulk = sqlite3Malloc( szBulk );
sqlite3EndBenignMalloc();
if( zBulk ){
int nBulk = sqlite3MallocSize(zBulk)/pCache->szAlloc;
int i;
for(i=0; i<nBulk; i++){
PgHdr1 *pX = (PgHdr1*)&zBulk[szPage];
pX->page.pBuf = zBulk;
pX->page.pExtra = &pX[1];
pX->isBulkLocal = 1;
pX->pNext = pCache->pFree;
pCache->pFree = pX;
zBulk += pCache->szAlloc;
}
}
}
if( pCache->nHash==0 ){ if( pCache->nHash==0 ){
pcache1Destroy((sqlite3_pcache*)pCache); pcache1Destroy((sqlite3_pcache*)pCache);
pCache = 0; pCache = 0;
@ -753,7 +774,7 @@ static void pcache1Cachesize(sqlite3_pcache *p, int nMax){
pGroup->mxPinned = pGroup->nMaxPage + 10 - pGroup->nMinPage; pGroup->mxPinned = pGroup->nMaxPage + 10 - pGroup->nMinPage;
pCache->nMax = nMax; pCache->nMax = nMax;
pCache->n90pct = pCache->nMax*9/10; pCache->n90pct = pCache->nMax*9/10;
pcache1EnforceMaxPage(pGroup); pcache1EnforceMaxPage(pCache);
pcache1LeaveMutex(pGroup); pcache1LeaveMutex(pGroup);
} }
} }
@ -771,7 +792,7 @@ static void pcache1Shrink(sqlite3_pcache *p){
pcache1EnterMutex(pGroup); pcache1EnterMutex(pGroup);
savedMaxPage = pGroup->nMaxPage; savedMaxPage = pGroup->nMaxPage;
pGroup->nMaxPage = 0; pGroup->nMaxPage = 0;
pcache1EnforceMaxPage(pGroup); pcache1EnforceMaxPage(pCache);
pGroup->nMaxPage = savedMaxPage; pGroup->nMaxPage = savedMaxPage;
pcache1LeaveMutex(pGroup); pcache1LeaveMutex(pGroup);
} }
@ -1108,7 +1129,7 @@ static void pcache1Destroy(sqlite3_pcache *p){
assert( pGroup->nMinPage >= pCache->nMin ); assert( pGroup->nMinPage >= pCache->nMin );
pGroup->nMinPage -= pCache->nMin; pGroup->nMinPage -= pCache->nMin;
pGroup->mxPinned = pGroup->nMaxPage + 10 - pGroup->nMinPage; pGroup->mxPinned = pGroup->nMaxPage + 10 - pGroup->nMinPage;
pcache1EnforceMaxPage(pGroup); pcache1EnforceMaxPage(pCache);
pcache1LeaveMutex(pGroup); pcache1LeaveMutex(pGroup);
sqlite3_free(pCache->pBulk); sqlite3_free(pCache->pBulk);
sqlite3_free(pCache->apHash); sqlite3_free(pCache->apHash);

View File

@ -721,6 +721,7 @@ void sqlite3Pragma(
case PragTyp_CACHE_SIZE: { case PragTyp_CACHE_SIZE: {
assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
if( !zRight ){ if( !zRight ){
if( sqlite3ReadSchema(pParse) ) goto pragma_out;
returnSingleInt(pParse, "cache_size", pDb->pSchema->cache_size); returnSingleInt(pParse, "cache_size", pDb->pSchema->cache_size);
}else{ }else{
int size = sqlite3Atoi(zRight); int size = sqlite3Atoi(zRight);

View File

@ -86,7 +86,7 @@ static const struct sPragmaNames {
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) #if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
{ /* zName: */ "cache_size", { /* zName: */ "cache_size",
/* ePragTyp: */ PragTyp_CACHE_SIZE, /* ePragTyp: */ PragTyp_CACHE_SIZE,
/* ePragFlag: */ PragFlag_NeedSchema, /* ePragFlag: */ 0,
/* iArg: */ 0 }, /* iArg: */ 0 },
#endif #endif
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) #if !defined(SQLITE_OMIT_FLAG_PRAGMAS)

View File

@ -1012,6 +1012,11 @@ char *sqlite3_snprintf(int n, char *zBuf, const char *zFormat, ...){
** sqlite3_log() must render into a static buffer. It cannot dynamically ** sqlite3_log() must render into a static buffer. It cannot dynamically
** allocate memory because it might be called while the memory allocator ** allocate memory because it might be called while the memory allocator
** mutex is held. ** mutex is held.
**
** sqlite3VXPrintf() might ask for *temporary* memory allocations for
** certain format characters (%q) or for very large precisions or widths.
** Care must be taken that any sqlite3_log() calls that occur while the
** memory mutex is held do not use these mechanisms.
*/ */
static void renderLogMsg(int iErrCode, const char *zFormat, va_list ap){ static void renderLogMsg(int iErrCode, const char *zFormat, va_list ap){
StrAccum acc; /* String accumulator */ StrAccum acc; /* String accumulator */

View File

@ -1082,7 +1082,6 @@ static KeyInfo *keyInfoFromExprList(
return pInfo; return pInfo;
} }
#ifndef SQLITE_OMIT_COMPOUND_SELECT
/* /*
** Name of the connection operator, used for error messages. ** Name of the connection operator, used for error messages.
*/ */
@ -1096,7 +1095,6 @@ static const char *selectOpName(int id){
} }
return z; return z;
} }
#endif /* SQLITE_OMIT_COMPOUND_SELECT */
#ifndef SQLITE_OMIT_EXPLAIN #ifndef SQLITE_OMIT_EXPLAIN
/* /*
@ -2099,19 +2097,6 @@ static int multiSelectOrderBy(
SelectDest *pDest /* What to do with query results */ SelectDest *pDest /* What to do with query results */
); );
/*
** Error message for when two or more terms of a compound select have different
** size result sets.
*/
void sqlite3SelectWrongNumTermsError(Parse *pParse, Select *p){
if( p->selFlags & SF_Values ){
sqlite3ErrorMsg(pParse, "all VALUES must have the same number of terms");
}else{
sqlite3ErrorMsg(pParse, "SELECTs to the left and right of %s"
" do not have the same number of result columns", selectOpName(p->op));
}
}
/* /*
** Handle the special case of a compound-select that originates from a ** Handle the special case of a compound-select that originates from a
** VALUES clause. By handling this as a special case, we avoid deep ** VALUES clause. By handling this as a special case, we avoid deep
@ -2538,6 +2523,19 @@ multi_select_end:
} }
#endif /* SQLITE_OMIT_COMPOUND_SELECT */ #endif /* SQLITE_OMIT_COMPOUND_SELECT */
/*
** Error message for when two or more terms of a compound select have different
** size result sets.
*/
void sqlite3SelectWrongNumTermsError(Parse *pParse, Select *p){
if( p->selFlags & SF_Values ){
sqlite3ErrorMsg(pParse, "all VALUES must have the same number of terms");
}else{
sqlite3ErrorMsg(pParse, "SELECTs to the left and right of %s"
" do not have the same number of result columns", selectOpName(p->op));
}
}
/* /*
** Code an output subroutine for a coroutine implementation of a ** Code an output subroutine for a coroutine implementation of a
** SELECT statment. ** SELECT statment.

View File

@ -967,9 +967,9 @@ struct sqlite3_io_methods {
** The [SQLITE_FCNTL_ZIPVFS] opcode is implemented by zipvfs only. All other ** The [SQLITE_FCNTL_ZIPVFS] opcode is implemented by zipvfs only. All other
** VFS should return SQLITE_NOTFOUND for this opcode. ** VFS should return SQLITE_NOTFOUND for this opcode.
** **
** <li>[[SQLITE_FCNTL_OTA]] ** <li>[[SQLITE_FCNTL_RBU]]
** The [SQLITE_FCNTL_OTA] opcode is implemented by the special VFS used by ** The [SQLITE_FCNTL_RBU] opcode is implemented by the special VFS used by
** the OTA extension only. All other VFS should return SQLITE_NOTFOUND for ** the RBU extension only. All other VFS should return SQLITE_NOTFOUND for
** this opcode. ** this opcode.
** </ul> ** </ul>
*/ */
@ -997,7 +997,7 @@ struct sqlite3_io_methods {
#define SQLITE_FCNTL_WIN32_SET_HANDLE 23 #define SQLITE_FCNTL_WIN32_SET_HANDLE 23
#define SQLITE_FCNTL_WAL_BLOCK 24 #define SQLITE_FCNTL_WAL_BLOCK 24
#define SQLITE_FCNTL_ZIPVFS 25 #define SQLITE_FCNTL_ZIPVFS 25
#define SQLITE_FCNTL_OTA 26 #define SQLITE_FCNTL_RBU 26
/* deprecated names */ /* deprecated names */
#define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE #define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE

View File

@ -189,7 +189,7 @@
** Make sure that the compiler intrinsics we desire are enabled when ** Make sure that the compiler intrinsics we desire are enabled when
** compiling with an appropriate version of MSVC. ** compiling with an appropriate version of MSVC.
*/ */
#if defined(_MSC_VER) && _MSC_VER>=1300 #if defined(_MSC_VER) && _MSC_VER>=1300 && !defined(_WIN32_WCE)
# include <intrin.h> # include <intrin.h>
# pragma intrinsic(_byteswap_ushort) # pragma intrinsic(_byteswap_ushort)
# pragma intrinsic(_byteswap_ulong) # pragma intrinsic(_byteswap_ulong)
@ -754,7 +754,9 @@ extern const int sqlite3one;
# if defined(__linux__) \ # if defined(__linux__) \
|| defined(_WIN32) \ || defined(_WIN32) \
|| (defined(__APPLE__) && defined(__MACH__)) \ || (defined(__APPLE__) && defined(__MACH__)) \
|| defined(__sun) || defined(__sun) \
|| defined(__FreeBSD__) \
|| defined(__DragonFly__)
# define SQLITE_MAX_MMAP_SIZE 0x7fff0000 /* 2147418112 */ # define SQLITE_MAX_MMAP_SIZE 0x7fff0000 /* 2147418112 */
# else # else
# define SQLITE_MAX_MMAP_SIZE 0 # define SQLITE_MAX_MMAP_SIZE 0

View File

@ -3910,7 +3910,7 @@ static void init_all(Tcl_Interp *interp){
extern int TestSession_Init(Tcl_Interp*); extern int TestSession_Init(Tcl_Interp*);
#endif #endif
extern int Fts5tcl_Init(Tcl_Interp *); extern int Fts5tcl_Init(Tcl_Interp *);
extern int SqliteOta_Init(Tcl_Interp*); extern int SqliteRbu_Init(Tcl_Interp*);
#if defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4) #if defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4)
extern int Sqlitetestfts3_Init(Tcl_Interp *interp); extern int Sqlitetestfts3_Init(Tcl_Interp *interp);
#endif #endif
@ -3957,7 +3957,7 @@ static void init_all(Tcl_Interp *interp){
TestSession_Init(interp); TestSession_Init(interp);
#endif #endif
Fts5tcl_Init(interp); Fts5tcl_Init(interp);
SqliteOta_Init(interp); SqliteRbu_Init(interp);
#if defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4) #if defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4)
Sqlitetestfts3_Init(interp); Sqlitetestfts3_Init(interp);

View File

@ -273,6 +273,9 @@ static int clang_sanitize_address(
# if __has_feature(address_sanitizer) # if __has_feature(address_sanitizer)
res = 1; res = 1;
# endif # endif
#endif
#ifdef __SANITIZE_ADDRESS__
res = 1;
#endif #endif
if( res==0 && getenv("OMIT_MISUSE")!=0 ) res = 1; if( res==0 && getenv("OMIT_MISUSE")!=0 ) res = 1;
Tcl_SetObjResult(interp, Tcl_NewIntObj(res)); Tcl_SetObjResult(interp, Tcl_NewIntObj(res));

View File

@ -442,10 +442,10 @@ Tcl_SetVar2(interp, "sqlite_options", "mergesort", "1", TCL_GLOBAL_ONLY);
Tcl_SetVar2(interp, "sqlite_options", "or_opt", "1", TCL_GLOBAL_ONLY); Tcl_SetVar2(interp, "sqlite_options", "or_opt", "1", TCL_GLOBAL_ONLY);
#endif #endif
#ifdef SQLITE_ENABLE_OTA #ifdef SQLITE_ENABLE_RBU
Tcl_SetVar2(interp, "sqlite_options", "ota", "1", TCL_GLOBAL_ONLY); Tcl_SetVar2(interp, "sqlite_options", "rbu", "1", TCL_GLOBAL_ONLY);
#else #else
Tcl_SetVar2(interp, "sqlite_options", "ota", "0", TCL_GLOBAL_ONLY); Tcl_SetVar2(interp, "sqlite_options", "rbu", "0", TCL_GLOBAL_ONLY);
#endif #endif
#ifdef SQLITE_OMIT_PAGER_PRAGMAS #ifdef SQLITE_OMIT_PAGER_PRAGMAS

View File

@ -648,9 +648,9 @@ static void walIndexWriteHdr(Wal *pWal){
pWal->hdr.isInit = 1; pWal->hdr.isInit = 1;
pWal->hdr.iVersion = WALINDEX_MAX_VERSION; pWal->hdr.iVersion = WALINDEX_MAX_VERSION;
walChecksumBytes(1, (u8*)&pWal->hdr, nCksum, 0, pWal->hdr.aCksum); walChecksumBytes(1, (u8*)&pWal->hdr, nCksum, 0, pWal->hdr.aCksum);
memcpy((void *)&aHdr[1], (void *)&pWal->hdr, sizeof(WalIndexHdr)); memcpy((void*)&aHdr[1], (const void*)&pWal->hdr, sizeof(WalIndexHdr));
walShmBarrier(pWal); walShmBarrier(pWal);
memcpy((void *)&aHdr[0], (void *)&pWal->hdr, sizeof(WalIndexHdr)); memcpy((void*)&aHdr[0], (const void*)&pWal->hdr, sizeof(WalIndexHdr));
} }
/* /*
@ -952,13 +952,13 @@ static void walCleanupHash(Wal *pWal){
** via the hash table even after the cleanup. ** via the hash table even after the cleanup.
*/ */
if( iLimit ){ if( iLimit ){
int i; /* Loop counter */ int j; /* Loop counter */
int iKey; /* Hash key */ int iKey; /* Hash key */
for(i=1; i<=iLimit; i++){ for(j=1; j<=iLimit; j++){
for(iKey=walHash(aPgno[i]); aHash[iKey]; iKey=walNextHash(iKey)){ for(iKey=walHash(aPgno[j]); aHash[iKey]; iKey=walNextHash(iKey)){
if( aHash[iKey]==i ) break; if( aHash[iKey]==j ) break;
} }
assert( aHash[iKey]==i ); assert( aHash[iKey]==j );
} }
} }
#endif /* SQLITE_ENABLE_EXPENSIVE_ASSERT */ #endif /* SQLITE_ENABLE_EXPENSIVE_ASSERT */
@ -1460,7 +1460,7 @@ static void walMergesort(
int nMerge = 0; /* Number of elements in list aMerge */ int nMerge = 0; /* Number of elements in list aMerge */
ht_slot *aMerge = 0; /* List to be merged */ ht_slot *aMerge = 0; /* List to be merged */
int iList; /* Index into input list */ int iList; /* Index into input list */
int iSub = 0; /* Index into aSub array */ u32 iSub = 0; /* Index into aSub array */
struct Sublist aSub[13]; /* Array of sub-lists */ struct Sublist aSub[13]; /* Array of sub-lists */
memset(aSub, 0, sizeof(aSub)); memset(aSub, 0, sizeof(aSub));
@ -1471,7 +1471,9 @@ static void walMergesort(
nMerge = 1; nMerge = 1;
aMerge = &aList[iList]; aMerge = &aList[iList];
for(iSub=0; iList & (1<<iSub); iSub++){ for(iSub=0; iList & (1<<iSub); iSub++){
struct Sublist *p = &aSub[iSub]; struct Sublist *p;
assert( iSub<ArraySize(aSub) );
p = &aSub[iSub];
assert( p->aList && p->nList<=(1<<iSub) ); assert( p->aList && p->nList<=(1<<iSub) );
assert( p->aList==&aList[iList&~((2<<iSub)-1)] ); assert( p->aList==&aList[iList&~((2<<iSub)-1)] );
walMerge(aContent, p->aList, p->nList, &aMerge, &nMerge, aBuffer); walMerge(aContent, p->aList, p->nList, &aMerge, &nMerge, aBuffer);
@ -1482,7 +1484,9 @@ static void walMergesort(
for(iSub++; iSub<ArraySize(aSub); iSub++){ for(iSub++; iSub<ArraySize(aSub); iSub++){
if( nList & (1<<iSub) ){ if( nList & (1<<iSub) ){
struct Sublist *p = &aSub[iSub]; struct Sublist *p;
assert( iSub<ArraySize(aSub) );
p = &aSub[iSub];
assert( p->nList<=(1<<iSub) ); assert( p->nList<=(1<<iSub) );
assert( p->aList==&aList[nList&~((2<<iSub)-1)] ); assert( p->aList==&aList[nList&~((2<<iSub)-1)] );
walMerge(aContent, p->aList, p->nList, &aMerge, &nMerge, aBuffer); walMerge(aContent, p->aList, p->nList, &aMerge, &nMerge, aBuffer);

View File

@ -1296,7 +1296,11 @@ Bitmask sqlite3WhereCodeOneLoopStart(
r = sqlite3GetTempRange(pParse, nPk); r = sqlite3GetTempRange(pParse, nPk);
for(iPk=0; iPk<nPk; iPk++){ for(iPk=0; iPk<nPk; iPk++){
int iCol = pPk->aiColumn[iPk]; int iCol = pPk->aiColumn[iPk];
sqlite3ExprCodeGetColumn(pParse, pTab, iCol, iCur, r+iPk, 0); int rx;
rx = sqlite3ExprCodeGetColumn(pParse, pTab, iCol, iCur,r+iPk,0);
if( rx!=r+iPk ){
sqlite3VdbeAddOp2(v, OP_SCopy, rx, r+iPk);
}
} }
/* Check if the temp table already contains this key. If so, /* Check if the temp table already contains this key. If so,

View File

@ -21,6 +21,13 @@ source $testdir/tester.tcl
# These tests deal with corrupt database files # These tests deal with corrupt database files
# #
database_may_be_corrupt database_may_be_corrupt
db close
sqlite3_shutdown
sqlite3_config_pagecache 0 0
sqlite3_initialize
autoinstall_test_functions
sqlite3 db test.db
expr srand(123) expr srand(123)

View File

@ -20,6 +20,11 @@
# #
# $Id: malloc5.test,v 1.22 2009/04/11 19:09:54 drh Exp $ # $Id: malloc5.test,v 1.22 2009/04/11 19:09:54 drh Exp $
sqlite3_shutdown
sqlite3_config_pagecache 0 100
sqlite3_initialize
autoinstall_test_functions
set testdir [file dirname $argv0] set testdir [file dirname $argv0]
source $testdir/tester.tcl source $testdir/tester.tcl
source $testdir/malloc_common.tcl source $testdir/malloc_common.tcl
@ -41,6 +46,7 @@ ifcapable !memorymanage {
sqlite3_soft_heap_limit 0 sqlite3_soft_heap_limit 0
sqlite3 db test.db sqlite3 db test.db
db eval {PRAGMA cache_size=1}
do_test malloc5-1.1 { do_test malloc5-1.1 {
# Simplest possible test. Call sqlite3_release_memory when there is exactly # Simplest possible test. Call sqlite3_release_memory when there is exactly
@ -61,15 +67,14 @@ do_test malloc5-1.2 {
# not the case before version 3.6.2). # not the case before version 3.6.2).
# #
sqlite3 db2 test.db sqlite3 db2 test.db
execsql { SELECT * FROM sqlite_master } db2 execsql {PRAGMA cache_size=2; SELECT * FROM sqlite_master } db2
} {} } {}
do_test malloc5-1.3 { do_test malloc5-1.3 {
# Call [sqlite3_release_memory] when there is exactly one unused page # Call [sqlite3_release_memory] when there is exactly one unused page
# in the cache belonging to db2. # in the cache belonging to db2.
# #
set ::pgalloc [sqlite3_release_memory] set ::pgalloc [sqlite3_release_memory]
expr $::pgalloc > 0 } {0}
} {1}
# The sizes of memory allocations from system malloc() might vary, # The sizes of memory allocations from system malloc() might vary,
# depending on the memory allocator algorithms used. The following # depending on the memory allocator algorithms used. The following
@ -231,6 +236,7 @@ do_test malloc5-4.1 {
expr $nMaxBytes > 1000000 expr $nMaxBytes > 1000000
} {1} } {1}
do_test malloc5-4.2 { do_test malloc5-4.2 {
db eval {PRAGMA cache_size=1}
db cache flush db cache flush
sqlite3_release_memory sqlite3_release_memory
sqlite3_soft_heap_limit 100000 sqlite3_soft_heap_limit 100000
@ -302,7 +308,7 @@ do_test malloc5-6.1.1 {
sqlite3 db test.db sqlite3 db test.db
execsql { execsql {
PRAGMA page_size=1024; PRAGMA page_size=1024;
PRAGMA default_cache_size=10; PRAGMA default_cache_size=2;
} }
execsql { execsql {
PRAGMA temp_store = memory; PRAGMA temp_store = memory;
@ -325,24 +331,25 @@ do_test malloc5-6.1.1 {
} }
forcecopy test.db test2.db forcecopy test.db test2.db
sqlite3 db2 test2.db sqlite3 db2 test2.db
db2 eval {PRAGMA cache_size=2}
list \ list \
[expr ([file size test.db]/1024)>20] [expr ([file size test2.db]/1024)>20] [expr ([file size test.db]/1024)>20] [expr ([file size test2.db]/1024)>20]
} {1 1} } {1 1}
do_test malloc5-6.1.2 { do_test malloc5-6.1.2 {
list [execsql {PRAGMA cache_size}] [execsql {PRAGMA cache_size} db2] list [execsql {PRAGMA cache_size}] [execsql {PRAGMA cache_size} db2]
} {10 10} } {2 2}
do_test malloc5-6.2.1 { do_test malloc5-6.2.1 {
execsql {SELECT * FROM abc} db2 execsql {SELECT * FROM abc} db2
execsql {SELECT * FROM abc} db execsql {SELECT * FROM abc} db
expr [nPage db] + [nPage db2] expr [nPage db] + [nPage db2]
} {20} } {4}
do_test malloc5-6.2.2 { do_test malloc5-6.2.2 {
# If we now try to reclaim some memory, it should come from the db2 cache. # If we now try to reclaim some memory, it should come from the db2 cache.
sqlite3_release_memory 3000 sqlite3_release_memory 3000
expr [nPage db] + [nPage db2] expr [nPage db] + [nPage db2]
} {17} } {4}
do_test malloc5-6.2.3 { do_test malloc5-6.2.3 {
# Access the db2 cache again, so that all the db2 pages have been used # Access the db2 cache again, so that all the db2 pages have been used
# more recently than all the db pages. Then try to reclaim 3000 bytes. # more recently than all the db pages. Then try to reclaim 3000 bytes.
@ -350,7 +357,7 @@ do_test malloc5-6.2.3 {
execsql { SELECT * FROM abc } db2 execsql { SELECT * FROM abc } db2
sqlite3_release_memory 3000 sqlite3_release_memory 3000
expr [nPage db] + [nPage db2] expr [nPage db] + [nPage db2]
} {17} } {4}
do_test malloc5-6.3.1 { do_test malloc5-6.3.1 {
# Now open a transaction and update 2 pages in the db2 cache. Then # Now open a transaction and update 2 pages in the db2 cache. Then
@ -367,19 +374,19 @@ do_test malloc5-6.3.1 {
} db2 } db2
execsql { SELECT * FROM abc } db execsql { SELECT * FROM abc } db
expr [nPage db] + [nPage db2] expr [nPage db] + [nPage db2]
} {20} } {4}
do_test malloc5-6.3.2 { do_test malloc5-6.3.2 {
# Try to release 7700 bytes. This should release all the # Try to release 7700 bytes. This should release all the
# non-dirty pages held by db2. # non-dirty pages held by db2.
sqlite3_release_memory [expr 7*1132] sqlite3_release_memory [expr 7*1132]
list [nPage db] [nPage db2] list [nPage db] [nPage db2]
} {10 3} } {1 3}
do_test malloc5-6.3.3 { do_test malloc5-6.3.3 {
# Try to release another 1000 bytes. This should come fromt the db # Try to release another 1000 bytes. This should come fromt the db
# cache, since all three pages held by db2 are either in-use or diry. # cache, since all three pages held by db2 are either in-use or diry.
sqlite3_release_memory 1000 sqlite3_release_memory 1000
list [nPage db] [nPage db2] list [nPage db] [nPage db2]
} {9 3} } {1 3}
do_test malloc5-6.3.4 { do_test malloc5-6.3.4 {
# Now release 9900 more (about 9 pages worth). This should expunge # Now release 9900 more (about 9 pages worth). This should expunge
# the rest of the db cache. But the db2 cache remains intact, because # the rest of the db cache. But the db2 cache remains intact, because
@ -390,20 +397,20 @@ do_test malloc5-6.3.4 {
sqlite3_release_memory 9900 sqlite3_release_memory 9900
} }
list [nPage db] [nPage db2] list [nPage db] [nPage db2]
} {0 3} } {1 3}
do_test malloc5-6.3.5 { do_test malloc5-6.3.5 {
# But if we are really insistent, SQLite will consent to call sync() # But if we are really insistent, SQLite will consent to call sync()
# if there is no other option. UPDATE: As of 3.6.2, SQLite will not # if there is no other option. UPDATE: As of 3.6.2, SQLite will not
# call sync() in this scenario. So no further memory can be reclaimed. # call sync() in this scenario. So no further memory can be reclaimed.
sqlite3_release_memory 1000 sqlite3_release_memory 1000
list [nPage db] [nPage db2] list [nPage db] [nPage db2]
} {0 3} } {1 3}
do_test malloc5-6.3.6 { do_test malloc5-6.3.6 {
# The referenced page (page 1 of the db2 cache) will not be freed no # The referenced page (page 1 of the db2 cache) will not be freed no
# matter how much memory we ask for: # matter how much memory we ask for:
sqlite3_release_memory 31459 sqlite3_release_memory 31459
list [nPage db] [nPage db2] list [nPage db] [nPage db2]
} {0 3} } {1 3}
db2 close db2 close

View File

@ -73,7 +73,7 @@ do_test pcache-1.4 {
do_test pcache-1.5 { do_test pcache-1.5 {
sqlite3 db2 test.db sqlite3 db2 test.db
execsql "PRAGMA cache_size=10" db2 execsql "PRAGMA cache_size; PRAGMA cache_size=10" db2
pcache_stats pcache_stats
} {current 11 max 22 min 20 recyclable 1} } {current 11 max 22 min 20 recyclable 1}

View File

@ -36,13 +36,13 @@ do_test pcache2-1.1 {
do_test pcache2-1.2 { do_test pcache2-1.2 {
forcedelete test.db test.db-journal forcedelete test.db test.db-journal
sqlite3 db test.db sqlite3 db test.db
db eval {PRAGMA cache_size=10} db eval {PRAGMA cache_size=10; SELECT 1 FROM sqlite_master;}
lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_USED 0] 1 lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_USED 0] 1
} {2} } {2}
do_test pcache2-1.3 { do_test pcache2-1.3 {
forcedelete test2.db test2.db-journal forcedelete test2.db test2.db-journal
sqlite3 db2 test2.db sqlite3 db2 test2.db
db2 eval {PRAGMA cache_size=50} db2 eval {PRAGMA cache_size=50; SELECT 1 FROM sqlite_master;}
lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_USED 0] 1 lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_USED 0] 1
} {4} } {4}

View File

@ -117,7 +117,7 @@ set allquicktests [test_set $alltests -exclude {
vtab_err.test walslow.test walcrash.test walcrash3.test vtab_err.test walslow.test walcrash.test walcrash3.test
walthread.test rtree3.test indexfault.test securedel2.test walthread.test rtree3.test indexfault.test securedel2.test
sort3.test sort4.test fts4growth.test fts4growth2.test sort3.test sort4.test fts4growth.test fts4growth2.test
bigsort.test ota.test bigsort.test rbu.test
}] }]
if {[info exists ::env(QUICKTEST_INCLUDE)]} { if {[info exists ::env(QUICKTEST_INCLUDE)]} {
set allquicktests [concat $allquicktests $::env(QUICKTEST_INCLUDE)] set allquicktests [concat $allquicktests $::env(QUICKTEST_INCLUDE)]
@ -986,10 +986,10 @@ test_suite "session_strm" -description {
set ::sqlite3session_streams 1 set ::sqlite3session_streams 1
} }
test_suite "ota" -description { test_suite "rbu" -description {
OTA tests. RBU tests.
} -files [ } -files [
test_set [glob -nocomplain $::testdir/../ext/ota/*.test] -exclude ota.test test_set [glob -nocomplain $::testdir/../ext/rbu/*.test] -exclude rbu.test
] ]
test_suite "no_optimization" -description { test_suite "no_optimization" -description {

View File

@ -5,14 +5,13 @@
# May you share freely, never taking more than you give. # May you share freely, never taking more than you give.
# #
#*********************************************************************** #***********************************************************************
# This file runs all rtree related tests. # This file runs all RBU related tests.
# #
set testdir [file dirname $argv0] set testdir [file dirname $argv0]
source $testdir/permutations.test source $testdir/permutations.test
ifcapable !ota { finish_test ; return } ifcapable !rbu { finish_test ; return }
run_test_suite ota run_test_suite rbu
finish_test finish_test

View File

@ -116,7 +116,7 @@ array set ::Configs [strip_comments {
-DSQLITE_ENABLE_FTS4=1 -DSQLITE_ENABLE_FTS4=1
-DSQLITE_ENABLE_RTREE=1 -DSQLITE_ENABLE_RTREE=1
-DSQLITE_ENABLE_STAT4 -DSQLITE_ENABLE_STAT4
-DSQLITE_ENABLE_OTA -DSQLITE_ENABLE_RBU
-DSQLITE_MAX_ATTACHED=125 -DSQLITE_MAX_ATTACHED=125
} }
"Device-One" { "Device-One" {

View File

@ -292,4 +292,34 @@ do_execsql_test skipscan1-7.3 {
EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE b=1; EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE b=1;
} {~/ANY/} } {~/ANY/}
# Ticket 8fd39115d8f46ece70e7d4b3c481d1bd86194746 2015-07-23
# Incorrect code generated for a skipscan within an OR optimization
# on a WITHOUT ROWID table.
#
do_execsql_test skipscan1-8.1 {
DROP TABLE IF EXISTS t1;
CREATE TABLE t1(x, y, PRIMARY KEY(x,y)) WITHOUT ROWID;
INSERT INTO t1(x,y) VALUES(1,'AB');
INSERT INTO t1(x,y) VALUES(2,'CD');
ANALYZE;
DROP TABLE IF EXISTS sqlite_stat4;
DELETE FROM sqlite_stat1;
INSERT INTO sqlite_stat1(tbl,idx,stat) VALUES('t1','t1','1000000 100 1');
ANALYZE sqlite_master;
SELECT * FROM t1
WHERE (y = 'AB' AND x <= 4)
OR (y = 'EF' AND x = 5);
} {1 AB}
do_execsql_test skipscan1-8.1eqp {
EXPLAIN QUERY PLAN
SELECT * FROM t1
WHERE (y = 'AB' AND x <= 4)
OR (y = 'EF' AND x = 5);
} {/ANY/}
do_execsql_test skipscan1-8.2 {
SELECT * FROM t1
WHERE y = 'AB' OR (y = 'CD' AND x = 2)
ORDER BY +x;
} {1 AB 2 CD}
finish_test finish_test

View File

@ -51,8 +51,8 @@ static const char zHelp[] =
#if SQLITE_VERSION_NUMBER<3005000 #if SQLITE_VERSION_NUMBER<3005000
# define sqlite3_int64 sqlite_int64 # define sqlite3_int64 sqlite_int64
#endif #endif
#ifdef SQLITE_ENABLE_OTA #ifdef SQLITE_ENABLE_RBU
# include "sqlite3ota.h" # include "sqlite3rbu.h"
#endif #endif
/* All global state is held in this structure */ /* All global state is held in this structure */
@ -1240,10 +1240,10 @@ int main(int argc, char **argv){
noSync = 1; noSync = 1;
}else if( strcmp(z,"notnull")==0 ){ }else if( strcmp(z,"notnull")==0 ){
g.zNN = "NOT NULL"; g.zNN = "NOT NULL";
#ifdef SQLITE_ENABLE_OTA #ifdef SQLITE_ENABLE_RBU
}else if( strcmp(z,"ota")==0 ){ }else if( strcmp(z,"rbu")==0 ){
sqlite3ota_create_vfs("ota", 0); sqlite3ota_create_vfs("rbu", 0);
sqlite3_vfs_register(sqlite3_vfs_find("ota"), 1); sqlite3_vfs_register(sqlite3_vfs_find("rbu"), 1);
#endif #endif
}else if( strcmp(z,"pagesize")==0 ){ }else if( strcmp(z,"pagesize")==0 ){
if( i>=argc-1 ) fatal_error("missing argument on %s\n", argv[i]); if( i>=argc-1 ) fatal_error("missing argument on %s\n", argv[i]);

View File

@ -170,7 +170,6 @@ set pragma_def {
IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS) IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS)
NAME: cache_size NAME: cache_size
FLAG: NeedSchema
IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS) IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS)
NAME: mmap_size NAME: mmap_size

View File

@ -180,6 +180,10 @@ proc copy_file {filename} {
copy_file tsrc/$hdr copy_file tsrc/$hdr
section_comment "Continuing where we left off in $tail" section_comment "Continuing where we left off in $tail"
if {$linemacros} {puts $out "#line [expr {$ln+1}] \"$filename\""} if {$linemacros} {puts $out "#line [expr {$ln+1}] \"$filename\""}
} else {
# Comment out the entire line, replacing any nested comment
# begin/end markers with the harmless substring "**".
puts $out "/* [string map [list /* ** */ **] $line] */"
} }
} elseif {![info exists seen_hdr($hdr)]} { } elseif {![info exists seen_hdr($hdr)]} {
if {![regexp {/\*\s+amalgamator:\s+dontcache\s+\*/} $line]} { if {![regexp {/\*\s+amalgamator:\s+dontcache\s+\*/} $line]} {

View File

@ -115,7 +115,7 @@ foreach hdr {
sqlite3ext.h sqlite3ext.h
sqlite3.h sqlite3.h
sqlite3ext.h sqlite3ext.h
sqlite3ota.h sqlite3rbu.h
sqliteicu.h sqliteicu.h
sqliteInt.h sqliteInt.h
sqliteLimit.h sqliteLimit.h
@ -191,6 +191,10 @@ proc copy_file {filename} {
copy_file tsrc/$hdr copy_file tsrc/$hdr
section_comment "Continuing where we left off in $tail" section_comment "Continuing where we left off in $tail"
if {$linemacros} {puts $out "#line [expr {$ln+1}] \"$filename\""} if {$linemacros} {puts $out "#line [expr {$ln+1}] \"$filename\""}
} else {
# Comment out the entire line, replacing any nested comment
# begin/end markers with the harmless substring "**".
puts $out "/* [string map [list /* ** */ **] $line] */"
} }
} elseif {![info exists seen_hdr($hdr)]} { } elseif {![info exists seen_hdr($hdr)]} {
if {![regexp {/\*\s+amalgamator:\s+dontcache\s+\*/} $line]} { if {![regexp {/\*\s+amalgamator:\s+dontcache\s+\*/} $line]} {
@ -375,7 +379,7 @@ foreach file {
rtree.c rtree.c
icu.c icu.c
fts3_icu.c fts3_icu.c
sqlite3ota.c sqlite3rbu.c
dbstat.c dbstat.c
sqlite3session.c sqlite3session.c
} { } {