aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--autoconf/Makefile.am5
-rw-r--r--autoconf/configure.ac2
-rw-r--r--ext/fts3/fts3_write.c10
-rw-r--r--ext/fts5/fts5Int.h7
-rw-r--r--ext/fts5/fts5_config.c18
-rw-r--r--ext/fts5/fts5_expr.c167
-rw-r--r--ext/fts5/fts5_index.c108
-rw-r--r--ext/fts5/fts5_main.c6
-rw-r--r--ext/fts5/fts5_test_mi.c25
-rw-r--r--ext/fts5/fts5parse.y2
-rw-r--r--ext/fts5/test/fts5_common.tcl6
-rw-r--r--ext/fts5/test/fts5config.test16
-rw-r--r--ext/fts5/test/fts5eb.test12
-rw-r--r--ext/fts5/test/fts5fault8.test25
-rw-r--r--ext/fts5/test/fts5fuzz1.test93
-rw-r--r--ext/fts5/test/fts5merge.test68
-rw-r--r--ext/fts5/test/fts5optimize.test47
-rw-r--r--ext/misc/spellfix.c10
-rw-r--r--ext/rbu/rbuC.test142
-rw-r--r--ext/rbu/sqlite3rbu.c168
-rw-r--r--manifest217
-rw-r--r--manifest.uuid2
-rw-r--r--src/attach.c2
-rw-r--r--src/btree.c28
-rw-r--r--src/build.c2
-rw-r--r--src/expr.c35
-rw-r--r--src/main.c2
-rw-r--r--src/memjournal.c158
-rw-r--r--src/os_win.c2
-rw-r--r--src/pager.c27
-rw-r--r--src/pragma.c29
-rw-r--r--src/select.c20
-rw-r--r--src/sqliteInt.h40
-rw-r--r--src/tclsqlite.c14
-rw-r--r--src/test1.c2
-rw-r--r--src/update.c2
-rw-r--r--src/util.c13
-rw-r--r--src/vdbe.c17
-rw-r--r--src/vdbeInt.h4
-rw-r--r--src/where.c123
-rw-r--r--src/wherecode.c10
-rw-r--r--test/analyzer1.test9
-rw-r--r--test/autovacuum.test17
-rw-r--r--test/backcompat.test13
-rw-r--r--test/backup4.test5
-rw-r--r--test/bc_common.tcl5
-rw-r--r--test/bestindex1.test7
-rw-r--r--test/bestindex2.test5
-rw-r--r--test/close.test4
-rw-r--r--test/corrupt2.test44
-rw-r--r--test/corrupt3.test7
-rw-r--r--test/corrupt4.test7
-rw-r--r--test/corrupt6.test7
-rw-r--r--test/corrupt7.test7
-rw-r--r--test/corruptE.test7
-rw-r--r--test/corruptG.test7
-rw-r--r--test/corruptH.test8
-rw-r--r--test/corruptI.test8
-rw-r--r--test/corruptJ.test8
-rw-r--r--test/crash8.test1
-rw-r--r--test/e_uri.test2
-rw-r--r--test/e_vacuum.test58
-rw-r--r--test/e_walauto.test5
-rw-r--r--test/eqp.test66
-rw-r--r--test/filefmt.test16
-rw-r--r--test/fts4growth.test40
-rw-r--r--test/fts4langid.test2
-rw-r--r--test/fts4merge.test26
-rw-r--r--test/fts4merge3.test6
-rw-r--r--test/fts4opt.test213
-rw-r--r--test/in5.test35
-rw-r--r--test/incrblob.test23
-rw-r--r--test/incrblob_err.test4
-rw-r--r--test/io.test2
-rw-r--r--test/memsubsys1.test2
-rw-r--r--test/mmap1.test6
-rw-r--r--test/mmap3.test3
-rw-r--r--test/nan.test80
-rw-r--r--test/nolock.test32
-rw-r--r--test/pager1.test85
-rw-r--r--test/pageropt.test5
-rw-r--r--test/permutations.test4
-rw-r--r--test/pragma.test126
-rw-r--r--test/pragma3.test1
-rw-r--r--test/select4.test37
-rw-r--r--test/shell1.test10
-rw-r--r--test/shell2.test10
-rw-r--r--test/shell3.test10
-rw-r--r--test/shell4.test10
-rw-r--r--test/shell5.test10
-rw-r--r--test/spellfix3.test11
-rw-r--r--test/stat.test4
-rw-r--r--test/superlock.test25
-rw-r--r--test/tclsqlite.test5
-rw-r--r--test/tester.tcl42
-rw-r--r--test/tkt4018.test1
-rw-r--r--test/unixexcl.test1
-rw-r--r--test/vtab6.test4
-rw-r--r--test/wal.test2
-rw-r--r--test/wal2.test2
-rw-r--r--test/wal5.test7
-rw-r--r--test/wal8.test1
-rw-r--r--test/walbak.test2
-rw-r--r--test/walro.test2
-rw-r--r--test/where2.test11
-rw-r--r--test/zerodamage.test1
-rwxr-xr-xtool/build-all-msvc.bat20
107 files changed, 2010 insertions, 922 deletions
diff --git a/autoconf/Makefile.am b/autoconf/Makefile.am
index 7b6934add..cca23ba67 100644
--- a/autoconf/Makefile.am
+++ b/autoconf/Makefile.am
@@ -6,8 +6,9 @@ libsqlite3_la_SOURCES = sqlite3.c
libsqlite3_la_LDFLAGS = -no-undefined -version-info 8:6:8
bin_PROGRAMS = sqlite3
-sqlite3_SOURCES = shell.c sqlite3.c sqlite3.h
-sqlite3_LDADD = @READLINE_LIBS@
+sqlite3_SOURCES = shell.c sqlite3.h
+EXTRA_sqlite3_SOURCES = sqlite3.c
+sqlite3_LDADD = @EXTRA_SHELL_OBJ@ @READLINE_LIBS@
sqlite3_DEPENDENCIES = @EXTRA_SHELL_OBJ@
sqlite3_CFLAGS = $(AM_CFLAGS) -DSQLITE_ENABLE_EXPLAIN_COMMENTS
diff --git a/autoconf/configure.ac b/autoconf/configure.ac
index 949253068..f86a39c37 100644
--- a/autoconf/configure.ac
+++ b/autoconf/configure.ac
@@ -130,7 +130,7 @@ AC_ARG_ENABLE(static-shell, [AS_HELP_STRING(
[statically link libsqlite3 into shell tool [default=yes]])],
[], [enable_static_shell=yes])
if test x"$enable_static_shell" == "xyes"; then
- EXTRA_SHELL_OBJ=sqlite3.$OBJEXT
+ EXTRA_SHELL_OBJ=sqlite3-sqlite3.$OBJEXT
else
EXTRA_SHELL_OBJ=libsqlite3.la
fi
diff --git a/ext/fts3/fts3_write.c b/ext/fts3/fts3_write.c
index d5a408222..3ff481b0b 100644
--- a/ext/fts3/fts3_write.c
+++ b/ext/fts3/fts3_write.c
@@ -333,7 +333,8 @@ static int fts3SqlStmt(
** of the oldest level in the db that contains at least ? segments. Or,
** if no level in the FTS index contains more than ? segments, the statement
** returns zero rows. */
-/* 28 */ "SELECT level FROM %Q.'%q_segdir' GROUP BY level HAVING count(*)>=?"
+/* 28 */ "SELECT level, count(*) AS cnt FROM %Q.'%q_segdir' "
+ " GROUP BY level HAVING cnt>=?"
" ORDER BY (level %% 1024) ASC LIMIT 1",
/* Estimate the upper limit on the number of leaf nodes in a new segment
@@ -3194,7 +3195,7 @@ static int fts3SegmentMerge(
** segment. The level of the new segment is equal to the numerically
** greatest segment level currently present in the database for this
** index. The idx of the new segment is always 0. */
- if( csr.nSegment==1 ){
+ if( csr.nSegment==1 && 0==fts3SegReaderIsPending(csr.apSegment[0]) ){
rc = SQLITE_DONE;
goto finished;
}
@@ -4836,10 +4837,11 @@ int sqlite3Fts3Incrmerge(Fts3Table *p, int nMerge, int nMin){
** set nSeg to -1.
*/
rc = fts3SqlStmt(p, SQL_FIND_MERGE_LEVEL, &pFindLevel, 0);
- sqlite3_bind_int(pFindLevel, 1, nMin);
+ sqlite3_bind_int(pFindLevel, 1, MAX(2, nMin));
if( sqlite3_step(pFindLevel)==SQLITE_ROW ){
iAbsLevel = sqlite3_column_int64(pFindLevel, 0);
- nSeg = nMin;
+ nSeg = sqlite3_column_int(pFindLevel, 1);
+ assert( nSeg>=2 );
}else{
nSeg = -1;
}
diff --git a/ext/fts5/fts5Int.h b/ext/fts5/fts5Int.h
index af4041216..35f15abba 100644
--- a/ext/fts5/fts5Int.h
+++ b/ext/fts5/fts5Int.h
@@ -172,6 +172,7 @@ struct Fts5Config {
int pgsz; /* Approximate page size used in %_data */
int nAutomerge; /* 'automerge' setting */
int nCrisisMerge; /* Maximum allowed segments per level */
+ int nUsermerge; /* 'usermerge' setting */
int nHashSize; /* Bytes of memory for in-memory hash */
char *zRank; /* Name of rank function */
char *zRankArgs; /* Arguments to rank function */
@@ -700,6 +701,12 @@ Fts5ExprNode *sqlite3Fts5ParseNode(
Fts5ExprNearset *pNear
);
+Fts5ExprNode *sqlite3Fts5ParseImplicitAnd(
+ Fts5Parse *pParse,
+ Fts5ExprNode *pLeft,
+ Fts5ExprNode *pRight
+);
+
Fts5ExprPhrase *sqlite3Fts5ParseTerm(
Fts5Parse *pParse,
Fts5ExprPhrase *pPhrase,
diff --git a/ext/fts5/fts5_config.c b/ext/fts5/fts5_config.c
index f49cede12..17fc43e01 100644
--- a/ext/fts5/fts5_config.c
+++ b/ext/fts5/fts5_config.c
@@ -18,6 +18,7 @@
#define FTS5_DEFAULT_PAGE_SIZE 4050
#define FTS5_DEFAULT_AUTOMERGE 4
+#define FTS5_DEFAULT_USERMERGE 4
#define FTS5_DEFAULT_CRISISMERGE 16
#define FTS5_DEFAULT_HASHSIZE (1024*1024)
@@ -441,7 +442,9 @@ static const char *fts5ConfigGobbleWord(
*pbQuoted = 1;
}else{
zRet = fts5ConfigSkipBareword(zIn);
- zOut[zRet-zIn] = '\0';
+ if( zRet ){
+ zOut[zRet-zIn] = '\0';
+ }
}
}
@@ -857,6 +860,18 @@ int sqlite3Fts5ConfigSetValue(
}
}
+ else if( 0==sqlite3_stricmp(zKey, "usermerge") ){
+ int nUsermerge = -1;
+ if( SQLITE_INTEGER==sqlite3_value_numeric_type(pVal) ){
+ nUsermerge = sqlite3_value_int(pVal);
+ }
+ if( nUsermerge<2 || nUsermerge>16 ){
+ *pbBadkey = 1;
+ }else{
+ pConfig->nUsermerge = nUsermerge;
+ }
+ }
+
else if( 0==sqlite3_stricmp(zKey, "crisismerge") ){
int nCrisisMerge = -1;
if( SQLITE_INTEGER==sqlite3_value_numeric_type(pVal) ){
@@ -903,6 +918,7 @@ int sqlite3Fts5ConfigLoad(Fts5Config *pConfig, int iCookie){
/* Set default values */
pConfig->pgsz = FTS5_DEFAULT_PAGE_SIZE;
pConfig->nAutomerge = FTS5_DEFAULT_AUTOMERGE;
+ pConfig->nUsermerge = FTS5_DEFAULT_USERMERGE;
pConfig->nCrisisMerge = FTS5_DEFAULT_CRISISMERGE;
pConfig->nHashSize = FTS5_DEFAULT_HASHSIZE;
diff --git a/ext/fts5/fts5_expr.c b/ext/fts5/fts5_expr.c
index d3f801b02..1e9be8117 100644
--- a/ext/fts5/fts5_expr.c
+++ b/ext/fts5/fts5_expr.c
@@ -258,6 +258,8 @@ int sqlite3Fts5ExprNew(
pNew->nPhrase = sParse.nPhrase;
sParse.apPhrase = 0;
}
+ }else{
+ sqlite3Fts5ParseNodeFree(sParse.pExpr);
}
sqlite3_free(sParse.apPhrase);
@@ -1268,6 +1270,8 @@ static int fts5ExprNodeFirst(Fts5Expr *pExpr, Fts5ExprNode *pNode){
if( Fts5NodeIsString(pNode) ){
/* Initialize all term iterators in the NEAR object. */
rc = fts5ExprNearInitAll(pExpr, pNode);
+ }else if( pNode->xNext==0 ){
+ pNode->bEof = 1;
}else{
int i;
int nEof = 0;
@@ -1319,23 +1323,22 @@ static int fts5ExprNodeFirst(Fts5Expr *pExpr, Fts5ExprNode *pNode){
*/
int sqlite3Fts5ExprFirst(Fts5Expr *p, Fts5Index *pIdx, i64 iFirst, int bDesc){
Fts5ExprNode *pRoot = p->pRoot;
- int rc = SQLITE_OK;
- if( pRoot->xNext ){
- p->pIndex = pIdx;
- p->bDesc = bDesc;
- rc = fts5ExprNodeFirst(p, pRoot);
+ int rc; /* Return code */
- /* If not at EOF but the current rowid occurs earlier than iFirst in
- ** the iteration order, move to document iFirst or later. */
- if( pRoot->bEof==0 && fts5RowidCmp(p, pRoot->iRowid, iFirst)<0 ){
- rc = fts5ExprNodeNext(p, pRoot, 1, iFirst);
- }
+ p->pIndex = pIdx;
+ p->bDesc = bDesc;
+ rc = fts5ExprNodeFirst(p, pRoot);
- /* If the iterator is not at a real match, skip forward until it is. */
- while( pRoot->bNomatch ){
- assert( pRoot->bEof==0 && rc==SQLITE_OK );
- rc = fts5ExprNodeNext(p, pRoot, 0, 0);
- }
+ /* If not at EOF but the current rowid occurs earlier than iFirst in
+ ** the iteration order, move to document iFirst or later. */
+ if( pRoot->bEof==0 && fts5RowidCmp(p, pRoot->iRowid, iFirst)<0 ){
+ rc = fts5ExprNodeNext(p, pRoot, 1, iFirst);
+ }
+
+ /* If the iterator is not at a real match, skip forward until it is. */
+ while( pRoot->bNomatch ){
+ assert( pRoot->bEof==0 && rc==SQLITE_OK );
+ rc = fts5ExprNodeNext(p, pRoot, 0, 0);
}
return rc;
}
@@ -1444,6 +1447,21 @@ Fts5ExprNearset *sqlite3Fts5ParseNearset(
sqlite3Fts5ParseNearsetFree(pNear);
sqlite3Fts5ParsePhraseFree(pPhrase);
}else{
+ if( pRet->nPhrase>0 ){
+ Fts5ExprPhrase *pLast = pRet->apPhrase[pRet->nPhrase-1];
+ assert( pLast==pParse->apPhrase[pParse->nPhrase-2] );
+ if( pPhrase->nTerm==0 ){
+ fts5ExprPhraseFree(pPhrase);
+ pRet->nPhrase--;
+ pParse->nPhrase--;
+ pPhrase = pLast;
+ }else if( pLast->nTerm==0 ){
+ fts5ExprPhraseFree(pLast);
+ pParse->apPhrase[pParse->nPhrase-2] = pPhrase;
+ pParse->nPhrase--;
+ pRet->nPhrase--;
+ }
+ }
pRet->apPhrase[pRet->nPhrase++] = pPhrase;
}
return pRet;
@@ -1476,8 +1494,7 @@ static int fts5ParseTokenize(
/* If an error has already occurred, this is a no-op */
if( pCtx->rc!=SQLITE_OK ) return pCtx->rc;
- assert( pPhrase==0 || pPhrase->nTerm>0 );
- if( pPhrase && (tflags & FTS5_TOKEN_COLOCATED) ){
+ if( pPhrase && pPhrase->nTerm>0 && (tflags & FTS5_TOKEN_COLOCATED) ){
Fts5ExprTerm *pSyn;
int nByte = sizeof(Fts5ExprTerm) + sizeof(Fts5Buffer) + nToken+1;
pSyn = (Fts5ExprTerm*)sqlite3_malloc(nByte);
@@ -1578,7 +1595,7 @@ Fts5ExprPhrase *sqlite3Fts5ParseTerm(
pParse->rc = rc;
fts5ExprPhraseFree(sCtx.pPhrase);
sCtx.pPhrase = 0;
- }else if( sCtx.pPhrase ){
+ }else{
if( pAppend==0 ){
if( (pParse->nPhrase % 8)==0 ){
@@ -1595,9 +1612,14 @@ Fts5ExprPhrase *sqlite3Fts5ParseTerm(
pParse->nPhrase++;
}
+ if( sCtx.pPhrase==0 ){
+ /* This happens when parsing a token or quoted phrase that contains
+ ** no token characters at all. (e.g ... MATCH '""'). */
+ sCtx.pPhrase = sqlite3Fts5MallocZero(&pParse->rc, sizeof(Fts5ExprPhrase));
+ }else if( sCtx.pPhrase->nTerm ){
+ sCtx.pPhrase->aTerm[sCtx.pPhrase->nTerm-1].bPrefix = bPrefix;
+ }
pParse->apPhrase[pParse->nPhrase-1] = sCtx.pPhrase;
- assert( sCtx.pPhrase->nTerm>0 );
- sCtx.pPhrase->aTerm[sCtx.pPhrase->nTerm-1].bPrefix = bPrefix;
}
return sCtx.pPhrase;
@@ -1693,23 +1715,25 @@ void sqlite3Fts5ParseSetDistance(
Fts5ExprNearset *pNear,
Fts5Token *p
){
- int nNear = 0;
- int i;
- if( p->n ){
- for(i=0; i<p->n; i++){
- char c = (char)p->p[i];
- if( c<'0' || c>'9' ){
- sqlite3Fts5ParseError(
- pParse, "expected integer, got \"%.*s\"", p->n, p->p
- );
- return;
+ if( pNear ){
+ int nNear = 0;
+ int i;
+ if( p->n ){
+ for(i=0; i<p->n; i++){
+ char c = (char)p->p[i];
+ if( c<'0' || c>'9' ){
+ sqlite3Fts5ParseError(
+ pParse, "expected integer, got \"%.*s\"", p->n, p->p
+ );
+ return;
+ }
+ nNear = nNear * 10 + (p->p[i] - '0');
}
- nNear = nNear * 10 + (p->p[i] - '0');
+ }else{
+ nNear = FTS5_DEFAULT_NEARDIST;
}
- }else{
- nNear = FTS5_DEFAULT_NEARDIST;
+ pNear->nNear = nNear;
}
- pNear->nNear = nNear;
}
/*
@@ -1896,10 +1920,14 @@ Fts5ExprNode *sqlite3Fts5ParseNode(
int iPhrase;
for(iPhrase=0; iPhrase<pNear->nPhrase; iPhrase++){
pNear->apPhrase[iPhrase]->pNode = pRet;
+ if( pNear->apPhrase[iPhrase]->nTerm==0 ){
+ pRet->xNext = 0;
+ pRet->eType = FTS5_EOF;
+ }
}
if( pParse->pConfig->eDetail!=FTS5_DETAIL_FULL
- && (pNear->nPhrase!=1 || pNear->apPhrase[0]->nTerm!=1)
+ && (pNear->nPhrase!=1 || pNear->apPhrase[0]->nTerm>1)
){
assert( pParse->rc==SQLITE_OK );
pParse->rc = SQLITE_ERROR;
@@ -1928,6 +1956,70 @@ Fts5ExprNode *sqlite3Fts5ParseNode(
return pRet;
}
+Fts5ExprNode *sqlite3Fts5ParseImplicitAnd(
+ Fts5Parse *pParse, /* Parse context */
+ Fts5ExprNode *pLeft, /* Left hand child expression */
+ Fts5ExprNode *pRight /* Right hand child expression */
+){
+ Fts5ExprNode *pRet = 0;
+ Fts5ExprNode *pPrev;
+
+ if( pParse->rc ){
+ sqlite3Fts5ParseNodeFree(pLeft);
+ sqlite3Fts5ParseNodeFree(pRight);
+ }else{
+
+ assert( pLeft->eType==FTS5_STRING
+ || pLeft->eType==FTS5_TERM
+ || pLeft->eType==FTS5_EOF
+ || pLeft->eType==FTS5_AND
+ );
+ assert( pRight->eType==FTS5_STRING
+ || pRight->eType==FTS5_TERM
+ || pRight->eType==FTS5_EOF
+ );
+
+ if( pLeft->eType==FTS5_AND ){
+ pPrev = pLeft->apChild[pLeft->nChild-1];
+ }else{
+ pPrev = pLeft;
+ }
+ assert( pPrev->eType==FTS5_STRING
+ || pPrev->eType==FTS5_TERM
+ || pPrev->eType==FTS5_EOF
+ );
+
+ if( pRight->eType==FTS5_EOF ){
+ assert( pParse->apPhrase[pParse->nPhrase-1]==pRight->pNear->apPhrase[0] );
+ sqlite3Fts5ParseNodeFree(pRight);
+ pRet = pLeft;
+ pParse->nPhrase--;
+ }
+ else if( pPrev->eType==FTS5_EOF ){
+ Fts5ExprPhrase **ap;
+
+ if( pPrev==pLeft ){
+ pRet = pRight;
+ }else{
+ pLeft->apChild[pLeft->nChild-1] = pRight;
+ pRet = pLeft;
+ }
+
+ ap = &pParse->apPhrase[pParse->nPhrase-1-pRight->pNear->nPhrase];
+ assert( ap[0]==pPrev->pNear->apPhrase[0] );
+ memmove(ap, &ap[1], sizeof(Fts5ExprPhrase*)*pRight->pNear->nPhrase);
+ pParse->nPhrase--;
+
+ sqlite3Fts5ParseNodeFree(pPrev);
+ }
+ else{
+ pRet = sqlite3Fts5ParseNode(pParse, FTS5_AND, pLeft, pRight, 0);
+ }
+ }
+
+ return pRet;
+}
+
static char *fts5ExprTermPrint(Fts5ExprTerm *pTerm){
int nByte = 0;
Fts5ExprTerm *p;
@@ -2062,6 +2154,9 @@ static char *fts5ExprPrintTcl(
static char *fts5ExprPrint(Fts5Config *pConfig, Fts5ExprNode *pExpr){
char *zRet = 0;
+ if( pExpr->eType==0 ){
+ return sqlite3_mprintf("\"\"");
+ }else
if( pExpr->eType==FTS5_STRING || pExpr->eType==FTS5_TERM ){
Fts5ExprNearset *pNear = pExpr->pNear;
int i;
@@ -2122,7 +2217,7 @@ static char *fts5ExprPrint(Fts5Config *pConfig, Fts5ExprNode *pExpr){
zRet = 0;
}else{
int e = pExpr->apChild[i]->eType;
- int b = (e!=FTS5_STRING && e!=FTS5_TERM);
+ int b = (e!=FTS5_STRING && e!=FTS5_TERM && e!=FTS5_EOF);
zRet = fts5PrintfAppend(zRet, "%s%s%z%s",
(i==0 ? "" : zOp),
(b?"(":""), z, (b?")":"")
diff --git a/ext/fts5/fts5_index.c b/ext/fts5/fts5_index.c
index ac97a7d75..323e6cefd 100644
--- a/ext/fts5/fts5_index.c
+++ b/ext/fts5/fts5_index.c
@@ -4179,13 +4179,17 @@ static void fts5IndexMergeLevel(
/*
** Do up to nPg pages of automerge work on the index.
+**
+** Return true if any changes were actually made, or false otherwise.
*/
-static void fts5IndexMerge(
+static int fts5IndexMerge(
Fts5Index *p, /* FTS5 backend object */
Fts5Structure **ppStruct, /* IN/OUT: Current structure of index */
- int nPg /* Pages of work to do */
+ int nPg, /* Pages of work to do */
+ int nMin /* Minimum number of segments to merge */
){
int nRem = nPg;
+ int bRet = 0;
Fts5Structure *pStruct = *ppStruct;
while( nRem>0 && p->rc==SQLITE_OK ){
int iLvl; /* To iterate through levels */
@@ -4216,17 +4220,17 @@ static void fts5IndexMerge(
}
#endif
- if( nBest<p->pConfig->nAutomerge
- && pStruct->aLevel[iBestLvl].nMerge==0
- ){
+ if( nBest<nMin && pStruct->aLevel[iBestLvl].nMerge==0 ){
break;
}
+ bRet = 1;
fts5IndexMergeLevel(p, &pStruct, iBestLvl, &nRem);
if( p->rc==SQLITE_OK && pStruct->aLevel[iBestLvl].nMerge==0 ){
fts5StructurePromote(p, iBestLvl+1, pStruct);
}
}
*ppStruct = pStruct;
+ return bRet;
}
/*
@@ -4254,7 +4258,7 @@ static void fts5IndexAutomerge(
pStruct->nWriteCounter += nLeaf;
nRem = (int)(p->nWorkUnit * nWork * pStruct->nLevel);
- fts5IndexMerge(p, ppStruct, nRem);
+ fts5IndexMerge(p, ppStruct, nRem, p->pConfig->nAutomerge);
}
}
@@ -4474,25 +4478,38 @@ static void fts5IndexFlush(Fts5Index *p){
}
}
-
-int sqlite3Fts5IndexOptimize(Fts5Index *p){
- Fts5Structure *pStruct;
+static Fts5Structure *fts5IndexOptimizeStruct(
+ Fts5Index *p,
+ Fts5Structure *pStruct
+){
Fts5Structure *pNew = 0;
- int nSeg = 0;
-
- assert( p->rc==SQLITE_OK );
- fts5IndexFlush(p);
- pStruct = fts5StructureRead(p);
+ int nByte = sizeof(Fts5Structure);
+ int nSeg = pStruct->nSegment;
+ int i;
- if( pStruct ){
- assert( pStruct->nSegment==fts5StructureCountSegments(pStruct) );
- nSeg = pStruct->nSegment;
- if( nSeg>1 ){
- int nByte = sizeof(Fts5Structure);
- nByte += (pStruct->nLevel+1) * sizeof(Fts5StructureLevel);
- pNew = (Fts5Structure*)sqlite3Fts5MallocZero(&p->rc, nByte);
+ /* Figure out if this structure requires optimization. A structure does
+ ** not require optimization if either:
+ **
+ ** + it consists of fewer than two segments, or
+ ** + all segments are on the same level, or
+ ** + all segments except one are currently inputs to a merge operation.
+ **
+ ** In the first case, return NULL. In the second, increment the ref-count
+ ** on *pStruct and return a copy of the pointer to it.
+ */
+ if( nSeg<2 ) return 0;
+ for(i=0; i<pStruct->nLevel; i++){
+ int nThis = pStruct->aLevel[i].nSeg;
+ if( nThis==nSeg || (nThis==nSeg-1 && pStruct->aLevel[i].nMerge==nThis) ){
+ fts5StructureRef(pStruct);
+ return pStruct;
}
+ assert( pStruct->aLevel[i].nMerge<=nThis );
}
+
+ nByte += (pStruct->nLevel+1) * sizeof(Fts5StructureLevel);
+ pNew = (Fts5Structure*)sqlite3Fts5MallocZero(&p->rc, nByte);
+
if( pNew ){
Fts5StructureLevel *pLvl;
int nByte = nSeg * sizeof(Fts5StructureSegment);
@@ -4520,8 +4537,26 @@ int sqlite3Fts5IndexOptimize(Fts5Index *p){
}
}
+ return pNew;
+}
+
+int sqlite3Fts5IndexOptimize(Fts5Index *p){
+ Fts5Structure *pStruct;
+ Fts5Structure *pNew = 0;
+
+ assert( p->rc==SQLITE_OK );
+ fts5IndexFlush(p);
+ pStruct = fts5StructureRead(p);
+
+ if( pStruct ){
+ pNew = fts5IndexOptimizeStruct(p, pStruct);
+ }
+ fts5StructureRelease(pStruct);
+
+ assert( pNew==0 || pNew->nSegment>0 );
if( pNew ){
- int iLvl = pNew->nLevel-1;
+ int iLvl;
+ for(iLvl=0; pNew->aLevel[iLvl].nSeg==0; iLvl++){}
while( p->rc==SQLITE_OK && pNew->aLevel[iLvl].nSeg>0 ){
int nRem = FTS5_OPT_WORK_UNIT;
fts5IndexMergeLevel(p, &pNew, iLvl, &nRem);
@@ -4531,20 +4566,31 @@ int sqlite3Fts5IndexOptimize(Fts5Index *p){
fts5StructureRelease(pNew);
}
- fts5StructureRelease(pStruct);
return fts5IndexReturn(p);
}
+/*
+** This is called to implement the special "VALUES('merge', $nMerge)"
+** INSERT command.
+*/
int sqlite3Fts5IndexMerge(Fts5Index *p, int nMerge){
- Fts5Structure *pStruct;
-
- pStruct = fts5StructureRead(p);
- if( pStruct && pStruct->nLevel ){
- fts5IndexMerge(p, &pStruct, nMerge);
- fts5StructureWrite(p, pStruct);
+ Fts5Structure *pStruct = fts5StructureRead(p);
+ if( pStruct ){
+ int nMin = p->pConfig->nUsermerge;
+ if( nMerge<0 ){
+ Fts5Structure *pNew = fts5IndexOptimizeStruct(p, pStruct);
+ fts5StructureRelease(pStruct);
+ pStruct = pNew;
+ nMin = 2;
+ nMerge = nMerge*-1;
+ }
+ if( pStruct && pStruct->nLevel ){
+ if( fts5IndexMerge(p, &pStruct, nMerge, nMin) ){
+ fts5StructureWrite(p, pStruct);
+ }
+ }
+ fts5StructureRelease(pStruct);
}
- fts5StructureRelease(pStruct);
-
return fts5IndexReturn(p);
}
diff --git a/ext/fts5/fts5_main.c b/ext/fts5/fts5_main.c
index 28f3f3e62..dcd131c74 100644
--- a/ext/fts5/fts5_main.c
+++ b/ext/fts5/fts5_main.c
@@ -1511,13 +1511,13 @@ static int fts5UpdateMethod(
rc = SQLITE_ERROR;
}
- /* Case 1: DELETE */
+ /* DELETE */
else if( nArg==1 ){
i64 iDel = sqlite3_value_int64(apVal[0]); /* Rowid to delete */
rc = sqlite3Fts5StorageDelete(pTab->pStorage, iDel, 0);
}
- /* Case 2: INSERT */
+ /* INSERT */
else if( eType0!=SQLITE_INTEGER ){
/* If this is a REPLACE, first remove the current entry (if any) */
if( eConflict==SQLITE_REPLACE
@@ -1529,7 +1529,7 @@ static int fts5UpdateMethod(
fts5StorageInsert(&rc, pTab, apVal, pRowid);
}
- /* Case 2: UPDATE */
+ /* UPDATE */
else{
i64 iOld = sqlite3_value_int64(apVal[0]); /* Old rowid */
i64 iNew = sqlite3_value_int64(apVal[1]); /* New rowid */
diff --git a/ext/fts5/fts5_test_mi.c b/ext/fts5/fts5_test_mi.c
index bc6d01f12..a905b85bb 100644
--- a/ext/fts5/fts5_test_mi.c
+++ b/ext/fts5/fts5_test_mi.c
@@ -68,18 +68,22 @@ struct Fts5MatchinfoCtx {
** If an error occurs, return NULL and leave an error in the database
** handle (accessible using sqlite3_errcode()/errmsg()).
*/
-static fts5_api *fts5_api_from_db(sqlite3 *db){
- fts5_api *pRet = 0;
+static int fts5_api_from_db(sqlite3 *db, fts5_api **ppApi){
sqlite3_stmt *pStmt = 0;
+ int rc;
- if( SQLITE_OK==sqlite3_prepare(db, "SELECT fts5()", -1, &pStmt, 0)
- && SQLITE_ROW==sqlite3_step(pStmt)
- && sizeof(pRet)==sqlite3_column_bytes(pStmt, 0)
- ){
- memcpy(&pRet, sqlite3_column_blob(pStmt, 0), sizeof(pRet));
+ *ppApi = 0;
+ rc = sqlite3_prepare(db, "SELECT fts5()", -1, &pStmt, 0);
+ if( rc==SQLITE_OK ){
+ if( SQLITE_ROW==sqlite3_step(pStmt)
+ && sizeof(fts5_api*)==sqlite3_column_bytes(pStmt, 0)
+ ){
+ memcpy(ppApi, sqlite3_column_blob(pStmt, 0), sizeof(fts5_api*));
+ }
+ rc = sqlite3_finalize(pStmt);
}
- sqlite3_finalize(pStmt);
- return pRet;
+
+ return rc;
}
@@ -399,7 +403,8 @@ int sqlite3Fts5TestRegisterMatchinfo(sqlite3 *db){
/* Extract the FTS5 API pointer from the database handle. The
** fts5_api_from_db() function above is copied verbatim from the
** FTS5 documentation. Refer there for details. */
- pApi = fts5_api_from_db(db);
+ rc = fts5_api_from_db(db, &pApi);
+ if( rc!=SQLITE_OK ) return rc;
/* If fts5_api_from_db() returns NULL, then either FTS5 is not registered
** with this database handle, or an error (OOM perhaps?) has occurred.
diff --git a/ext/fts5/fts5parse.y b/ext/fts5/fts5parse.y
index 2bdf4b09b..1607d3846 100644
--- a/ext/fts5/fts5parse.y
+++ b/ext/fts5/fts5parse.y
@@ -104,7 +104,7 @@ expr(A) ::= exprlist(X). {A = X;}
exprlist(A) ::= cnearset(X). {A = X;}
exprlist(A) ::= exprlist(X) cnearset(Y). {
- A = sqlite3Fts5ParseNode(pParse, FTS5_AND, X, Y, 0);
+ A = sqlite3Fts5ParseImplicitAnd(pParse, X, Y);
}
cnearset(A) ::= nearset(X). {
diff --git a/ext/fts5/test/fts5_common.tcl b/ext/fts5/test/fts5_common.tcl
index 32691d1c8..0f371dcfd 100644
--- a/ext/fts5/test/fts5_common.tcl
+++ b/ext/fts5/test/fts5_common.tcl
@@ -159,6 +159,12 @@ proc fts5_aux_test_functions {db} {
}
}
+proc fts5_segcount {tbl} {
+ set N 0
+ foreach n [fts5_level_segs $tbl] { incr N $n }
+ set N
+}
+
proc fts5_level_segs {tbl} {
set sql "SELECT fts5_decode(rowid,block) aS r FROM ${tbl}_data WHERE rowid=10"
set ret [list]
diff --git a/ext/fts5/test/fts5config.test b/ext/fts5/test/fts5config.test
index c30a59724..386d112e7 100644
--- a/ext/fts5/test/fts5config.test
+++ b/ext/fts5/test/fts5config.test
@@ -247,5 +247,21 @@ do_catchsql_test 12.1 {
INSERT INTO t1(t1, rank) VALUES('rank', NULL);;
} {1 {SQL logic error or missing database}}
+#-------------------------------------------------------------------------
+# errors in the 'usermerge' option
+#
+do_execsql_test 13.0 {
+ CREATE VIRTUAL TABLE tt USING fts5(ttt);
+}
+foreach {tn val} {
+ 1 -1
+ 2 4.2
+ 3 17
+ 4 1
+} {
+ set sql "INSERT INTO tt(tt, rank) VALUES('usermerge', $val)"
+ do_catchsql_test 13.$tn $sql {1 {SQL logic error or missing database}}
+}
+
finish_test
diff --git a/ext/fts5/test/fts5eb.test b/ext/fts5/test/fts5eb.test
index 820539604..69418aae6 100644
--- a/ext/fts5/test/fts5eb.test
+++ b/ext/fts5/test/fts5eb.test
@@ -33,12 +33,12 @@ foreach {tn expr res} {
1 {abc} {"abc"}
2 {abc ""} {"abc"}
3 {""} {}
- 4 {abc OR ""} {"abc"}
- 5 {abc NOT ""} {"abc"}
- 6 {abc AND ""} {"abc"}
- 7 {"" OR abc} {"abc"}
- 8 {"" NOT abc} {"abc"}
- 9 {"" AND abc} {"abc"}
+ 4 {abc OR ""} {"abc" OR ""}
+ 5 {abc NOT ""} {"abc" NOT ""}
+ 6 {abc AND ""} {"abc" AND ""}
+ 7 {"" OR abc} {"" OR "abc"}
+ 8 {"" NOT abc} {"" NOT "abc"}
+ 9 {"" AND abc} {"" AND "abc"}
10 {abc + "" + def} {"abc" + "def"}
11 {abc "" def} {"abc" AND "def"}
12 {r+e OR w} {"r" + "e" OR "w"}
diff --git a/ext/fts5/test/fts5fault8.test b/ext/fts5/test/fts5fault8.test
index ae5849495..c613490e5 100644
--- a/ext/fts5/test/fts5fault8.test
+++ b/ext/fts5/test/fts5fault8.test
@@ -54,7 +54,32 @@ foreach_detail_mode $testprefix {
faultsim_test_result {0 {1 3}} {1 SQLITE_NOMEM}
}
}
+
} ;# foreach_detail_mode...
+
+do_execsql_test 4.0 {
+ CREATE VIRTUAL TABLE x2 USING fts5(a);
+ INSERT INTO x2(x2, rank) VALUES('crisismerge', 2);
+ INSERT INTO x2(x2, rank) VALUES('pgsz', 32);
+ INSERT INTO x2 VALUES('a b c d');
+ INSERT INTO x2 VALUES('e f g h');
+ INSERT INTO x2 VALUES('i j k l');
+ INSERT INTO x2 VALUES('m n o p');
+ INSERT INTO x2 VALUES('q r s t');
+ INSERT INTO x2 VALUES('u v w x');
+ INSERT INTO x2 VALUES('y z a b');
+}
+faultsim_save_and_close
+
+do_faultsim_test 4 -faults oom-* -prep {
+ faultsim_restore_and_reopen
+} -body {
+ execsql { INSERT INTO x2(x2) VALUES('optimize') }
+} -test {
+ faultsim_test_result {0 {}} {1 SQLITE_NOMEM}
+}
+
+
finish_test
diff --git a/ext/fts5/test/fts5fuzz1.test b/ext/fts5/test/fts5fuzz1.test
new file mode 100644
index 000000000..599d7bcc8
--- /dev/null
+++ b/ext/fts5/test/fts5fuzz1.test
@@ -0,0 +1,93 @@
+# 2014 June 17
+#
+# The author disclaims copyright to this source code. In place of
+# a legal notice, here is a blessing:
+#
+# May you do good and not evil.
+# May you find forgiveness for yourself and forgive others.
+# May you share freely, never taking more than you give.
+#
+#*************************************************************************
+# This file implements regression tests for SQLite library. The
+# focus of this script is testing the FTS5 module.
+#
+
+source [file join [file dirname [info script]] fts5_common.tcl]
+return_if_no_fts5
+set testprefix fts5fuzz1
+
+
+#-------------------------------------------------------------------------
+reset_db
+do_catchsql_test 1.1 {
+ CREATE VIRTUAL TABLE f1 USING fts5(a b);
+} {/1 {parse error in.*}/}
+
+
+#-------------------------------------------------------------------------
+reset_db
+do_execsql_test 2.1 {
+ CREATE VIRTUAL TABLE f1 USING fts5(a, b);
+ INSERT INTO f1 VALUES('a b', 'c d');
+ INSERT INTO f1 VALUES('e f', 'a b');
+}
+
+do_execsql_test 2.2.1 {
+ SELECT rowid FROM f1('""');
+} {}
+
+do_execsql_test 2.2.2 {
+ SELECT rowid FROM f1('"" AND a');
+} {}
+
+
+do_execsql_test 2.2.3 {
+ SELECT rowid FROM f1('"" a');
+} {1 2}
+
+do_execsql_test 2.2.4 {
+ SELECT rowid FROM f1('"" OR a');
+} {1 2}
+
+do_execsql_test 2.3 {
+ SELECT a, b FROM f1('NEAR("")');
+} {}
+
+do_execsql_test 2.4 {
+ SELECT a, b FROM f1('NEAR("", 5)');
+} {}
+
+do_execsql_test 2.5 {
+ SELECT a, b FROM f1('NEAR("" c, 5)');
+} {{a b} {c d}}
+
+do_execsql_test 2.6 {
+ SELECT a, b FROM f1('NEAR("" c d, 5)');
+} {{a b} {c d}}
+
+do_execsql_test 2.7 {
+ SELECT a, b FROM f1('NEAR(c d, 5)');
+} {{a b} {c d}}
+
+do_execsql_test 2.8 {
+ SELECT rowid FROM f1('NEAR("a" "b", 5)');
+} {1 2}
+
+#-------------------------------------------------------------------------
+reset_db
+do_execsql_test 3.2 {
+ CREATE VIRTUAL TABLE f2 USING fts5(o, t, tokenize="ascii separators abc");
+ SELECT * FROM f2('a+4');
+} {}
+
+
+
+#-------------------------------------------------------------------------
+reset_db
+do_catchsql_test 4.1 {
+ CREATE VIRTUAL TABLE f2 USING fts5(o, t);
+ SELECT * FROM f2('(8 AND 9)`AND 10');
+} {1 {fts5: syntax error near "`"}}
+
+finish_test
+
diff --git a/ext/fts5/test/fts5merge.test b/ext/fts5/test/fts5merge.test
index 9dd1ecd02..73e006a7d 100644
--- a/ext/fts5/test/fts5merge.test
+++ b/ext/fts5/test/fts5merge.test
@@ -45,7 +45,7 @@ proc do_merge1_test {testname nRowPerSeg} {
WITH ii(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM ii WHERE i<$::nRowPerSeg)
INSERT INTO x8 SELECT repeat('x y ', i % 16) FROM ii;
- INSERT INTO x8(x8, rank) VALUES('automerge', 2);
+ INSERT INTO x8(x8, rank) VALUES('usermerge', 2);
}
for {set tn 1} {[lindex [fts5_level_segs x8] 0]>0} {incr tn} {
@@ -84,9 +84,9 @@ proc do_merge2_test {testname nRow} {
execsql { INSERT INTO x8 VALUES( rnddoc(($i%16) + 5) ) }
while {[not_merged x8]} {
execsql {
- INSERT INTO x8(x8, rank) VALUES('automerge', 2);
+ INSERT INTO x8(x8, rank) VALUES('usermerge', 2);
INSERT INTO x8(x8, rank) VALUES('merge', 1);
- INSERT INTO x8(x8, rank) VALUES('automerge', 16);
+ INSERT INTO x8(x8, rank) VALUES('usermerge', 16);
INSERT INTO x8(x8) VALUES('integrity-check');
}
}
@@ -104,9 +104,9 @@ do_merge2_test 2.2 10
do_merge2_test 2.3 20
#-------------------------------------------------------------------------
-# Test that an auto-merge will complete any merge that has already been
+# Test that a merge will complete any merge that has already been
# started, even if the number of input segments is less than the current
-# value of the 'automerge' configuration parameter.
+# value of the 'usermerge' configuration parameter.
#
db func rnddoc fts5_rnddoc
@@ -119,7 +119,7 @@ do_execsql_test 3.1 {
}
do_test 3.2 {
execsql {
- INSERT INTO x8(x8, rank) VALUES('automerge', 4);
+ INSERT INTO x8(x8, rank) VALUES('usermerge', 4);
INSERT INTO x8(x8, rank) VALUES('merge', 1);
}
fts5_level_segs x8
@@ -127,14 +127,14 @@ do_test 3.2 {
do_test 3.3 {
execsql {
- INSERT INTO x8(x8, rank) VALUES('automerge', 2);
+ INSERT INTO x8(x8, rank) VALUES('usermerge', 2);
INSERT INTO x8(x8, rank) VALUES('merge', 1);
}
fts5_level_segs x8
} {2 1}
do_test 3.4 {
- execsql { INSERT INTO x8(x8, rank) VALUES('automerge', 4) }
+ execsql { INSERT INTO x8(x8, rank) VALUES('usermerge', 4) }
while {[not_merged x8]} {
execsql { INSERT INTO x8(x8, rank) VALUES('merge', 1) }
}
@@ -176,7 +176,7 @@ foreach {tn pgsz} {
INSERT INTO x8 SELECT mydoc() FROM ii;
WITH ii(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM ii WHERE i<100)
INSERT INTO x8 SELECT mydoc() FROM ii;
- INSERT INTO x8(x8, rank) VALUES('automerge', 2);
+ INSERT INTO x8(x8, rank) VALUES('usermerge', 2);
}
set expect [mycount]
@@ -190,5 +190,55 @@ foreach {tn pgsz} {
# db eval {SELECT fts5_decode(rowid, block) AS r FROM x8_data} { puts $r }
}
+#-------------------------------------------------------------------------
+# Test that the 'merge' command does not modify the database if there is
+# no work to do.
+
+do_execsql_test 5.1 {
+ CREATE VIRTUAL TABLE x9 USING fts5(one, two);
+ INSERT INTO x9(x9, rank) VALUES('pgsz', 32);
+ INSERT INTO x9(x9, rank) VALUES('automerge', 2);
+ INSERT INTO x9(x9, rank) VALUES('usermerge', 2);
+ INSERT INTO x9 VALUES(rnddoc(100), rnddoc(100));
+ INSERT INTO x9 VALUES(rnddoc(100), rnddoc(100));
+ INSERT INTO x9 VALUES(rnddoc(100), rnddoc(100));
+ INSERT INTO x9 VALUES(rnddoc(100), rnddoc(100));
+ INSERT INTO x9 VALUES(rnddoc(100), rnddoc(100));
+ INSERT INTO x9 VALUES(rnddoc(100), rnddoc(100));
+ INSERT INTO x9 VALUES(rnddoc(100), rnddoc(100));
+ INSERT INTO x9 VALUES(rnddoc(100), rnddoc(100));
+}
+
+do_test 5.2 {
+ while 1 {
+ set nChange [db total_changes]
+ execsql { INSERT INTO x9(x9, rank) VALUES('merge', 1); }
+ set nChange [expr [db total_changes] - $nChange]
+ #puts $nChange
+ if {$nChange<2} break
+ }
+} {}
+
+
+#--------------------------------------------------------------------------
+# Test that running 'merge' on an empty database does not cause a
+# problem.
+#
+reset_db
+do_execsql_test 6.0 {
+ CREATE VIRTUAL TABLE g1 USING fts5(a, b);
+}
+do_execsql_test 6.1 {
+ INSERT INTO g1(g1, rank) VALUES('merge', 10);
+}
+do_execsql_test 6.2 {
+ INSERT INTO g1(g1, rank) VALUES('merge', -10);
+}
+do_execsql_test 6.3 {
+ INSERT INTO g1(g1) VALUES('integrity-check');
+}
+
+
+
finish_test
diff --git a/ext/fts5/test/fts5optimize.test b/ext/fts5/test/fts5optimize.test
index 984af8c53..3ef6d8a16 100644
--- a/ext/fts5/test/fts5optimize.test
+++ b/ext/fts5/test/fts5optimize.test
@@ -20,6 +20,12 @@ ifcapable !fts5 {
return
}
+#
+# 1.* - Warm body tests for index optimization using ('optimize')
+#
+# 2.* - Warm body tests for index optimization using ('merge', -1)
+#
+
proc rnddoc {nWord} {
set vocab {a b c d e f g h i j k l m n o p q r s t u v w x y z}
set nVocab [llength $vocab]
@@ -30,14 +36,12 @@ proc rnddoc {nWord} {
return $ret
}
-
foreach {tn nStep} {
1 2
2 10
3 50
4 500
} {
-if {$tn!=4} continue
reset_db
db func rnddoc rnddoc
do_execsql_test 1.$tn.1 {
@@ -60,7 +64,46 @@ if {$tn!=4} continue
do_execsql_test 1.$tn.5 {
INSERT INTO t1(t1) VALUES('integrity-check');
}
+
+ do_test 1.$tn.6 { fts5_segcount t1 } 1
}
+foreach {tn nStep} {
+ 1 2
+ 2 10
+ 3 50
+ 4 500
+} {
+ reset_db
+ db func rnddoc rnddoc
+ do_execsql_test 1.$tn.1 {
+ CREATE VIRTUAL TABLE t1 USING fts5(x, y);
+ }
+ do_test 2.$tn.2 {
+ for {set i 0} {$i < $nStep} {incr i} {
+ execsql { INSERT INTO t1 VALUES( rnddoc(5), rnddoc(5) ) }
+ }
+ } {}
+
+ do_execsql_test 2.$tn.3 {
+ INSERT INTO t1(t1) VALUES('integrity-check');
+ }
+
+ do_test 2.$tn.4 {
+ execsql { INSERT INTO t1(t1, rank) VALUES('merge', -1) }
+ while 1 {
+ set c [db total_changes]
+ execsql { INSERT INTO t1(t1, rank) VALUES('merge', 1) }
+ set c [expr [db total_changes]-$c]
+ if {$c<2} break
+ }
+ } {}
+
+ do_execsql_test 2.$tn.5 {
+ INSERT INTO t1(t1) VALUES('integrity-check');
+ }
+
+ do_test 2.$tn.6 { fts5_segcount t1 } 1
+}
finish_test
diff --git a/ext/misc/spellfix.c b/ext/misc/spellfix.c
index 5734d04f4..b5859ea2c 100644
--- a/ext/misc/spellfix.c
+++ b/ext/misc/spellfix.c
@@ -1734,6 +1734,7 @@ static void scriptCodeSqlFunc(
int c, sz;
int scriptMask = 0;
int res;
+ int seenDigit = 0;
# define SCRIPT_LATIN 0x0001
# define SCRIPT_CYRILLIC 0x0002
# define SCRIPT_GREEK 0x0004
@@ -1744,8 +1745,12 @@ static void scriptCodeSqlFunc(
c = utf8Read(zIn, nIn, &sz);
zIn += sz;
nIn -= sz;
- if( c<0x02af && (c>=0x80 || midClass[c&0x7f]<CCLASS_DIGIT) ){
- scriptMask |= SCRIPT_LATIN;
+ if( c<0x02af ){
+ if( c>=0x80 || midClass[c&0x7f]<CCLASS_DIGIT ){
+ scriptMask |= SCRIPT_LATIN;
+ }else if( c>='0' && c<='9' ){
+ seenDigit = 1;
+ }
}else if( c>=0x0400 && c<=0x04ff ){
scriptMask |= SCRIPT_CYRILLIC;
}else if( c>=0x0386 && c<=0x03ce ){
@@ -1756,6 +1761,7 @@ static void scriptCodeSqlFunc(
scriptMask |= SCRIPT_ARABIC;
}
}
+ if( scriptMask==0 && seenDigit ) scriptMask = SCRIPT_LATIN;
switch( scriptMask ){
case 0: res = 999; break;
case SCRIPT_LATIN: res = 215; break;
diff --git a/ext/rbu/rbuC.test b/ext/rbu/rbuC.test
new file mode 100644
index 000000000..89fd01518
--- /dev/null
+++ b/ext/rbu/rbuC.test
@@ -0,0 +1,142 @@
+# 2016 March 7
+#
+# The author disclaims copyright to this source code. In place of
+# a legal notice, here is a blessing:
+#
+# May you do good and not evil.
+# May you find forgiveness for yourself and forgive others.
+# May you share freely, never taking more than you give.
+#
+#***********************************************************************
+# Tests for RBU focused on the REPLACE operation (rbu_control column
+# contains integer value 2).
+#
+
+source [file join [file dirname [info script]] rbu_common.tcl]
+set ::testprefix rbuC
+
+#-------------------------------------------------------------------------
+# This test is actually of an UPDATE directive. Just to establish that
+# these work with UNIQUE indexes before preceding to REPLACE.
+#
+do_execsql_test 1.0 {
+ CREATE TABLE t1(i INTEGER PRIMARY KEY, a, b, c UNIQUE);
+ INSERT INTO t1 VALUES(1, 'a', 'b', 'c');
+}
+
+forcedelete rbu.db
+do_execsql_test 1.1 {
+ ATTACH 'rbu.db' AS rbu;
+ CREATE TABLE rbu.data_t1(i, a, b, c, rbu_control);
+ INSERT INTO data_t1 VALUES(1, 'a', 'b', 'c', '.xxx');
+}
+
+do_test 1.2 {
+ step_rbu test.db rbu.db
+} {SQLITE_DONE}
+
+do_execsql_test 1.3 {
+ SELECT * FROM t1
+} {
+ 1 a b c
+}
+
+#-------------------------------------------------------------------------
+#
+foreach {tn schema} {
+ 1 {
+ CREATE TABLE t1(i INTEGER PRIMARY KEY, a, b, c UNIQUE);
+ CREATE INDEX t1a ON t1(a);
+ }
+ 2 {
+ CREATE TABLE t1(i PRIMARY KEY, a, b, c UNIQUE);
+ CREATE INDEX t1a ON t1(a);
+ }
+ 3 {
+ CREATE TABLE t1(i PRIMARY KEY, a, b, c UNIQUE) WITHOUT ROWID;
+ CREATE INDEX t1a ON t1(a);
+ }
+} {
+ reset_db
+ forcedelete rbu.db
+ execsql $schema
+
+ do_execsql_test 2.$tn.0 {
+ INSERT INTO t1 VALUES(1, 'a', 'b', 'c');
+ INSERT INTO t1 VALUES(2, 'b', 'c', 'd');
+ INSERT INTO t1 VALUES(3, 'c', 'd', 'e');
+ }
+
+ do_execsql_test 2.$tn.1 {
+ ATTACH 'rbu.db' AS rbu;
+ CREATE TABLE rbu.data_t1(i, a, b, c, rbu_control);
+ INSERT INTO data_t1 VALUES(1, 1, 2, 3, 2);
+ INSERT INTO data_t1 VALUES(3, 'c', 'd', 'e', 2);
+ INSERT INTO data_t1 VALUES(4, 'd', 'e', 'f', 2);
+ }
+
+ do_test 2.$tn.2 {
+ step_rbu test.db rbu.db
+ } {SQLITE_DONE}
+
+ do_execsql_test 2.$tn.3 {
+ SELECT * FROM t1 ORDER BY i
+ } {
+ 1 1 2 3
+ 2 b c d
+ 3 c d e
+ 4 d e f
+ }
+
+ integrity_check 2.$tn.4
+}
+
+foreach {tn schema} {
+ 1 {
+ CREATE TABLE t1(a, b, c UNIQUE);
+ CREATE INDEX t1a ON t1(a);
+ }
+
+ 2 {
+ CREATE VIRTUAL TABLE t1 USING fts5(a, b, c);
+ }
+} {
+ if {$tn==2} { ifcapable !fts5 break }
+ reset_db
+ forcedelete rbu.db
+ execsql $schema
+
+ do_execsql_test 3.$tn.0 {
+ INSERT INTO t1 VALUES('a', 'b', 'c');
+ INSERT INTO t1 VALUES('b', 'c', 'd');
+ INSERT INTO t1 VALUES('c', 'd', 'e');
+ }
+
+ do_execsql_test 3.$tn.1 {
+ ATTACH 'rbu.db' AS rbu;
+ CREATE TABLE rbu.data_t1(rbu_rowid, a, b, c, rbu_control);
+ INSERT INTO data_t1 VALUES(1, 1, 2, 3, 2);
+ INSERT INTO data_t1 VALUES(3, 'c', 'd', 'e', 2);
+ INSERT INTO data_t1 VALUES(4, 'd', 'e', 'f', 2);
+ }
+
+ do_test 3.$tn.2 {
+ step_rbu test.db rbu.db
+ } {SQLITE_DONE}
+
+ do_execsql_test 3.$tn.3 {
+ SELECT rowid, * FROM t1 ORDER BY 1
+ } {
+ 1 1 2 3
+ 2 b c d
+ 3 c d e
+ 4 d e f
+ }
+
+ integrity_check 3.$tn.4
+}
+
+
+
+finish_test
+
diff --git a/ext/rbu/sqlite3rbu.c b/ext/rbu/sqlite3rbu.c
index 682becbb5..474e39fe8 100644
--- a/ext/rbu/sqlite3rbu.c
+++ b/ext/rbu/sqlite3rbu.c
@@ -280,10 +280,11 @@ struct RbuObjIter {
*/
#define RBU_INSERT 1 /* Insert on a main table b-tree */
#define RBU_DELETE 2 /* Delete a row from a main table b-tree */
-#define RBU_IDX_DELETE 3 /* Delete a row from an aux. index b-tree */
-#define RBU_IDX_INSERT 4 /* Insert on an aux. index b-tree */
-#define RBU_UPDATE 5 /* Update a row in a main table b-tree */
+#define RBU_REPLACE 3 /* Delete and then insert a row */
+#define RBU_IDX_DELETE 4 /* Delete a row from an aux. index b-tree */
+#define RBU_IDX_INSERT 5 /* Insert on an aux. index b-tree */
+#define RBU_UPDATE 6 /* Update a row in a main table b-tree */
/*
** A single step of an incremental checkpoint - frame iWalFrame of the wal
@@ -1909,13 +1910,13 @@ static int rbuObjIterPrepareAll(
);
}else{
zSql = sqlite3_mprintf(
+ "SELECT %s, rbu_control FROM %s.'rbu_tmp_%q' "
+ "UNION ALL "
"SELECT %s, rbu_control FROM '%q' "
"WHERE typeof(rbu_control)='integer' AND rbu_control!=1 "
- "UNION ALL "
- "SELECT %s, rbu_control FROM %s.'rbu_tmp_%q' "
"ORDER BY %s%s",
- zCollist, pIter->zDataTbl,
zCollist, p->zStateDb, pIter->zDataTbl,
+ zCollist, pIter->zDataTbl,
zCollist, zLimit
);
}
@@ -1981,17 +1982,17 @@ static int rbuObjIterPrepareAll(
rbuMPrintfExec(p, p->dbMain,
"CREATE TEMP TRIGGER rbu_delete_tr BEFORE DELETE ON \"%s%w\" "
"BEGIN "
- " SELECT rbu_tmp_insert(2, %s);"
+ " SELECT rbu_tmp_insert(3, %s);"
"END;"
"CREATE TEMP TRIGGER rbu_update1_tr BEFORE UPDATE ON \"%s%w\" "
"BEGIN "
- " SELECT rbu_tmp_insert(2, %s);"
+ " SELECT rbu_tmp_insert(3, %s);"
"END;"
"CREATE TEMP TRIGGER rbu_update2_tr AFTER UPDATE ON \"%s%w\" "
"BEGIN "
- " SELECT rbu_tmp_insert(3, %s);"
+ " SELECT rbu_tmp_insert(4, %s);"
"END;",
zWrite, zTbl, zOldlist,
zWrite, zTbl, zOldlist,
@@ -2509,14 +2510,12 @@ static int rbuStepType(sqlite3rbu *p, const char **pzMask){
switch( sqlite3_column_type(p->objiter.pSelect, iCol) ){
case SQLITE_INTEGER: {
int iVal = sqlite3_column_int(p->objiter.pSelect, iCol);
- if( iVal==0 ){
- res = RBU_INSERT;
- }else if( iVal==1 ){
- res = RBU_DELETE;
- }else if( iVal==2 ){
- res = RBU_IDX_DELETE;
- }else if( iVal==3 ){
- res = RBU_IDX_INSERT;
+ switch( iVal ){
+ case 0: res = RBU_INSERT; break;
+ case 1: res = RBU_DELETE; break;
+ case 2: res = RBU_REPLACE; break;
+ case 3: res = RBU_IDX_DELETE; break;
+ case 4: res = RBU_IDX_INSERT; break;
}
break;
}
@@ -2556,6 +2555,67 @@ static void assertColumnName(sqlite3_stmt *pStmt, int iCol, const char *zName){
#endif
/*
+** Argument eType must be one of RBU_INSERT, RBU_DELETE, RBU_IDX_INSERT or
+** RBU_IDX_DELETE. This function performs the work of a single
+** sqlite3rbu_step() call for the type of operation specified by eType.
+*/
+static void rbuStepOneOp(sqlite3rbu *p, int eType){
+ RbuObjIter *pIter = &p->objiter;
+ sqlite3_value *pVal;
+ sqlite3_stmt *pWriter;
+ int i;
+
+ assert( p->rc==SQLITE_OK );
+ assert( eType!=RBU_DELETE || pIter->zIdx==0 );
+
+ if( eType==RBU_IDX_DELETE || eType==RBU_DELETE ){
+ pWriter = pIter->pDelete;
+ }else{
+ pWriter = pIter->pInsert;
+ }
+
+ for(i=0; i<pIter->nCol; i++){
+ /* If this is an INSERT into a table b-tree and the table has an
+ ** explicit INTEGER PRIMARY KEY, check that this is not an attempt
+ ** to write a NULL into the IPK column. That is not permitted. */
+ if( eType==RBU_INSERT
+ && pIter->zIdx==0 && pIter->eType==RBU_PK_IPK && pIter->abTblPk[i]
+ && sqlite3_column_type(pIter->pSelect, i)==SQLITE_NULL
+ ){
+ p->rc = SQLITE_MISMATCH;
+ p->zErrmsg = sqlite3_mprintf("datatype mismatch");
+ return;
+ }
+
+ if( eType==RBU_DELETE && pIter->abTblPk[i]==0 ){
+ continue;
+ }
+
+ pVal = sqlite3_column_value(pIter->pSelect, i);
+ p->rc = sqlite3_bind_value(pWriter, i+1, pVal);
+ if( p->rc ) return;
+ }
+ if( pIter->zIdx==0
+ && (pIter->eType==RBU_PK_VTAB || pIter->eType==RBU_PK_NONE)
+ ){
+ /* For a virtual table, or a table with no primary key, the
+ ** SELECT statement is:
+ **
+ ** SELECT <cols>, rbu_control, rbu_rowid FROM ....
+ **
+ ** Hence column_value(pIter->nCol+1).
+ */
+ assertColumnName(pIter->pSelect, pIter->nCol+1, "rbu_rowid");
+ pVal = sqlite3_column_value(pIter->pSelect, pIter->nCol+1);
+ p->rc = sqlite3_bind_value(pWriter, pIter->nCol+1, pVal);
+ }
+ if( p->rc==SQLITE_OK ){
+ sqlite3_step(pWriter);
+ p->rc = resetAndCollectError(pWriter, &p->zErrmsg);
+ }
+}
+
+/*
** This function does the work for an sqlite3rbu_step() call.
**
** The object-iterator (p->objiter) currently points to a valid object,
@@ -2569,78 +2629,32 @@ static void assertColumnName(sqlite3_stmt *pStmt, int iCol, const char *zName){
static int rbuStep(sqlite3rbu *p){
RbuObjIter *pIter = &p->objiter;
const char *zMask = 0;
- int i;
int eType = rbuStepType(p, &zMask);
if( eType ){
+ assert( eType==RBU_INSERT || eType==RBU_DELETE
+ || eType==RBU_REPLACE || eType==RBU_IDX_DELETE
+ || eType==RBU_IDX_INSERT || eType==RBU_UPDATE
+ );
assert( eType!=RBU_UPDATE || pIter->zIdx==0 );
if( pIter->zIdx==0 && eType==RBU_IDX_DELETE ){
rbuBadControlError(p);
}
- else if(
- eType==RBU_INSERT
- || eType==RBU_DELETE
- || eType==RBU_IDX_DELETE
- || eType==RBU_IDX_INSERT
- ){
- sqlite3_value *pVal;
- sqlite3_stmt *pWriter;
-
- assert( eType!=RBU_UPDATE );
- assert( eType!=RBU_DELETE || pIter->zIdx==0 );
-
- if( eType==RBU_IDX_DELETE || eType==RBU_DELETE ){
- pWriter = pIter->pDelete;
- }else{
- pWriter = pIter->pInsert;
- }
-
- for(i=0; i<pIter->nCol; i++){
- /* If this is an INSERT into a table b-tree and the table has an
- ** explicit INTEGER PRIMARY KEY, check that this is not an attempt
- ** to write a NULL into the IPK column. That is not permitted. */
- if( eType==RBU_INSERT
- && pIter->zIdx==0 && pIter->eType==RBU_PK_IPK && pIter->abTblPk[i]
- && sqlite3_column_type(pIter->pSelect, i)==SQLITE_NULL
- ){
- p->rc = SQLITE_MISMATCH;
- p->zErrmsg = sqlite3_mprintf("datatype mismatch");
- goto step_out;
- }
-
- if( eType==RBU_DELETE && pIter->abTblPk[i]==0 ){
- continue;
- }
-
- pVal = sqlite3_column_value(pIter->pSelect, i);
- p->rc = sqlite3_bind_value(pWriter, i+1, pVal);
- if( p->rc ) goto step_out;
- }
- if( pIter->zIdx==0
- && (pIter->eType==RBU_PK_VTAB || pIter->eType==RBU_PK_NONE)
- ){
- /* For a virtual table, or a table with no primary key, the
- ** SELECT statement is:
- **
- ** SELECT <cols>, rbu_control, rbu_rowid FROM ....
- **
- ** Hence column_value(pIter->nCol+1).
- */
- assertColumnName(pIter->pSelect, pIter->nCol+1, "rbu_rowid");
- pVal = sqlite3_column_value(pIter->pSelect, pIter->nCol+1);
- p->rc = sqlite3_bind_value(pWriter, pIter->nCol+1, pVal);
- }
- if( p->rc==SQLITE_OK ){
- sqlite3_step(pWriter);
- p->rc = resetAndCollectError(pWriter, &p->zErrmsg);
- }
- }else{
+ else if( eType==RBU_REPLACE ){
+ if( pIter->zIdx==0 ) rbuStepOneOp(p, RBU_DELETE);
+ if( p->rc==SQLITE_OK ) rbuStepOneOp(p, RBU_INSERT);
+ }
+ else if( eType!=RBU_UPDATE ){
+ rbuStepOneOp(p, eType);
+ }
+ else{
sqlite3_value *pVal;
sqlite3_stmt *pUpdate = 0;
assert( eType==RBU_UPDATE );
rbuGetUpdateStmt(p, pIter, zMask, &pUpdate);
if( pUpdate ){
+ int i;
for(i=0; p->rc==SQLITE_OK && i<pIter->nCol; i++){
char c = zMask[pIter->aiSrcOrder[i]];
pVal = sqlite3_column_value(pIter->pSelect, i);
@@ -2663,8 +2677,6 @@ static int rbuStep(sqlite3rbu *p){
}
}
}
-
- step_out:
return p->rc;
}
diff --git a/manifest b/manifest
index ee71dadf9..c10bdd869 100644
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Merge\sthe\svirtual\stable\squery\splanner\senhancement,\sthe\sRTREE\scost\sestimate\nfix,\sand\sthe\sstatement\sjournal\sspill\sdelay\senhancement\sfrom\strunk.
-D 2016-03-07T17:49:17.995
+C Merge\sall\srecent\senhancements\sfrom\strunk.
+D 2016-03-16T01:16:30.929
F Makefile.in e812bb732d7af01baa09f1278bd4f4a2e3a09449
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
F Makefile.msc e6ee58b849c116d5554024f524cbf61f064f6f01
@@ -10,11 +10,11 @@ F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2
F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90
F art/sqlite370.jpg d512473dae7e378a67e28ff96a34da7cb331def2
F autoconf/INSTALL 83e4a25da9fd053c7b3665eaaaf7919707915903
-F autoconf/Makefile.am 4b8bd7896fffb6b22a57747f1f98cba1da9108ae
+F autoconf/Makefile.am 42f7eb1fb2b06ddd6c6adab3e4388cc0a237ba40
F autoconf/Makefile.msc b8ada5177e6f39c126a88295af5ad0255e08d280
F autoconf/README.first 6c4f34fe115ff55d4e8dbfa3cecf04a0188292f7
F autoconf/README.txt 4f04b0819303aabaa35fff5f7b257fb0c1ef95f1
-F autoconf/configure.ac 72a5e42beb090b32bca580285dc0ab3c4670adb8
+F autoconf/configure.ac d807b567f73a2b0986ccdd206b782cecb4d08fff
F autoconf/tea/Makefile.in b438a7020446c8a8156e8d97c8914a04833da6fd
F autoconf/tea/README 3e9a3c060f29a44344ab50aec506f4db903fb873
F autoconf/tea/aclocal.m4 52c47aac44ce0ddb1f918b6993e8beb8eee88f43
@@ -88,7 +88,7 @@ F ext/fts3/fts3_tokenizer.h 64c6ef6c5272c51ebe60fc607a896e84288fcbc3
F ext/fts3/fts3_tokenizer1.c 5c98225a53705e5ee34824087478cf477bdb7004
F ext/fts3/fts3_unicode.c a93f5edc0aff44ef8b06d7cb55b52026541ca145
F ext/fts3/fts3_unicode2.c c3d01968d497bd7001e7dc774ba75b372738c057
-F ext/fts3/fts3_write.c f442223e4a1914dc1fc12b65af7e4f2c255fa47c
+F ext/fts3/fts3_write.c c3863f23b6b4623c8b9d5cf31c12ce4469f78ca9
F ext/fts3/fts3speed.tcl b54caf6a18d38174f1a6e84219950d85e98bb1e9
F ext/fts3/mkfts3amal.tcl 252ecb7fe6467854f2aa237bf2c390b74e71f100
F ext/fts3/tool/fts3view.c 5d78b668f4e9598af9147f8999632599fb0d9dd5
@@ -98,25 +98,25 @@ F ext/fts3/unicode/mkunicode.tcl 2debed3f582d77b3fdd0b8830880250021571fd8
F ext/fts3/unicode/parseunicode.tcl da577d1384810fb4e2b209bf3313074353193e95
F ext/fts5/extract_api_docs.tcl a36e54ec777172ddd3f9a88daf593b00848368e0
F ext/fts5/fts5.h ff9c2782e8ed890b0de2f697a8d63971939e70c7
-F ext/fts5/fts5Int.h fa7c17e5c3ec9c8690387ff962f9dc6aee75e114
+F ext/fts5/fts5Int.h 4060504b7979601d99e1385c2b5713036854979a
F ext/fts5/fts5_aux.c daa57fb45216491814520bbb587e97bf81ced458
F ext/fts5/fts5_buffer.c 4c1502d4c956cd092c89ce4480867f9d8bf325cd
-F ext/fts5/fts5_config.c 35c5173cae4eb17e82164a7f5aeef56a48903079
-F ext/fts5/fts5_expr.c 8e8e4635f655133eb39018072fc0f0942a2c4337
+F ext/fts5/fts5_config.c 5af9c360e99669d29f06492c370892394aba0857
+F ext/fts5/fts5_expr.c be309fb227003c931107bfcc12d5be4f2fd2bb8c
F ext/fts5/fts5_hash.c f3a7217c86eb8f272871be5f6aa1b6798960a337
-F ext/fts5/fts5_index.c 26a4a6112864feb599a6f6144d06a78bb179736a
-F ext/fts5/fts5_main.c db24ac714c6c4a1b3c24a1f8c25889f2952148c1
+F ext/fts5/fts5_index.c d4f0c12e4f04bbc3a06b6da052039f2ce3e45438
+F ext/fts5/fts5_main.c b8501e1a6a11591c53b18ce7aea7e5386cfb0421
F ext/fts5/fts5_storage.c f8343db90d8c95a4d4b52f6676e354b4649ffd6e
F ext/fts5/fts5_tcl.c f8731e0508299bd43f1a2eff7dbeaac870768966
-F ext/fts5/fts5_test_mi.c b8d04816428202b2898d4ca38deb1739ac0110ae
+F ext/fts5/fts5_test_mi.c 783b86697ebf773c18fc109992426c0173a055bc
F ext/fts5/fts5_test_tok.c db08af63673c3a7d39f053b36fd6e065017706be
F ext/fts5/fts5_tokenize.c 2ce7b44183538ec46b7907726262ee43ffdd39a8
F ext/fts5/fts5_unicode2.c b450b209b157d598f7b9df9f837afb75a14c24bf
F ext/fts5/fts5_varint.c a5aceacda04dafcbae725413d7a16818ecd65738
F ext/fts5/fts5_vocab.c dba72ca393d71c2588548b51380387f6b44c77a8
-F ext/fts5/fts5parse.y 86fe6ba094a47e02fe8be2571539e6833d197764
+F ext/fts5/fts5parse.y fcc5e92e570d38cab38488b2109cbf67468923b2
F ext/fts5/mkportersteps.tcl 5acf962d2e0074f701620bb5308155fa1e4a63ba
-F ext/fts5/test/fts5_common.tcl b9b1fed811c0390511cef8b254826ea15d380f4d
+F ext/fts5/test/fts5_common.tcl b01c584144b5064f30e6c648145a2dd6bc440841
F ext/fts5/test/fts5aa.test 7e814df4a0e6c22a6fe2d84f210fdc0b5068a084
F ext/fts5/test/fts5ab.test 30325a89453280160106be411bba3acf138e6d1b
F ext/fts5/test/fts5ac.test 55cad4275a1f5acabfe14d8442a8046b47e49e5f
@@ -136,7 +136,7 @@ F ext/fts5/test/fts5auxdata.test 141a7cbffcceb1bd2799b4b29c183ff8780d586e
F ext/fts5/test/fts5bigpl.test 04ee0d7eebbebf17c31f5a0b5c5f9494eac3a0cb
F ext/fts5/test/fts5bigtok.test 017a9397b14e7598883a6328ead4a6539b42d59a
F ext/fts5/test/fts5columnsize.test a8cfef21ffa1c264b9f670a7d94eeaccb5341c07
-F ext/fts5/test/fts5config.test 8b2bc6dcc0eb06fa2b7dd65b2ce2db09e829e873
+F ext/fts5/test/fts5config.test 7788b9c058074d640dfcdd81d97b6a9480000368
F ext/fts5/test/fts5conflict.test 26f4e46c4d31e16221794832a990dc4e30e18de5
F ext/fts5/test/fts5content.test 9a952c95518a14182dc3b59e3c8fa71cda82a4e1
F ext/fts5/test/fts5corrupt.test c2ad090192708150d50d961278df10ae7a4b8b62
@@ -146,7 +146,7 @@ F ext/fts5/test/fts5detail.test ef5c690535a797413acaf5ad9b8ab5d49972df69
F ext/fts5/test/fts5dlidx.test 13871a14641017ae42f6f1055a8067bafd44cb3d
F ext/fts5/test/fts5doclist.test 8edb5b57e5f144030ed74ec00ef6fa4294fed79b
F ext/fts5/test/fts5ea.test b01e3a18cdfabbff8104a96a5242a06a68a998a0
-F ext/fts5/test/fts5eb.test 021aa80b7ac09b964249aa32ced9ee908703e4aa
+F ext/fts5/test/fts5eb.test c516ae0c934be6fd29ec95ea8b5f11f461311535
F ext/fts5/test/fts5fault1.test e09040d3e17b8c0837101e8c79c8a874c4376fb7
F ext/fts5/test/fts5fault2.test d8c6c7f916ccbdfc10b2c69530e9dd3bc8313232
F ext/fts5/test/fts5fault3.test d6e9577d4312e331a913c72931bf131704efc8f3
@@ -154,19 +154,20 @@ F ext/fts5/test/fts5fault4.test 532b6dacb963016cbf7003196bd87fb366540277
F ext/fts5/test/fts5fault5.test 10c13a783de3f42a21e3e53e123b62ed0c3a1618
F ext/fts5/test/fts5fault6.test 9682664d679643ac6736e90c225526cc84073cda
F ext/fts5/test/fts5fault7.test cb14ea3c1f42394f06f2284abc58eecee6ff8080
-F ext/fts5/test/fts5fault8.test 430837fe6dd0511fd3aea52bd602ac02441bcb58
+F ext/fts5/test/fts5fault8.test 6785af34bd1760de74e2824ea9c161965af78f85
F ext/fts5/test/fts5fault9.test e10e395428a9ea0596ebe752ff7123d16ab78e08
F ext/fts5/test/fts5faultA.test fa5d59c0ff62b7125cd14eee38ded1c46e15a7ea
F ext/fts5/test/fts5faultB.test 92ae906284062bf081b6c854afa54dcb1aa9ef88
F ext/fts5/test/fts5full.test 6f6143af0c6700501d9fd597189dfab1555bb741
+F ext/fts5/test/fts5fuzz1.test bece4695fc169b61ab236ada7931c6e4942cbef9
F ext/fts5/test/fts5hash.test 06f9309ccb4d5050a131594e9e47d0b21456837d
F ext/fts5/test/fts5integrity.test f5e4f8d284385875068ad0f3e894ce43e9de835d
F ext/fts5/test/fts5matchinfo.test f7dde99697bcb310ea8faa8eb2714d9f4dfc0e1b
-F ext/fts5/test/fts5merge.test 8f3cdba2ec9c5e7e568246e81b700ad37f764367
+F ext/fts5/test/fts5merge.test 9f65f090d214ff865c56bef4f864aaa1182af6e3
F ext/fts5/test/fts5merge2.test a6da3c16d694235938d1939f503cfa53f0943d75
F ext/fts5/test/fts5near.test b214cddb1c1f1bddf45c75af768f20145f7e71cc
F ext/fts5/test/fts5onepass.test 7ed9608e258132cb8d55e7c479b08676ad68810c
-F ext/fts5/test/fts5optimize.test 42741e7c085ee0a1276140a752d4407d97c2c9f5
+F ext/fts5/test/fts5optimize.test 9d3ac53bb9cae58cb070d795db86bcb2f9fec105
F ext/fts5/test/fts5phrase.test f6d1d464da5beb25dc56277aa4f1d6102f0d9a2f
F ext/fts5/test/fts5plan.test 6a55ecbac9890765b0e16f8c421c7e0888cfe436
F ext/fts5/test/fts5porter.test 7cdc07bef301d70eebbfa75dcaf45c3680e1d0e1
@@ -214,7 +215,7 @@ F ext/misc/regexp.c af92cdaa5058fcec1451e49becc7ba44dba023dc
F ext/misc/rot13.c 1ac6f95f99b575907b9b09c81a349114cf9be45a
F ext/misc/series.c e11e534ada797d5b816d7e7a93c022306563ca35
F ext/misc/showauth.c 732578f0fe4ce42d577e1c86dc89dd14a006ab52
-F ext/misc/spellfix.c 194b5fc3a9a63cb6c5680d8f713800012bddca7c
+F ext/misc/spellfix.c 598bbc45516227701558becdd38f4e6fe8e97cc2
F ext/misc/totype.c 4a167594e791abeed95e0a8db028822b5e8fe512
F ext/misc/vfslog.c fe40fab5c077a40477f7e5eba994309ecac6cc95
F ext/misc/vtshim.c babb0dc2bf116029e3e7c9a618b8a1377045303e
@@ -234,6 +235,7 @@ F ext/rbu/rbu8.test 3bbf2c35d71a843c463efe93946f14ad10c3ede0
F ext/rbu/rbu9.test 0806d1772c9f4981774ff028de6656e4183082af
F ext/rbu/rbuA.test c1a7b3e2d926b8f8448bb3b4ae787e314ee4b2b3
F ext/rbu/rbuB.test c25bc325b8072a766e56bb76c001866b405925c2
+F ext/rbu/rbuC.test efe47db508a0269b683cb2a1913a425ffd39a831
F ext/rbu/rbu_common.tcl 0398545fed614f807d5f0ba55a85a51f08ba8f1a
F ext/rbu/rbucrash.test 8d2ed5d4b05fef6c00c2a6b5f7ead71fa172a695
F ext/rbu/rbudiff.test 6cc806dc36389292f2a8f5842d0103721df4a07d
@@ -241,7 +243,7 @@ F ext/rbu/rbufault.test cc0be8d5d392d98b0c2d6a51be377ea989250a89
F ext/rbu/rbufault2.test 9a7f19edd6ea35c4c9f807d8a3db0a03a5670c06
F ext/rbu/rbufts.test 828cd689da825f0a7b7c53ffc1f6f7fdb6fa5bda
F ext/rbu/rbusave.test 0f43b6686084f426ddd040b878426452fd2c2f48
-F ext/rbu/sqlite3rbu.c 371e8bf06cfb3f691adac47eb15ab1073ed92dcf
+F ext/rbu/sqlite3rbu.c 5956f8bee63b5ab2b04e65c1801ea0f5920dac92
F ext/rbu/sqlite3rbu.h 0bdeb3be211aaba7d85445fa36f4701a25a3dbde
F ext/rbu/test_rbu.c 4a4cdcef4ef9379fc2a21f008805c80b27bcf573
F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761
@@ -307,22 +309,22 @@ F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
F src/alter.c 1bb0709b3048e24217b80ec6bd78a3e99a47c01b
F src/analyze.c ab57b6763dd4c6170a20673d14882c033affd188
-F src/attach.c a3724c64de1099d85e30751213d285752aed9505
+F src/attach.c 771153bd1f4ab0b97a44a13dde2c7e5e1efeba22
F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240
F src/backup.c f60f0aa55d25d853ffde53d0b0370a7bb7ee41ce
F src/bitvec.c 3ee4c8b2c94ed3a7377256e18199e6ff5cf33f63
F src/btmutex.c bc87dd3b062cc26edfe79918de2200ccb8d41e73
-F src/btree.c 7bb920c473c277380fcb3e8a8ee28ce1a48e0abc
+F src/btree.c 6eee126fe9d1f57118de9be2be840a4c6e691828
F src/btree.h a5008b9afe56e8e54ade6c436a910f112defcca9
F src/btreeInt.h c18b7d2a3494695133e4e60ee36061d37f45d9a5
-F src/build.c 43b93fe757bfffe00f97462596418b052eefdccd
+F src/build.c 213cbf84e99dd834e6ea46615633656d7ef79321
F src/callback.c 2e76147783386374bf01b227f752c81ec872d730
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
F src/ctime.c 60e135af364d777a9ab41c97e5e89cd224da6198
F src/date.c 0b73e681c11fca867fec554750c07fe0d4e417c1
F src/dbstat.c c845548d4346e606e2f2b7d2e714ace2b8a7dd1b
F src/delete.c eeac28b3d3d88e3541bdf93e91ea7492a7b67842
-F src/expr.c c4dad2cd6cec00387b75fef4551aff655430dcd2
+F src/expr.c c329d581e5d631153456369684d7d4bcd94c907d
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
F src/fkey.c 5da47ff524e2f687997a74737ce598f043e1342a
F src/func.c 552d300265aed09eea21f68ac742a440550c0062
@@ -333,14 +335,14 @@ F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08
F src/insert.c 8f4e9fcbd8e95e85f15647ba8b413b18d556ec2b
F src/legacy.c 75d3023be8f0d2b99d60f905090341a03358c58e
F src/loadext.c 9e2a41adcaff16ebc1ebff1f336cbf33de55396f
-F src/main.c e5675877b35bd894e5803588974fc59369d5a6f2
+F src/main.c 0a3dc6c0bac5d4abdc74449f895e1599542acfca
F src/malloc.c 1443d1ad95d67c21d77af7ae3f44678252f0efec
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c 6919bcf12f221868ea066eec27e579fed95ce98b
F src/mem2.c f1940d9e91948dd6a908fbb9ce3835c36b5d83c3
F src/mem3.c 8768ac94694f31ffaf8b4d0ea5dc08af7010a35a
F src/mem5.c 9bf955937b07f8c32541c8a9991f33ce3173d944
-F src/memjournal.c 011da5236a7250385cc74c253f14bbee04c0d61e
+F src/memjournal.c 6423a0817ffd8c7a04ef9e5fb974b6b9dd71f8b6
F src/msvc.h d9ba56c6851227ab44b3f228a35f3f5772296495
F src/mutex.c 8e45800ee78e0cd1f1f3fe8e398853307f4a085c
F src/mutex.h 779d588e3b7756ec3ecf7d78cde1d84aba414f85
@@ -353,32 +355,32 @@ F src/os.h 3e57a24e2794a94d3cf2342c6d9a884888cd96bf
F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85
F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa
F src/os_unix.c f5bac8e74aaefc4ea520e43b4540793c3b8a9e8f
-F src/os_win.c f0d7aa603eb6262143d7169a222aea07c4fca91d
+F src/os_win.c cbf8c442a0d818d05bcf40b093cb3ebad435b9be
F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca
-F src/pager.c d40cf1e890a0582b6ac7cb208c24619d72d2c900
+F src/pager.c 38718a019ca762ba4f6795425d5a54db70d1790d
F src/pager.h e1d38a2f14849e219df0f91f8323504d134c8a56
F src/parse.y 5ea8c81c5c41b27887f41b4a7e1c58470d7d3821
F src/pcache.c 647bb53a86b7bbcf55ad88089b3ea5a9170b90df
F src/pcache.h 4d0ccaad264d360981ec5e6a2b596d6e85242545
F src/pcache1.c 72f644dc9e1468c72922eff5904048427b817051
-F src/pragma.c 42b3f1475b483710ba1dd1cc1ecc0c0f8db59a2e
+F src/pragma.c 04baa9343771f913f1c86b2720f768be8a3ad52a
F src/pragma.h 64c78a648751b9f4f297276c4eb7507b14b4628c
F src/prepare.c 22df6171aec1d86904ed2ad30c2348a5748aa04e
F src/printf.c 63e6fb12bbe702dd664dc3703776c090383a5a26
F src/random.c ba2679f80ec82c4190062d756f22d0c358180696
F src/resolve.c b8f7174e5f8c33c44ded3a25a973d0bb89228c20
F src/rowset.c 9fe4b3ad7cc00944386bb600233d8f523de07a6e
-F src/select.c 137b31daa84d57d67847bf621bb54f3353e2077b
+F src/select.c 6dd2097bb158efe3b8d68683dcc3b4a49e907a34
F src/shell.c cd3f82fdc5c895b817a375b7ab8319cb41f447ce
F src/sqlite.h.in 86884a006a451c22d342da18d8e373aa70e65ec0
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h dfbe62ffd95b99afe2140d8c35b180d11924072d
-F src/sqliteInt.h cd85b90d949c7270266f997ed9796371e6019c53
+F src/sqliteInt.h a8838eed1eb20f794ce929597864d070944f15b7
F src/sqliteLimit.h 7b28cf72cbd52f178bfc97ea266445e351f2cd24
F src/status.c 70912d7be68e9e2dbc4010c93d344af61d4c59ba
F src/table.c 5226df15ab9179b9ed558d89575ea0ce37b03fc9
-F src/tclsqlite.c 23a5c328898b86177b21718834d2b7b4f7bc083c
-F src/test1.c f14a6f9e2cff6cba4d83e2b0c52857f61886cead
+F src/tclsqlite.c 56569acc73d36e836b64aefecbbb709a92ba0077
+F src/test1.c 52965bd684ddcd7f22328ebd7d50fd0b6e51f0d4
F src/test2.c 5586f43fcd9a1be0830793cf9d354082c261b25b
F src/test3.c a8887dabbbee3059af338f20d290084a63ed1b0f
F src/test4.c d168f83cc78d02e8d35567bb5630e40dcd85ac1e
@@ -430,13 +432,13 @@ F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
F src/tokenize.c 3d338cdd00d916ce8a05c397001d64ed58e6fe1c
F src/treeview.c e4b41a37530a191579d3c53142cc44ee2eb99373
F src/trigger.c e14840ee0c3e549e758ec9bf3e4146e166002280
-F src/update.c c0016d277a418360456ff6af29363effbd4272f7
+F src/update.c 14c6916d0194a7f25ad429292f4831b8c31e93d9
F src/utf.c 699001c79f28e48e9bcdf8a463da029ea660540c
-F src/util.c 12800a93f0664f41575f96799eb881a786d565e6
+F src/util.c 34ef7be420f82415ec48131404995ddb6ee7502f
F src/vacuum.c feb1eabb20987983d9350cad98299b21fa811f52
-F src/vdbe.c 9ccb138cb7ac6c1bcda23dfaf52eff1f7761dfe5
+F src/vdbe.c 8e9452b8bc241ae2031c35764b78ae8b4804effb
F src/vdbe.h 594aef1a7dcfc2944e2f266f148140c3427fd0f0
-F src/vdbeInt.h a205ce1ece3ab90be78a374e93cb5402fccdf865
+F src/vdbeInt.h 9b704336a69f62ba189eafb06a46171e3463d27b
F src/vdbeapi.c ba85b78fe08dc4a9ce747e62c89a2b4a4547e74c
F src/vdbeaux.c 325dcf1b944e6d339a5c5210b7b8c5724a8496fb
F src/vdbeblob.c c9f2f494b911c6fa34efd9803f0a10807da80f77
@@ -448,9 +450,9 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
F src/wal.c 10deb6b43887662691e5f53d10b3c171c401169b
F src/wal.h 2f7c831cf3b071fa548bf2d5cac640846a7ff19c
F src/walker.c 0f142b5bd3ed2041fc52d773880748b212e63354
-F src/where.c ccc62c39af1e6340f6af36fcf68efb96482d4c3a
+F src/where.c 5533002ddf4fbc256f450cb629668a200b06a3ce
F src/whereInt.h 93297d56edd137b7ea004490690fb6e2ce028a34
-F src/wherecode.c 3ca820435c5b597bb50e63ed11e938786fe5c23e
+F src/wherecode.c 863aedf086131743763c1960637fde904eadc442
F src/whereexpr.c fb87944b1254234e5bba671aaf6dee476241506a
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd
@@ -478,7 +480,7 @@ F test/analyzeC.test 555a6cc388b9818b6eda6df816f01ce0a75d3a93
F test/analyzeD.test 42af58de25a6436502e43006e9e59e2d71bcb0cf
F test/analyzeE.test 8684e8ac5722fb97c251887ad97e5d496a98af1d
F test/analyzeF.test 5d1fe1024ba2dfea3c18bede8c1ccef8aba1ab34
-F test/analyzer1.test 498e2ff4b62740c2751c3a2f8b744fe26689fae9
+F test/analyzer1.test 459fa02c445ddbf0101a3bad47b34290a35f2e49
F test/async.test 1d0e056ba1bb9729283a0f22718d3a25e82c277b
F test/async2.test c0a9bd20816d7d6a2ceca7b8c03d3d69c28ffb8b
F test/async3.test d73a062002376d7edc1fe3edff493edbec1fc2f7
@@ -499,21 +501,21 @@ F test/autoindex2.test 12ef578928102baaa0dc23ad397601a2f4ecb0df
F test/autoindex3.test a3be0d1a53a7d2edff208a5e442312957047e972
F test/autoindex4.test 49d3cd791a9baa16fb461d7ea3de80d019a819cf
F test/autoindex5.test 96f084a5e6024ea07cace5888df3223f3ea86990
-F test/autovacuum.test 941892505d2c0f410a0cb5970dfa1c7c4e5f6e74
+F test/autovacuum.test 92c24eedbdb68e49f3fb71f26f9ce6d8988cac15
F test/autovacuum_ioerr2.test 8a367b224183ad801e0e24dcb7d1501f45f244b4
F test/avtrans.test 0252654f4295ddda3b2cce0e894812259e655a85
-F test/backcompat.test 19a1f337c68419b020a7481dd272a472c4ad8ef4
+F test/backcompat.test 3e64cedda754c778ef6bbe417b6e7a295e662a4d
F test/backup.test b79299a536a4c6d919094786595b95be56d02014
F test/backup2.test 34986ef926ea522911a51dfdb2f8e99b7b75ebcf
-F test/backup4.test 2a2e4a64388090b152de753fd9e123f28f6a3bd4
+F test/backup4.test 8f6fd48e0dfde77b9a3bb26dc471ede3e101df32
F test/backup5.test ee5da6d7fe5082f5b9b0bbfa31d016f52412a2e4
F test/backup_ioerr.test 4c3c7147cee85b024ecf6e150e090c32fdbb5135
F test/backup_malloc.test 7162d604ec2b4683c4b3799a48657fb8b5e2d450
F test/badutf.test d5360fc31f643d37a973ab0d8b4fb85799c3169f
F test/badutf2.test f5bc7f2d280670ecd79b9cf4f0f1760c607fe51f
-F test/bc_common.tcl 3eda41ef9cda7d5f6c205462c96228b301da4191
-F test/bestindex1.test e228fe1e3794dbe20271481164e000d695abcd24
-F test/bestindex2.test 10f2c6791f1cd0de414012528cd10a114648fd8f
+F test/bc_common.tcl b5e42d80305be95697e6370e015af571e5333a1c
+F test/bestindex1.test d5ba89a7941a941476d8d69be39b146aaed3614c
+F test/bestindex2.test 4a06b8922ab2fd09434870da8d1cdf525aaf7060
F test/between.test 34d375fb5ce1ae283ffe82b6b233e9f38e84fc6c
F test/bigfile.test aa74f4e5db51c8e54a1d9de9fa65d01d1eb20b59
F test/bigfile2.test 1b489a3a39ae90c7f027b79110d6b4e1dbc71bfc
@@ -546,7 +548,7 @@ F test/capi3e.test 3d49c01ef2a1a55f41d73cba2b23b5059ec460fe
F test/cast.test 4c275cbdc8202d6f9c54a3596701719868ac7dc3
F test/cffault.test aadc1f61f8811cb600e3e069acbf8796f472a096
F test/check.test 85a84bfc4be0e83f668747211c7cd45a6721d485
-F test/close.test 340bd24cc58b16c6bc01967402755027c37eb815
+F test/close.test 83947daf3b700631f90f4850ddaab455be4af73d
F test/closure01.test b1703ba40639cfc9b295cf478d70739415eec6a4
F test/coalesce.test cee0dccb9fbd2d494b77234bccf9dc6c6786eb91
F test/collate1.test 08c18e7512a5a32c97938854263fa15362eeb846
@@ -566,24 +568,24 @@ F test/conflict2.test bb0b94cf7196c64a3cbd815c66d3ee98c2fecd9c
F test/conflict3.test dec0634c0f31dec9a4b01c63063e939f0cd21b6b
F test/contrib01.test 2a1cbc0f2f48955d7d073f725765da6fbceda6b4
F test/corrupt.test 141c39ea650c1365e85a49e402fa05cb9617fb97
-F test/corrupt2.test cb787825d761b0f869764d6990531382840de872
-F test/corrupt3.test 4b548d0bbe2933bc81d3f54099a05fc4d28aff18
-F test/corrupt4.test b99652079d542b21f4965f6248703b983e40fe80
+F test/corrupt2.test e4964cee73dda57a90958e0087a6b388b1d9cb58
+F test/corrupt3.test e676f478fe602915d721472811f6f410b75ddc7e
+F test/corrupt4.test 8d1d86b850fcc43e417450454f2044e52d55778a
F test/corrupt5.test 8ead52af76006f3286e9396cb41898018ccea107
-F test/corrupt6.test 269548d19427ac554c830763b1c5ea54a0252f80
-F test/corrupt7.test e4fa6d6584276679cc1d20c4e58beb9559a4eb85
+F test/corrupt6.test fc6a891716139665dae0073b6945e3670bf92568
+F test/corrupt7.test b036f94bda4b0b23a2919bf717046ce9ecca4543
F test/corrupt8.test 2399dfe40d2c0c63af86706e30f3e6302a8d0516
F test/corrupt9.test 730a3db08d4ab9aa43392ea30d9c2b4879cbff85
F test/corruptA.test 53e56dafd180addcdadb402244b8cb9771d2ba26
F test/corruptB.test 73a8d6c0b9833697ecf16b63e3c5c05c945b5dec
F test/corruptC.test 0c46574f8d4f27ecc799b1b5c4cbf9b1817bce9a
F test/corruptD.test b3c205fac7952b1de645ce44bb02335cd9e3e040
-F test/corruptE.test be8e5088c369fc7979c662cd644efdaafc0f7f6d
+F test/corruptE.test 82ccf4f8f543fdbedd4aa42c709cb077f7374c62
F test/corruptF.test be9fde98e4c93648f1ba52b74e5318edc8f59fe4
-F test/corruptG.test 1ab3bf97ee7bdba70e0ff3ba2320657df55d1804
-F test/corruptH.test 99ad81a4bda7cc078c589ef7542ecbc64e453c80
-F test/corruptI.test 347babbf970e7947e3f91dccf7a1bec28a1bab04
-F test/corruptJ.test 9e29e7a81ee3b6ac50f77ea7a9e2f3fa03f32d91
+F test/corruptG.test adf79b669cbfd19e28c8191a610d083ae53a6d51
+F test/corruptH.test 79801d97ec5c2f9f3c87739aa1ec2eb786f96454
+F test/corruptI.test 075fe1d75aa1d84e2949be56b6264376c41502e4
+F test/corruptJ.test 4d5ccc4bf959464229a836d60142831ef76a5aa4
F test/cost.test 1eedbfd868f806f3fa08ff072b04cf270dcf61c8
F test/count.test cb2e0f934c6eb33670044520748d2ecccd46259c
F test/coveridxscan.test b629e896b14df2f000a99b8d170d80589c46562c
@@ -594,7 +596,7 @@ F test/crash4.test fe2821baf37168dc59dd733dcf7dba2a401487bc
F test/crash5.test 05dd3aa9dbb751a22d5cdaf22a9c49b6667aa219
F test/crash6.test 4c56f1e40d0291e1110790a99807aa875b1647ba
F test/crash7.test 1a194c4900a255258cf94b7fcbfd29536db572df
-F test/crash8.test 61442a9964ab6b124fc5254e4258b45747842e6f
+F test/crash8.test a63907617d8e74fb54b4bff23eca8a4435625245
F test/crashM.test d95f59046fa749b0d0822edf18a717788c8f318d
F test/crashtest1.c 09c1c7d728ccf4feb9e481671e29dda5669bbcc2
F test/createtab.test b5de160630b209c4b8925bdcbbaf48cc90b67fe8
@@ -634,17 +636,17 @@ F test/e_select.test 52692ff3849541e828ad4661fe3773a9b8711763
F test/e_select2.test aceb80ab927d46fba5ce7586ebabf23e2bb0604f
F test/e_totalchanges.test b12ee5809d3e63aeb83238dd501a7bca7fd72c10
F test/e_update.test f46c2554d915c9197548681e8d8c33a267e84528
-F test/e_uri.test eed3eb41b22d051a1164110dacdc778899126e14
-F test/e_vacuum.test 5bfbdc21b65c0abf24398d0ba31dc88d93ca77a9
+F test/e_uri.test 25385396082b67fd02ae0038b95a3b3575fe0519
+F test/e_vacuum.test 4d5b391384bb7d56bb9337d956f08035332421fc
F test/e_wal.test ae9a593207a77d711443ee69ffe081fda9243625
-F test/e_walauto.test 280714ddf14e1a47dcbc59d515cd0b026dfd5567
+F test/e_walauto.test 248af31e73c98df23476a22bdb815524c9dc3ba8
F test/e_walckpt.test 28c371a6bb5e5fe7f31679c1df1763a19d19e8a0
F test/e_walhook.test 4c0613a0c76e7a9d5c4c211e1b4cbcc1143914df
F test/enc.test e54531cd6bf941ee6760be041dff19a104c7acea
F test/enc2.test 83437a79ba1545a55fb549309175c683fb334473
F test/enc3.test 6807f7a7740a00361ca8d0ccd66bc60c8dc5f2b6
F test/enc4.test c8f1ce3618508fd0909945beb8b8831feef2c020
-F test/eqp.test 85873fa5816c48915c82c4e74cb5c35a5b48160f
+F test/eqp.test 3fe051af50921284189d1970eb653f9fcf5117d2
F test/errmsg.test f31592a594b44ee121371d25ddd5d63497bb3401
F test/eval.test a64c9105d6ff163df7cf09d6ac29cdad5922078c
F test/exclusive.test f48243eaf40e0957215501a12f510a8644d13a02
@@ -656,7 +658,7 @@ F test/extension01.test 00d13cec817f331a687a243e0e5a2d87b0e358c9
F test/extraquick.test cb254400bd42bfb777ff675356aabf3287978f79
F test/fallocate.test 3e979af17dfa7e5e9dda5eba1a696c04fa9d47f7
F test/filectrl.test 7c13f96457435238da99aff7343ad6a3a4885787
-F test/filefmt.test cb34663f126cbc2d358af552dcaf5c72769b0146
+F test/filefmt.test e4edbdc637ca9576ccf4337a3cce627d9df7a56c
F test/fkey1.test 13e3d48236a2b9f5c5ebd232eef9b3ab682a8a2c
F test/fkey2.test f3d27ecba480a348c328965d154214719bb158a9
F test/fkey3.test 76d475c80b84ee7a5d062e56ccb6ea68882e2b49
@@ -764,16 +766,17 @@ F test/fts4aa.test 10aac8e9d62c7357590acfabe3fad01e9a9ce1cb
F test/fts4check.test c3056eab9524232e4c9bdcd119912947e07bcc1c
F test/fts4content.test 05716af19a899cd70d5cd916c580043c03f30db4
F test/fts4docid.test e33c383cfbdff0284685604d256f347a18fdbf01
-F test/fts4growth.test 60d6bb3f78e25b34f533797dd9f2f9402310a13a
+F test/fts4growth.test e5390da74619cacc389711bac9349640b32c4f9a
F test/fts4growth2.test 13ad4e76451af6e6906c95cdc725d01b00044269
F test/fts4incr.test 4e353a0bd886ea984e56fce9e77724fc923b8d0d
-F test/fts4langid.test 9794addcc8faaee85ac60eceecdb52feb0c70f68
-F test/fts4merge.test c424309743fdd203f8e56a1f1cd7872cd66cc0ee
+F test/fts4langid.test 65a7332c9bc257919e259a304aa8a38c41655b9d
+F test/fts4merge.test d2b39f6b1bd4a9738a13540e2d044cba11c43d47
F test/fts4merge2.test 5faa558d1b672f82b847d2a337465fa745e46891
-F test/fts4merge3.test aab02a09f50fe6baaddc2e159c3eabc116d45fc7
+F test/fts4merge3.test 8d9ccb4a3d41c4c617a149d6c4b13ad02de797d0
F test/fts4merge4.test d895b1057a7798b67e03455d0fa50e9ea836c47b
F test/fts4noti.test 5553d7bb2e20bf4a06b23e849352efc022ce6309
F test/fts4onepass.test 7319d61a2ed1325fc54afd0c060a0513b462303a
+F test/fts4opt.test fd6a11684b965e1999564ae763797b7fb9e34c96
F test/fts4unicode.test 27378af76394542cf490cf001d8d1505fe55f6a9
F test/full.test 6b3c8fb43c6beab6b95438c1675374b95fab245d
F test/func.test ae97561957aba6ca9e3a7b8a13aac41830d701ef
@@ -806,12 +809,12 @@ F test/in.test 61a24ae38d4b64ec69f06ccdf022992f68a98176
F test/in2.test 5d4c61d17493c832f7d2d32bef785119e87bde75
F test/in3.test 3cbf58c87f4052cee3a58b37b6389777505aa0c0
F test/in4.test d2b38cba404bc4320f4fe1b595b3d163f212c068
-F test/in5.test 1de657472fa9ac2924be25c2c959ac5ca1aae554
-F test/incrblob.test e81846d214f3637622620fbde7cd526781cfe328
+F test/in5.test acc710c12af118df5f8645eaba9479f5619eed81
+F test/incrblob.test c9b96afc292aeff43d6687bcb09b0280aa599822
F test/incrblob2.test a5ce5ed1d0b01e2ed347245a21170372528af0a5
F test/incrblob3.test d8d036fde015d4a159cd3cbae9d29003b37227a4
F test/incrblob4.test f26502a5697893e5acea268c910f16478c2f0fab
-F test/incrblob_err.test af1f12ba60d220c9752073ff2bda2ad59e88960d
+F test/incrblob_err.test 69f9247fed50278d48ea710d1a8f9cdb09e4c0b8
F test/incrblobfault.test 280474078f6da9e732cd2a215d3d854969014b6e
F test/incrcorrupt.test 6c567fbf870aa9e91866fe52ce6f200cd548939a
F test/incrvacuum.test d2a6ddf5e429720b5fe502766af747915ccf6c32
@@ -838,7 +841,7 @@ F test/instr.test 737bbf80685232033f3abedc6ae92f75860b5dd2
F test/intarray.test 066b7d7ac38d25bf96f87f1b017bfc687551cdd4
F test/interrupt.test dfe9a67a94b0b2d8f70545ba1a6cca10780d71cc
F test/intpkey.test 7506090fc08e028712a8bf47e5f54111947e3844
-F test/io.test 3a7abcef18727cc0f2399e04b0e8903eccae50f8
+F test/io.test f95bca1783b01ea7761671560d023360d2dfa4cc
F test/ioerr.test 2a24bd6ed5a8b062e64bfe1f6cf94fb25e92210d
F test/ioerr2.test 2593563599e2cc6b6b4fcf5878b177bdd5d8df26
F test/ioerr3.test d3cec5e1a11ad6d27527d0d38573fbff14c71bdd
@@ -906,7 +909,7 @@ F test/manydb.test 28385ae2087967aa05c38624cec7d96ec74feb3e
F test/mem5.test c6460fba403c5703141348cd90de1c294188c68f
F test/memdb.test c1f2a343ad14398d5d6debda6ea33e80d0dafcc7
F test/memleak.test 10b9c6c57e19fc68c32941495e9ba1c50123f6e2
-F test/memsubsys1.test d2b2d6ca37890b26703a2258df8fd66f9869da02
+F test/memsubsys1.test 0311bfb4edd2615e3aa56c7a9cf44574e4229077
F test/memsubsys2.test 3e4a8d0c05fd3e5fa92017c64666730a520c7e08
F test/minmax.test 42fbad0e81afaa6e0de41c960329f2b2c3526efd
F test/minmax2.test b44bae787fc7b227597b01b0ca5575c7cb54d3bc
@@ -921,9 +924,9 @@ F test/misc6.test 953cc693924d88e6117aeba16f46f0bf5abede91
F test/misc7.test edd0b63e2ee29a256900b0514f6fff27e19e9bb2
F test/misc8.test 21ac9d35a5e110279ae9e1588b8914f54de1c60b
F test/misuse.test 3c34719944ba045cc6c188a4852ba04680728912
-F test/mmap1.test 44a5ff1c1bcc7dcf2de50227d1f997e75a8ef1ae
+F test/mmap1.test d2cfc1635171c434dcff0ece2f1c8e0a658807ce
F test/mmap2.test 9d6dd9ddb4ad2379f29cc78f38ce1e63ed418022
-F test/mmap3.test c92273e16eb8d23c1d55c9815b446bb72ef0512e
+F test/mmap3.test b3c297e78e6a8520aafcc1a8f140535594c9086e
F test/mmap4.test 2e2b4e32555b58da15176e6fe750f17c9dcf7f93
F test/mmapfault.test d4c9eff9cd8c2dc14bc43e71e042f175b0a26fe3
F test/multiplex.test efd015ca0b5b4a57dc9535b8feb1273eebeadb60
@@ -932,8 +935,8 @@ F test/multiplex3.test d228f59eac91839a977eac19f21d053f03e4d101
F test/multiplex4.test e8ae4c4bd70606a5727743241f13b5701990abe4
F test/mutex1.test e0a44072d98189003deae4b091106f085d94bea8
F test/mutex2.test bfeaeac2e73095b2ac32285d2756e3a65e681660
-F test/nan.test e9648b9d007c7045242af35e11a984d4b169443a
-F test/nolock.test 0540dd96f39b8876e3ffdd8814fad0ea425efeee
+F test/nan.test dacc57f80859c06a433d30839336fe227d2038b3
+F test/nolock.test 96e922d2d3db71c2dd6557c98e8027a28277b415
F test/notify1.test 669b2b743618efdc18ca4b02f45423d5d2304abf
F test/notify2.test 2ecabaa1305083856b7c39cf32816b612740c161
F test/notify3.test 10ff25cde502e72a92053a2f215d64bece4ef934
@@ -954,23 +957,23 @@ F test/orderby8.test 23ef1a5d72bd3adcc2f65561c654295d1b8047bd
F test/orderby9.test 87fb9548debcc2cd141c5299002dd94672fa76a3
F test/oserror.test b32dc34f2363ef18532e3a0a7358e3e7e321974f
F test/ovfl.test 199c482696defceacee8c8e0e0ef36da62726b2f
-F test/pager1.test f49df1a8b0e38b9ee3a7dd2ab4d427507b7314ce
+F test/pager1.test 841868017e9dd3cb459b8d78862091a7d9cff21d
F test/pager2.test 67b8f40ae98112bcdba1f2b2d03ea83266418c71
F test/pager3.test 3856d9c80839be0668efee1b74811b1b7f7fc95f
F test/pager4.test a122e9e6925d5b23b31e3dfef8c6a44bbf19590e
F test/pagerfault.test ae9ee0db5a30aecda9db8290ce3dd12e5f7bbaa1
F test/pagerfault2.test caf4c7facb914fd3b03a17b31ae2b180c8d6ca1f
F test/pagerfault3.test 1003fcda009bf48a8e22a516e193b6ef0dd1bbd8
-F test/pageropt.test 6b8f6a123a5572c195ad4ae40f2987007923bbd6
+F test/pageropt.test 84e4cc5cbca285357f7906e99b21be4f2bf5abc0
F test/pagesize.test 5769fc62d8c890a83a503f67d47508dfdc543305
F test/parser1.test 222b5cbf3e2e659fec1bf7d723488c8b9c94f1d0
F test/pcache.test c8acbedd3b6fd0f9a7ca887a83b11d24a007972b
F test/pcache2.test af7f3deb1a819f77a6d0d81534e97d1cf62cd442
F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff
-F test/permutations.test 1281140205caa8c2a957aa099a25a36fd3ab2f44
-F test/pragma.test 507ac7ef2ea5682241ea0ef041799ca70bb5e0bf
+F test/permutations.test cd1fa041074ed08eeaa563e4d1bacb0c69337ec1
+F test/pragma.test afbf028be1c35b68f57db8eb015c4a3c59d8f28e
F test/pragma2.test e5d5c176360c321344249354c0c16aec46214c9f
-F test/pragma3.test 6f849ccffeee7e496d2f2b5e74152306c0b8757c
+F test/pragma3.test 3f1984a04657331f838df5c519b443c2088df922
F test/printf.test b3ff34e73d59124140eaf89f7672e21bc2ca5fcc
F test/printf2.test 0b61566dd1c0f0b802f59dffa228c5dc5aa6b054
F test/progress.test ebab27f670bd0d4eb9d20d49cef96e68141d92fb
@@ -1016,7 +1019,7 @@ F test/securedel2.test 2d54c28e46eb1fd6902089958b20b1b056c6f1c5
F test/select1.test be62204d2bd9a5a8a149e9974cfddce893d8f686
F test/select2.test 352480e0e9c66eda9c3044e412abdf5be0215b56
F test/select3.test 2ce595f8fb8e2ac10071d3b4e424cadd4634a054
-F test/select4.test 453631158540e5f685b81cac5b7e8bd8c6b4c5fc
+F test/select4.test d926792a5e4d88fef0ddcddeb45d27ce75f7296c
F test/select5.test e758b8ef94f69b111df4cb819008856655dcd535
F test/select6.test 39eac4a5c03650b2b473c532882273283ee8b7a0
F test/select7.test 95e370c42d47c3c52377d05e9ffc01ccff7c1f61
@@ -1043,11 +1046,11 @@ F test/sharedA.test 0cdf1a76dfa00e6beee66af5b534b1e8df2720f5
F test/sharedB.test 16cc7178e20965d75278f410943109b77b2e645e
F test/shared_err.test 2f2aee20db294b9924e81f6ccbe60f19e21e8506
F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304
-F test/shell1.test a45b424ec23a4b946848ff9e1af5186c677162ab
-F test/shell2.test 12b8bf901b0e3a8ac58cf5c0c63a0a388d4d1862
-F test/shell3.test 5e8545ec72c4413a0e8d4c6be56496e3c257ca29
-F test/shell4.test f43e250139dc5dc5f0f2ec1752c50284a1ede102
-F test/shell5.test c04e9f9f948305706b88377c464c7f08ce7479f9
+F test/shell1.test e7dac9830b7d80432be9cebfae06eff9c18675f5
+F test/shell2.test 2e7a32c9ee03c6398478637d72416d5b9ebd9777
+F test/shell3.test c39453d3012a39ffec944566eca8a6bda10a2284
+F test/shell4.test 69995ee1cc278eb149aa8746ce1f935f4eaf98b9
+F test/shell5.test 50a732c1c2158b1cd62cf53975ce1ea7ce6b9dc9
F test/shortread1.test bb591ef20f0fd9ed26d0d12e80eee6d7ac8897a3
F test/show_speedtest1_rtree.tcl 32e6c5f073d7426148a6936a0408f4b5b169aba5
F test/shrink.test 1b4330b1fd9e818c04726d45cb28db73087535ce
@@ -1078,11 +1081,11 @@ F test/speed4p.test 0e51908951677de5a969b723e03a27a1c45db38b
F test/speedtest1.c 1478cb3fb64ad30f291ddca87ca9dbd72ff552aa
F test/spellfix.test f9c1f431e2c096c8775fec032952320c0e4700db
F test/spellfix2.test dfc8f519a3fc204cb2dfa8b4f29821ae90f6f8c3
-F test/spellfix3.test f7bf7b3482971473d32b6b00f6944c5c066cff97
+F test/spellfix3.test 0f9efaaa502a0e0a09848028518a6fb096c8ad33
F test/sqldiff1.test 8f6bc7c6a5b3585d350d779c6078869ba402f8f5
F test/sqllimits1.test a74ee2a3740b9f9c2437c246d8fb77354862a142
F test/sqllog.test 6af6cb0b09f4e44e1917e06ce85be7670302517a
-F test/stat.test acc91e80517fff447ae8adcfd953cfdaa5efc0af
+F test/stat.test b65bad7120c52583b8f0054d99eff80718119a77
F test/statfault.test f525a7bf633e50afd027700e9a486090684b1ac1
F test/stmt.test 64844332db69cf1a735fcb3e11548557fc95392f
F test/subquery.test d7268d193dd33d5505df965399d3a594e76ae13f
@@ -1090,7 +1093,7 @@ F test/subquery2.test 438f8a7da1457277b22e4176510f7659b286995f
F test/subselect.test d24fd8757daf97dafd2e889c73ea4c4272dcf4e4
F test/substr.test 18f57c4ca8a598805c4d64e304c418734d843c1a
F test/subtype1.test 7fe09496352f97053af1437150751be2d0a0cae8
-F test/superlock.test 1cde669f68d2dd37d6c9bd35eee1d95491ae3fc2
+F test/superlock.test ec94f0556b6488d97f71c79f9061ae08d9ab8f12
F test/symlink.test c9ebe7330d228249e447038276bfc8a7b22f4849
F test/sync.test 2f607e1821aa3af3c5c53b58835c05e511c95899
F test/syscall.test f59ba4e25f7ba4a4c031026cc2ef8b6e4b4c639c
@@ -1099,11 +1102,11 @@ F test/tabfunc01.test f977868fa8bb7beb4b2072883190411653473906
F test/table.test b708f3e5fa2542fa51dfab21fc07b36ea445cb2f
F test/tableapi.test 2674633fa95d80da917571ebdd759a14d9819126
F test/tableopts.test dba698ba97251017b7c80d738c198d39ab747930
-F test/tclsqlite.test 7179b4e0bf236ddf0bfa6bfaefa76fbe0a23c28a
+F test/tclsqlite.test e1306001a0ca92250b691ea6d3cecaca5b6342aa
F test/tempdb.test bd92eba8f20e16a9136e434e20b280794de3cdb6
F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30
F test/temptrigger.test 8ec228b0db5d7ebc4ee9b458fc28cb9e7873f5e1
-F test/tester.tcl 9310df7ac540d4e97d8fa4a9605a639801ede65f
+F test/tester.tcl ac5f9558e2fbef44facc1639e3738394dc110852
F test/thread001.test 9f22fd3525a307ff42a326b6bc7b0465be1745a5
F test/thread002.test e630504f8a06c00bf8bbe68528774dd96aeb2e58
F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7
@@ -1255,7 +1258,7 @@ F test/tkt3929.test cdf67acf5aa936ec4ffead81db87f8a71fe40e59
F test/tkt3935.test e15261fedb9e30a4305a311da614a5d8e693c767
F test/tkt3992.test f3e7d548ac26f763b47bc0f750da3d03c81071da
F test/tkt3997.test a335fa41ca3985660a139df7b734a26ef53284bd
-F test/tkt4018.test 7c2c9ba4df489c676a0a7a0e809a1fb9b2185bd1
+F test/tkt4018.test 18dbc6617f7a4b90e938d1bd6d26ad18daafaf08
F test/tokenize.test ce430a7aed48fc98301611429595883fdfcab5d7
F test/tpch01.test 04adbf8d8300fa60a222f28d901abd76e7be6dd4
F test/trace.test 6f676313e3ebd2a50585036d2f212a3319dd5836
@@ -1288,7 +1291,7 @@ F test/types2.test 3555aacf8ed8dc883356e59efc314707e6247a84
F test/types3.test 99e009491a54f4dc02c06bdbc0c5eea56ae3e25a
F test/unique.test 93f8b2ef5ea51b9495f8d6493429b1fd0f465264
F test/unique2.test 3674e9f2a3f1fbbfd4772ac74b7a97090d0f77d2
-F test/unixexcl.test cd6c765f75e50e8e2c2ba763149e5d340ea19825
+F test/unixexcl.test d936ba2b06794018e136418addd59a2354eeae97
F test/unordered.test ca7adce0419e4ca0c50f039885e76ed2c531eda8
F test/update.test 6c68446b8a0a33d522a7c72b320934596a2d7d32
F test/uri.test 6630ecbdea2aac10df3c89dbae2243f4c2c353e4
@@ -1306,7 +1309,7 @@ F test/vtab2.test f8cd1bb9aba7143eba97812d9617880a36d247ad
F test/vtab3.test b45f47d20f225ccc9c28dc915d92740c2dee311e
F test/vtab4.test 8e73ed268f3d596bc3590f45fc948fb40f28e9c3
F test/vtab5.test 889f444970393c73f1e077e2bdc5d845e157a391
-F test/vtab6.test d2986cf418dc51e7fb81d12366bea2caa8b812df
+F test/vtab6.test 8e789f526e6594cf7ae933d1adee0caa87dc9f78
F test/vtab7.test ae560ebea870ed04e9aa4177cc302f910faaabb5
F test/vtab8.test e19fa4a538fcd1bb66c22825fa8f71618fb13583
F test/vtab9.test ea58d2b95d61955f87226381716b2d0b1d4e4f9b
@@ -1321,18 +1324,18 @@ F test/vtabI.test 751b07636700dbdea328e4265b6077ccd6811a3f
F test/vtab_alter.test 9e374885248f69e251bdaacf480b04a197f125e5
F test/vtab_err.test 0d4d8eb4def1d053ac7c5050df3024fd47a3fbd8
F test/vtab_shared.test 5253bff2355a9a3f014c15337da7e177ab0ef8ad
-F test/wal.test 0148c8b3421a25fdb4d9c160e84a681d0646371b
-F test/wal2.test 1f841d2048080d32f552942e333fd99ce541dada
+F test/wal.test 613efec03e517e1775d86b993a54877d2e29a477
+F test/wal2.test 25ae059e900dbb584e0775627e45415ba5940df1
F test/wal3.test 5dd734147f1f8f958c5261a1f2775d346d7013ce
F test/wal4.test 4744e155cd6299c6bd99d3eab1c82f77db9cdb3c
-F test/wal5.test 88b5d9a6a3d1532497ee9f4296f010d66f07e33c
+F test/wal5.test 9c11da7aeccd83a46d79a556ad11a18d3cb15aa9
F test/wal6.test a9d6aa635b9d63607dabdc11406f5f96ca986635
F test/wal64k.test 163655ecd2cb8afef4737cac2a40fdd2eeaf20b8
F test/wal7.test 2ae8f427d240099cc4b2dfef63cff44e2a68a1bd
-F test/wal8.test 75c42e1bc4545c277fed212f8fc9b7723cd02216
+F test/wal8.test d9df3fba4caad5854ed69ed673c68482514203c8
F test/wal9.test 378e76a9ad09cd9bee06c172ad3547b0129a6750
F test/wal_common.tcl a98f17fba96206122eff624db0ab13ec377be4fe
-F test/walbak.test b9f68e39646375c2b877be906babcc15d38b4877
+F test/walbak.test 018d4e5a3d45c6298d11b99f09a8ef6876527946
F test/walbig.test f437473a16cfb314867c6b5d1dbcd519e73e3434
F test/walblock.test be48f3a75eff0b4456209f26b3ce186c2015497d
F test/walcksum.test bb234a1bb42248b3515d992b719708015c384278
@@ -1346,12 +1349,12 @@ F test/walnoshm.test 84ca10c544632a756467336b7c3b864d493ee496
F test/waloverwrite.test dad2f26567f1b45174e54fbf9a8dc1cb876a7f03
F test/walpersist.test 8c6b7e3ec1ba91b5e4dc4e0921d6d3f87cd356a6
F test/walprotocol.test 059cb75484a1ecf6357a2c1b3324b8156749221e
-F test/walro.test 34422d1d95aaff0388f0791ec20edb34e2a3ed57
+F test/walro.test 4ab7ac01b77c2f894235c699d59e3e3c7f15a160
F test/walshared.test 0befc811dcf0b287efae21612304d15576e35417
F test/walslow.test c05c68d4dc2700a982f89133ce103a1a84cc285f
F test/walthread.test de8dbaf6d9e41481c460ba31ca61e163d7348f8e
F test/where.test f0c325563acde44f2c4ea6ba348e9e29f7121757
-F test/where2.test af78c55589cbc82d793449493adba0dc3d659f23
+F test/where2.test 478d2170637b9211f593120648858593bf2445a1
F test/where3.test 1ad55ba900bd7747f98b6082e65bd3e442c5004e
F test/where4.test 4a371bfcc607f41d233701bdec33ac2972908ba8
F test/where5.test fdf66f96d29a064b63eb543e28da4dfdccd81ad2
@@ -1388,12 +1391,12 @@ F test/without_rowid5.test 89b1c587bd92a0590e440da33e7666bf4891572a
F test/without_rowid6.test 1f99644e6508447fb050f73697350c7ceca3392e
F test/wordcount.c 2a0a6c0d0e8e8bbbac1f06d72a6791828c37c0cf
F test/zeroblob.test 3857870fe681b8185654414a9bccfde80b62a0fa
-F test/zerodamage.test cf6748bad89553cc1632be51a6f54e487e4039ac
+F test/zerodamage.test 2d725c214b883e25ae6bb85ef228ecdfa03c6a7b
F tool/GetFile.cs a15e08acb5dd7539b75ba23501581d7c2b462cb5
F tool/GetTclKit.bat 629d87562e0487c386db630033931d12d62e6372
F tool/Replace.cs 02c67258801c2fb5f63231e0ac0f220b4b36ba91
F tool/addopcodes.tcl 2b089684eb8b7d0db64cf9d8e6d2fe1b6d279e8d
-F tool/build-all-msvc.bat 55be1cf8545dabd69df2ba6b3de6868da0c26f52 x
+F tool/build-all-msvc.bat 3e4e4043b53f1aede4308e0d2567bbd773614630 x
F tool/build-shell.sh 950f47c6174f1eea171319438b93ba67ff5bf367
F tool/cg_anno.tcl 692ce4b8693d59e3a3de77ca97f4139ecfa641b0 x
F tool/checkSpacing.c 810e51703529a204fc4e1eb060e9ab663e3c06d2
@@ -1474,7 +1477,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 456df3365e2df60e34762f2024bb551538b3f72b b6c4202432dc96f8f1740f52d0bf872116357fcc
-R 2f497816caa21168c1331f3fb71a39ba
+P 17fd8f3cf0ec565e08403dc8e10a1cffc2bbe165 45f7f0c80bd91a0c7ff859c27fd9e82e551bd83e
+R 7b1ff29ad9cf7b5c8ae4f4645405d6a4
U drh
-Z a204fd45fac574847e4285c8445e5721
+Z 05e24502adf6b1cda5add372ab8596b8
diff --git a/manifest.uuid b/manifest.uuid
index 4c042e948..d4116a6ec 100644
--- a/manifest.uuid
+++ b/manifest.uuid
@@ -1 +1 @@
-17fd8f3cf0ec565e08403dc8e10a1cffc2bbe165 \ No newline at end of file
+6a7ee04b0ddac36a87d5ed2ac89a53e537f4d5a3 \ No newline at end of file
diff --git a/src/attach.c b/src/attach.c
index 484a5a110..ea378a40a 100644
--- a/src/attach.c
+++ b/src/attach.c
@@ -161,7 +161,7 @@ static void attachFunc(
#endif
sqlite3BtreeLeave(aNew->pBt);
}
- aNew->safety_level = 3;
+ aNew->safety_level = SQLITE_DEFAULT_SYNCHRONOUS+1;
aNew->zName = sqlite3DbStrDup(db, zName);
if( rc==SQLITE_OK && aNew->zName==0 ){
rc = SQLITE_NOMEM_BKPT;
diff --git a/src/btree.c b/src/btree.c
index 036e63a01..18e6be9f3 100644
--- a/src/btree.c
+++ b/src/btree.c
@@ -2864,9 +2864,25 @@ static int lockBtree(BtShared *pBt){
rc = sqlite3PagerOpenWal(pBt->pPager, &isOpen);
if( rc!=SQLITE_OK ){
goto page1_init_failed;
- }else if( isOpen==0 ){
- releasePage(pPage1);
- return SQLITE_OK;
+ }else{
+#if SQLITE_DEFAULT_SYNCHRONOUS!=SQLITE_DEFAULT_WAL_SYNCHRONOUS
+ sqlite3 *db;
+ Db *pDb;
+ if( (db=pBt->db)!=0 && (pDb=db->aDb)!=0 ){
+ while( pDb->pBt==0 || pDb->pBt->pBt!=pBt ){ pDb++; }
+ if( pDb->bSyncSet==0
+ && pDb->safety_level==SQLITE_DEFAULT_SYNCHRONOUS+1
+ ){
+ pDb->safety_level = SQLITE_DEFAULT_WAL_SYNCHRONOUS+1;
+ sqlite3PagerSetFlags(pBt->pPager,
+ pDb->safety_level | (db->flags & PAGER_FLAGS_MASK));
+ }
+ }
+#endif
+ if( isOpen==0 ){
+ releasePage(pPage1);
+ return SQLITE_OK;
+ }
}
rc = SQLITE_NOTADB;
}
@@ -7556,9 +7572,9 @@ static int balance_nonroot(
** any cell). But it is important to pass the correct size to
** insertCell(), so reparse the cell now.
**
- ** Note that this can never happen in an SQLite data file, as all
- ** cells are at least 4 bytes. It only happens in b-trees used
- ** to evaluate "IN (SELECT ...)" and similar clauses.
+ ** This can only happen for b-trees used to evaluate "IN (SELECT ...)"
+ ** and WITHOUT ROWID tables with exactly one column which is the
+ ** primary key.
*/
if( b.szCell[j]==4 ){
assert(leafCorrection==4);
diff --git a/src/build.c b/src/build.c
index a32dfbd02..e89c74446 100644
--- a/src/build.c
+++ b/src/build.c
@@ -1135,7 +1135,7 @@ char sqlite3AffinityType(const char *zIn, u8 *pszEst){
char aff = SQLITE_AFF_NUMERIC;
const char *zChar = 0;
- if( zIn==0 ) return aff;
+ assert( zIn!=0 );
while( zIn[0] ){
h = (h<<8) + sqlite3UpperToLower[(*zIn)&0xff];
zIn++;
diff --git a/src/expr.c b/src/expr.c
index 8a6973219..3672d02df 100644
--- a/src/expr.c
+++ b/src/expr.c
@@ -1568,23 +1568,22 @@ int sqlite3IsRowid(const char *z){
}
/*
-** Return true if we are able to the IN operator optimization on a
-** query of the form
-**
-** x IN (SELECT ...)
-**
-** Where the SELECT... clause is as specified by the parameter to this
-** routine.
-**
-** The Select object passed in has already been preprocessed and no
-** errors have been found.
+** pX is the RHS of an IN operator. If pX is a SELECT statement
+** that can be simplified to a direct table access, then return
+** a pointer to the SELECT statement. If pX is not a SELECT statement,
+** or if the SELECT statement needs to be manifested into a transient
+** table, then return NULL.
*/
#ifndef SQLITE_OMIT_SUBQUERY
-static int isCandidateForInOpt(Select *p){
+static Select *isCandidateForInOpt(Expr *pX){
+ Select *p;
SrcList *pSrc;
ExprList *pEList;
+ Expr *pRes;
Table *pTab;
- if( p==0 ) return 0; /* right-hand side of IN is SELECT */
+ if( !ExprHasProperty(pX, EP_xIsSelect) ) return 0; /* Not a subquery */
+ if( ExprHasProperty(pX, EP_VarSelect) ) return 0; /* Correlated subq */
+ p = pX->x.pSelect;
if( p->pPrior ) return 0; /* Not a compound SELECT */
if( p->selFlags & (SF_Distinct|SF_Aggregate) ){
testcase( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct );
@@ -1600,13 +1599,15 @@ static int isCandidateForInOpt(Select *p){
if( pSrc->nSrc!=1 ) return 0; /* Single term in FROM clause */
if( pSrc->a[0].pSelect ) return 0; /* FROM is not a subquery or view */
pTab = pSrc->a[0].pTab;
- if( NEVER(pTab==0) ) return 0;
+ assert( pTab!=0 );
assert( pTab->pSelect==0 ); /* FROM clause is not a view */
if( IsVirtual(pTab) ) return 0; /* FROM clause not a virtual table */
pEList = p->pEList;
if( pEList->nExpr!=1 ) return 0; /* One column in the result set */
- if( pEList->a[0].pExpr->op!=TK_COLUMN ) return 0; /* Result is a column */
- return 1;
+ pRes = pEList->a[0].pExpr;
+ if( pRes->op!=TK_COLUMN ) return 0; /* Result is a column */
+ assert( pRes->iTable==pSrc->a[0].iCursor ); /* Not a correlated subquery */
+ return p;
}
#endif /* SQLITE_OMIT_SUBQUERY */
@@ -1738,15 +1739,13 @@ int sqlite3FindInIndex(Parse *pParse, Expr *pX, u32 inFlags, int *prRhsHasNull){
** satisfy the query. This is preferable to generating a new
** ephemeral table.
*/
- p = (ExprHasProperty(pX, EP_xIsSelect) ? pX->x.pSelect : 0);
- if( pParse->nErr==0 && isCandidateForInOpt(p) ){
+ if( pParse->nErr==0 && (p = isCandidateForInOpt(pX))!=0 ){
sqlite3 *db = pParse->db; /* Database connection */
Table *pTab; /* Table <table>. */
Expr *pExpr; /* Expression <column> */
i16 iCol; /* Index of column <column> */
i16 iDb; /* Database idx for pTab */
- assert( p ); /* Because of isCandidateForInOpt(p) */
assert( p->pEList!=0 ); /* Because of isCandidateForInOpt(p) */
assert( p->pEList->a[0].pExpr!=0 ); /* Because of isCandidateForInOpt(p) */
assert( p->pSrc!=0 ); /* Because of isCandidateForInOpt(p) */
diff --git a/src/main.c b/src/main.c
index 422b970cc..40a192e16 100644
--- a/src/main.c
+++ b/src/main.c
@@ -2899,7 +2899,7 @@ static int openDatabase(
** database it is OFF. This matches the pager layer defaults.
*/
db->aDb[0].zName = "main";
- db->aDb[0].safety_level = PAGER_SYNCHRONOUS_FULL;
+ db->aDb[0].safety_level = SQLITE_DEFAULT_SYNCHRONOUS+1;
db->aDb[1].zName = "temp";
db->aDb[1].safety_level = PAGER_SYNCHRONOUS_OFF;
diff --git a/src/memjournal.c b/src/memjournal.c
index 04780df99..b81682de8 100644
--- a/src/memjournal.c
+++ b/src/memjournal.c
@@ -69,7 +69,6 @@ struct MemJournal {
int flags; /* xOpen flags */
sqlite3_vfs *pVfs; /* The "real" underlying VFS */
const char *zJournal; /* Name of the journal file */
- sqlite3_file *pReal; /* The "real" underlying file descriptor */
};
/*
@@ -83,41 +82,42 @@ static int memjrnlRead(
sqlite_int64 iOfst /* Begin reading at this offset */
){
MemJournal *p = (MemJournal *)pJfd;
- if( p->pReal ){
- return sqlite3OsRead(p->pReal, zBuf, iAmt, iOfst);
- }else if( (iAmt+iOfst)>p->endpoint.iOffset ){
+ u8 *zOut = zBuf;
+ int nRead = iAmt;
+ int iChunkOffset;
+ FileChunk *pChunk;
+
+#ifdef SQLITE_ENABLE_ATOMIC_WRITE
+ if( (iAmt+iOfst)>p->endpoint.iOffset ){
return SQLITE_IOERR_SHORT_READ;
- }else{
- u8 *zOut = zBuf;
- int nRead = iAmt;
- int iChunkOffset;
- FileChunk *pChunk;
-
- if( p->readpoint.iOffset!=iOfst || iOfst==0 ){
- sqlite3_int64 iOff = 0;
- for(pChunk=p->pFirst;
- ALWAYS(pChunk) && (iOff+p->nChunkSize)<=iOfst;
- pChunk=pChunk->pNext
- ){
- iOff += p->nChunkSize;
- }
- }else{
- pChunk = p->readpoint.pChunk;
- }
+ }
+#endif
- iChunkOffset = (int)(iOfst%p->nChunkSize);
- do {
- int iSpace = p->nChunkSize - iChunkOffset;
- int nCopy = MIN(nRead, (p->nChunkSize - iChunkOffset));
- memcpy(zOut, (u8*)pChunk->zChunk + iChunkOffset, nCopy);
- zOut += nCopy;
- nRead -= iSpace;
- iChunkOffset = 0;
- } while( nRead>=0 && (pChunk=pChunk->pNext)!=0 && nRead>0 );
- p->readpoint.iOffset = iOfst+iAmt;
- p->readpoint.pChunk = pChunk;
+ assert( (iAmt+iOfst)<=p->endpoint.iOffset );
+ if( p->readpoint.iOffset!=iOfst || iOfst==0 ){
+ sqlite3_int64 iOff = 0;
+ for(pChunk=p->pFirst;
+ ALWAYS(pChunk) && (iOff+p->nChunkSize)<=iOfst;
+ pChunk=pChunk->pNext
+ ){
+ iOff += p->nChunkSize;
+ }
+ }else{
+ pChunk = p->readpoint.pChunk;
}
+ iChunkOffset = (int)(iOfst%p->nChunkSize);
+ do {
+ int iSpace = p->nChunkSize - iChunkOffset;
+ int nCopy = MIN(nRead, (p->nChunkSize - iChunkOffset));
+ memcpy(zOut, (u8*)pChunk->zChunk + iChunkOffset, nCopy);
+ zOut += nCopy;
+ nRead -= iSpace;
+ iChunkOffset = 0;
+ } while( nRead>=0 && (pChunk=pChunk->pNext)!=0 && nRead>0 );
+ p->readpoint.iOffset = iOfst+iAmt;
+ p->readpoint.pChunk = pChunk;
+
return SQLITE_OK;
}
@@ -138,37 +138,37 @@ static void memjrnlFreeChunks(MemJournal *p){
** Flush the contents of memory to a real file on disk.
*/
static int memjrnlCreateFile(MemJournal *p){
- int rc = SQLITE_OK;
- if( !p->pReal ){
- sqlite3_file *pReal = (sqlite3_file *)&p[1];
- rc = sqlite3OsOpen(p->pVfs, p->zJournal, pReal, p->flags, 0);
- if( rc==SQLITE_OK ){
- int nChunk = p->nChunkSize;
- i64 iOff = 0;
- FileChunk *pIter;
- p->pReal = pReal;
- for(pIter=p->pFirst; pIter && rc==SQLITE_OK; pIter=pIter->pNext){
- int nWrite = nChunk;
- if( pIter==p->endpoint.pChunk ){
- nWrite = p->endpoint.iOffset % p->nChunkSize;
- if( nWrite==0 ) nWrite = p->nChunkSize;
- }
- rc = sqlite3OsWrite(pReal, (u8*)pIter->zChunk, nWrite, iOff);
- iOff += nWrite;
- }
- if( rc!=SQLITE_OK ){
- /* If an error occurred while writing to the file, close it before
- ** returning. This way, SQLite uses the in-memory journal data to
- ** roll back changes made to the internal page-cache before this
- ** function was called. */
- sqlite3OsClose(pReal);
- p->pReal = 0;
- }else{
- /* No error has occurred. Free the in-memory buffers. */
- memjrnlFreeChunks(p);
+ int rc;
+ sqlite3_file *pReal = (sqlite3_file*)p;
+ MemJournal copy = *p;
+
+ memset(p, 0, sizeof(MemJournal));
+ rc = sqlite3OsOpen(copy.pVfs, copy.zJournal, pReal, copy.flags, 0);
+ if( rc==SQLITE_OK ){
+ int nChunk = copy.nChunkSize;
+ i64 iOff = 0;
+ FileChunk *pIter;
+ for(pIter=copy.pFirst; pIter; pIter=pIter->pNext){
+ if( iOff + nChunk > copy.endpoint.iOffset ){
+ nChunk = copy.endpoint.iOffset - iOff;
}
+ rc = sqlite3OsWrite(pReal, (u8*)pIter->zChunk, nChunk, iOff);
+ if( rc ) break;
+ iOff += nChunk;
+ }
+ if( rc==SQLITE_OK ){
+ /* No error has occurred. Free the in-memory buffers. */
+ memjrnlFreeChunks(&copy);
}
}
+ if( rc!=SQLITE_OK ){
+ /* If an error occurred while creating or writing to the file, restore
+ ** the original before returning. This way, SQLite uses the in-memory
+ ** journal data to roll back changes made to the internal page-cache
+ ** before this function was called. */
+ sqlite3OsClose(pReal);
+ *p = copy;
+ }
return rc;
}
@@ -186,16 +186,12 @@ static int memjrnlWrite(
int nWrite = iAmt;
u8 *zWrite = (u8 *)zBuf;
- /* If the file has already been created on disk. */
- if( p->pReal ){
- return sqlite3OsWrite(p->pReal, zBuf, iAmt, iOfst);
- }
-
- /* If the file should be created now. */
- else if( p->nSpill>0 && (iAmt+iOfst)>p->nSpill ){
+ /* If the file should be created now, create it and write the new data
+ ** into the file on disk. */
+ if( p->nSpill>0 && (iAmt+iOfst)>p->nSpill ){
int rc = memjrnlCreateFile(p);
if( rc==SQLITE_OK ){
- rc = memjrnlWrite(pJfd, zBuf, iAmt, iOfst);
+ rc = sqlite3OsWrite(pJfd, zBuf, iAmt, iOfst);
}
return rc;
}
@@ -208,10 +204,15 @@ static int memjrnlWrite(
** atomic-write optimization. In this case the first 28 bytes of the
** journal file may be written as part of committing the transaction. */
assert( iOfst==p->endpoint.iOffset || iOfst==0 );
+#ifdef SQLITE_ENABLE_ATOMIC_WRITE
if( iOfst==0 && p->pFirst ){
assert( p->nChunkSize>iAmt );
memcpy((u8*)p->pFirst->zChunk, zBuf, iAmt);
- }else{
+ }else
+#else
+ assert( iOfst>0 || p->pFirst==0 );
+#endif
+ {
while( nWrite>0 ){
FileChunk *pChunk = p->endpoint.pChunk;
int iChunkOffset = (int)(p->endpoint.iOffset%p->nChunkSize);
@@ -255,9 +256,7 @@ static int memjrnlWrite(
*/
static int memjrnlTruncate(sqlite3_file *pJfd, sqlite_int64 size){
MemJournal *p = (MemJournal *)pJfd;
- if( p->pReal ){
- return sqlite3OsTruncate(p->pReal, size);
- }else if( size==0 ){
+ if( ALWAYS(size==0) ){
memjrnlFreeChunks(p);
p->nSize = 0;
p->endpoint.pChunk = 0;
@@ -274,7 +273,6 @@ static int memjrnlTruncate(sqlite3_file *pJfd, sqlite_int64 size){
static int memjrnlClose(sqlite3_file *pJfd){
MemJournal *p = (MemJournal *)pJfd;
memjrnlFreeChunks(p);
- if( p->pReal ) sqlite3OsClose(p->pReal);
return SQLITE_OK;
}
@@ -285,10 +283,7 @@ static int memjrnlClose(sqlite3_file *pJfd){
** syncing an in-memory journal is a no-op.
*/
static int memjrnlSync(sqlite3_file *pJfd, int flags){
- MemJournal *p = (MemJournal *)pJfd;
- if( p->pReal ){
- return sqlite3OsSync(p->pReal, flags);
- }
+ UNUSED_PARAMETER2(pJfd, flags);
return SQLITE_OK;
}
@@ -297,9 +292,6 @@ static int memjrnlSync(sqlite3_file *pJfd, int flags){
*/
static int memjrnlFileSize(sqlite3_file *pJfd, sqlite_int64 *pSize){
MemJournal *p = (MemJournal *)pJfd;
- if( p->pReal ){
- return sqlite3OsFileSize(p->pReal, pSize);
- }
*pSize = (sqlite_int64) p->endpoint.iOffset;
return SQLITE_OK;
}
@@ -354,7 +346,7 @@ int sqlite3JournalOpen(
** it using the sqlite3OsOpen() function of the underlying VFS. In this
** case none of the code in this module is executed as a result of calls
** made on the journal file-handle. */
- memset(p, 0, sizeof(MemJournal) + (pVfs ? pVfs->szOsFile : 0));
+ memset(p, 0, sizeof(MemJournal));
if( nSpill==0 ){
return sqlite3OsOpen(pVfs, zName, pJfd, flags, 0);
}
@@ -403,7 +395,7 @@ int sqlite3JournalCreate(sqlite3_file *p){
** or false otherwise.
*/
int sqlite3JournalIsInMemory(sqlite3_file *p){
- return p->pMethods==&MemJournalMethods && ((MemJournal*)p)->pReal==0;
+ return p->pMethods==&MemJournalMethods;
}
/*
@@ -411,5 +403,5 @@ int sqlite3JournalIsInMemory(sqlite3_file *p){
** pVfs to create the underlying on-disk files.
*/
int sqlite3JournalSize(sqlite3_vfs *pVfs){
- return pVfs->szOsFile + sizeof(MemJournal);
+ return MAX(pVfs->szOsFile, sizeof(MemJournal));
}
diff --git a/src/os_win.c b/src/os_win.c
index af6b1c814..6ff50c554 100644
--- a/src/os_win.c
+++ b/src/os_win.c
@@ -3257,7 +3257,7 @@ static int winFileControl(sqlite3_file *id, int op, void *pArg){
OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
return SQLITE_OK;
}
- case SQLITE_LAST_ERRNO: {
+ case SQLITE_FCNTL_LAST_ERRNO: {
*(int*)pArg = (int)pFile->lastErrno;
OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
return SQLITE_OK;
diff --git a/src/pager.c b/src/pager.c
index f045ce0ef..c18b3a32f 100644
--- a/src/pager.c
+++ b/src/pager.c
@@ -428,19 +428,6 @@ int sqlite3PagerTrace=1; /* True to enable tracing */
*/
#define MAX_SECTOR_SIZE 0x10000
-/*
-** If the option SQLITE_EXTRA_DURABLE option is set at compile-time, then
-** SQLite will do extra fsync() operations when synchronous==FULL to help
-** ensure that transactions are durable across a power failure. Most
-** applications are happy as long as transactions are consistent across
-** a power failure, and are perfectly willing to lose the last transaction
-** in exchange for the extra performance of avoiding directory syncs.
-** And so the default SQLITE_EXTRA_DURABLE setting is off.
-*/
-#ifndef SQLITE_EXTRA_DURABLE
-# define SQLITE_EXTRA_DURABLE 0
-#endif
-
/*
** An instance of the following structure is allocated for each active
@@ -3460,7 +3447,7 @@ void sqlite3PagerShrink(Pager *pPager){
** The "level" in pgFlags & PAGER_SYNCHRONOUS_MASK sets the robustness
** of the database to damage due to OS crashes or power failures by
** changing the number of syncs()s when writing the journals.
-** There are three levels:
+** There are four levels:
**
** OFF sqlite3OsSync() is never called. This is the default
** for temporary and transient files.
@@ -3480,6 +3467,10 @@ void sqlite3PagerShrink(Pager *pPager){
** assurance that the journal will not be corrupted to the
** point of causing damage to the database during rollback.
**
+** EXTRA This is like FULL except that is also syncs the directory
+** that contains the rollback journal after the rollback
+** journal is unlinked.
+**
** The above is for a rollback-journal mode. For WAL mode, OFF continues
** to mean that no syncs ever occur. NORMAL means that the WAL is synced
** prior to the start of checkpoint and that the database file is synced
@@ -3487,7 +3478,8 @@ void sqlite3PagerShrink(Pager *pPager){
** was written back into the database. But no sync operations occur for
** an ordinary commit in NORMAL mode with WAL. FULL means that the WAL
** file is synced following each commit operation, in addition to the
-** syncs associated with NORMAL.
+** syncs associated with NORMAL. There is no difference between FULL
+** and EXTRA for WAL mode.
**
** Do not confuse synchronous=FULL with SQLITE_SYNC_FULL. The
** SQLITE_SYNC_FULL macro means to use the MacOSX-style full-fsync
@@ -4818,11 +4810,7 @@ act_like_temp_file:
assert( pPager->ckptSyncFlags==0 );
}else{
pPager->fullSync = 1;
-#if SQLITE_EXTRA_DURABLE
- pPager->extraSync = 1;
-#else
pPager->extraSync = 0;
-#endif
pPager->syncFlags = SQLITE_SYNC_NORMAL;
pPager->walSyncFlags = SQLITE_SYNC_NORMAL | WAL_SYNC_TRANSACTIONS;
pPager->ckptSyncFlags = SQLITE_SYNC_NORMAL;
@@ -7179,6 +7167,7 @@ int sqlite3PagerWalCallback(Pager *pPager){
*/
int sqlite3PagerWalSupported(Pager *pPager){
const sqlite3_io_methods *pMethods = pPager->fd->pMethods;
+ if( pPager->noLock ) return 0;
return pPager->exclusiveMode || (pMethods->iVersion>=2 && pMethods->xShmMap);
}
diff --git a/src/pragma.c b/src/pragma.c
index 1d6291431..70c2950c8 100644
--- a/src/pragma.c
+++ b/src/pragma.c
@@ -993,6 +993,7 @@ void sqlite3Pragma(
int iLevel = (getSafetyLevel(zRight,0,1)+1) & PAGER_SYNCHRONOUS_MASK;
if( iLevel==0 ) iLevel = 1;
pDb->safety_level = iLevel;
+ pDb->bSyncSet = 1;
setAllPagerFlags(db);
}
}
@@ -1438,6 +1439,7 @@ void sqlite3Pragma(
for(i=0; i<db->nDb; i++){
HashElem *x;
Hash *pTbls;
+ int *aRoot;
int cnt = 0;
if( OMIT_TEMPDB && i==1 ) continue;
@@ -1451,31 +1453,34 @@ void sqlite3Pragma(
/* Do an integrity check of the B-Tree
**
- ** Begin by filling registers 2, 3, ... with the root pages numbers
+ ** Begin by finding the root pages numbers
** for all tables and indices in the database.
*/
assert( sqlite3SchemaMutexHeld(db, i, 0) );
pTbls = &db->aDb[i].pSchema->tblHash;
- for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){
+ for(cnt=0, x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){
Table *pTab = sqliteHashData(x);
Index *pIdx;
- if( HasRowid(pTab) ){
- sqlite3VdbeAddOp2(v, OP_Integer, pTab->tnum, 2+cnt);
- VdbeComment((v, "%s", pTab->zName));
- cnt++;
- }
+ if( HasRowid(pTab) ) cnt++;
+ for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ cnt++; }
+ }
+ aRoot = sqlite3DbMallocRawNN(db, sizeof(int)*(cnt+1));
+ if( aRoot==0 ) break;
+ for(cnt=0, x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){
+ Table *pTab = sqliteHashData(x);
+ Index *pIdx;
+ if( HasRowid(pTab) ) aRoot[cnt++] = pTab->tnum;
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
- sqlite3VdbeAddOp2(v, OP_Integer, pIdx->tnum, 2+cnt);
- VdbeComment((v, "%s", pIdx->zName));
- cnt++;
+ aRoot[cnt++] = pIdx->tnum;
}
}
+ aRoot[cnt] = 0;
/* Make sure sufficient number of registers have been allocated */
- pParse->nMem = MAX( pParse->nMem, cnt+8 );
+ pParse->nMem = MAX( pParse->nMem, 14 );
/* Do the b-tree integrity checks */
- sqlite3VdbeAddOp3(v, OP_IntegrityCk, 2, cnt, 1);
+ sqlite3VdbeAddOp4(v, OP_IntegrityCk, 2, cnt, 1, (char*)aRoot,P4_INTARRAY);
sqlite3VdbeChangeP5(v, (u8)i);
addr = sqlite3VdbeAddOp1(v, OP_IsNull, 2); VdbeCoverage(v);
sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0,
diff --git a/src/select.c b/src/select.c
index c9bc389b2..a62581efc 100644
--- a/src/select.c
+++ b/src/select.c
@@ -4970,10 +4970,24 @@ int sqlite3Select(
}
/* Generate code to implement the subquery
+ **
+ ** The subquery is implemented as a co-routine if all of these are true:
+ ** (1) The subquery is guaranteed to be the outer loop (so that it
+ ** does not need to be computed more than once)
+ ** (2) The ALL keyword after SELECT is omitted. (Applications are
+ ** allowed to say "SELECT ALL" instead of just "SELECT" to disable
+ ** the use of co-routines.)
+ ** (3) Co-routines are not disabled using sqlite3_test_control()
+ ** with SQLITE_TESTCTRL_OPTIMIZATIONS.
+ **
+ ** TODO: Are there other reasons beside (1) to use a co-routine
+ ** implementation?
*/
- if( pTabList->nSrc==1
- && (p->selFlags & SF_All)==0
- && OptimizationEnabled(db, SQLITE_SubqCoroutine)
+ if( i==0
+ && (pTabList->nSrc==1
+ || (pTabList->a[1].fg.jointype&(JT_LEFT|JT_CROSS))!=0) /* (1) */
+ && (p->selFlags & SF_All)==0 /* (2) */
+ && OptimizationEnabled(db, SQLITE_SubqCoroutine) /* (3) */
){
/* Implement a co-routine that will return a single row of the result
** set on each invocation.
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index e1e37b61d..de357537e 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -452,6 +452,13 @@
#endif
/*
+** SQLITE_ENABLE_EXPLAIN_COMMENTS is incompatible with SQLITE_OMIT_EXPLAIN
+*/
+#ifdef SQLITE_OMIT_EXPLAIN
+# undef SQLITE_ENABLE_EXPLAIN_COMMENTS
+#endif
+
+/*
** Return true (non-zero) if the input is an integer that is too large
** to fit in 32-bits. This macro is used inside of various testcase()
** macros to verify that we have tested SQLite for large-file support.
@@ -1003,10 +1010,39 @@ typedef struct With With;
#include "vdbe.h"
#include "pager.h"
#include "pcache.h"
-
#include "os.h"
#include "mutex.h"
+/* The SQLITE_EXTRA_DURABLE compile-time option used to set the default
+** synchronous setting to EXTRA. It is no longer supported.
+*/
+#ifdef SQLITE_EXTRA_DURABLE
+# warning Use SQLITE_DEFAULT_SYNCHRONOUS=3 instead of SQLITE_EXTRA_DURABLE
+# define SQLITE_DEFAULT_SYNCHRONOUS 3
+#endif
+
+/*
+** Default synchronous levels.
+**
+** Note that (for historcal reasons) the PAGER_SYNCHRONOUS_* macros differ
+** from the SQLITE_DEFAULT_SYNCHRONOUS value by 1.
+**
+** PAGER_SYNCHRONOUS DEFAULT_SYNCHRONOUS
+** OFF 1 0
+** NORMAL 2 1
+** FULL 3 2
+** EXTRA 4 3
+**
+** The "PRAGMA synchronous" statement also uses the zero-based numbers.
+** In other words, the zero-based numbers are used for all external interfaces
+** and the one-based values are used internally.
+*/
+#ifndef SQLITE_DEFAULT_SYNCHRONOUS
+# define SQLITE_DEFAULT_SYNCHRONOUS (PAGER_SYNCHRONOUS_FULL-1)
+#endif
+#ifndef SQLITE_DEFAULT_WAL_SYNCHRONOUS
+# define SQLITE_DEFAULT_WAL_SYNCHRONOUS SQLITE_DEFAULT_SYNCHRONOUS
+#endif
/*
** Each database file to be accessed by the system is an instance
@@ -1019,6 +1055,7 @@ struct Db {
char *zName; /* Name of this database */
Btree *pBt; /* The B*Tree structure for this database file */
u8 safety_level; /* How aggressive at syncing data to disk */
+ u8 bSyncSet; /* True if "PRAGMA synchronous=N" has been run */
Schema *pSchema; /* Pointer to database schema (possibly shared) */
};
@@ -2361,6 +2398,7 @@ struct IdList {
*/
#define MASKBIT(n) (((Bitmask)1)<<(n))
#define MASKBIT32(n) (((unsigned int)1)<<(n))
+#define ALLBITS ((Bitmask)-1)
/*
** The following structure describes the FROM clause of a SELECT statement.
diff --git a/src/tclsqlite.c b/src/tclsqlite.c
index 164664a6e..96b5691f1 100644
--- a/src/tclsqlite.c
+++ b/src/tclsqlite.c
@@ -2659,7 +2659,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
** Change the encryption key on the currently open database.
*/
case DB_REKEY: {
-#ifdef SQLITE_HAS_CODEC
+#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_CODEC_FROM_TCL)
int nKey;
void *pKey;
#endif
@@ -2667,7 +2667,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
Tcl_WrongNumArgs(interp, 2, objv, "KEY");
return TCL_ERROR;
}
-#ifdef SQLITE_HAS_CODEC
+#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_CODEC_FROM_TCL)
pKey = Tcl_GetByteArrayFromObj(objv[2], &nKey);
rc = sqlite3_rekey(pDb->db, pKey, nKey);
if( rc ){
@@ -3101,7 +3101,7 @@ static int DbMain(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
const char *zVfs = 0;
int flags;
Tcl_DString translatedFilename;
-#ifdef SQLITE_HAS_CODEC
+#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_CODEC_FROM_TCL)
void *pKey = 0;
int nKey = 0;
#endif
@@ -3130,7 +3130,7 @@ static int DbMain(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
return TCL_OK;
}
if( strcmp(zArg,"-has-codec")==0 ){
-#ifdef SQLITE_HAS_CODEC
+#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_CODEC_FROM_TCL)
Tcl_AppendResult(interp,"1",(char*)0);
#else
Tcl_AppendResult(interp,"0",(char*)0);
@@ -3141,7 +3141,7 @@ static int DbMain(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
for(i=3; i+1<objc; i+=2){
zArg = Tcl_GetString(objv[i]);
if( strcmp(zArg,"-key")==0 ){
-#ifdef SQLITE_HAS_CODEC
+#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_CODEC_FROM_TCL)
pKey = Tcl_GetByteArrayFromObj(objv[i+1], &nKey);
#endif
}else if( strcmp(zArg, "-vfs")==0 ){
@@ -3199,7 +3199,7 @@ static int DbMain(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
Tcl_WrongNumArgs(interp, 1, objv,
"HANDLE FILENAME ?-vfs VFSNAME? ?-readonly BOOLEAN? ?-create BOOLEAN?"
" ?-nomutex BOOLEAN? ?-fullmutex BOOLEAN? ?-uri BOOLEAN?"
-#ifdef SQLITE_HAS_CODEC
+#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_CODEC_FROM_TCL)
" ?-key CODECKEY?"
#endif
);
@@ -3225,7 +3225,7 @@ static int DbMain(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
}else{
zErrMsg = sqlite3_mprintf("%s", sqlite3_errstr(rc));
}
-#ifdef SQLITE_HAS_CODEC
+#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_CODEC_FROM_TCL)
if( p->db ){
sqlite3_key(p->db, pKey, nKey);
}
diff --git a/src/test1.c b/src/test1.c
index 744b400b2..8ad653ca6 100644
--- a/src/test1.c
+++ b/src/test1.c
@@ -651,7 +651,7 @@ static int test_key(
int argc, /* Number of arguments */
char **argv /* Text of each argument */
){
-#ifdef SQLITE_HAS_CODEC
+#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_CODEC_FROM_TCL)
sqlite3 *db;
const char *zKey;
int nKey;
diff --git a/src/update.c b/src/update.c
index 1e6cb83b4..c147eaaad 100644
--- a/src/update.c
+++ b/src/update.c
@@ -268,7 +268,7 @@ void sqlite3Update(
** case, set all bits of the colUsed mask (to ensure that the virtual
** table implementation makes all columns available).
*/
- pTabList->a[0].colUsed = IsVirtual(pTab) ? (Bitmask)-1 : 0;
+ pTabList->a[0].colUsed = IsVirtual(pTab) ? ALLBITS : 0;
hasFK = sqlite3FkRequired(pParse, pTab, aXRef, chngKey);
diff --git a/src/util.c b/src/util.c
index 6aead47fa..d6a6f6b95 100644
--- a/src/util.c
+++ b/src/util.c
@@ -1424,9 +1424,14 @@ u64 sqlite3LogEstToInt(LogEst x){
x /= 10;
if( n>=5 ) n -= 2;
else if( n>=1 ) n -= 1;
- if( x>=3 ){
- return x>60 ? (u64)LARGEST_INT64 : (n+8)<<(x-3);
- }
- return (n+8)>>(3-x);
+#if defined(SQLITE_ENABLE_STMT_SCANSTATUS) || \
+ defined(SQLITE_EXPLAIN_ESTIMATED_ROWS)
+ if( x>60 ) return (u64)LARGEST_INT64;
+#else
+ /* If only SQLITE_ENABLE_STAT3_OR_STAT4 is on, then the largest input
+ ** possible to this routine is 310, resulting in a maximum x of 31 */
+ assert( x<=60 );
+#endif
+ return x>=3 ? (n+8)<<(x-3) : (n+8)>>(3-x);
}
#endif /* defined SCANSTAT or STAT4 or ESTIMATED_ROWS */
diff --git a/src/vdbe.c b/src/vdbe.c
index 7a47ef8b8..2757a624e 100644
--- a/src/vdbe.c
+++ b/src/vdbe.c
@@ -5482,7 +5482,7 @@ case OP_DropTrigger: {
#ifndef SQLITE_OMIT_INTEGRITY_CHECK
-/* Opcode: IntegrityCk P1 P2 P3 * P5
+/* Opcode: IntegrityCk P1 P2 P3 P4 P5
**
** Do an analysis of the currently open database. Store in
** register P1 the text of an error message describing any problems.
@@ -5493,9 +5493,8 @@ case OP_DropTrigger: {
** In other words, the analysis stops as soon as reg(P1) errors are
** seen. Reg(P1) is updated with the number of errors remaining.
**
-** The root page numbers of all tables in the database are integer
-** stored in reg(P1), reg(P1+1), reg(P1+2), .... There are P2 tables
-** total.
+** The root page numbers of all tables in the database are integers
+** stored in P4_INTARRAY argument.
**
** If P5 is not zero, the check is done on the auxiliary database
** file, not the main database file.
@@ -5505,30 +5504,24 @@ case OP_DropTrigger: {
case OP_IntegrityCk: {
int nRoot; /* Number of tables to check. (Number of root pages.) */
int *aRoot; /* Array of rootpage numbers for tables to be checked */
- int j; /* Loop counter */
int nErr; /* Number of errors reported */
char *z; /* Text of the error report */
Mem *pnErr; /* Register keeping track of errors remaining */
assert( p->bIsReader );
nRoot = pOp->p2;
+ aRoot = pOp->p4.ai;
assert( nRoot>0 );
- aRoot = sqlite3DbMallocRawNN(db, sizeof(int)*(nRoot+1) );
- if( aRoot==0 ) goto no_mem;
+ assert( aRoot[nRoot]==0 );
assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) );
pnErr = &aMem[pOp->p3];
assert( (pnErr->flags & MEM_Int)!=0 );
assert( (pnErr->flags & (MEM_Str|MEM_Blob))==0 );
pIn1 = &aMem[pOp->p1];
- for(j=0; j<nRoot; j++){
- aRoot[j] = (int)sqlite3VdbeIntValue(&pIn1[j]);
- }
- aRoot[j] = 0;
assert( pOp->p5<db->nDb );
assert( DbMaskTest(p->btreeMask, pOp->p5) );
z = sqlite3BtreeIntegrityCheck(db->aDb[pOp->p5].pBt, aRoot, nRoot,
(int)pnErr->u.i, &nErr);
- sqlite3DbFree(db, aRoot);
pnErr->u.i -= nErr;
sqlite3VdbeMemSetNull(pIn1);
if( nErr==0 ){
diff --git a/src/vdbeInt.h b/src/vdbeInt.h
index 448163302..1218009d0 100644
--- a/src/vdbeInt.h
+++ b/src/vdbeInt.h
@@ -381,16 +381,16 @@ struct Vdbe {
#endif
u16 nResColumn; /* Number of columns in one row of the result set */
u8 errorAction; /* Recovery action to do in case of an error */
+ bft expired:1; /* True if the VM needs to be recompiled */
+ bft doingRerun:1; /* True if rerunning after an auto-reprepare */
u8 minWriteFileFormat; /* Minimum file format for writable database files */
bft explain:2; /* True if EXPLAIN present on SQL command */
bft changeCntOn:1; /* True to update the change-counter */
- bft expired:1; /* True if the VM needs to be recompiled */
bft runOnlyOnce:1; /* Automatically expire on reset */
bft usesStmtJournal:1; /* True if uses a statement journal */
bft readOnly:1; /* True for statements that do not write */
bft bIsReader:1; /* True for statements that read */
bft isPrepareV2:1; /* True if prepared with prepare_v2() */
- bft doingRerun:1; /* True if rerunning after an auto-reprepare */
int nChange; /* Number of db changes made since last reset */
yDbMask btreeMask; /* Bitmask of db->aDb[] entries referenced */
yDbMask lockMask; /* Subset of btreeMask that requires a lock */
diff --git a/src/where.c b/src/where.c
index ea62617c5..83d72ee39 100644
--- a/src/where.c
+++ b/src/where.c
@@ -934,7 +934,6 @@ static sqlite3_index_info *allocateIndexInfo(
*/
static int vtabBestIndex(Parse *pParse, Table *pTab, sqlite3_index_info *p){
sqlite3_vtab *pVtab = sqlite3GetVTable(pParse->db, pTab)->pVtab;
- int i;
int rc;
TRACE_IDX_INPUTS(p);
@@ -953,12 +952,16 @@ static int vtabBestIndex(Parse *pParse, Table *pTab, sqlite3_index_info *p){
sqlite3_free(pVtab->zErrMsg);
pVtab->zErrMsg = 0;
+#if 0
+ /* This error is now caught by the caller.
+ ** Search for "xBestIndex malfunction" below */
for(i=0; i<p->nConstraint; i++){
if( !p->aConstraint[i].usable && p->aConstraintUsage[i].argvIndex>0 ){
sqlite3ErrorMsg(pParse,
"table %s: xBestIndex returned an invalid plan", pTab->zName);
}
}
+#endif
return pParse->nErr;
}
@@ -1976,6 +1979,7 @@ static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){
WhereLoop **ppPrev, *p;
WhereInfo *pWInfo = pBuilder->pWInfo;
sqlite3 *db = pWInfo->pParse->db;
+ int rc;
/* If pBuilder->pOrSet is defined, then only keep track of the costs
** and prereqs.
@@ -2058,14 +2062,14 @@ static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){
whereLoopDelete(db, pToDel);
}
}
- whereLoopXfer(db, p, pTemplate);
+ rc = whereLoopXfer(db, p, pTemplate);
if( (p->wsFlags & WHERE_VIRTUALTABLE)==0 ){
Index *pIndex = p->u.btree.pIndex;
if( pIndex && pIndex->tnum==0 ){
p->u.btree.pIndex = 0;
}
}
- return SQLITE_OK;
+ return rc;
}
/*
@@ -2554,7 +2558,7 @@ static int whereUsablePartialIndex(int iTab, WhereClause *pWC, Expr *pWhere){
*/
static int whereLoopAddBtree(
WhereLoopBuilder *pBuilder, /* WHERE clause information */
- Bitmask mExtra /* Extra prerequesites for using this table */
+ Bitmask mPrereq /* Extra prerequesites for using this table */
){
WhereInfo *pWInfo; /* WHERE analysis context */
Index *pProbe; /* An index we are evaluating */
@@ -2654,7 +2658,7 @@ static int whereLoopAddBtree(
pNew->nOut = 43; assert( 43==sqlite3LogEst(20) );
pNew->rRun = sqlite3LogEstAdd(rLogSize,pNew->nOut);
pNew->wsFlags = WHERE_AUTO_INDEX;
- pNew->prereq = mExtra | pTerm->prereqRight;
+ pNew->prereq = mPrereq | pTerm->prereqRight;
rc = whereLoopInsert(pBuilder, pNew);
}
}
@@ -2675,7 +2679,7 @@ static int whereLoopAddBtree(
pNew->nLTerm = 0;
pNew->iSortIdx = 0;
pNew->rSetup = 0;
- pNew->prereq = mExtra;
+ pNew->prereq = mPrereq;
pNew->nOut = rSize;
pNew->u.btree.pIndex = pProbe;
b = indexMightHelpWithOrderBy(pBuilder, pProbe, pSrc->iCursor);
@@ -2762,7 +2766,7 @@ static int whereLoopAddBtree(
** * It is not one of the operators specified in the mExclude mask passed
** as the fourth argument (which in practice is either WO_IN or 0).
**
-** Argument mExtra is a mask of tables that must be scanned before the
+** Argument mPrereq is a mask of tables that must be scanned before the
** virtual table in question. These are added to the plans prerequisites
** before it is added to pBuilder.
**
@@ -2771,9 +2775,9 @@ static int whereLoopAddBtree(
*/
static int whereLoopAddVirtualOne(
WhereLoopBuilder *pBuilder,
- Bitmask mExtra, /* Mask of tables that must be used. */
- Bitmask mUsable, /* Mask of usable prereqs */
- u16 mExclude, /* Exclude terms for this operator */
+ Bitmask mPrereq, /* Mask of tables that must be used. */
+ Bitmask mUsable, /* Mask of usable tables */
+ u16 mExclude, /* Exclude terms using these operators */
sqlite3_index_info *pIdxInfo, /* Populated object for xBestIndex */
int *pbIn /* OUT: True if plan uses an IN(...) op */
){
@@ -2788,9 +2792,9 @@ static int whereLoopAddVirtualOne(
struct SrcList_item *pSrc = &pBuilder->pWInfo->pTabList->a[pNew->iTab];
int nConstraint = pIdxInfo->nConstraint;
- assert( (mUsable & mExtra)==mExtra );
+ assert( (mUsable & mPrereq)==mPrereq );
*pbIn = 0;
- pNew->prereq = mExtra;
+ pNew->prereq = mPrereq;
/* Set the usable flag on the subset of constraints identified by
** arguments mUsable and mExclude. */
@@ -2807,10 +2811,9 @@ static int whereLoopAddVirtualOne(
/* Initialize the output fields of the sqlite3_index_info structure */
memset(pUsage, 0, sizeof(pUsage[0])*nConstraint);
- if( pIdxInfo->needToFreeIdxStr ) sqlite3_free(pIdxInfo->idxStr);
+ assert( pIdxInfo->needToFreeIdxStr==0 );
pIdxInfo->idxStr = 0;
pIdxInfo->idxNum = 0;
- pIdxInfo->needToFreeIdxStr = 0;
pIdxInfo->orderByConsumed = 0;
pIdxInfo->estimatedCost = SQLITE_BIG_DBL / (double)2;
pIdxInfo->estimatedRows = 25;
@@ -2835,9 +2838,10 @@ static int whereLoopAddVirtualOne(
|| j<0
|| j>=pWC->nTerm
|| pNew->aLTerm[iTerm]!=0
+ || pIdxCons->usable==0
){
rc = SQLITE_ERROR;
- sqlite3ErrorMsg(pParse,"%s.xBestIndex() malfunction",pSrc->pTab->zName);
+ sqlite3ErrorMsg(pParse,"%s.xBestIndex malfunction",pSrc->pTab->zName);
return rc;
}
testcase( iTerm==nConstraint-1 );
@@ -2859,7 +2863,7 @@ static int whereLoopAddVirtualOne(
** together. */
pIdxInfo->orderByConsumed = 0;
pIdxInfo->idxFlags &= ~SQLITE_INDEX_SCAN_UNIQUE;
- *pbIn = 1;
+ *pbIn = 1; assert( (mExclude & WO_IN)==0 );
}
}
}
@@ -2883,13 +2887,16 @@ static int whereLoopAddVirtualOne(
}else{
pNew->wsFlags &= ~WHERE_ONEROW;
}
- whereLoopInsert(pBuilder, pNew);
+ rc = whereLoopInsert(pBuilder, pNew);
if( pNew->u.vtab.needFree ){
sqlite3_free(pNew->u.vtab.idxStr);
pNew->u.vtab.needFree = 0;
}
+ WHERETRACE(0xffff, (" bIn=%d prereqIn=%04llx prereqOut=%04llx\n",
+ *pbIn, (sqlite3_uint64)mPrereq,
+ (sqlite3_uint64)(pNew->prereq & ~mPrereq)));
- return SQLITE_OK;
+ return rc;
}
@@ -2897,8 +2904,8 @@ static int whereLoopAddVirtualOne(
** Add all WhereLoop objects for a table of the join identified by
** pBuilder->pNew->iTab. That table is guaranteed to be a virtual table.
**
-** If there are no LEFT or CROSS JOIN joins in the query, both mExtra and
-** mUnusable are set to 0. Otherwise, mExtra is a mask of all FROM clause
+** If there are no LEFT or CROSS JOIN joins in the query, both mPrereq and
+** mUnusable are set to 0. Otherwise, mPrereq is a mask of all FROM clause
** entries that occur before the virtual table in the FROM clause and are
** separated from it by at least one LEFT or CROSS JOIN. Similarly, the
** mUnusable mask contains all FROM clause entries that occur after the
@@ -2909,18 +2916,18 @@ static int whereLoopAddVirtualOne(
**
** ... FROM t1, t2 LEFT JOIN t3, t4, vt CROSS JOIN t5, t6;
**
-** then mExtra corresponds to (t1, t2) and mUnusable to (t5, t6).
+** then mPrereq corresponds to (t1, t2) and mUnusable to (t5, t6).
**
-** All the tables in mExtra must be scanned before the current virtual
+** All the tables in mPrereq must be scanned before the current virtual
** table. So any terms for which all prerequisites are satisfied by
-** mExtra may be specified as "usable" in all calls to xBestIndex.
+** mPrereq may be specified as "usable" in all calls to xBestIndex.
** Conversely, all tables in mUnusable must be scanned after the current
** virtual table, so any terms for which the prerequisites overlap with
** mUnusable should always be configured as "not-usable" for xBestIndex.
*/
static int whereLoopAddVirtual(
WhereLoopBuilder *pBuilder, /* WHERE clause information */
- Bitmask mExtra, /* Tables that must be scanned before this one */
+ Bitmask mPrereq, /* Tables that must be scanned before this one */
Bitmask mUnusable /* Tables that must be scanned after this one */
){
int rc = SQLITE_OK; /* Return code */
@@ -2934,14 +2941,14 @@ static int whereLoopAddVirtual(
WhereLoop *pNew;
Bitmask mBest; /* Tables used by best possible plan */
- assert( (mExtra & mUnusable)==0 );
+ assert( (mPrereq & mUnusable)==0 );
pWInfo = pBuilder->pWInfo;
pParse = pWInfo->pParse;
pWC = pBuilder->pWC;
pNew = pBuilder->pNew;
pSrc = &pWInfo->pTabList->a[pNew->iTab];
assert( IsVirtual(pSrc->pTab) );
- p = allocateIndexInfo(pParse, pWC, mUnusable, pSrc,pBuilder->pOrderBy);
+ p = allocateIndexInfo(pParse, pWC, mUnusable, pSrc, pBuilder->pOrderBy);
if( p==0 ) return SQLITE_NOMEM_BKPT;
pNew->rSetup = 0;
pNew->wsFlags = WHERE_VIRTUALTABLE;
@@ -2954,15 +2961,15 @@ static int whereLoopAddVirtual(
}
/* First call xBestIndex() with all constraints usable. */
- rc = whereLoopAddVirtualOne(pBuilder, mExtra, (Bitmask)(-1), 0, p, &bIn);
- mBest = pNew->prereq & ~mExtra;
+ WHERETRACE(0x40, (" VirtualOne: all usable\n"));
+ rc = whereLoopAddVirtualOne(pBuilder, mPrereq, ALLBITS, 0, p, &bIn);
/* If the call to xBestIndex() with all terms enabled produced a plan
- ** that does not require any source tables, there is no point in making
- ** any further calls - if the xBestIndex() method is sane they will all
- ** return the same plan anyway.
- */
- if( mBest ){
+ ** that does not require any source tables (IOW: a plan with mBest==0),
+ ** then there is no point in making any further calls to xBestIndex()
+ ** since they will all return the same result (if the xBestIndex()
+ ** implementation is sane). */
+ if( rc==SQLITE_OK && (mBest = (pNew->prereq & ~mPrereq))!=0 ){
int seenZero = 0; /* True if a plan with no prereqs seen */
int seenZeroNoIN = 0; /* Plan with no prereqs and no IN(...) seen */
Bitmask mPrev = 0;
@@ -2970,32 +2977,36 @@ static int whereLoopAddVirtual(
/* If the plan produced by the earlier call uses an IN(...) term, call
** xBestIndex again, this time with IN(...) terms disabled. */
- if( rc==SQLITE_OK && bIn ){
- rc = whereLoopAddVirtualOne(pBuilder, mExtra, (Bitmask)-1, WO_IN, p,&bIn);
- mBestNoIn = pNew->prereq & ~mExtra;
+ if( bIn ){
+ WHERETRACE(0x40, (" VirtualOne: all usable w/o IN\n"));
+ rc = whereLoopAddVirtualOne(pBuilder, mPrereq, ALLBITS, WO_IN, p, &bIn);
+ assert( bIn==0 );
+ mBestNoIn = pNew->prereq & ~mPrereq;
if( mBestNoIn==0 ){
seenZero = 1;
- if( bIn==0 ) seenZeroNoIN = 1;
+ seenZeroNoIN = 1;
}
}
- /* Call xBestIndex once for each distinct value of (prereqRight & ~mExtra)
+ /* Call xBestIndex once for each distinct value of (prereqRight & ~mPrereq)
** in the set of terms that apply to the current virtual table. */
while( rc==SQLITE_OK ){
int i;
- Bitmask mNext = (Bitmask)(-1);
+ Bitmask mNext = ALLBITS;
assert( mNext>0 );
for(i=0; i<nConstraint; i++){
Bitmask mThis = (
- pWC->a[p->aConstraint[i].iTermOffset].prereqRight & ~mExtra
+ pWC->a[p->aConstraint[i].iTermOffset].prereqRight & ~mPrereq
);
if( mThis>mPrev && mThis<mNext ) mNext = mThis;
}
mPrev = mNext;
- if( mNext==(Bitmask)(-1) ) break;
+ if( mNext==ALLBITS ) break;
if( mNext==mBest || mNext==mBestNoIn ) continue;
- rc = whereLoopAddVirtualOne(pBuilder, mExtra, mNext|mExtra, 0, p, &bIn);
- if( pNew->prereq==mExtra ){
+ WHERETRACE(0x40, (" VirtualOne: mPrev=%04llx mNext=%04llx\n",
+ (sqlite3_uint64)mPrev, (sqlite3_uint64)mNext));
+ rc = whereLoopAddVirtualOne(pBuilder, mPrereq, mNext|mPrereq, 0, p, &bIn);
+ if( pNew->prereq==mPrereq ){
seenZero = 1;
if( bIn==0 ) seenZeroNoIN = 1;
}
@@ -3005,7 +3016,8 @@ static int whereLoopAddVirtual(
** that requires no source tables at all (i.e. one guaranteed to be
** usable), make a call here with all source tables disabled */
if( rc==SQLITE_OK && seenZero==0 ){
- rc = whereLoopAddVirtualOne(pBuilder, mExtra, mExtra, 0, p, &bIn);
+ WHERETRACE(0x40, (" VirtualOne: all disabled\n"));
+ rc = whereLoopAddVirtualOne(pBuilder, mPrereq, mPrereq, 0, p, &bIn);
if( bIn==0 ) seenZeroNoIN = 1;
}
@@ -3013,7 +3025,8 @@ static int whereLoopAddVirtual(
** that requires no source tables at all and does not use an IN(...)
** operator, make a final call to obtain one here. */
if( rc==SQLITE_OK && seenZeroNoIN==0 ){
- rc = whereLoopAddVirtualOne(pBuilder, mExtra, mExtra, WO_IN, p, &bIn);
+ WHERETRACE(0x40, (" VirtualOne: all disabled and w/o IN\n"));
+ rc = whereLoopAddVirtualOne(pBuilder, mPrereq, mPrereq, WO_IN, p, &bIn);
}
}
@@ -3029,7 +3042,7 @@ static int whereLoopAddVirtual(
*/
static int whereLoopAddOr(
WhereLoopBuilder *pBuilder,
- Bitmask mExtra,
+ Bitmask mPrereq,
Bitmask mUnusable
){
WhereInfo *pWInfo = pBuilder->pWInfo;
@@ -3090,14 +3103,14 @@ static int whereLoopAddOr(
#endif
#ifndef SQLITE_OMIT_VIRTUALTABLE
if( IsVirtual(pItem->pTab) ){
- rc = whereLoopAddVirtual(&sSubBuild, mExtra, mUnusable);
+ rc = whereLoopAddVirtual(&sSubBuild, mPrereq, mUnusable);
}else
#endif
{
- rc = whereLoopAddBtree(&sSubBuild, mExtra);
+ rc = whereLoopAddBtree(&sSubBuild, mPrereq);
}
if( rc==SQLITE_OK ){
- rc = whereLoopAddOr(&sSubBuild, mExtra, mUnusable);
+ rc = whereLoopAddOr(&sSubBuild, mPrereq, mUnusable);
}
assert( rc==SQLITE_OK || sCur.n==0 );
if( sCur.n==0 ){
@@ -3154,7 +3167,7 @@ static int whereLoopAddOr(
*/
static int whereLoopAddAll(WhereLoopBuilder *pBuilder){
WhereInfo *pWInfo = pBuilder->pWInfo;
- Bitmask mExtra = 0;
+ Bitmask mPrereq = 0;
Bitmask mPrior = 0;
int iTab;
SrcList *pTabList = pWInfo->pTabList;
@@ -3175,7 +3188,7 @@ static int whereLoopAddAll(WhereLoopBuilder *pBuilder){
if( ((pItem->fg.jointype|priorJointype) & (JT_LEFT|JT_CROSS))!=0 ){
/* This condition is true when pItem is the FROM clause term on the
** right-hand-side of a LEFT or CROSS JOIN. */
- mExtra = mPrior;
+ mPrereq = mPrior;
}
priorJointype = pItem->fg.jointype;
if( IsVirtual(pItem->pTab) ){
@@ -3185,12 +3198,12 @@ static int whereLoopAddAll(WhereLoopBuilder *pBuilder){
mUnusable |= sqlite3WhereGetMask(&pWInfo->sMaskSet, p->iCursor);
}
}
- rc = whereLoopAddVirtual(pBuilder, mExtra, mUnusable);
+ rc = whereLoopAddVirtual(pBuilder, mPrereq, mUnusable);
}else{
- rc = whereLoopAddBtree(pBuilder, mExtra);
+ rc = whereLoopAddBtree(pBuilder, mPrereq);
}
if( rc==SQLITE_OK ){
- rc = whereLoopAddOr(pBuilder, mExtra, mUnusable);
+ rc = whereLoopAddOr(pBuilder, mPrereq, mUnusable);
}
mPrior |= pNew->maskSelf;
if( rc || db->mallocFailed ) break;
@@ -4280,7 +4293,7 @@ WhereInfo *sqlite3WhereBegin(
}
}
if( pWInfo->pOrderBy==0 && (db->flags & SQLITE_ReverseOrder)!=0 ){
- pWInfo->revMask = (Bitmask)(-1);
+ pWInfo->revMask = ALLBITS;
}
if( pParse->nErr || NEVER(db->mallocFailed) ){
goto whereBeginError;
diff --git a/src/wherecode.c b/src/wherecode.c
index bfc52fb47..3705aab51 100644
--- a/src/wherecode.c
+++ b/src/wherecode.c
@@ -882,7 +882,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
for(j=0; j<nConstraint; j++){
int iTarget = iReg+j+2;
pTerm = pLoop->aLTerm[j];
- if( pTerm==0 ) continue;
+ if( NEVER(pTerm==0) ) continue;
if( pTerm->eOperator & WO_IN ){
codeEqualityTerm(pParse, pTerm, pLevel, j, bRev, iTarget);
addrNotFound = pLevel->addrNxt;
@@ -915,7 +915,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
** the xFilter implementation might have changed the datatype or
** encoding of the value in the register, so it *must* be reloaded. */
assert( pLevel->u.in.aInLoop!=0 || db->mallocFailed );
- if( pLevel->u.in.aInLoop!=0 ){
+ if( !db->mallocFailed ){
assert( iIn>0 );
pOp = sqlite3VdbeGetOp(v, pLevel->u.in.aInLoop[--iIn].addrInTop);
assert( pOp->opcode==OP_Column || pOp->opcode==OP_Rowid );
@@ -932,8 +932,10 @@ Bitmask sqlite3WhereCodeOneLoopStart(
if( pCompare ){
pCompare->pLeft = pTerm->pExpr->pLeft;
pCompare->pRight = pRight = sqlite3Expr(db, TK_REGISTER, 0);
- if( pRight ) pRight->iTable = iReg+j+2;
- sqlite3ExprIfFalse(pParse, pCompare, pLevel->addrCont, 0);
+ if( pRight ){
+ pRight->iTable = iReg+j+2;
+ sqlite3ExprIfFalse(pParse, pCompare, pLevel->addrCont, 0);
+ }
pCompare->pLeft = 0;
sqlite3ExprDelete(db, pCompare);
}
diff --git a/test/analyzer1.test b/test/analyzer1.test
index ac46704fb..51b5f8b6a 100644
--- a/test/analyzer1.test
+++ b/test/analyzer1.test
@@ -25,9 +25,12 @@ if {$tcl_platform(platform)=="windows"} {
set PROG "./sqlite3_analyzer"
}
if {![file exe $PROG]} {
- puts "analyzer1 cannot run because $PROG is not available"
- finish_test
- return
+ set PROG [file normalize [file join $::cmdlinearg(TESTFIXTURE_HOME) $PROG]]
+ if {![file exe $PROG]} {
+ puts "analyzer1 cannot run because $PROG is not available"
+ finish_test
+ return
+ }
}
db close
forcedelete test.db test.db-journal test.db-wal
diff --git a/test/autovacuum.test b/test/autovacuum.test
index 9ee2cd0fa..5c14ed85d 100644
--- a/test/autovacuum.test
+++ b/test/autovacuum.test
@@ -269,7 +269,7 @@ do_test autovacuum-2.4.3 {
} {3 4 5 6 7 8 9 10}
# Right now there are 5 free pages in the database. Consume and then free
-# a 520 pages. Then create 520 tables. This ensures that at least some of the
+# all 520 pages. Then create 520 tables. This ensures that at least some of the
# desired root-pages reside on the second free-list trunk page, and that the
# trunk itself is required at some point.
do_test autovacuum-2.4.4 {
@@ -280,9 +280,20 @@ do_test autovacuum-2.4.4 {
} {}
set root_page_list [list]
set pending_byte_page [expr ($::sqlite_pending_byte / 1024) + 1]
+
+# unusable_pages
+# These are either the pending_byte page or the pointer map pages
+#
+unset -nocomplain unusable_page
+if {[sqlite3 -has-codec]} {
+ array set unusable_page {205 1 408 1}
+} else {
+ array set unusable_page {207 1 412 1}
+}
+set unusable_page($pending_byte_page) 1
+
for {set i 3} {$i<=532} {incr i} {
- # 207 and 412 are pointer-map pages.
- if { $i!=207 && $i!=412 && $i != $pending_byte_page} {
+ if {![info exists unusable_page($i)]} {
lappend root_page_list $i
}
}
diff --git a/test/backcompat.test b/test/backcompat.test
index ea7e6a9ee..87ffc4b3e 100644
--- a/test/backcompat.test
+++ b/test/backcompat.test
@@ -63,7 +63,7 @@ proc do_backcompat_test {rv bin1 bin2 script} {
set v [split [db version] .]
if {[llength $v]==3} {lappend v 0}
set ::sqlite_libversion [format \
- "%d%.2d%.2d%2d" [lindex $v 0] [lindex $v 1] [lindex $v 2] [lindex $v 3]
+ "%d%.2d%.2d%.2d" [lindex $v 0] [lindex $v 1] [lindex $v 2] [lindex $v 3]
]
}
}
@@ -85,7 +85,8 @@ proc do_allbackcompat_test {script} {
set nErr [set_test_counter errors]
foreach dir {0 1} {
- set bintag [string map {testfixture {}} $bin]
+ set bintag $bin
+ regsub {.*testfixture\.} $bintag {} bintag
set bintag [string map {\.exe {}} $bintag]
if {$bintag == ""} {set bintag self}
set ::bcname ".$bintag.$dir."
@@ -420,6 +421,12 @@ ifcapable fts3 {
if {[code1 { set ::sqlite_libversion }] >=3071200
&& [code2 { set ::sqlite_libversion }] >=3071200
} {
+ if {[code1 { set ::sqlite_libversion }]<3120000} {
+ set res {0 {0 1} 1 0}
+ } else {
+ set res {1 0}
+ }
+
do_test backcompat-3.9 {
sql1 { INSERT INTO t2(t2) VALUES('merge=100,4'); }
sql2 { INSERT INTO t2(t2) VALUES('merge=100,4'); }
@@ -428,7 +435,7 @@ ifcapable fts3 {
sql2 {
SELECT level, group_concat(idx, ' ') FROM t2_segdir GROUP BY level;
}
- } {0 {0 1} 1 0}
+ } $res
do_test backcompat-3.10 {
sql1 { INSERT INTO t2(t2) VALUES('integrity-check') }
diff --git a/test/backup4.test b/test/backup4.test
index 417df80e5..2756995c3 100644
--- a/test/backup4.test
+++ b/test/backup4.test
@@ -23,6 +23,11 @@ set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix backup4
+# The codec logic does not work for zero-length database files. A database
+# file must contain at least one page in order to be recognized as an
+# encrypted database.
+do_not_use_codec
+
#-------------------------------------------------------------------------
# At one point this test was failing because [db] was using an out of
# date schema in test case 1.2.
diff --git a/test/bc_common.tcl b/test/bc_common.tcl
index 78010dfa4..c47f99681 100644
--- a/test/bc_common.tcl
+++ b/test/bc_common.tcl
@@ -7,7 +7,7 @@ proc bc_find_binaries {zCaption} {
# against.
#
set binaries [list]
- set self [file tail [info nameofexec]]
+ set self [info nameofexec]
set pattern "$self?*"
if {$::tcl_platform(platform)=="windows"} {
set pattern [string map {\.exe {}} $pattern]
@@ -52,7 +52,8 @@ proc do_bc_test {bin script} {
code1 { sqlite3 db test.db }
code2 { sqlite3 db test.db }
- set bintag [string map {testfixture {}} $bin]
+ set bintag $bin
+ regsub {.*testfixture\.} $bintag {} bintag
set bintag [string map {\.exe {}} $bintag]
if {$bintag == ""} {set bintag self}
set saved_prefix $::testprefix
diff --git a/test/bestindex1.test b/test/bestindex1.test
index fffb7aebe..97ae4b0f8 100644
--- a/test/bestindex1.test
+++ b/test/bestindex1.test
@@ -15,6 +15,11 @@ set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix bestindex1
+ifcapable !vtab {
+ finish_test
+ return
+}
+
register_tcl_module db
proc vtab_command {method args} {
@@ -161,5 +166,3 @@ foreach {tn mode} {
}
finish_test
-
-
diff --git a/test/bestindex2.test b/test/bestindex2.test
index 7ccd61640..8bc3fbc32 100644
--- a/test/bestindex2.test
+++ b/test/bestindex2.test
@@ -13,6 +13,10 @@ set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix bestindex2
+ifcapable !vtab {
+ finish_test
+ return
+}
#-------------------------------------------------------------------------
# Virtual table callback for table named $tbl, with the columns specified
@@ -135,4 +139,3 @@ do_eqp_test 1.7.2 {
}
finish_test
-
diff --git a/test/close.test b/test/close.test
index d5d6391ae..1b789bc77 100644
--- a/test/close.test
+++ b/test/close.test
@@ -17,6 +17,10 @@ set testdir [file dirname $argv0]
source $testdir/tester.tcl
set ::testprefix close
+# This module bypasses the "-key" logic in tester.tcl, so it cannot run
+# with the codec enabled.
+do_not_use_codec
+
do_execsql_test 1.0 {
CREATE TABLE t1(x);
INSERT INTO t1 VALUES('one');
diff --git a/test/corrupt2.test b/test/corrupt2.test
index 9bd29cf90..efeb26bc8 100644
--- a/test/corrupt2.test
+++ b/test/corrupt2.test
@@ -346,27 +346,29 @@ ifcapable autovacuum {
} {1 {database disk image is malformed}}
}
- corruption_test -sqlprep {
- PRAGMA auto_vacuum = 1;
- PRAGMA page_size = 1024;
- CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
- INSERT INTO t1 VALUES(1, randomblob(2500));
- DELETE FROM t1 WHERE a = 1;
- } -corrupt {
- set nAppend [expr 1024*207 - [file size corrupt.db]]
- set fd [open corrupt.db r+]
- seek $fd 0 end
- puts -nonewline $fd [string repeat x $nAppend]
- close $fd
- hexio_write corrupt.db 28 00000000
- } -test {
- do_test corrupt2-6.4 {
- catchsql "
- $::presql
- BEGIN EXCLUSIVE;
- COMMIT;
- "
- } {1 {database disk image is malformed}}
+ if {![nonzero_reserved_bytes]} {
+ corruption_test -sqlprep {
+ PRAGMA auto_vacuum = 1;
+ PRAGMA page_size = 1024;
+ CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
+ INSERT INTO t1 VALUES(1, randomblob(2500));
+ DELETE FROM t1 WHERE a = 1;
+ } -corrupt {
+ set nAppend [expr 1024*207 - [file size corrupt.db]]
+ set fd [open corrupt.db r+]
+ seek $fd 0 end
+ puts -nonewline $fd [string repeat x $nAppend]
+ close $fd
+ hexio_write corrupt.db 28 00000000
+ } -test {
+ do_test corrupt2-6.4 {
+ catchsql "
+ $::presql
+ BEGIN EXCLUSIVE;
+ COMMIT;
+ "
+ } {1 {database disk image is malformed}}
+ }
}
}
diff --git a/test/corrupt3.test b/test/corrupt3.test
index 436a46618..85139420b 100644
--- a/test/corrupt3.test
+++ b/test/corrupt3.test
@@ -18,10 +18,9 @@
set testdir [file dirname $argv0]
source $testdir/tester.tcl
-# Do not use a codec for tests in this file, as the database file is
-# manipulated directly using tcl scripts (using the [hexio_write] command).
-#
-do_not_use_codec
+# This module uses hard-coded offsets which do not work if the reserved_bytes
+# value is nonzero.
+if {[nonzero_reserved_bytes]} {finish_test; return;}
# These tests deal with corrupt database files
#
diff --git a/test/corrupt4.test b/test/corrupt4.test
index 24db60fd5..55969c6a8 100644
--- a/test/corrupt4.test
+++ b/test/corrupt4.test
@@ -18,10 +18,9 @@
set testdir [file dirname $argv0]
source $testdir/tester.tcl
-# Do not use a codec for tests in this file, as the database file is
-# manipulated directly using tcl scripts (using the [hexio_write] command).
-#
-do_not_use_codec
+# This module uses hard-coded offsets which do not work if the reserved_bytes
+# value is nonzero.
+if {[nonzero_reserved_bytes]} {finish_test; return;}
# These tests deal with corrupt database files
#
diff --git a/test/corrupt6.test b/test/corrupt6.test
index 7d90c4a3b..dd773c926 100644
--- a/test/corrupt6.test
+++ b/test/corrupt6.test
@@ -19,10 +19,9 @@
set testdir [file dirname $argv0]
source $testdir/tester.tcl
-# Do not use a codec for tests in this file, as the database file is
-# manipulated directly using tcl scripts (using the [hexio_write] command).
-#
-do_not_use_codec
+# This module uses hard-coded offsets which do not work if the reserved_bytes
+# value is nonzero.
+if {[nonzero_reserved_bytes]} {finish_test; return;}
# These tests deal with corrupt database files
#
diff --git a/test/corrupt7.test b/test/corrupt7.test
index 7ebebd94e..aa66cc7ec 100644
--- a/test/corrupt7.test
+++ b/test/corrupt7.test
@@ -19,10 +19,9 @@
set testdir [file dirname $argv0]
source $testdir/tester.tcl
-# Do not use a codec for tests in this file, as the database file is
-# manipulated directly using tcl scripts (using the [hexio_write] command).
-#
-do_not_use_codec
+# This module uses hard-coded offsets which do not work if the reserved_bytes
+# value is nonzero.
+if {[nonzero_reserved_bytes]} {finish_test; return;}
# These tests deal with corrupt database files
#
diff --git a/test/corruptE.test b/test/corruptE.test
index 78cabbec8..54aa420f4 100644
--- a/test/corruptE.test
+++ b/test/corruptE.test
@@ -18,10 +18,9 @@
set testdir [file dirname $argv0]
source $testdir/tester.tcl
-# Do not use a codec for tests in this file, as the database file is
-# manipulated directly using tcl scripts (using the [hexio_write] command).
-#
-do_not_use_codec
+# This module uses hard-coded offsets which do not work if the reserved_bytes
+# value is nonzero.
+if {[nonzero_reserved_bytes]} {finish_test; return;}
# These tests deal with corrupt database files
#
diff --git a/test/corruptG.test b/test/corruptG.test
index af920edf4..94480340a 100644
--- a/test/corruptG.test
+++ b/test/corruptG.test
@@ -14,10 +14,9 @@ set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix corruptG
-# Do not use a codec for tests in this file, as the database file is
-# manipulated directly using tcl scripts (using the [hexio_write] command).
-#
-do_not_use_codec
+# This module uses hard-coded offsets which do not work if the reserved_bytes
+# value is nonzero.
+if {[nonzero_reserved_bytes]} {finish_test; return;}
# These tests deal with corrupt database files
#
diff --git a/test/corruptH.test b/test/corruptH.test
index 0e1a1d442..9ba752242 100644
--- a/test/corruptH.test
+++ b/test/corruptH.test
@@ -14,10 +14,10 @@ set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix corruptH
-# Do not use a codec for tests in this file, as the database file is
-# manipulated directly using tcl scripts (using the [hexio_write] command).
-#
-do_not_use_codec
+# This module uses hard-coded offsets which do not work if the reserved_bytes
+# value is nonzero.
+if {[nonzero_reserved_bytes]} {finish_test; return;}
+
database_may_be_corrupt
# The corruption migrations tested by the code in this file are not detected
diff --git a/test/corruptI.test b/test/corruptI.test
index 9f46efb74..cdcb94201 100644
--- a/test/corruptI.test
+++ b/test/corruptI.test
@@ -19,10 +19,10 @@ if {[permutation]=="mmap"} {
return
}
-# Do not use a codec for tests in this file, as the database file is
-# manipulated directly using tcl scripts (using the [hexio_write] command).
-#
-do_not_use_codec
+# This module uses hard-coded offsets which do not work if the reserved_bytes
+# value is nonzero.
+if {[nonzero_reserved_bytes]} {finish_test; return;}
+
database_may_be_corrupt
# Initialize the database.
diff --git a/test/corruptJ.test b/test/corruptJ.test
index c08e628e2..732adb085 100644
--- a/test/corruptJ.test
+++ b/test/corruptJ.test
@@ -22,10 +22,10 @@ if {[permutation]=="mmap"} {
return
}
-# Do not use a codec for tests in this file, as the database file is
-# manipulated directly using tcl scripts (using the [hexio_write] command).
-#
-do_not_use_codec
+# This module uses hard-coded offsets which do not work if the reserved_bytes
+# value is nonzero.
+if {[nonzero_reserved_bytes]} {finish_test; return;}
+
database_may_be_corrupt
# Initialize the database.
diff --git a/test/crash8.test b/test/crash8.test
index 930834a96..f3b6f6e24 100644
--- a/test/crash8.test
+++ b/test/crash8.test
@@ -25,6 +25,7 @@ ifcapable !crashtest {
finish_test
return
}
+do_not_use_codec
do_test crash8-1.1 {
execsql {
diff --git a/test/e_uri.test b/test/e_uri.test
index 7a7f2559e..95b53f1d6 100644
--- a/test/e_uri.test
+++ b/test/e_uri.test
@@ -13,7 +13,7 @@
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix e_uri
-
+do_not_use_codec
db close
proc parse_uri {uri} {
diff --git a/test/e_vacuum.test b/test/e_vacuum.test
index 99b31aaca..1113a1fb6 100644
--- a/test/e_vacuum.test
+++ b/test/e_vacuum.test
@@ -159,35 +159,37 @@ do_test e_vacuum-1.3.1.2 {
execsql { PRAGMA page_size ; PRAGMA auto_vacuum }
} {1024 1}
-# EVIDENCE-OF: R-08570-19916 However, when not in write-ahead log mode,
-# the page_size and/or auto_vacuum properties of an existing database
-# may be changed by using the page_size and/or pragma auto_vacuum
-# pragmas and then immediately VACUUMing the database.
-#
-do_test e_vacuum-1.3.2.1 {
- execsql { PRAGMA journal_mode = delete }
- execsql { PRAGMA page_size = 2048 }
- execsql { PRAGMA auto_vacuum = NONE }
- execsql VACUUM
- execsql { PRAGMA page_size ; PRAGMA auto_vacuum }
-} {2048 0}
-
-# EVIDENCE-OF: R-48521-51450 When in write-ahead log mode, only the
-# auto_vacuum support property can be changed using VACUUM.
-#
-ifcapable wal {
-do_test e_vacuum-1.3.3.1 {
- execsql { PRAGMA journal_mode = wal }
- execsql { PRAGMA page_size ; PRAGMA auto_vacuum }
-} {2048 0}
-do_test e_vacuum-1.3.3.2 {
- execsql { PRAGMA page_size = 1024 }
- execsql { PRAGMA auto_vacuum = FULL }
- execsql VACUUM
- execsql { PRAGMA page_size ; PRAGMA auto_vacuum }
-} {2048 1}
+if {![nonzero_reserved_bytes]} {
+ # EVIDENCE-OF: R-08570-19916 However, when not in write-ahead log mode,
+ # the page_size and/or auto_vacuum properties of an existing database
+ # may be changed by using the page_size and/or pragma auto_vacuum
+ # pragmas and then immediately VACUUMing the database.
+ #
+ do_test e_vacuum-1.3.2.1 {
+ execsql { PRAGMA journal_mode = delete }
+ execsql { PRAGMA page_size = 2048 }
+ execsql { PRAGMA auto_vacuum = NONE }
+ execsql VACUUM
+ execsql { PRAGMA page_size ; PRAGMA auto_vacuum }
+ } {2048 0}
+
+ # EVIDENCE-OF: R-48521-51450 When in write-ahead log mode, only the
+ # auto_vacuum support property can be changed using VACUUM.
+ #
+ ifcapable wal {
+ do_test e_vacuum-1.3.3.1 {
+ execsql { PRAGMA journal_mode = wal }
+ execsql { PRAGMA page_size ; PRAGMA auto_vacuum }
+ } {2048 0}
+ do_test e_vacuum-1.3.3.2 {
+ execsql { PRAGMA page_size = 1024 }
+ execsql { PRAGMA auto_vacuum = FULL }
+ execsql VACUUM
+ execsql { PRAGMA page_size ; PRAGMA auto_vacuum }
+ } {2048 1}
+ }
}
-
+
# EVIDENCE-OF: R-38001-03952 VACUUM only works on the main database. It
# is not possible to VACUUM an attached database file.
forcedelete test.db2
diff --git a/test/e_walauto.test b/test/e_walauto.test
index 093b13f94..7665b1bf7 100644
--- a/test/e_walauto.test
+++ b/test/e_walauto.test
@@ -24,6 +24,11 @@ if {$tcl_platform(os) == "OpenBSD"} {
return
}
+# This module uses hard-coded offsets which do not work if the reserved_bytes
+# value is nonzero.
+if {[nonzero_reserved_bytes]} {finish_test; return;}
+
+
proc read_nbackfill {} {
seek $::shmfd 96
binary scan [read $::shmfd 4] n nBackfill
diff --git a/test/eqp.test b/test/eqp.test
index 046088c9c..c955a80c2 100644
--- a/test/eqp.test
+++ b/test/eqp.test
@@ -516,45 +516,47 @@ det 5.13 "SELECT a FROM t1 EXCEPT SELECT d FROM t2 ORDER BY 1" {
}
-#-------------------------------------------------------------------------
-# The following tests - eqp-6.* - test that the example C code on
-# documentation page eqp.html works. The C code is duplicated in test1.c
-# and wrapped in Tcl command [print_explain_query_plan]
-#
-set boilerplate {
- proc explain_query_plan {db sql} {
- set stmt [sqlite3_prepare_v2 db $sql -1 DUMMY]
- print_explain_query_plan $stmt
- sqlite3_finalize $stmt
+if {![nonzero_reserved_bytes]} {
+ #-------------------------------------------------------------------------
+ # The following tests - eqp-6.* - test that the example C code on
+ # documentation page eqp.html works. The C code is duplicated in test1.c
+ # and wrapped in Tcl command [print_explain_query_plan]
+ #
+ set boilerplate {
+ proc explain_query_plan {db sql} {
+ set stmt [sqlite3_prepare_v2 db $sql -1 DUMMY]
+ print_explain_query_plan $stmt
+ sqlite3_finalize $stmt
+ }
+ sqlite3 db test.db
+ explain_query_plan db {%SQL%}
+ db close
+ exit
}
- sqlite3 db test.db
- explain_query_plan db {%SQL%}
- db close
- exit
-}
-
-# Do a "Print Explain Query Plan" test.
-proc do_peqp_test {tn sql res} {
- set fd [open script.tcl w]
- puts $fd [string map [list %SQL% $sql] $::boilerplate]
- close $fd
-
- uplevel do_test $tn [list {
- set fd [open "|[info nameofexec] script.tcl"]
- set data [read $fd]
+
+ # Do a "Print Explain Query Plan" test.
+ proc do_peqp_test {tn sql res} {
+ set fd [open script.tcl w]
+ puts $fd [string map [list %SQL% $sql] $::boilerplate]
close $fd
- set data
- }] [list $res]
-}
-
-do_peqp_test 6.1 {
- SELECT a, b FROM t1 EXCEPT SELECT d, 99 FROM t2 ORDER BY 1
-} [string trimleft {
+
+ uplevel do_test $tn [list {
+ set fd [open "|[info nameofexec] script.tcl"]
+ set data [read $fd]
+ close $fd
+ set data
+ }] [list $res]
+ }
+
+ do_peqp_test 6.1 {
+ SELECT a, b FROM t1 EXCEPT SELECT d, 99 FROM t2 ORDER BY 1
+ } [string trimleft {
1 0 0 SCAN TABLE t1 USING COVERING INDEX i2
2 0 0 SCAN TABLE t2
2 0 0 USE TEMP B-TREE FOR ORDER BY
0 0 0 COMPOUND SUBQUERIES 1 AND 2 (EXCEPT)
}]
+}
#-------------------------------------------------------------------------
# The following tests - eqp-7.* - test that queries that use the OP_Count
diff --git a/test/filefmt.test b/test/filefmt.test
index 2df142443..087a955c3 100644
--- a/test/filefmt.test
+++ b/test/filefmt.test
@@ -144,9 +144,11 @@ do_execsql_test filefmt-2.1.1 {
CREATE TABLE t2(a);
INSERT INTO t2 VALUES(1);
} {}
-do_test filefmt-2.1.2 {
- hexio_read test.db 28 4
-} {00000009}
+if {![nonzero_reserved_bytes]} {
+ do_test filefmt-2.1.2 {
+ hexio_read test.db 28 4
+ } {00000009}
+}
do_test filefmt-2.1.3 {
sql36231 { INSERT INTO t1 VALUES(a_string(3000)) }
@@ -170,9 +172,11 @@ do_execsql_test filefmt-2.2.1 {
CREATE TABLE t2(a);
INSERT INTO t2 VALUES(1);
} {}
-do_test filefmt-2.2.2 {
- hexio_read test.db 28 4
-} {00000009}
+if {![nonzero_reserved_bytes]} {
+ do_test filefmt-2.2.2 {
+ hexio_read test.db 28 4
+ } {00000009}
+}
do_test filefmt-2.2.3 {
sql36231 { INSERT INTO t1 VALUES(a_string(3000)) }
diff --git a/test/fts4growth.test b/test/fts4growth.test
index e4b5f19ec..4dc221246 100644
--- a/test/fts4growth.test
+++ b/test/fts4growth.test
@@ -59,11 +59,11 @@ do_test 1.4 {
INSERT INTO x1(x1) VALUES('merge=4,4');
SELECT level, end_block, length(root) FROM x1_segdir;
}
-} {0 {0 110} 110 0 {0 132} 132 0 {0 129} 129 1 {128 658} 2}
+} {1 {224 921} 2}
do_execsql_test 1.5 {
SELECT length(block) FROM x1_segments;
-} {658 {}}
+} {921 {}}
do_test 1.6 {
foreach L {
@@ -71,27 +71,33 @@ do_test 1.6 {
{That perched above Dead Man's Creek, beside the mountain road.}
{He turned the cycle down the hill and mounted for the fray,}
{But 'ere he'd gone a dozen yards it bolted clean away.}
+
{It left the track, and through the trees, just like a silver steak,}
{It whistled down the awful slope towards the Dead Man's Creek.}
{It shaved a stump by half an inch, it dodged a big white-box:}
{The very wallaroos in fright went scrambling up the rocks,}
+
{The wombats hiding in their caves dug deeper underground,}
{As Mulga Bill, as white as chalk, sat tight to every bound.}
{It struck a stone and gave a spring that cleared a fallen tree,}
{It raced beside a precipice as close as close could be;}
+
{And then as Mulga Bill let out one last despairing shriek}
{It made a leap of twenty feet into the Dead Man's Creek.}
+ {It shaved a stump by half an inch, it dodged a big white-box:}
+ {The very wallaroos in fright went scrambling up the rocks,}
+ {The wombats hiding in their caves dug deeper underground,}
} {
execsql { INSERT INTO x1 VALUES($L) }
}
execsql {
SELECT level, end_block, length(root) FROM x1_segdir;
}
-} {1 {128 658} 2 1 {130 1377} 6 0 {0 117} 117}
+} {1 {224 921} 2 1 {226 1230} 7 0 {0 98} 98}
do_execsql_test 1.7 {
- SELECT sum(length(block)) FROM x1_segments WHERE blockid IN (129, 130);
-} {1377}
+ SELECT sum(length(block)) FROM x1_segments WHERE blockid IN (224,225,226)
+} {1230}
#-------------------------------------------------------------------------
#
@@ -131,24 +137,24 @@ do_execsql_test 2.5 {
SELECT end_block FROM x2_segdir WHERE level=3;
INSERT INTO x2(x2) VALUES('merge=4,4');
SELECT end_block FROM x2_segdir WHERE level=3;
-} {{3828 -3430} {3828 -10191} {3828 -14109}}
+} {{5588 -3950} {5588 -11766} {5588 -15541}}
do_execsql_test 2.6 {
SELECT sum(length(block)) FROM x2_segdir, x2_segments WHERE
blockid BETWEEN start_block AND leaves_end_block
AND level=3
-} {14109}
+} {15541}
do_execsql_test 2.7 {
INSERT INTO x2(x2) VALUES('merge=1000,4');
SELECT end_block FROM x2_segdir WHERE level=3;
-} {{3828 86120}}
+} {{5588 127563}}
do_execsql_test 2.8 {
SELECT sum(length(block)) FROM x2_segdir, x2_segments WHERE
blockid BETWEEN start_block AND leaves_end_block
AND level=3
-} {86120}
+} {127563}
#--------------------------------------------------------------------------
# Test that delete markers are removed from FTS segments when possible.
@@ -391,7 +397,7 @@ do_execsql_test 7.2 {
} {
0 0 {118 117483} 0 1 {238 118006} 0 2 {358 118006}
0 3 {478 118006} 0 4 {598 118006} 0 5 {718 118006}
- 1 0 {16014 -51226}
+ 1 0 {23694 -69477}
}
do_execsql_test 7.3 {
@@ -400,7 +406,7 @@ do_execsql_test 7.3 {
} {
0 0 {118 117483} 0 1 {238 118006} 0 2 {358 118006}
0 3 {478 118006} 0 4 {598 118006} 0 5 {718 118006}
- 1 0 16014
+ 1 0 23694
}
do_execsql_test 7.4 {
@@ -409,28 +415,26 @@ do_execsql_test 7.4 {
} {
0 0 {118 117483} 0 1 {238 118006} 0 2 {358 118006}
0 3 {478 118006} 0 4 {598 118006} 0 5 {718 118006}
- 1 0 16014
+ 1 0 23694
}
do_execsql_test 7.5 {
INSERT INTO x6(x6) VALUES('merge=2500,4');
- SELECT level, idx, end_block FROM x6_segdir;
+ SELECT level, idx, start_block, leaves_end_block, end_block FROM x6_segdir;
} {
- 0 0 {598 118006} 0 1 {718 118006} 1 0 16014
+ 1 0 719 1171 23694
}
do_execsql_test 7.6 {
INSERT INTO x6(x6) VALUES('merge=2500,2');
SELECT level, idx, start_block, leaves_end_block, end_block FROM x6_segdir;
} {
- 2 0 23695 24147 {41262 633507}
+ 1 0 719 1171 23694
}
do_execsql_test 7.7 {
SELECT sum(length(block)) FROM x6_segments
- WHERE blockid BETWEEN 23695 AND 24147
-} {633507}
-
+} {635247}
finish_test
diff --git a/test/fts4langid.test b/test/fts4langid.test
index eb3602b4b..fdb1876be 100644
--- a/test/fts4langid.test
+++ b/test/fts4langid.test
@@ -481,6 +481,6 @@ foreach lid [list 4 [expr 1<<30]] {
do_execsql_test 5.4.$lid.5 {
SELECT count(*) FROM t6_segdir;
SELECT count(*) FROM t6_segments;
- } {4 4}
+ } {1 2}
}
finish_test
diff --git a/test/fts4merge.test b/test/fts4merge.test
index fabb651e6..eac18311d 100644
--- a/test/fts4merge.test
+++ b/test/fts4merge.test
@@ -55,8 +55,6 @@ foreach mod {fts3 fts4} {
do_execsql_test 1.3 {
SELECT level, group_concat(idx, ' ') FROM t1_segdir GROUP BY level
} {
- 0 {0 1 2 3}
- 1 {0 1 2 3 4 5 6}
2 {0 1 2 3}
}
@@ -71,7 +69,6 @@ foreach mod {fts3 fts4} {
do_execsql_test 1.5 {
SELECT level, group_concat(idx, ' ') FROM t1_segdir GROUP BY level
} {
- 2 {0 1}
3 0
}
@@ -89,7 +86,6 @@ foreach mod {fts3 fts4} {
5 {merge=6,%}
6 {merge=6,six}
7 {merge=6,1}
- 8 {merge=6,0}
} {
do_catchsql_test 2.$tn {
INSERT INTO t2(t2) VALUES($arg);
@@ -119,11 +115,7 @@ foreach mod {fts3 fts4} {
INSERT INTO t2(t2) VALUES('merge=1000000,2');
SELECT level, group_concat(idx, ' ') FROM t2_segdir GROUP BY level
} {
- 0 0
- 2 0
- 3 0
4 0
- 6 0
}
#-------------------------------------------------------------------------
@@ -203,28 +195,27 @@ foreach mod {fts3 fts4} {
INSERT INTO t1(t1) VALUES('merge=1,5');
SELECT level, group_concat(idx, ' ') FROM t1_segdir GROUP BY level;
} {
- 0 {0 1 2}
1 {0 1 2 3 4 5 6 7 8 9 10 11 12 13 14}
2 {0 1 2 3}
}
- do_execsql_test 5.4 {SELECT quote(value) from t1_stat WHERE rowid=1} {X'0105'}
+ do_execsql_test 5.4 {SELECT quote(value) from t1_stat WHERE rowid=1} {X'010F'}
do_test 5.5 {
foreach docid [execsql {SELECT docid FROM t1}] {
execsql {INSERT INTO t1 SELECT * FROM t1 WHERE docid=$docid}
}
} {}
- do_execsql_test 5.6 {SELECT quote(value) from t1_stat WHERE rowid=1} {X'0105'}
+ do_execsql_test 5.6 {SELECT quote(value) from t1_stat WHERE rowid=1} {X'010F'}
do_execsql_test 5.7 {
SELECT level, group_concat(idx, ' ') FROM t1_segdir GROUP BY level;
SELECT quote(value) from t1_stat WHERE rowid=1;
} {
- 0 {0 1 2 3 4 5 6 7 8 9 10}
+ 0 {0 1 2 3 4 5 6 7}
1 {0 1 2 3 4 5 6 7 8 9 10 11 12}
- 2 {0 1 2 3 4 5 6 7}
- X'0105'
+ 2 {0 1 2 3 4 5 6 7}
+ X'010F'
}
do_execsql_test 5.8 {
@@ -233,9 +224,8 @@ foreach mod {fts3 fts4} {
SELECT level, group_concat(idx, ' ') FROM t1_segdir GROUP BY level;
SELECT quote(value) from t1_stat WHERE rowid=1;
} {
- 0 {0 1 2 3 4}
1 {0 1 2 3 4 5 6 7 8 9 10 11 12 13}
- 2 {0 1 2 3 4 5 6 7 8} X'0106'
+ 2 {0 1 2 3 4 5 6 7 8} X'010E'
}
do_test 5.8.1 { fts3_integrity_check t1 } ok
@@ -253,7 +243,7 @@ foreach mod {fts3 fts4} {
SELECT level, group_concat(idx, ' ') FROM t1_segdir GROUP BY level;
SELECT quote(value) from t1_stat WHERE rowid=1;
} {
- 0 0 1 {0 1} 2 0 3 0 X'0106'
+ 0 {0 1 2 3 4 5 6 7 8 9 10 11} 1 0 2 0 3 0 X'010E'
}
do_execsql_test 5.11 {
@@ -261,7 +251,7 @@ foreach mod {fts3 fts4} {
SELECT level, group_concat(idx, ' ') FROM t1_segdir GROUP BY level;
SELECT quote(value) from t1_stat WHERE rowid=1;
} {
- 0 0 1 {0 1} 2 0 3 0 X''
+ 1 {0 1} 2 0 3 0 X'010E'
}
#-------------------------------------------------------------------------
diff --git a/test/fts4merge3.test b/test/fts4merge3.test
index 329b4d2cc..08b68b97d 100644
--- a/test/fts4merge3.test
+++ b/test/fts4merge3.test
@@ -62,7 +62,7 @@ do_all_bc_test {
do_test 1.7 { sql2 {
SELECT level, count(*) FROM t2_segdir GROUP BY level ORDER BY 1
- } } [list 0 1 2 18 3 5]
+ } } {2 15 3 5}
# Using the old connection, insert many rows.
do_test 1.8 {
@@ -73,7 +73,7 @@ do_all_bc_test {
do_test 1.9 { sql2 {
SELECT level, count(*) FROM t2_segdir GROUP BY level ORDER BY 1
- } } [list 0 13 1 13 2 5 3 6]
+ } } [list 0 12 1 13 2 4 3 6]
# Run a big incr-merge operation on the db.
do_test 1.10 { sql1 { INSERT INTO t2(t2) VALUES('merge=2000,2') } } {}
@@ -97,7 +97,7 @@ do_all_bc_test {
do_test 1.15 { sql2 {
SELECT level, count(*) FROM t2_segdir GROUP BY level ORDER BY 1
- } } {6 1}
+ } } {4 1}
}
}
diff --git a/test/fts4opt.test b/test/fts4opt.test
new file mode 100644
index 000000000..0d0ed9f4f
--- /dev/null
+++ b/test/fts4opt.test
@@ -0,0 +1,213 @@
+# 2016 March 8
+#
+# The author disclaims copyright to this source code. In place of
+# a legal notice, here is a blessing:
+#
+# May you do good and not evil.
+# May you find forgiveness for yourself and forgive others.
+# May you share freely, never taking more than you give.
+#
+#*************************************************************************
+#
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+source $testdir/fts3_common.tcl
+set ::testprefix fts4opt
+
+# If SQLITE_ENABLE_FTS3 is defined, omit this file.
+ifcapable !fts3 {
+ finish_test
+ return
+}
+
+# Create the fts_kjv_genesis procedure which fills and FTS3/4 table
+# with the complete text of the Book of Genesis.
+#
+source $testdir/genesis.tcl
+
+do_execsql_test 1.0 { CREATE TABLE t1(docid, words) }
+fts_kjv_genesis
+
+#-------------------------------------------------------------------------
+# Argument $db is an open database handle. $tbl is the name of an FTS3/4
+# table with the database. This command rearranges the contents of the
+# %_segdir table so that all segments within each index are on the same
+# level. This means that the 'merge' command can then be used for an
+# incremental optimize routine.
+#
+proc prepare_for_optimize {db tbl} {
+ $db eval [string map [list % $tbl] {
+ BEGIN;
+ CREATE TEMP TABLE tmp_segdir(
+ level, idx, start_block, leaves_end_block, end_block, root
+ );
+
+ INSERT INTO temp.tmp_segdir
+ SELECT
+ 1024*(o.level / 1024) + 32, -- level
+ sum(o.level<i.level OR (o.level=i.level AND o.idx>i.idx)), -- idx
+ o.start_block, o.leaves_end_block, o.end_block, o.root -- other
+ FROM %_segdir o, %_segdir i
+ WHERE (o.level / 1024) = (i.level / 1024)
+ GROUP BY o.level, o.idx;
+
+ DELETE FROM %_segdir;
+ INSERT INTO %_segdir SELECT * FROM temp.tmp_segdir;
+ DROP TABLE temp.tmp_segdir;
+
+ COMMIT;
+ }]
+}
+
+do_test 1.1 {
+ execsql { CREATE VIRTUAL TABLE t2 USING fts4(words, prefix="1,2,3") }
+ foreach {docid words} [db eval { SELECT * FROM t1 }] {
+ execsql { INSERT INTO t2(docid, words) VALUES($docid, $words) }
+ }
+} {}
+
+do_execsql_test 1.2 {
+ SELECT level, count(*) FROM t2_segdir GROUP BY level
+} {
+ 0 13 1 15 2 5
+ 1024 13 1025 15 1026 5
+ 2048 13 2049 15 2050 5
+ 3072 13 3073 15 3074 5
+}
+
+do_execsql_test 1.3 { INSERT INTO t2(t2) VALUES('integrity-check') }
+prepare_for_optimize db t2
+do_execsql_test 1.4 { INSERT INTO t2(t2) VALUES('integrity-check') }
+
+do_execsql_test 1.5 {
+ SELECT level, count(*) FROM t2_segdir GROUP BY level
+} {
+ 32 33
+ 1056 33
+ 2080 33
+ 3104 33
+}
+
+do_test 1.6 {
+ while 1 {
+ set tc1 [db total_changes]
+ execsql { INSERT INTO t2(t2) VALUES('merge=5,2') }
+ set tc2 [db total_changes]
+ if {($tc2 - $tc1) < 2} break
+ }
+ execsql { SELECT level, count(*) FROM t2_segdir GROUP BY level }
+} {33 1 1057 1 2081 1 3105 1}
+do_execsql_test 1.7 { INSERT INTO t2(t2) VALUES('integrity-check') }
+
+do_execsql_test 1.8 {
+ INSERT INTO t2(words) SELECT words FROM t1;
+ SELECT level, count(*) FROM t2_segdir GROUP BY level;
+} {0 2 1024 2 2048 2 3072 2}
+
+#-------------------------------------------------------------------------
+
+do_execsql_test 2.0 {
+ DELETE FROM t2;
+}
+do_test 2.1 {
+ foreach {docid words} [db eval { SELECT * FROM t1 }] {
+ execsql { INSERT INTO t2(docid, words) VALUES($docid, $words) }
+ }
+
+ set i 0
+ foreach {docid words} [db eval { SELECT * FROM t1 }] {
+ if {[incr i] % 2} { execsql { DELETE FROM t2 WHERE docid = $docid } }
+ }
+
+ set i 0
+ foreach {docid words} [db eval { SELECT * FROM t1 }] {
+ if {[incr i] % 3} {
+ execsql { INSERT OR REPLACE INTO t2(docid, words) VALUES($docid, $words) }
+ }
+ }
+} {}
+
+do_execsql_test 2.2 {
+ SELECT level, count(*) FROM t2_segdir GROUP BY level
+} {
+ 0 10 1 15 2 12
+ 1024 10 1025 15 1026 12
+ 2048 10 2049 15 2050 12
+ 3072 10 3073 15 3074 12
+}
+
+do_execsql_test 2.3 { INSERT INTO t2(t2) VALUES('integrity-check') }
+prepare_for_optimize db t2
+do_execsql_test 2.4 { INSERT INTO t2(t2) VALUES('integrity-check') }
+
+do_execsql_test 2.5 {
+ SELECT level, count(*) FROM t2_segdir GROUP BY level
+} {
+ 32 37
+ 1056 37
+ 2080 37
+ 3104 37
+}
+
+do_test 2.6 {
+ while 1 {
+ set tc1 [db total_changes]
+ execsql { INSERT INTO t2(t2) VALUES('merge=5,2') }
+ set tc2 [db total_changes]
+ if {($tc2 - $tc1) < 2} break
+ }
+ execsql { SELECT level, count(*) FROM t2_segdir GROUP BY level }
+} {33 1 1057 1 2081 1 3105 1}
+do_execsql_test 2.7 { INSERT INTO t2(t2) VALUES('integrity-check') }
+
+do_execsql_test 2.8 {
+ INSERT INTO t2(words) SELECT words FROM t1;
+ SELECT level, count(*) FROM t2_segdir GROUP BY level;
+} {0 2 1024 2 2048 2 3072 2}
+
+#-------------------------------------------------------------------------
+# Check that 'optimize' works when there is data in the in-memory hash
+# table, but no segments at all on disk.
+#
+do_execsql_test 3.1 {
+ CREATE VIRTUAL TABLE fts USING fts4 (t);
+ INSERT INTO fts (fts) VALUES ('optimize');
+}
+do_execsql_test 3.2 {
+ INSERT INTO fts(fts) VALUES('integrity-check');
+ SELECT count(*) FROM fts_segdir;
+} {0}
+do_execsql_test 3.3 {
+ BEGIN;
+ INSERT INTO fts (rowid, t) VALUES (2, 'test');
+ INSERT INTO fts (fts) VALUES ('optimize');
+ COMMIT;
+ SELECT level, idx FROM fts_segdir;
+} {0 0}
+do_execsql_test 3.4 {
+ INSERT INTO fts(fts) VALUES('integrity-check');
+ SELECT rowid FROM fts WHERE fts MATCH 'test';
+} {2}
+do_execsql_test 3.5 {
+ INSERT INTO fts (fts) VALUES ('optimize');
+ INSERT INTO fts(fts) VALUES('integrity-check');
+}
+do_test 3.6 {
+ set c1 [db total_changes]
+ execsql { INSERT INTO fts (fts) VALUES ('optimize') }
+ expr {[db total_changes] - $c1}
+} {1}
+do_test 3.7 {
+ execsql { INSERT INTO fts (rowid, t) VALUES (3, 'xyz') }
+ set c1 [db total_changes]
+ execsql { INSERT INTO fts (fts) VALUES ('optimize') }
+ expr {([db total_changes] - $c1) > 1}
+} {1}
+do_test 3.8 {
+ set c1 [db total_changes]
+ execsql { INSERT INTO fts (fts) VALUES ('optimize') }
+ expr {[db total_changes] - $c1}
+} {1}
+
+finish_test
diff --git a/test/in5.test b/test/in5.test
index 67d212589..b49c93e15 100644
--- a/test/in5.test
+++ b/test/in5.test
@@ -183,4 +183,39 @@ do_execsql_test 6.3.1 {
SELECT count(*) FROM x2 WHERE b IN (SELECT DISTINCT a FROM x1 LIMIT 2);
} {2}
+#-------------------------------------------------------------------------
+# Test to confirm that bug [5e3c886796e5] is fixed.
+#
+do_execsql_test 7.1 {
+ CREATE TABLE y1(a, b);
+ CREATE TABLE y2(c);
+
+ INSERT INTO y1 VALUES(1, 'one');
+ INSERT INTO y1 VALUES('two', 'two');
+ INSERT INTO y1 VALUES(3, 'three');
+
+ INSERT INTO y2 VALUES('one');
+ INSERT INTO y2 VALUES('two');
+ INSERT INTO y2 VALUES('three');
+} {}
+
+do_execsql_test 7.2.1 {
+ SELECT a FROM y1 WHERE b NOT IN (SELECT a FROM y2);
+} {1 3}
+do_execsql_test 7.2.2 {
+ SELECT a FROM y1 WHERE b IN (SELECT a FROM y2);
+} {two}
+
+do_execsql_test 7.3.1 {
+ CREATE INDEX y2c ON y2(c);
+ SELECT a FROM y1 WHERE b NOT IN (SELECT a FROM y2);
+} {1 3}
+do_execsql_test 7.3.2 {
+ SELECT a FROM y1 WHERE b IN (SELECT a FROM y2);
+} {two}
+
+finish_test
+
+
+
finish_test
diff --git a/test/incrblob.test b/test/incrblob.test
index 4277e5c4c..c56689ee1 100644
--- a/test/incrblob.test
+++ b/test/incrblob.test
@@ -126,6 +126,11 @@ foreach AutoVacuumMode [list 0 1] {
execsql "PRAGMA mmap_size = 0"
execsql "PRAGMA auto_vacuum = $AutoVacuumMode"
+ # Extra value added to size answers
+ set ib2_extra 0
+ if {$AutoVacuumMode} {incr ib2_extra}
+ if {[nonzero_reserved_bytes]} {incr ib2_extra}
+
do_test incrblob-2.$AutoVacuumMode.1 {
set ::str [string repeat abcdefghij 2900]
execsql {
@@ -136,7 +141,7 @@ foreach AutoVacuumMode [list 0 1] {
COMMIT;
}
expr [file size test.db]/1024
- } [expr 31 + $AutoVacuumMode]
+ } [expr 31 + $ib2_extra]
ifcapable autovacuum {
do_test incrblob-2.$AutoVacuumMode.2 {
@@ -163,7 +168,7 @@ foreach AutoVacuumMode [list 0 1] {
# sqlite uses the ptrmap pages to avoid reading the other pages.
#
nRead db
- } [expr $AutoVacuumMode ? 4 : 30]
+ } [expr $AutoVacuumMode ? 4 : 30+$ib2_extra]
do_test incrblob-2.$AutoVacuumMode.4 {
string range [db one {SELECT v FROM blobs}] end-19 end
@@ -187,7 +192,7 @@ foreach AutoVacuumMode [list 0 1] {
# sqlite uses the ptrmap pages to avoid reading the other pages.
#
nRead db
- } [expr $AutoVacuumMode ? 4 : 30]
+ } [expr $AutoVacuumMode ? 4 : 30 + $ib2_extra]
# Pages 1 (the write-counter) and 32 (the blob data) were written.
do_test incrblob-2.$AutoVacuumMode.6 {
@@ -210,7 +215,7 @@ foreach AutoVacuumMode [list 0 1] {
do_test incrblob-2.$AutoVacuumMode.9 {
nRead db
- } [expr $AutoVacuumMode ? 4 : 30]
+ } [expr $AutoVacuumMode ? 4 : 30 + $ib2_extra]
}
sqlite3_soft_heap_limit $cmdlinearg(soft-heap-limit)
@@ -384,7 +389,7 @@ ifcapable vtab {
ifcapable attach {
do_test incrblob-5.1 {
forcedelete test2.db test2.db-journal
- set ::size [expr [file size [info script]]]
+ set ::size [expr [file size $::cmdlinearg(INFO_SCRIPT)]]
execsql {
ATTACH 'test2.db' AS aux;
CREATE TABLE aux.files(name, text);
@@ -392,16 +397,16 @@ ifcapable attach {
}
set fd [db incrblob aux files text 1]
fconfigure $fd -translation binary
- set fd2 [open [info script]]
+ set fd2 [open $::cmdlinearg(INFO_SCRIPT)]
fconfigure $fd2 -translation binary
puts -nonewline $fd [read $fd2]
close $fd
close $fd2
set ::text [db one {select text from aux.files}]
string length $::text
- } [file size [info script]]
+ } [file size $::cmdlinearg(INFO_SCRIPT)]
do_test incrblob-5.2 {
- set fd2 [open [info script]]
+ set fd2 [open $::cmdlinearg(INFO_SCRIPT)]
fconfigure $fd2 -translation binary
set ::data [read $fd2]
close $fd2
@@ -576,7 +581,7 @@ foreach {tn arg} {1 "" 2 -readonly} {
}
-set fd [open [info script]]
+set fd [open $::cmdlinearg(INFO_SCRIPT)]
fconfigure $fd -translation binary
set ::data [read $fd 14000]
close $fd
diff --git a/test/incrblob_err.test b/test/incrblob_err.test
index a08bea3e4..0db8b0dcb 100644
--- a/test/incrblob_err.test
+++ b/test/incrblob_err.test
@@ -24,12 +24,12 @@ ifcapable {!incrblob || !memdebug || !tclvar} {
source $testdir/malloc_common.tcl
unset -nocomplain ::fd ::data
-set ::fd [open [info script]]
+set ::fd [open $::cmdlinearg(INFO_SCRIPT)]
set ::data [read $::fd]
close $::fd
do_malloc_test 1 -tclprep {
- set bytes [file size [info script]]
+ set bytes [file size $::cmdlinearg(INFO_SCRIPT)]
execsql {
CREATE TABLE blobs(k, v BLOB);
INSERT INTO blobs VALUES(1, zeroblob($::bytes));
diff --git a/test/io.test b/test/io.test
index c5086c10e..e1af808a3 100644
--- a/test/io.test
+++ b/test/io.test
@@ -424,7 +424,7 @@ ifcapable pager_pragmas {
# The COMMIT requires a single fsync() - to the database file.
execsql { COMMIT }
list [file size test.db] [nSync]
- } {39936 1}
+ } "[expr {[nonzero_reserved_bytes]?40960:39936}] 1"
}
#----------------------------------------------------------------------
diff --git a/test/memsubsys1.test b/test/memsubsys1.test
index 8265ce631..e9a4cf08a 100644
--- a/test/memsubsys1.test
+++ b/test/memsubsys1.test
@@ -255,7 +255,7 @@ do_test memsubsys1-7.4 {
} 0
do_test memsubsys1-7.5 {
set maxreq [lindex [sqlite3_status SQLITE_STATUS_MALLOC_SIZE 0] 2]
- expr {$maxreq<4100}
+ expr {$maxreq<4100 + 4200*[nonzero_reserved_bytes]}
} 1
do_test memsubsys1-7.6 {
set s_used [lindex [sqlite3_status SQLITE_STATUS_SCRATCH_USED 0] 2]
diff --git a/test/mmap1.test b/test/mmap1.test
index 199a05875..c7c72c0ab 100644
--- a/test/mmap1.test
+++ b/test/mmap1.test
@@ -88,7 +88,7 @@ foreach {t mmap_size nRead c2init} {
sql2 { DELETE FROM t1 WHERE rowid%2; }
do_test $t.$tn.2 {
sql1 "SELECT count(*) FROM t1; PRAGMA integrity_check ; PRAGMA page_count"
- } {16 ok 42}
+ } "16 ok [expr {42+[nonzero_reserved_bytes]}]"
# Have connection 2 grow the file. Check connection 1 can still read it.
sql2 { INSERT INTO t1 SELECT rblob(500), rblob(500) FROM t1 }
@@ -104,7 +104,9 @@ foreach {t mmap_size nRead c2init} {
# Check that the number of pages read by connection 1 indicates that the
# "PRAGMA mmap_size" command worked.
- do_test $t.$tn.5 { nRead db } $nRead
+ if {[nonzero_reserved_bytes]==0} {
+ do_test $t.$tn.5 { nRead db } $nRead
+ }
}
}
diff --git a/test/mmap3.test b/test/mmap3.test
index 07b515296..184dda5f8 100644
--- a/test/mmap3.test
+++ b/test/mmap3.test
@@ -19,6 +19,9 @@ ifcapable !mmap||!vtab {
source $testdir/lock_common.tcl
set testprefix mmap3
+# A codec shuts down memory-mapped I/O
+if {[nonzero_reserved_bytes]} {finish_test; return;}
+
do_test mmap3-1.0 {
load_static_extension db wholenumber
db eval {
diff --git a/test/nan.test b/test/nan.test
index df3f65b8e..27fa04a35 100644
--- a/test/nan.test
+++ b/test/nan.test
@@ -151,45 +151,47 @@ sqlite3_finalize $::STMT
# Then it reads the value of the database to verify it is converted into
# NULL.
#
-do_test nan-3.1 {
- db eval {
- DELETE FROM t1;
- INSERT INTO t1 VALUES(0.5);
- PRAGMA auto_vacuum=OFF;
- PRAGMA page_size=1024;
- VACUUM;
- }
- hexio_read test.db 2040 8
-} {3FE0000000000000}
-do_test nan-3.2 {
- db eval {
- SELECT x, typeof(x) FROM t1
- }
-} {0.5 real}
-do_test nan-3.3 {
- db close
- hexio_write test.db 2040 FFF8000000000000
- sqlite3 db test.db
- db eval {SELECT x, typeof(x) FROM t1}
-} {{} null}
-do_test nan-3.4 {
- db close
- hexio_write test.db 2040 7FF8000000000000
- sqlite3 db test.db
- db eval {SELECT x, typeof(x) FROM t1}
-} {{} null}
-do_test nan-3.5 {
- db close
- hexio_write test.db 2040 FFFFFFFFFFFFFFFF
- sqlite3 db test.db
- db eval {SELECT x, typeof(x) FROM t1}
-} {{} null}
-do_test nan-3.6 {
- db close
- hexio_write test.db 2040 7FFFFFFFFFFFFFFF
- sqlite3 db test.db
- db eval {SELECT x, typeof(x) FROM t1}
-} {{} null}
+if {![nonzero_reserved_bytes]} {
+ do_test nan-3.1 {
+ db eval {
+ DELETE FROM t1;
+ INSERT INTO t1 VALUES(0.5);
+ PRAGMA auto_vacuum=OFF;
+ PRAGMA page_size=1024;
+ VACUUM;
+ }
+ hexio_read test.db 2040 8
+ } {3FE0000000000000}
+ do_test nan-3.2 {
+ db eval {
+ SELECT x, typeof(x) FROM t1
+ }
+ } {0.5 real}
+ do_test nan-3.3 {
+ db close
+ hexio_write test.db 2040 FFF8000000000000
+ sqlite3 db test.db
+ db eval {SELECT x, typeof(x) FROM t1}
+ } {{} null}
+ do_test nan-3.4 {
+ db close
+ hexio_write test.db 2040 7FF8000000000000
+ sqlite3 db test.db
+ db eval {SELECT x, typeof(x) FROM t1}
+ } {{} null}
+ do_test nan-3.5 {
+ db close
+ hexio_write test.db 2040 FFFFFFFFFFFFFFFF
+ sqlite3 db test.db
+ db eval {SELECT x, typeof(x) FROM t1}
+ } {{} null}
+ do_test nan-3.6 {
+ db close
+ hexio_write test.db 2040 7FFFFFFFFFFFFFFF
+ sqlite3 db test.db
+ db eval {SELECT x, typeof(x) FROM t1}
+ } {{} null}
+}
# Verify that the sqlite3AtoF routine is able to handle extreme
# numbers.
diff --git a/test/nolock.test b/test/nolock.test
index 331af08ad..fdaef6ef0 100644
--- a/test/nolock.test
+++ b/test/nolock.test
@@ -182,4 +182,36 @@ do_test nolock-3.12 {
db2 close
db close
tvfs delete
+
+# 2016-03-11: Make sure all works when transitioning to WAL mode under nolock.
+#
+do_test nolock-4.1 {
+ forcedelete test.db
+ sqlite3 db file:test.db?nolock=1 -uri 1
+ db eval {
+ PRAGMA journal_mode=WAL;
+ CREATE TABLE t1(x);
+ INSERT INTO t1 VALUES('youngling');
+ SELECT * FROM t1;
+ }
+} {delete youngling}
+db close
+
+do_test nolock-4.2 {
+ forcedelete test.db
+ sqlite3 db test.db
+ db eval {
+ PRAGMA journal_mode=WAL;
+ CREATE TABLE t1(x);
+ INSERT INTO t1 VALUES('catbird');
+ SELECT * FROM t1;
+ }
+} {wal catbird}
+do_test nolock-4.3 {
+ db close
+ sqlite3 db file:test.db?nolock=1 -uri 1
+ set rc [catch {db eval {SELECT * FROM t1}} msg]
+ lappend rc $msg
+} {1 {unable to open database file}}
+
finish_test
diff --git a/test/pager1.test b/test/pager1.test
index bc9ad83fd..c25c837b6 100644
--- a/test/pager1.test
+++ b/test/pager1.test
@@ -1396,26 +1396,47 @@ do_test pager1-9.3.1 {
execsql { PRAGMA page_size = 1024 }
for {set ii 0} {$ii < 4} {incr ii} { execsql "CREATE TABLE t${ii}(a, b)" }
} {}
-do_test pager1-9.3.2 {
- sqlite3 db2 test.db2
-
- execsql {
- PRAGMA page_size = 4096;
- PRAGMA synchronous = OFF;
- CREATE TABLE t1(a, b);
- CREATE TABLE t2(a, b);
- } db2
-
- sqlite3_backup B db2 main db main
- B step 30
- list [B step 10000] [B finish]
-} {SQLITE_DONE SQLITE_OK}
-do_test pager1-9.3.3 {
- db2 close
- db close
- tv delete
- file size test.db2
-} [file size test.db]
+if {[nonzero_reserved_bytes]} {
+ # backup with a page size changes is not possible with the codec
+ #
+ do_test pager1-9.3.2codec {
+ sqlite3 db2 test.db2
+ execsql {
+ PRAGMA page_size = 4096;
+ PRAGMA synchronous = OFF;
+ CREATE TABLE t1(a, b);
+ CREATE TABLE t2(a, b);
+ } db2
+ sqlite3_backup B db2 main db main
+ B step 30
+ list [B step 10000] [B finish]
+ } {SQLITE_READONLY SQLITE_READONLY}
+ do_test pager1-9.3.3codec {
+ db2 close
+ db close
+ tv delete
+ file size test.db2
+ } [file size test.db2]
+} else {
+ do_test pager1-9.3.2 {
+ sqlite3 db2 test.db2
+ execsql {
+ PRAGMA page_size = 4096;
+ PRAGMA synchronous = OFF;
+ CREATE TABLE t1(a, b);
+ CREATE TABLE t2(a, b);
+ } db2
+ sqlite3_backup B db2 main db main
+ B step 30
+ list [B step 10000] [B finish]
+ } {SQLITE_DONE SQLITE_OK}
+ do_test pager1-9.3.3 {
+ db2 close
+ db close
+ tv delete
+ file size test.db2
+ } [file size test.db]
+}
do_test pager1-9.4.1 {
faultsim_delete_and_reopen
@@ -2447,13 +2468,23 @@ do_test pager1-29.1 {
}
file size test.db
} [expr 1024*3]
-do_test pager1-29.2 {
- execsql {
- PRAGMA page_size = 4096;
- VACUUM;
- }
- file size test.db
-} [expr 4096*3]
+if {[nonzero_reserved_bytes]} {
+ # VACUUM with size changes is not possible with the codec.
+ do_test pager1-29.2 {
+ catchsql {
+ PRAGMA page_size = 4096;
+ VACUUM;
+ }
+ } {1 {attempt to write a readonly database}}
+} else {
+ do_test pager1-29.2 {
+ execsql {
+ PRAGMA page_size = 4096;
+ VACUUM;
+ }
+ file size test.db
+ } [expr 4096*3]
+}
#-------------------------------------------------------------------------
# Test that if an empty database file (size 0 bytes) is opened in
diff --git a/test/pageropt.test b/test/pageropt.test
index 7191661ba..f58b8ee78 100644
--- a/test/pageropt.test
+++ b/test/pageropt.test
@@ -16,12 +16,17 @@
set testdir [file dirname $argv0]
source $testdir/tester.tcl
+do_not_use_codec
ifcapable {!pager_pragmas||secure_delete||direct_read} {
finish_test
return
}
+# A non-zero reserved_bytes value changes the number of pages in the
+# database file, which messes up the results in this test.
+if {[nonzero_reserved_bytes]} {finish_test; return;}
+
# Run the SQL statement supplied by the argument and return
# the results. Prepend four integers to the beginning of the
# result which are
diff --git a/test/permutations.test b/test/permutations.test
index a3fef7f14..308d8bde7 100644
--- a/test/permutations.test
+++ b/test/permutations.test
@@ -1092,12 +1092,12 @@ proc help {} {
exit -1
}
-if {[info script] == $argv0} {
+if {[file tail $argv0] == "permutations.test"} {
proc main {argv} {
if {[llength $argv]==0} {
help
} else {
- set suite [lindex $argv 0]
+ set suite [file tail [lindex $argv 0]]
if {[info exists ::testspec($suite)]==0} help
set extra ""
if {[llength $argv]>1} { set extra [list -files [lrange $argv 1 end]] }
diff --git a/test/pragma.test b/test/pragma.test
index befa5cf54..acbe74599 100644
--- a/test/pragma.test
+++ b/test/pragma.test
@@ -1741,73 +1741,75 @@ forcedelete data_dir
} ;# endif windows
database_may_be_corrupt
+if {![nonzero_reserved_bytes]} {
-do_test 21.1 {
- # Create a corrupt database in testerr.db. And a non-corrupt at test.db.
- #
- db close
- forcedelete test.db
- sqlite3 db test.db
- execsql {
- PRAGMA page_size = 1024;
- PRAGMA auto_vacuum = 0;
- CREATE TABLE t1(a PRIMARY KEY, b);
- INSERT INTO t1 VALUES(1, 1);
- }
- for {set i 0} {$i < 10} {incr i} {
- execsql { INSERT INTO t1 SELECT a + (1 << $i), b + (1 << $i) FROM t1 }
- }
- db close
- forcecopy test.db testerr.db
- hexio_write testerr.db 15000 [string repeat 55 100]
-} {100}
-
-set mainerr {*** in database main ***
+ do_test 21.1 {
+ # Create a corrupt database in testerr.db. And a non-corrupt at test.db.
+ #
+ db close
+ forcedelete test.db
+ sqlite3 db test.db
+ execsql {
+ PRAGMA page_size = 1024;
+ PRAGMA auto_vacuum = 0;
+ CREATE TABLE t1(a PRIMARY KEY, b);
+ INSERT INTO t1 VALUES(1, 1);
+ }
+ for {set i 0} {$i < 10} {incr i} {
+ execsql { INSERT INTO t1 SELECT a + (1 << $i), b + (1 << $i) FROM t1 }
+ }
+ db close
+ forcecopy test.db testerr.db
+ hexio_write testerr.db 15000 [string repeat 55 100]
+ } {100}
+
+ set mainerr {*** in database main ***
Multiple uses for byte 672 of page 15}
-set auxerr {*** in database aux ***
+ set auxerr {*** in database aux ***
Multiple uses for byte 672 of page 15}
-
-set mainerr {/{\*\*\* in database main \*\*\*
+
+ set mainerr {/{\*\*\* in database main \*\*\*
Multiple uses for byte 672 of page 15}.*/}
-set auxerr {/{\*\*\* in database aux \*\*\*
+ set auxerr {/{\*\*\* in database aux \*\*\*
Multiple uses for byte 672 of page 15}.*/}
-
-do_test 22.2 {
- catch { db close }
- sqlite3 db testerr.db
- execsql { PRAGMA integrity_check }
-} $mainerr
-
-do_test 22.3.1 {
- catch { db close }
- sqlite3 db test.db
- execsql {
- ATTACH 'testerr.db' AS 'aux';
- PRAGMA integrity_check;
- }
-} $auxerr
-do_test 22.3.2 {
- execsql { PRAGMA main.integrity_check; }
-} {ok}
-do_test 22.3.3 {
- execsql { PRAGMA aux.integrity_check; }
-} $auxerr
-
-do_test 22.4.1 {
- catch { db close }
- sqlite3 db testerr.db
- execsql {
- ATTACH 'test.db' AS 'aux';
- PRAGMA integrity_check;
- }
-} $mainerr
-do_test 22.4.2 {
- execsql { PRAGMA main.integrity_check; }
-} $mainerr
-do_test 22.4.3 {
- execsql { PRAGMA aux.integrity_check; }
-} {ok}
-
+
+ do_test 22.2 {
+ catch { db close }
+ sqlite3 db testerr.db
+ execsql { PRAGMA integrity_check }
+ } $mainerr
+
+ do_test 22.3.1 {
+ catch { db close }
+ sqlite3 db test.db
+ execsql {
+ ATTACH 'testerr.db' AS 'aux';
+ PRAGMA integrity_check;
+ }
+ } $auxerr
+ do_test 22.3.2 {
+ execsql { PRAGMA main.integrity_check; }
+ } {ok}
+ do_test 22.3.3 {
+ execsql { PRAGMA aux.integrity_check; }
+ } $auxerr
+
+ do_test 22.4.1 {
+ catch { db close }
+ sqlite3 db testerr.db
+ execsql {
+ ATTACH 'test.db' AS 'aux';
+ PRAGMA integrity_check;
+ }
+ } $mainerr
+ do_test 22.4.2 {
+ execsql { PRAGMA main.integrity_check; }
+ } $mainerr
+ do_test 22.4.3 {
+ execsql { PRAGMA aux.integrity_check; }
+ } {ok}
+}
+
db close
forcedelete test.db test.db-wal test.db-journal
sqlite3 db test.db
diff --git a/test/pragma3.test b/test/pragma3.test
index b7ea4d3fc..1a67d7235 100644
--- a/test/pragma3.test
+++ b/test/pragma3.test
@@ -15,6 +15,7 @@
set testdir [file dirname $argv0]
source $testdir/tester.tcl
+do_not_use_codec
do_execsql_test pragma3-100 {
PRAGMA data_version;
diff --git a/test/select4.test b/test/select4.test
index be8d0e0ab..1f29f2907 100644
--- a/test/select4.test
+++ b/test/select4.test
@@ -12,7 +12,6 @@
# focus of this file is testing UNION, INTERSECT and EXCEPT operators
# in SELECT statements.
#
-# $Id: select4.test,v 1.30 2009/04/16 00:24:24 drh Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
@@ -936,4 +935,40 @@ do_execsql_test select4-15.1 {
ORDER BY 1;
} {1 33 456 2 33 789}
+# Enhancement (2016-03-15): Use a co-routine for subqueries if the
+# subquery is guaranteed to be the outer-most query
+#
+do_execsql_test select4-16.1 {
+ DROP TABLE IF EXISTS t1;
+ CREATE TABLE t1(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,
+ PRIMARY KEY(a,b DESC)) WITHOUT ROWID;
+
+ WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<100)
+ INSERT INTO t1(a,b,c,d)
+ SELECT x%10, x/10, x, printf('xyz%dabc',x) FROM c;
+
+ SELECT t3.c FROM
+ (SELECT a,max(b) AS m FROM t1 WHERE a>=5 GROUP BY a) AS t2
+ JOIN t1 AS t3
+ WHERE t2.a=t3.a AND t2.m=t3.b
+ ORDER BY t3.a;
+} {95 96 97 98 99}
+do_execsql_test select4-16.2 {
+ SELECT t3.c FROM
+ (SELECT a,max(b) AS m FROM t1 WHERE a>=5 GROUP BY a) AS t2
+ CROSS JOIN t1 AS t3
+ WHERE t2.a=t3.a AND t2.m=t3.b
+ ORDER BY t3.a;
+} {95 96 97 98 99}
+do_execsql_test select4-16.3 {
+ SELECT t3.c FROM
+ (SELECT a,max(b) AS m FROM t1 WHERE a>=5 GROUP BY a) AS t2
+ LEFT JOIN t1 AS t3
+ WHERE t2.a=t3.a AND t2.m=t3.b
+ ORDER BY t3.a;
+} {95 96 97 98 99}
+
+
+
+
finish_test
diff --git a/test/shell1.test b/test/shell1.test
index 1b9ea1d38..1f1f3de32 100644
--- a/test/shell1.test
+++ b/test/shell1.test
@@ -21,15 +21,7 @@
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
-if {$tcl_platform(platform)=="windows"} {
- set CLI "sqlite3.exe"
-} else {
- set CLI "./sqlite3"
-}
-if {![file executable $CLI]} {
- finish_test
- return
-}
+set CLI [test_find_cli]
db close
forcedelete test.db test.db-journal test.db-wal
sqlite3 db test.db
diff --git a/test/shell2.test b/test/shell2.test
index 616610bd4..9388b719b 100644
--- a/test/shell2.test
+++ b/test/shell2.test
@@ -20,15 +20,7 @@
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
-if {$tcl_platform(platform)=="windows"} {
- set CLI "sqlite3.exe"
-} else {
- set CLI "./sqlite3"
-}
-if {![file executable $CLI]} {
- finish_test
- return
-}
+set CLI [test_find_cli]
db close
forcedelete test.db test.db-journal test.db-wal
sqlite3 db test.db
diff --git a/test/shell3.test b/test/shell3.test
index ce1fd4ecb..3ded8f5cc 100644
--- a/test/shell3.test
+++ b/test/shell3.test
@@ -21,15 +21,7 @@
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
-if {$tcl_platform(platform)=="windows"} {
- set CLI "sqlite3.exe"
-} else {
- set CLI "./sqlite3"
-}
-if {![file executable $CLI]} {
- finish_test
- return
-}
+set CLI [test_find_cli]
db close
forcedelete test.db test.db-journal test.db-wal
sqlite3 db test.db
diff --git a/test/shell4.test b/test/shell4.test
index 18e7d7fdf..3e4ae5581 100644
--- a/test/shell4.test
+++ b/test/shell4.test
@@ -21,15 +21,7 @@
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
-if {$tcl_platform(platform)=="windows"} {
- set CLI "sqlite3.exe"
-} else {
- set CLI "./sqlite3"
-}
-if {![file executable $CLI]} {
- finish_test
- return
-}
+set CLI [test_find_cli]
db close
forcedelete test.db test.db-journal test.db-wal
sqlite3 db test.db
diff --git a/test/shell5.test b/test/shell5.test
index b921accca..bb2511a52 100644
--- a/test/shell5.test
+++ b/test/shell5.test
@@ -21,15 +21,7 @@
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
-if {$tcl_platform(platform)=="windows"} {
- set CLI "sqlite3.exe"
-} else {
- set CLI "./sqlite3"
-}
-if {![file executable $CLI]} {
- finish_test
- return
-}
+set CLI [test_find_cli]
db close
forcedelete test.db test.db-journal test.db-wal
diff --git a/test/spellfix3.test b/test/spellfix3.test
index ce002edd4..e24ea31ee 100644
--- a/test/spellfix3.test
+++ b/test/spellfix3.test
@@ -35,9 +35,18 @@ do_execsql_test 140 {
} {160}
do_execsql_test 200 {
SELECT spellfix1_scriptcode('+3.14159');
-} {999}
+} {215}
do_execsql_test 210 {
SELECT spellfix1_scriptcode('And God said: "Да будет свет"');
} {998}
+do_execsql_test 220 {
+ SELECT spellfix1_scriptcode('+3.14159 light');
+} {215}
+do_execsql_test 230 {
+ SELECT spellfix1_scriptcode('+3.14159 свет');
+} {220}
+do_execsql_test 240 {
+ SELECT spellfix1_scriptcode('וַיֹּ֥אמֶר +3.14159');
+} {125}
finish_test
diff --git a/test/stat.test b/test/stat.test
index 288153dbb..95586e94b 100644
--- a/test/stat.test
+++ b/test/stat.test
@@ -21,6 +21,10 @@ ifcapable !vtab||!compound {
return
}
+# This module uses hard-coded results that depend on exact measurements of
+# pages sizes at the byte level, and hence will not work if the reserved_bytes
+# value is nonzero.
+if {[nonzero_reserved_bytes]} {finish_test; return;}
set ::asc 1
proc a_string {n} { string range [string repeat [incr ::asc]. $n] 1 $n }
diff --git a/test/superlock.test b/test/superlock.test
index 8199d5218..704b0677a 100644
--- a/test/superlock.test
+++ b/test/superlock.test
@@ -15,6 +15,7 @@ source $testdir/tester.tcl
source $testdir/lock_common.tcl
set testprefix superlock
+do_not_use_codec
# Test organization:
#
@@ -238,13 +239,23 @@ db_swap test.db2 test.db
do_catchsql_test 6.9 { SELECT * FROM t1 } {0 {1 2 3 4}}
do_catchsql_test 6.10 { SELECT * FROM t2 } {1 {no such table: t2}}
-do_execsql_test 6.11 {
- PRAGMA journal_mode = delete;
- PRAGMA page_size = 512;
- VACUUM;
- PRAGMA journal_mode = wal;
- INSERT INTO t1 VALUES(5, 6);
-} {delete wal}
+if {[nonzero_reserved_bytes]} {
+ # Vacuum with a size change is not allowed with the codec
+ do_execsql_test 6.11codec {
+ PRAGMA journal_mode = delete;
+ VACUUM;
+ PRAGMA journal_mode = wal;
+ INSERT INTO t1 VALUES(5, 6);
+ } {delete wal}
+} else {
+ do_execsql_test 6.11 {
+ PRAGMA journal_mode = delete;
+ PRAGMA page_size = 512;
+ VACUUM;
+ PRAGMA journal_mode = wal;
+ INSERT INTO t1 VALUES(5, 6);
+ } {delete wal}
+}
db_swap test.db2 test.db
do_catchsql_test 6.12 { SELECT * FROM t1 } {1 {no such table: t1}}
diff --git a/test/tclsqlite.test b/test/tclsqlite.test
index 8ce8e9c42..44d5c5634 100644
--- a/test/tclsqlite.test
+++ b/test/tclsqlite.test
@@ -22,10 +22,9 @@ source $testdir/tester.tcl
# Check the error messages generated by tclsqlite
#
+set r "sqlite_orig HANDLE FILENAME ?-vfs VFSNAME? ?-readonly BOOLEAN? ?-create BOOLEAN? ?-nomutex BOOLEAN? ?-fullmutex BOOLEAN? ?-uri BOOLEAN?"
if {[sqlite3 -has-codec]} {
- set r "sqlite_orig HANDLE FILENAME ?-key CODEC-KEY?"
-} else {
- set r "sqlite_orig HANDLE FILENAME ?-vfs VFSNAME? ?-readonly BOOLEAN? ?-create BOOLEAN? ?-nomutex BOOLEAN? ?-fullmutex BOOLEAN? ?-uri BOOLEAN?"
+ append r " ?-key CODECKEY?"
}
do_test tcl-1.1 {
set v [catch {sqlite3 bogus} msg]
diff --git a/test/tester.tcl b/test/tester.tcl
index 47a71debe..dc0c73eab 100644
--- a/test/tester.tcl
+++ b/test/tester.tcl
@@ -374,6 +374,12 @@ proc do_not_use_codec {} {
reset_db
}
+# Return true if the "reserved_bytes" integer on database files is non-zero.
+#
+proc nonzero_reserved_bytes {} {
+ return [sqlite3 -has-codec]
+}
+
# Print a HELP message and exit
#
proc print_help_and_quit {} {
@@ -411,6 +417,8 @@ if {[info exists cmdlinearg]==0} {
# --match=$pattern
# --verbose=$val
# --output=$filename
+ # -q Reduce output
+ # --testdir=$dir Run tests in subdirectory $dir
# --help
#
set cmdlinearg(soft-heap-limit) 0
@@ -425,6 +433,7 @@ if {[info exists cmdlinearg]==0} {
set cmdlinearg(match) ""
set cmdlinearg(verbose) ""
set cmdlinearg(output) ""
+ set cmdlinearg(testdir) "testdir"
set leftover [list]
foreach a $argv {
@@ -454,6 +463,7 @@ if {[info exists cmdlinearg]==0} {
}
{^-+binarylog=.+$} {
foreach {dummy cmdlinearg(binarylog)} [split $a =] break
+ set cmdlinearg(binarylog) [file normalize $cmdlinearg(binarylog)]
}
{^-+soak=.+$} {
foreach {dummy cmdlinearg(soak)} [split $a =] break
@@ -486,6 +496,7 @@ if {[info exists cmdlinearg]==0} {
{^-+output=.+$} {
foreach {dummy cmdlinearg(output)} [split $a =] break
+ set cmdlinearg(output) [file normalize $cmdlinearg(output)]
if {$cmdlinearg(verbose)==""} {
set cmdlinearg(verbose) 2
}
@@ -498,6 +509,9 @@ if {[info exists cmdlinearg]==0} {
error "option --verbose= must be set to a boolean or to \"file\""
}
}
+ {^-+testdir=.*$} {
+ foreach {dummy cmdlinearg(testdir)} [split $a =] break
+ }
{.*help.*} {
print_help_and_quit
}
@@ -507,10 +521,18 @@ if {[info exists cmdlinearg]==0} {
}
default {
- lappend leftover $a
+ lappend leftover [file normalize $a]
}
}
}
+ set testdir [file normalize $testdir]
+ set cmdlinearg(TESTFIXTURE_HOME) [pwd]
+ set cmdlinearg(INFO_SCRIPT) [file normalize [info script]]
+ set argv0 [file normalize $argv0]
+ if {$cmdlinearg(testdir)!=""} {
+ file mkdir $cmdlinearg(testdir)
+ cd $cmdlinearg(testdir)
+ }
set argv $leftover
# Install the malloc layer used to inject OOM errors. And the 'automatic'
@@ -2120,6 +2142,24 @@ proc test_restore_config_pagecache {} {
sqlite3 db test.db
}
+# Find the name of the 'shell' executable (e.g. "sqlite3.exe") to use for
+# the tests in shell[1-5].test. If no such executable can be found, invoke
+# [finish_test ; return] in the callers context.
+#
+proc test_find_cli {} {
+ if {$::tcl_platform(platform)=="windows"} {
+ set ret "sqlite3.exe"
+ } else {
+ set ret "sqlite3"
+ }
+ set ret [file normalize [file join $::cmdlinearg(TESTFIXTURE_HOME) $ret]]
+ if {![file executable $ret]} {
+ finish_test
+ return -code return
+ }
+ return $ret
+}
+
# If the library is compiled with the SQLITE_DEFAULT_AUTOVACUUM macro set
# to non-zero, then set the global variable $AUTOVACUUM to 1.
set AUTOVACUUM $sqlite_options(default_autovacuum)
diff --git a/test/tkt4018.test b/test/tkt4018.test
index 2bc41d47a..77582a5c4 100644
--- a/test/tkt4018.test
+++ b/test/tkt4018.test
@@ -16,6 +16,7 @@
set testdir [file dirname $argv0]
source $testdir/tester.tcl
+do_not_use_codec
proc testsql {sql} {
set fd [open tf_main.tcl w]
diff --git a/test/unixexcl.test b/test/unixexcl.test
index d6762178d..8e9c4644d 100644
--- a/test/unixexcl.test
+++ b/test/unixexcl.test
@@ -87,6 +87,7 @@ do_multiclient_test tn {
sql1 {
PRAGMA auto_vacuum = 0;
PRAGMA journal_mode = WAL;
+ PRAGMA synchronous = FULL;
CREATE TABLE t1(a, b);
INSERT INTO t1 VALUES(1, 2);
}
diff --git a/test/vtab6.test b/test/vtab6.test
index f8e0935a2..f4504b017 100644
--- a/test/vtab6.test
+++ b/test/vtab6.test
@@ -566,12 +566,12 @@ do_test vtab6-11.4.1 {
catchsql {
SELECT a, b, c FROM ab NATURAL JOIN bc;
}
-} {1 {table ab: xBestIndex returned an invalid plan}}
+} {1 {ab.xBestIndex malfunction}}
do_test vtab6-11.4.2 {
catchsql {
SELECT a, b, c FROM bc NATURAL JOIN ab;
}
-} {1 {table bc: xBestIndex returned an invalid plan}}
+} {1 {bc.xBestIndex malfunction}}
unset ::echo_module_ignore_usable
diff --git a/test/wal.test b/test/wal.test
index 92b65e66b..bb164bb76 100644
--- a/test/wal.test
+++ b/test/wal.test
@@ -1378,6 +1378,7 @@ do_test wal-21.3 {
#-------------------------------------------------------------------------
# Test reading and writing of databases with different page-sizes.
#
+incr ::do_not_use_codec
foreach pgsz {512 1024 2048 4096 8192 16384 32768 65536} {
do_multiclient_test tn [string map [list %PGSZ% $pgsz] {
do_test wal-22.%PGSZ%.$tn.1 {
@@ -1398,6 +1399,7 @@ foreach pgsz {512 1024 2048 4096 8192 16384 32768 65536} {
} {0}
}]
}
+incr ::do_not_use_codec -1
#-------------------------------------------------------------------------
# Test that when 1 or more pages are recovered from a WAL file,
diff --git a/test/wal2.test b/test/wal2.test
index 9d45444d6..4b9bbf315 100644
--- a/test/wal2.test
+++ b/test/wal2.test
@@ -1196,7 +1196,7 @@ foreach {tn sql reslist} {
} {
faultsim_delete_and_reopen
- execsql {PRAGMA auto_vacuum = 0}
+ execsql {PRAGMA auto_vacuum = 0; PRAGMA synchronous = FULL;}
execsql $sql
do_execsql_test wal2-14.$tn.0 { PRAGMA page_size = 4096 } {}
do_execsql_test wal2-14.$tn.1 { PRAGMA journal_mode = WAL } {wal}
diff --git a/test/wal5.test b/test/wal5.test
index 360d9c911..50c517286 100644
--- a/test/wal5.test
+++ b/test/wal5.test
@@ -18,6 +18,7 @@ source $testdir/tester.tcl
source $testdir/lock_common.tcl
source $testdir/wal_common.tcl
ifcapable !wal {finish_test ; return }
+do_not_use_codec
set testprefix wal5
@@ -140,13 +141,13 @@ foreach {testprefix do_wal_checkpoint} {
do_test 1.$tn.7 {
reopen_all
list [db_page_count] [wal_page_count] $::nBusyHandler
- } {7 0 0}
+ } [expr {[nonzero_reserved_bytes]?"/# # 0/":"7 0 0"}]
do_test 1.$tn.8 { sql2 { BEGIN ; SELECT x FROM t1 } } {1 2 3 4 5}
do_test 1.$tn.9 {
sql1 { INSERT INTO t1 VALUES(6, zeroblob(1200)) }
list [db_page_count] [wal_page_count] $::nBusyHandler
- } {7 5 0}
+ } [expr {[nonzero_reserved_bytes]?"/# # #/":"7 5 0"}]
do_test 1.$tn.10 { sql3 { BEGIN ; SELECT x FROM t1 } } {1 2 3 4 5 6}
set ::busy_handler_script {
@@ -157,7 +158,7 @@ foreach {testprefix do_wal_checkpoint} {
do_test 1.$tn.11 {
code1 { do_wal_checkpoint db -mode restart }
list [db_page_count] [wal_page_count] $::nBusyHandler
- } {10 5 8}
+ } [expr {[nonzero_reserved_bytes]?"/# # #/":"10 5 8"}]
do_test 1.$tn.12 { set ::db_file_size } 10
}
diff --git a/test/wal8.test b/test/wal8.test
index 0682fce35..3e5a0c261 100644
--- a/test/wal8.test
+++ b/test/wal8.test
@@ -27,6 +27,7 @@ set testdir [file dirname $argv0]
source $testdir/tester.tcl
set ::testprefix wal8
ifcapable !wal {finish_test ; return }
+do_not_use_codec
db close
forcedelete test.db test.db-wal
diff --git a/test/walbak.test b/test/walbak.test
index 303a628a8..0e0f99953 100644
--- a/test/walbak.test
+++ b/test/walbak.test
@@ -127,6 +127,7 @@ do_test walbak-2.1 {
}
} {}
do_test walbak-2.2 {
+ forcedelete abc.db
db backup abc.db
sqlite3 db2 abc.db
string compare [sig db] [sig db2]
@@ -239,6 +240,7 @@ foreach {tn setup} {
}
} {
+ if {$tn==4 && [sqlite3 -has-codec]} continue
foreach f [glob -nocomplain test.db*] { forcedelete $f }
eval $setup
diff --git a/test/walro.test b/test/walro.test
index 6d920b1e2..f46e44d4c 100644
--- a/test/walro.test
+++ b/test/walro.test
@@ -212,7 +212,7 @@ do_multiclient_test tn {
INSERT INTO t2 SELECT x||y, y||x FROM t2;
}
file size test.db-wal
- } {147800}
+ } [expr {[nonzero_reserved_bytes]?148848:147800}]
do_test 1.4.4.2 {
csql1 { SELECT * FROM t1 }
} {0 {a b c d e f g h i j k l 1 2 3 4 5 6}}
diff --git a/test/where2.test b/test/where2.test
index 434a7bcd9..0a0533506 100644
--- a/test/where2.test
+++ b/test/where2.test
@@ -765,4 +765,15 @@ do_execsql_test where2-13.1 {
SELECT * FROM t13 WHERE (1=2 AND a=3) OR a=4;
} {4 5}
+# https://www.sqlite.org/src/info/5e3c886796e5512e (2016-03-09)
+# Correlated subquery on the RHS of an IN operator
+#
+do_execsql_test where2-14.1 {
+ CREATE TABLE t14a(x INTEGER PRIMARY KEY);
+ INSERT INTO t14a(x) VALUES(1),(2),(3),(4);
+ CREATE TABLE t14b(y INTEGER PRIMARY KEY);
+ INSERT INTO t14b(y) VALUES(1);
+ SELECT x FROM t14a WHERE x NOT IN (SELECT x FROM t14b);
+} {}
+
finish_test
diff --git a/test/zerodamage.test b/test/zerodamage.test
index dccaba816..d781ab89a 100644
--- a/test/zerodamage.test
+++ b/test/zerodamage.test
@@ -112,6 +112,7 @@ ifcapable wal {
db close
sqlite3 db file:test.db?psow=FALSE -uri 1
db eval {
+ PRAGMA synchronous=FULL;
UPDATE t1 SET y=randomblob(50) WHERE x=124;
}
file size test.db-wal
diff --git a/tool/build-all-msvc.bat b/tool/build-all-msvc.bat
index c96708cef..ae8b76af5 100755
--- a/tool/build-all-msvc.bat
+++ b/tool/build-all-msvc.bat
@@ -665,11 +665,13 @@ FOR %%P IN (%PLATFORMS%) DO (
REM are prevented from doing so.
REM
IF NOT DEFINED NOSYMBOLS (
- %__ECHO% XCOPY "%DLL_PDB_FILE_NAME%" "%BINARYDIRECTORY%\%%B\%%D\" %FFLAGS% %DFLAGS%
+ IF EXIST "%DLL_PDB_FILE_NAME%" (
+ %__ECHO% XCOPY "%DLL_PDB_FILE_NAME%" "%BINARYDIRECTORY%\%%B\%%D\" %FFLAGS% %DFLAGS%
- IF ERRORLEVEL 1 (
- ECHO Failed to copy "%DLL_PDB_FILE_NAME%" to "%BINARYDIRECTORY%\%%B\%%D\".
- GOTO errors
+ IF ERRORLEVEL 1 (
+ ECHO Failed to copy "%DLL_PDB_FILE_NAME%" to "%BINARYDIRECTORY%\%%B\%%D\".
+ GOTO errors
+ )
)
)
@@ -722,11 +724,13 @@ FOR %%P IN (%PLATFORMS%) DO (
REM unless we are prevented from doing so.
REM
IF NOT DEFINED NOSYMBOLS (
- %__ECHO% XCOPY "%EXE_PDB_FILE_NAME%" "%BINARYDIRECTORY%\%%B\%%D\" %FFLAGS% %DFLAGS%
+ IF EXIST "%EXE_PDB_FILE_NAME%" (
+ %__ECHO% XCOPY "%EXE_PDB_FILE_NAME%" "%BINARYDIRECTORY%\%%B\%%D\" %FFLAGS% %DFLAGS%
- IF ERRORLEVEL 1 (
- ECHO Failed to copy "%EXE_PDB_FILE_NAME%" to "%BINARYDIRECTORY%\%%B\%%D\".
- GOTO errors
+ IF ERRORLEVEL 1 (
+ ECHO Failed to copy "%EXE_PDB_FILE_NAME%" to "%BINARYDIRECTORY%\%%B\%%D\".
+ GOTO errors
+ )
)
)
)