diff --git a/Makefile.in b/Makefile.in
index 98f88135ef..a10705e7f5 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -545,7 +545,14 @@ TESTPROGS = \
FUZZDATA = \
$(TOP)/test/fuzzdata1.db \
$(TOP)/test/fuzzdata2.db \
- $(TOP)/test/fuzzdata3.db
+ $(TOP)/test/fuzzdata3.db \
+ $(TOP)/test/fuzzdata4.db
+
+# Extra arguments for including json1 in the build of tools
+#
+JSON1_DEP = $(TOP)/ext/misc/json1.c sqlite3ext.h
+JSON1_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_CORE
+JSON1_SRC = $(TOP)/ext/misc/json1.c
# Standard options to testfixture
#
@@ -573,19 +580,20 @@ libtclsqlite3.la: tclsqlite.lo libsqlite3.la
-version-info "8:6:8" \
-avoid-version
-sqlite3$(TEXE): $(TOP)/src/shell.c libsqlite3.la sqlite3.h $(TOP)/ext/misc/json1.c
- $(LTLINK) $(READLINE_FLAGS) -DSQLITE_ENABLE_JSON1 -o $@ \
- $(TOP)/src/shell.c $(TOP)/ext/misc/json1.c libsqlite3.la \
+sqlite3$(TEXE): $(TOP)/src/shell.c libsqlite3.la sqlite3.h $(JSON1_DEP)
+ $(LTLINK) $(READLINE_FLAGS) $(JSON1_OPT) -o $@ \
+ $(TOP)/src/shell.c $(JSON1_SRC) libsqlite3.la \
$(LIBREADLINE) $(TLIBS) -rpath "$(libdir)"
sqldiff$(TEXE): $(TOP)/tool/sqldiff.c sqlite3.c sqlite3.h
$(LTLINK) -o $@ $(TOP)/tool/sqldiff.c sqlite3.c $(TLIBS)
-fuzzershell$(TEXE): $(TOP)/tool/fuzzershell.c sqlite3.c sqlite3.h
- $(LTLINK) -o $@ $(TOP)/tool/fuzzershell.c sqlite3.c $(TLIBS)
+fuzzershell$(TEXE): $(TOP)/tool/fuzzershell.c sqlite3.c sqlite3.h $(JSON1_DEP)
+ $(LTLINK) -o $@ $(JSON1_OPT) \
+ $(TOP)/tool/fuzzershell.c $(JSON1_SRC) sqlite3.c $(TLIBS)
-fuzzcheck$(TEXE): $(TOP)/test/fuzzcheck.c sqlite3.c sqlite3.h
- $(LTLINK) -o $@ $(TOP)/test/fuzzcheck.c sqlite3.c $(TLIBS)
+fuzzcheck$(TEXE): $(TOP)/test/fuzzcheck.c sqlite3.c sqlite3.h $(JSON1_DEP)
+ $(LTLINK) -o $@ $(JSON1_OPT) $(TOP)/test/fuzzcheck.c $(JSON1_SRC) sqlite3.c $(TLIBS)
mptester$(TEXE): sqlite3.c $(TOP)/mptest/mptest.c
$(LTLINK) -o $@ -I. $(TOP)/mptest/mptest.c sqlite3.c \
diff --git a/Makefile.msc b/Makefile.msc
index f8bb61d9b7..7f4ef98ab0 100644
--- a/Makefile.msc
+++ b/Makefile.msc
@@ -1231,7 +1231,14 @@ TESTPROGS = \
FUZZDATA = \
$(TOP)\test\fuzzdata1.db \
$(TOP)\test\fuzzdata2.db \
- $(TOP)\test\fuzzdata3.db
+ $(TOP)\test\fuzzdata3.db \
+ $(TOP)\test\fuzzdata4.db
+
+# Extra arguments for including json1 in the build of tools
+#
+JSON1_DEP = sqlite3ext.h $(TOP)\ext\misc\json1.c
+JSON1_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_CORE
+JSON1_SRC = $(TOP)\ext\misc\json1.c
# Standard options to testfixture
#
@@ -1248,18 +1255,19 @@ libsqlite3.lib: $(LIBOBJ)
libtclsqlite3.lib: tclsqlite.lo libsqlite3.lib
$(LTLIB) $(LTLIBOPTS) $(LTLIBPATHS) /OUT:$@ tclsqlite.lo libsqlite3.lib $(LIBTCL:tcl=tclstub) $(TLIBS)
-sqlite3.exe: $(TOP)\src\shell.c $(TOP)\ext\misc\json1.c $(SHELL_CORE_DEP) $(LIBRESOBJS) sqlite3.h
- $(LTLINK) $(SHELL_COMPILE_OPTS) $(READLINE_FLAGS) $(TOP)\src\shell.c $(TOP)\ext\misc\json1.c \
+sqlite3.exe: $(TOP)\src\shell.c $(JSON1_DEP) $(SHELL_CORE_DEP) $(LIBRESOBJS) sqlite3.h
+ $(LTLINK) $(SHELL_COMPILE_OPTS) $(JSON1_OPT) $(READLINE_FLAGS) $(TOP)\src\shell.c $(JSON1_SRC) \
/link /pdb:sqlite3sh.pdb $(LTLINKOPTS) $(SHELL_LINK_OPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LIBREADLINE) $(LTLIBS) $(TLIBS)
sqldiff.exe: $(TOP)\tool\sqldiff.c sqlite3.c sqlite3.h
$(LTLINK) $(NO_WARN) $(TOP)\tool\sqldiff.c sqlite3.c
-fuzzershell.exe: $(TOP)\tool\fuzzershell.c sqlite3.c sqlite3.h
- $(LTLINK) $(NO_WARN) $(TOP)\tool\fuzzershell.c sqlite3.c
+fuzzershell.exe: $(TOP)\tool\fuzzershell.c sqlite3.c sqlite3.h $(JSON1_DEP)
+ $(LTLINK) $(NO_WARN) $(JSON1_OPT) \
+ $(TOP)\tool\fuzzershell.c $(JSON1_SRC) sqlite3.c
-fuzzcheck.exe: $(TOP)\test\fuzzcheck.c sqlite3.c sqlite3.h
- $(LTLINK) $(NO_WARN) $(TOP)\test\fuzzcheck.c sqlite3.c
+fuzzcheck.exe: $(TOP)\test\fuzzcheck.c sqlite3.c sqlite3.h $(JSON1_DEP)
+ $(LTLINK) $(NO_WARN) $(JSON1_OPT) $(TOP)\test\fuzzcheck.c $(JSON1_SRC) sqlite3.c
mptester.exe: $(TOP)\mptest\mptest.c $(SHELL_CORE_DEP) $(LIBRESOBJS) sqlite3.h
$(LTLINK) $(NO_WARN) $(SHELL_COMPILE_OPTS) $(TOP)\mptest\mptest.c \
@@ -1298,10 +1306,9 @@ mptest: mptester.exe
move vdbe.new tsrc\vdbe.c
echo > .target_source
-sqlite3.c: .target_source $(TOP)\tool\mksqlite3c.tcl
+sqlite3.c: .target_source sqlite3ext.h $(TOP)\tool\mksqlite3c.tcl
$(TCLSH_CMD) $(TOP)\tool\mksqlite3c.tcl $(MKSQLITE3C_ARGS)
copy tsrc\shell.c .
- copy tsrc\sqlite3ext.h .
copy $(TOP)\ext\session\sqlite3session.h .
sqlite3-all.c: sqlite3.c $(TOP)\tool\split-sqlite3c.tcl
@@ -1610,6 +1617,9 @@ parse.c: $(TOP)\src\parse.y lemon.exe $(TOP)\addopcodes.awk
sqlite3.h: $(TOP)\src\sqlite.h.in $(TOP)\manifest.uuid $(TOP)\VERSION
$(TCLSH_CMD) $(TOP)\tool\mksqlite3h.tcl $(TOP:\=/) > sqlite3.h
+sqlite3ext.h: .target_source
+ copy tsrc\sqlite3ext.h .
+
mkkeywordhash.exe: $(TOP)\tool\mkkeywordhash.c
$(BCC) $(NO_WARN) -Fe$@ $(REQ_FEATURE_FLAGS) $(OPT_FEATURE_FLAGS) $(OPTS) \
$(TOP)\tool\mkkeywordhash.c /link $(NLTLINKOPTS) $(NLTLIBPATHS)
diff --git a/ext/fts5/fts5.h b/ext/fts5/fts5.h
index 6872918e94..7d974921d1 100644
--- a/ext/fts5/fts5.h
+++ b/ext/fts5/fts5.h
@@ -384,7 +384,7 @@ struct Fts5ExtensionApi {
** FTS index corresponding to both forms of the first token.
**
**
-** Whether is is parsing document or query text, any call to xToken that
+** Whether it is parsing document or query text, any call to xToken that
** specifies a tflags argument with the FTS5_TOKEN_COLOCATED bit
** is considered to supply a synonym for the previous token. For example,
** when parsing the document "I won first place", a tokenizer that supports
diff --git a/ext/fts5/fts5_main.c b/ext/fts5/fts5_main.c
index 5590816bc2..3d4741f95f 100644
--- a/ext/fts5/fts5_main.c
+++ b/ext/fts5/fts5_main.c
@@ -1116,6 +1116,7 @@ static int fts5FilterMethod(
rc = fts5CursorFirst(pTab, pCsr, bDesc);
}else if( pMatch ){
const char *zExpr = (const char*)sqlite3_value_text(apVal[0]);
+ if( zExpr==0 ) zExpr = "";
rc = fts5CursorParseRank(pConfig, pCsr, pRank);
if( rc==SQLITE_OK ){
diff --git a/ext/fts5/test/fts5simple.test b/ext/fts5/test/fts5simple.test
index c93519e6b9..6a980c1b19 100644
--- a/ext/fts5/test/fts5simple.test
+++ b/ext/fts5/test/fts5simple.test
@@ -169,5 +169,21 @@ do_execsql_test 5.8 {
SELECT rowid FROM tt WHERE tt MATCH 'a*';
} {1}
+#-------------------------------------------------------------------------
+
+reset_db
+do_execsql_test 6.1 {
+ CREATE VIRTUAL TABLE xyz USING fts5(x, y, z);
+ INSERT INTO xyz VALUES('x', 'y', 'z');
+}
+
+do_catchsql_test 6.2 {
+ SELECT * FROM xyz WHERE xyz MATCH ''
+} {1 {fts5: syntax error near ""}}
+do_catchsql_test 6.3 {
+ SELECT * FROM xyz WHERE xyz MATCH NULL
+} {1 {fts5: syntax error near ""}}
+
+
finish_test
diff --git a/ext/misc/json1.c b/ext/misc/json1.c
index ca6021733c..89b70f0838 100644
--- a/ext/misc/json1.c
+++ b/ext/misc/json1.c
@@ -33,6 +33,38 @@ SQLITE_EXTENSION_INIT1
#define UNUSED_PARAM(X) (void)(X)
+/*
+** Versions of isspace(), isalnum() and isdigit() to which it is safe
+** to pass signed char values.
+*/
+#define safe_isdigit(x) isdigit((unsigned char)(x))
+#define safe_isalnum(x) isalnum((unsigned char)(x))
+
+/*
+** Growing our own isspace() routine this way is twice as fast as
+** the library isspace() function, resulting in a 7% overall performance
+** increase for the parser. (Ubuntu14.10 gcc 4.8.4 x64 with -Os).
+*/
+static const char jsonIsSpace[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+};
+#define safe_isspace(x) (jsonIsSpace[(unsigned char)x])
+
/* Unsigned integer types */
typedef sqlite3_uint64 u64;
typedef unsigned int u32;
@@ -148,11 +180,9 @@ static void jsonReset(JsonString *p){
/* Report an out-of-memory (OOM) condition
*/
static void jsonOom(JsonString *p){
- if( !p->bErr ){
- p->bErr = 1;
- sqlite3_result_error_nomem(p->pCtx);
- jsonReset(p);
- }
+ p->bErr = 1;
+ sqlite3_result_error_nomem(p->pCtx);
+ jsonReset(p);
}
/* Enlarge pJson->zBuf so that it can hold at least N more bytes.
@@ -231,12 +261,13 @@ static void jsonAppendString(JsonString *p, const char *zIn, u32 N){
for(i=0; inUsed+N+1-i > p->nAlloc) && jsonGrow(p,N+1-i)!=0 ) return;
+ if( (p->nUsed+N+3-i > p->nAlloc) && jsonGrow(p,N+3-i)!=0 ) return;
p->zBuf[p->nUsed++] = '\\';
}
p->zBuf[p->nUsed++] = c;
}
p->zBuf[p->nUsed++] = '"';
+ assert( p->nUsednAlloc );
}
/*
@@ -334,7 +365,8 @@ static void jsonRenderNode(
sqlite3_value **aReplace /* Replacement values */
){
switch( pNode->eType ){
- case JSON_NULL: {
+ default: {
+ assert( pNode->eType==JSON_NULL );
jsonAppendRaw(pOut, "null", 4);
break;
}
@@ -432,7 +464,8 @@ static void jsonReturn(
sqlite3_value **aReplace /* Array of replacement values */
){
switch( pNode->eType ){
- case JSON_NULL: {
+ default: {
+ assert( pNode->eType==JSON_NULL );
sqlite3_result_null(pCtx);
break;
}
@@ -459,10 +492,16 @@ static void jsonReturn(
break;
}
case JSON_STRING: {
+#if 0 /* Never happens because JNODE_RAW is only set by json_set(),
+ ** json_insert() and json_replace() and those routines do not
+ ** call jsonReturn() */
if( pNode->jnFlags & JNODE_RAW ){
sqlite3_result_text(pCtx, pNode->u.zJContent, pNode->n,
SQLITE_TRANSIENT);
- }else if( (pNode->jnFlags & JNODE_ESCAPE)==0 ){
+ }else
+#endif
+ assert( (pNode->jnFlags & JNODE_RAW)==0 );
+ if( (pNode->jnFlags & JNODE_ESCAPE)==0 ){
/* JSON formatted without any backslash-escapes */
sqlite3_result_text(pCtx, pNode->u.zJContent+1, pNode->n-2,
SQLITE_TRANSIENT);
@@ -533,6 +572,44 @@ static void jsonReturn(
}
}
+/* Forward reference */
+static int jsonParseAddNode(JsonParse*,u32,u32,const char*);
+
+/*
+** A macro to hint to the compiler that a function should not be
+** inlined.
+*/
+#if defined(__GNUC__)
+# define JSON_NOINLINE __attribute__((noinline))
+#elif defined(_MSC_VER) && _MSC_VER>=1310
+# define JSON_NOINLINE __declspec(noinline)
+#else
+# define JSON_NOINLINE
+#endif
+
+
+static JSON_NOINLINE int jsonParseAddNodeExpand(
+ JsonParse *pParse, /* Append the node to this object */
+ u32 eType, /* Node type */
+ u32 n, /* Content size or sub-node count */
+ const char *zContent /* Content */
+){
+ u32 nNew;
+ JsonNode *pNew;
+ assert( pParse->nNode>=pParse->nAlloc );
+ if( pParse->oom ) return -1;
+ nNew = pParse->nAlloc*2 + 10;
+ pNew = sqlite3_realloc(pParse->aNode, sizeof(JsonNode)*nNew);
+ if( pNew==0 ){
+ pParse->oom = 1;
+ return -1;
+ }
+ pParse->nAlloc = nNew;
+ pParse->aNode = pNew;
+ assert( pParse->nNodenAlloc );
+ return jsonParseAddNode(pParse, eType, n, zContent);
+}
+
/*
** Create a new JsonNode instance based on the arguments and append that
** instance to the JsonParse. Return the index in pParse->aNode[] of the
@@ -546,21 +623,7 @@ static int jsonParseAddNode(
){
JsonNode *p;
if( pParse->nNode>=pParse->nAlloc ){
- u32 nNew;
- JsonNode *pNew;
- if( pParse->oom ) return -1;
- nNew = pParse->nAlloc*2 + 10;
- if( nNew<=pParse->nNode ){
- pParse->oom = 1;
- return -1;
- }
- pNew = sqlite3_realloc(pParse->aNode, sizeof(JsonNode)*nNew);
- if( pNew==0 ){
- pParse->oom = 1;
- return -1;
- }
- pParse->nAlloc = nNew;
- pParse->aNode = pNew;
+ return jsonParseAddNodeExpand(pParse, eType, n, zContent);
}
p = &pParse->aNode[pParse->nNode];
p->eType = (u8)eType;
@@ -585,14 +648,13 @@ static int jsonParseValue(JsonParse *pParse, u32 i){
int iThis;
int x;
JsonNode *pNode;
- while( isspace(pParse->zJson[i]) ){ i++; }
- if( (c = pParse->zJson[i])==0 ) return 0;
- if( c=='{' ){
+ while( safe_isspace(pParse->zJson[i]) ){ i++; }
+ if( (c = pParse->zJson[i])=='{' ){
/* Parse object */
iThis = jsonParseAddNode(pParse, JSON_OBJECT, 0, 0);
if( iThis<0 ) return -1;
for(j=i+1;;j++){
- while( isspace(pParse->zJson[j]) ){ j++; }
+ while( safe_isspace(pParse->zJson[j]) ){ j++; }
x = jsonParseValue(pParse, j);
if( x<0 ){
if( x==(-2) && pParse->nNode==(u32)iThis+1 ) return j+1;
@@ -603,13 +665,13 @@ static int jsonParseValue(JsonParse *pParse, u32 i){
if( pNode->eType!=JSON_STRING ) return -1;
pNode->jnFlags |= JNODE_LABEL;
j = x;
- while( isspace(pParse->zJson[j]) ){ j++; }
+ while( safe_isspace(pParse->zJson[j]) ){ j++; }
if( pParse->zJson[j]!=':' ) return -1;
j++;
x = jsonParseValue(pParse, j);
if( x<0 ) return -1;
j = x;
- while( isspace(pParse->zJson[j]) ){ j++; }
+ while( safe_isspace(pParse->zJson[j]) ){ j++; }
c = pParse->zJson[j];
if( c==',' ) continue;
if( c!='}' ) return -1;
@@ -622,14 +684,14 @@ static int jsonParseValue(JsonParse *pParse, u32 i){
iThis = jsonParseAddNode(pParse, JSON_ARRAY, 0, 0);
if( iThis<0 ) return -1;
for(j=i+1;;j++){
- while( isspace(pParse->zJson[j]) ){ j++; }
+ while( safe_isspace(pParse->zJson[j]) ){ j++; }
x = jsonParseValue(pParse, j);
if( x<0 ){
if( x==(-3) && pParse->nNode==(u32)iThis+1 ) return j+1;
return -1;
}
j = x;
- while( isspace(pParse->zJson[j]) ){ j++; }
+ while( safe_isspace(pParse->zJson[j]) ){ j++; }
c = pParse->zJson[j];
if( c==',' ) continue;
if( c!=']' ) return -1;
@@ -658,17 +720,17 @@ static int jsonParseValue(JsonParse *pParse, u32 i){
return j+1;
}else if( c=='n'
&& strncmp(pParse->zJson+i,"null",4)==0
- && !isalnum(pParse->zJson[i+4]) ){
+ && !safe_isalnum(pParse->zJson[i+4]) ){
jsonParseAddNode(pParse, JSON_NULL, 0, 0);
return i+4;
}else if( c=='t'
&& strncmp(pParse->zJson+i,"true",4)==0
- && !isalnum(pParse->zJson[i+4]) ){
+ && !safe_isalnum(pParse->zJson[i+4]) ){
jsonParseAddNode(pParse, JSON_TRUE, 0, 0);
return i+4;
}else if( c=='f'
&& strncmp(pParse->zJson+i,"false",5)==0
- && !isalnum(pParse->zJson[i+5]) ){
+ && !safe_isalnum(pParse->zJson[i+5]) ){
jsonParseAddNode(pParse, JSON_FALSE, 0, 0);
return i+5;
}else if( c=='-' || (c>='0' && c<='9') ){
@@ -707,6 +769,8 @@ static int jsonParseValue(JsonParse *pParse, u32 i){
return -2; /* End of {...} */
}else if( c==']' ){
return -3; /* End of [...] */
+ }else if( c==0 ){
+ return 0; /* End of file */
}else{
return -1; /* Syntax error */
}
@@ -731,7 +795,7 @@ static int jsonParse(
i = jsonParseValue(pParse, 0);
if( pParse->oom ) i = -1;
if( i>0 ){
- while( isspace(zJson[i]) ) i++;
+ while( safe_isspace(zJson[i]) ) i++;
if( zJson[i] ) i = -1;
}
if( i<=0 ){
@@ -790,6 +854,20 @@ static int jsonParseFindParents(JsonParse *pParse){
return SQLITE_OK;
}
+/*
+** Compare the OBJECT label at pNode against zKey,nKey. Return true on
+** a match.
+*/
+static int jsonLabelCompare(JsonNode *pNode, const char *zKey, int nKey){
+ if( pNode->jnFlags & JNODE_RAW ){
+ if( pNode->n!=nKey ) return 0;
+ return strncmp(pNode->u.zJContent, zKey, nKey)==0;
+ }else{
+ if( pNode->n!=nKey+2 ) return 0;
+ return strncmp(pNode->u.zJContent+1, zKey, nKey)==0;
+ }
+}
+
/* forward declaration */
static JsonNode *jsonLookupAppend(JsonParse*,const char*,int*,const char**);
@@ -820,7 +898,12 @@ static JsonNode *jsonLookupStep(
zKey = zPath + 1;
for(i=1; zPath[i] && zPath[i]!='"'; i++){}
nKey = i-1;
- if( zPath[i] ) i++;
+ if( zPath[i] ){
+ i++;
+ }else{
+ *pzErr = zPath;
+ return 0;
+ }
}else{
zKey = zPath;
for(i=0; zPath[i] && zPath[i]!='.' && zPath[i]!='['; i++){}
@@ -833,9 +916,7 @@ static JsonNode *jsonLookupStep(
j = 1;
for(;;){
while( j<=pRoot->n ){
- if( pRoot[j].n==nKey+2
- && strncmp(&pRoot[j].u.zJContent[1],zKey,nKey)==0
- ){
+ if( jsonLabelCompare(pRoot+j, zKey, nKey) ){
return jsonLookupStep(pParse, iRoot+j+1, &zPath[i], pApnd, pzErr);
}
j++;
@@ -862,19 +943,19 @@ static JsonNode *jsonLookupStep(
}
return pNode;
}
- }else if( zPath[0]=='[' && isdigit(zPath[1]) ){
+ }else if( zPath[0]=='[' && safe_isdigit(zPath[1]) ){
if( pRoot->eType!=JSON_ARRAY ) return 0;
i = 0;
- zPath++;
- while( isdigit(zPath[0]) ){
- i = i*10 + zPath[0] - '0';
- zPath++;
+ j = 1;
+ while( safe_isdigit(zPath[j]) ){
+ i = i*10 + zPath[j] - '0';
+ j++;
}
- if( zPath[0]!=']' ){
+ if( zPath[j]!=']' ){
*pzErr = zPath;
return 0;
}
- zPath++;
+ zPath += j + 1;
j = 1;
for(;;){
while( j<=pRoot->n && (i>0 || (pRoot[j].jnFlags & JNODE_REMOVE)!=0) ){
@@ -902,7 +983,7 @@ static JsonNode *jsonLookupStep(
}
return pNode;
}
- }else if( zPath[0]!=0 ){
+ }else{
*pzErr = zPath;
}
return 0;
@@ -960,6 +1041,7 @@ static JsonNode *jsonLookup(
){
const char *zErr = 0;
JsonNode *pNode = 0;
+ char *zMsg;
if( zPath==0 ) return 0;
if( zPath[0]!='$' ){
@@ -968,18 +1050,17 @@ static JsonNode *jsonLookup(
}
zPath++;
pNode = jsonLookupStep(pParse, 0, zPath, pApnd, &zErr);
- return pNode;
+ if( zErr==0 ) return pNode;
lookup_err:
pParse->nErr++;
- if( zErr!=0 && pCtx!=0 ){
- char *z = jsonPathSyntaxError(zErr);
- if( z ){
- sqlite3_result_error(pCtx, z, -1);
- sqlite3_free(z);
- }else{
- sqlite3_result_error_nomem(pCtx);
- }
+ assert( zErr!=0 && pCtx!=0 );
+ zMsg = jsonPathSyntaxError(zErr);
+ if( zMsg ){
+ sqlite3_result_error(pCtx, zMsg, -1);
+ sqlite3_free(zMsg);
+ }else{
+ sqlite3_result_error_nomem(pCtx);
}
return 0;
}
@@ -1102,23 +1183,22 @@ static void jsonArrayLengthFunc(
JsonParse x; /* The parse */
sqlite3_int64 n = 0;
u32 i;
+ JsonNode *pNode;
if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return;
- if( x.nNode ){
- JsonNode *pNode;
- if( argc==2 ){
- const char *zPath = (const char*)sqlite3_value_text(argv[1]);
- pNode = jsonLookup(&x, zPath, 0, ctx);
- }else{
- pNode = x.aNode;
- }
- if( pNode==0 ){
- x.nErr = 1;
- }else if( pNode->eType==JSON_ARRAY ){
- assert( (pNode->jnFlags & JNODE_APPEND)==0 );
- for(i=1; i<=pNode->n; n++){
- i += jsonNodeSize(&pNode[i]);
- }
+ assert( x.nNode );
+ if( argc==2 ){
+ const char *zPath = (const char*)sqlite3_value_text(argv[1]);
+ pNode = jsonLookup(&x, zPath, 0, ctx);
+ }else{
+ pNode = x.aNode;
+ }
+ if( pNode==0 ){
+ x.nErr = 1;
+ }else if( pNode->eType==JSON_ARRAY ){
+ assert( (pNode->jnFlags & JNODE_APPEND)==0 );
+ for(i=1; i<=pNode->n; n++){
+ i += jsonNodeSize(&pNode[i]);
}
}
if( x.nErr==0 ) sqlite3_result_int64(ctx, n);
@@ -1197,7 +1277,7 @@ static void jsonObjectFunc(
for(i=0; ijnFlags |= JNODE_REMOVE;
- }
- if( (x.aNode[0].jnFlags & JNODE_REMOVE)==0 ){
- jsonReturnJson(x.aNode, ctx, 0);
- }
+ assert( x.nNode );
+ for(i=1; i<(u32)argc; i++){
+ zPath = (const char*)sqlite3_value_text(argv[i]);
+ if( zPath==0 ) goto remove_done;
+ pNode = jsonLookup(&x, zPath, 0, ctx);
+ if( x.nErr ) goto remove_done;
+ if( pNode ) pNode->jnFlags |= JNODE_REMOVE;
+ }
+ if( (x.aNode[0].jnFlags & JNODE_REMOVE)==0 ){
+ jsonReturnJson(x.aNode, ctx, 0);
}
remove_done:
jsonParseReset(&x);
@@ -1269,22 +1348,21 @@ static void jsonReplaceFunc(
return;
}
if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return;
- if( x.nNode ){
- for(i=1; i<(u32)argc; i+=2){
- zPath = (const char*)sqlite3_value_text(argv[i]);
- pNode = jsonLookup(&x, zPath, 0, ctx);
- if( x.nErr ) goto replace_err;
- if( pNode ){
- pNode->jnFlags |= (u8)JNODE_REPLACE;
- pNode->iVal = (u8)(i+1);
- }
- }
- if( x.aNode[0].jnFlags & JNODE_REPLACE ){
- sqlite3_result_value(ctx, argv[x.aNode[0].iVal]);
- }else{
- jsonReturnJson(x.aNode, ctx, argv);
+ assert( x.nNode );
+ for(i=1; i<(u32)argc; i+=2){
+ zPath = (const char*)sqlite3_value_text(argv[i]);
+ pNode = jsonLookup(&x, zPath, 0, ctx);
+ if( x.nErr ) goto replace_err;
+ if( pNode ){
+ pNode->jnFlags |= (u8)JNODE_REPLACE;
+ pNode->iVal = (u8)(i+1);
}
}
+ if( x.aNode[0].jnFlags & JNODE_REPLACE ){
+ sqlite3_result_value(ctx, argv[x.aNode[0].iVal]);
+ }else{
+ jsonReturnJson(x.aNode, ctx, argv);
+ }
replace_err:
jsonParseReset(&x);
}
@@ -1319,27 +1397,26 @@ static void jsonSetFunc(
return;
}
if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return;
- if( x.nNode ){
- for(i=1; i<(u32)argc; i+=2){
- zPath = (const char*)sqlite3_value_text(argv[i]);
- bApnd = 0;
- pNode = jsonLookup(&x, zPath, &bApnd, ctx);
- if( x.oom ){
- sqlite3_result_error_nomem(ctx);
- goto jsonSetDone;
- }else if( x.nErr ){
- goto jsonSetDone;
- }else if( pNode && (bApnd || bIsSet) ){
- pNode->jnFlags |= (u8)JNODE_REPLACE;
- pNode->iVal = (u8)(i+1);
- }
- }
- if( x.aNode[0].jnFlags & JNODE_REPLACE ){
- sqlite3_result_value(ctx, argv[x.aNode[0].iVal]);
- }else{
- jsonReturnJson(x.aNode, ctx, argv);
+ assert( x.nNode );
+ for(i=1; i<(u32)argc; i+=2){
+ zPath = (const char*)sqlite3_value_text(argv[i]);
+ bApnd = 0;
+ pNode = jsonLookup(&x, zPath, &bApnd, ctx);
+ if( x.oom ){
+ sqlite3_result_error_nomem(ctx);
+ goto jsonSetDone;
+ }else if( x.nErr ){
+ goto jsonSetDone;
+ }else if( pNode && (bApnd || bIsSet) ){
+ pNode->jnFlags |= (u8)JNODE_REPLACE;
+ pNode->iVal = (u8)(i+1);
}
}
+ if( x.aNode[0].jnFlags & JNODE_REPLACE ){
+ sqlite3_result_value(ctx, argv[x.aNode[0].iVal]);
+ }else{
+ jsonReturnJson(x.aNode, ctx, argv);
+ }
jsonSetDone:
jsonParseReset(&x);
}
@@ -1358,19 +1435,18 @@ static void jsonTypeFunc(
){
JsonParse x; /* The parse */
const char *zPath;
+ JsonNode *pNode;
if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return;
- if( x.nNode ){
- JsonNode *pNode;
- if( argc==2 ){
- zPath = (const char*)sqlite3_value_text(argv[1]);
- pNode = jsonLookup(&x, zPath, 0, ctx);
- }else{
- pNode = x.aNode;
- }
- if( pNode ){
- sqlite3_result_text(ctx, jsonType[pNode->eType], -1, SQLITE_STATIC);
- }
+ assert( x.nNode );
+ if( argc==2 ){
+ zPath = (const char*)sqlite3_value_text(argv[1]);
+ pNode = jsonLookup(&x, zPath, 0, ctx);
+ }else{
+ pNode = x.aNode;
+ }
+ if( pNode ){
+ sqlite3_result_text(ctx, jsonType[pNode->eType], -1, SQLITE_STATIC);
}
jsonParseReset(&x);
}
@@ -1390,9 +1466,7 @@ static void jsonValidFunc(
int rc = 0;
UNUSED_PARAM(argc);
- if( jsonParse(&x, 0, (const char*)sqlite3_value_text(argv[0]))==0
- && x.nNode>0
- ){
+ if( jsonParse(&x, 0, (const char*)sqlite3_value_text(argv[0]))==0 ){
rc = 1;
}
jsonParseReset(&x);
@@ -1669,7 +1743,7 @@ static int jsonEachColumn(
sqlite3_result_text(ctx, zRoot, -1, SQLITE_STATIC);
break;
}
- default: {
+ case JEACH_JSON: {
assert( i==JEACH_JSON );
sqlite3_result_text(ctx, p->sParse.zJson, -1, SQLITE_STATIC);
break;
@@ -1745,15 +1819,6 @@ static int jsonEachFilter(
if( idxNum==0 ) return SQLITE_OK;
z = (const char*)sqlite3_value_text(argv[0]);
if( z==0 ) return SQLITE_OK;
- if( idxNum&2 ){
- zRoot = (const char*)sqlite3_value_text(argv[1]);
- if( zRoot==0 ) return SQLITE_OK;
- if( zRoot[0]!='$' ){
- sqlite3_free(cur->pVtab->zErrMsg);
- cur->pVtab->zErrMsg = jsonPathSyntaxError(zRoot);
- return cur->pVtab->zErrMsg ? SQLITE_ERROR : SQLITE_NOMEM;
- }
- }
n = sqlite3_value_bytes(argv[0]);
p->zJson = sqlite3_malloc64( n+1 );
if( p->zJson==0 ) return SQLITE_NOMEM;
@@ -1771,15 +1836,21 @@ static int jsonEachFilter(
jsonEachCursorReset(p);
return SQLITE_NOMEM;
}else{
- JsonNode *pNode;
+ JsonNode *pNode = 0;
if( idxNum==3 ){
const char *zErr = 0;
+ zRoot = (const char*)sqlite3_value_text(argv[1]);
+ if( zRoot==0 ) return SQLITE_OK;
n = sqlite3_value_bytes(argv[1]);
p->zRoot = sqlite3_malloc64( n+1 );
if( p->zRoot==0 ) return SQLITE_NOMEM;
memcpy(p->zRoot, zRoot, (size_t)n+1);
- pNode = jsonLookupStep(&p->sParse, 0, p->zRoot+1, 0, &zErr);
- if( p->sParse.nErr ){
+ if( zRoot[0]!='$' ){
+ zErr = zRoot;
+ }else{
+ pNode = jsonLookupStep(&p->sParse, 0, p->zRoot+1, 0, &zErr);
+ }
+ if( zErr ){
sqlite3_free(cur->pVtab->zErrMsg);
cur->pVtab->zErrMsg = jsonPathSyntaxError(zErr);
jsonEachCursorReset(p);
@@ -1796,6 +1867,7 @@ static int jsonEachFilter(
pNode->u.iKey = 0;
p->iEnd = p->i + pNode->n + 1;
if( p->bRecursive ){
+ p->eType = p->sParse.aNode[p->sParse.aUp[p->i]].eType;
if( p->i>0 && (p->sParse.aNode[p->i-1].jnFlags & JNODE_LABEL)!=0 ){
p->i--;
}
@@ -1806,7 +1878,7 @@ static int jsonEachFilter(
p->iEnd = p->i+1;
}
}
- return p->sParse.oom ? SQLITE_NOMEM : SQLITE_OK;
+ return SQLITE_OK;
}
/* The methods of the json_each virtual table */
diff --git a/main.mk b/main.mk
index 7b42c0bfbd..1584f57a6c 100644
--- a/main.mk
+++ b/main.mk
@@ -455,7 +455,14 @@ TESTPROGS = \
FUZZDATA = \
$(TOP)/test/fuzzdata1.db \
$(TOP)/test/fuzzdata2.db \
- $(TOP)/test/fuzzdata3.db
+ $(TOP)/test/fuzzdata3.db \
+ $(TOP)/test/fuzzdata4.db
+
+# Extra arguments for including json1 in the build of tools
+#
+JSON1_DEP = $(TOP)/ext/misc/json1.c sqlite3ext.h
+JSON1_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_CORE
+JSON1_SRC = $(TOP)/ext/misc/json1.c
# Standard options to testfixture
#
@@ -470,23 +477,24 @@ libsqlite3.a: $(LIBOBJ)
$(AR) libsqlite3.a $(LIBOBJ)
$(RANLIB) libsqlite3.a
-sqlite3$(EXE): $(TOP)/src/shell.c libsqlite3.a sqlite3.h $(TOP)/ext/misc/json1.c
- $(TCCX) $(READLINE_FLAGS) -DSQLITE_ENABLE_JSON1 -o sqlite3$(EXE) \
- $(TOP)/src/shell.c $(TOP)/ext/misc/json1.c \
+sqlite3$(EXE): $(TOP)/src/shell.c libsqlite3.a sqlite3.h $(JSON1_DEP)
+ $(TCCX) $(READLINE_FLAGS) $(JSON1_OPT) -o sqlite3$(EXE) \
+ $(TOP)/src/shell.c $(JSON1_SRC) \
libsqlite3.a $(LIBREADLINE) $(TLIBS) $(THREADLIB)
sqldiff$(EXE): $(TOP)/tool/sqldiff.c sqlite3.c sqlite3.h
$(TCCX) -o sqldiff$(EXE) -DSQLITE_THREADSAFE=0 \
$(TOP)/tool/sqldiff.c sqlite3.c $(TLIBS) $(THREADLIB)
-fuzzershell$(EXE): $(TOP)/tool/fuzzershell.c sqlite3.c sqlite3.h
+fuzzershell$(EXE): $(TOP)/tool/fuzzershell.c sqlite3.c sqlite3.h $(JSON1_DEP)
$(TCCX) -o fuzzershell$(EXE) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
- $(TOP)/tool/fuzzershell.c sqlite3.c $(TLIBS) $(THREADLIB)
+ $(JSON1_OPT) $(TOP)/tool/fuzzershell.c $(JSON1_SRC) sqlite3.c \
+ $(TLIBS) $(THREADLIB)
-fuzzcheck$(EXE): $(TOP)/test/fuzzcheck.c sqlite3.c sqlite3.h
+fuzzcheck$(EXE): $(TOP)/test/fuzzcheck.c sqlite3.c sqlite3.h $(JSON1_DEP)
$(TCCX) -o fuzzcheck$(EXE) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
- -DSQLITE_ENABLE_MEMSYS5 \
- $(TOP)/test/fuzzcheck.c sqlite3.c $(TLIBS) $(THREADLIB)
+ -DSQLITE_ENABLE_MEMSYS5 $(JSON1_OPT) \
+ $(TOP)/test/fuzzcheck.c $(JSON1_SRC) sqlite3.c $(TLIBS) $(THREADLIB)
mptester$(EXE): sqlite3.c $(TOP)/mptest/mptest.c
$(TCCX) -o $@ -I. $(TOP)/mptest/mptest.c sqlite3.c \
diff --git a/manifest b/manifest
index 6e3727b25d..248e5f6dc3 100644
--- a/manifest
+++ b/manifest
@@ -1,9 +1,9 @@
-C Merge\sthe\slatest\strunk\senhancements\swith\sthis\sbranch.
-D 2015-09-15T15:55:15.671
+C Merge\sall\sthe\slatest\strunk\senhancements\sinto\sthe\ssessions\sbranch.
+D 2015-09-24T14:26:51.287
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
-F Makefile.in 00b690660681c22e7ce3a9cbebd69894766ebbd8
+F Makefile.in 5bda8cc6bbd2be407f4ef679f4f235ba47c7a3c0
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
-F Makefile.msc a71cfab97780281290f01b212f907d6d438b7e2d
+F Makefile.msc fd760727d07ba21b5f779c6a056a0c6ea7f40979
F Makefile.vxworks e1b65dea203f054e71653415bd8f96dcaed47858
F README.md 8ecc12493ff9f820cdea6520a9016001cb2e59b7
F VERSION ccfc4d1576dbfdeece0a4372a2e6a2e37d3e7975
@@ -105,7 +105,7 @@ F ext/fts3/unicode/UnicodeData.txt cd07314edb62d49fde34debdaf92fa2aa69011e7
F ext/fts3/unicode/mkunicode.tcl 95cf7ec186e48d4985e433ff8a1c89090a774252
F ext/fts3/unicode/parseunicode.tcl da577d1384810fb4e2b209bf3313074353193e95
F ext/fts5/extract_api_docs.tcl a36e54ec777172ddd3f9a88daf593b00848368e0
-F ext/fts5/fts5.h f04659e0df5af83731b102189a32280f74f4a6bc
+F ext/fts5/fts5.h 98f802fe41481f9d797fce496f0fefcad72c7782
F ext/fts5/fts5Int.h 666aba8432940a8449a3bd4636e898fe906ed95d
F ext/fts5/fts5_aux.c 7a307760a9c57c750d043188ec0bad59f5b5ec7e
F ext/fts5/fts5_buffer.c 64dcaf36a3ebda9e84b7c3b8788887ec325e12a4
@@ -113,7 +113,7 @@ F ext/fts5/fts5_config.c 57ee5fe71578cb494574fc0e6e51acb9a22a8695
F ext/fts5/fts5_expr.c 667faaf14a69a5683ac383acdc8d942cf32c3f93
F ext/fts5/fts5_hash.c 4bf4b99708848357b8a2b5819e509eb6d3df9246
F ext/fts5/fts5_index.c 4fdbc0a321e3a1d73741a623d7aea4db78d6a86d
-F ext/fts5/fts5_main.c 3fa906f6c0177caf8f82862bc70f37b28bb3305c
+F ext/fts5/fts5_main.c 53116cffeb26898832ff7700cc5ebac5fe085d32
F ext/fts5/fts5_storage.c 120f7b143688b5b7710dacbd48cff211609b8059
F ext/fts5/fts5_tcl.c 6da58d6e8f42a93c4486b5ba9b187a7f995dee37
F ext/fts5/fts5_test_mi.c e96be827aa8f571031e65e481251dc1981d608bf
@@ -173,7 +173,7 @@ F ext/fts5/test/fts5rank.test 11dcebba31d822f7e99685b4ea2c2ae3ec0b16f1
F ext/fts5/test/fts5rebuild.test 03935f617ace91ed23a6099c7c74d905227ff29b
F ext/fts5/test/fts5restart.test c17728fdea26e7d0f617d22ad5b4b2862b994c17
F ext/fts5/test/fts5rowid.test 400384798349d658eaf06aefa1e364957d5d4821
-F ext/fts5/test/fts5simple.test f629e24a35a9f31cfb16c9920e8c2316e3d93e94
+F ext/fts5/test/fts5simple.test 967b7144644ad4b40b2526160a5adfa896864c55
F ext/fts5/test/fts5synonym.test cf88c0a56d5ea9591e3939ef1f6e294f7f2d0671
F ext/fts5/test/fts5tokenizer.test ea4df698b35cc427ebf2ba22829d0e28386d8c89
F ext/fts5/test/fts5unicode.test fbef8d8a3b4b88470536cc57604a82ca52e51841
@@ -195,7 +195,7 @@ F ext/misc/eval.c f971962e92ebb8b0a4e6b62949463ee454d88fa2
F ext/misc/fileio.c d4171c815d6543a9edef8308aab2951413cd8d0f
F ext/misc/fuzzer.c 4c84635c71c26cfa7c2e5848cf49fe2d2cfcd767
F ext/misc/ieee754.c b0362167289170627659e84173f5d2e8fee8566e
-F ext/misc/json1.c f35d00fbd79a7e23af18d7630a2fcf22dce3692b
+F ext/misc/json1.c 557d6b2d0c3d26625e686a4b4ef8d4a50b8cec94
F ext/misc/nextchar.c 35c8b8baacb96d92abbb34a83a997b797075b342
F ext/misc/percentile.c bcbee3c061b884eccb80e21651daaae8e1e43c63
F ext/misc/regexp.c af92cdaa5058fcec1451e49becc7ba44dba023dc
@@ -280,7 +280,7 @@ F ext/userauth/userauth.c 5fa3bdb492f481bbc1709fc83c91ebd13460c69e
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60
-F main.mk ffd9a2beb9583da4c54fcd811daf4c770bf9bcfe
+F main.mk 284e224af00642c0e5e9454c4b07ec5c2d7860d5
F mkopcodec.awk c2ff431854d702cdd2d779c9c0d1f58fa16fa4ea
F mkopcodeh.awk 0e7f04a8eb90f92259e47d80110e4e98d7ce337a
F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83
@@ -298,10 +298,10 @@ F src/alter.c 4911e1f18fc11b60edbc6410643e938762969a6a
F src/analyze.c 4c308880cf53c558070cb8513bdff4ffb1a38a77
F src/attach.c e944d0052b577703b9b83aac1638452ff42a8395
F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240
-F src/backup.c 4d9134dc988a87838c06056c89c0e8c4700a0452
+F src/backup.c c3a9c4209439b806c44cf30daf466955727bf46c
F src/bitvec.c d1f21d7d91690747881f03940584f4cc548c9d3d
F src/btmutex.c 45a968cc85afed9b5e6cf55bf1f42f8d18107f79
-F src/btree.c d31008cfbf83e3ae5cb96bae3a00f4b57f244a16
+F src/btree.c 164583151135a3764672c2c25aa8e4fa06bdb12b
F src/btree.h 40189aefdc2b830d25c8b58fd7d56538481bfdd7
F src/btreeInt.h 8177c9ab90d772d6d2c6c517e05bed774b7c92c0
F src/build.c 8a86f4203ac8a9ac0734f242a96f043edffb6018
@@ -310,7 +310,7 @@ F src/complete.c addcd8160b081131005d5bc2d34adf20c1c5c92f
F src/ctime.c 5a0b735dc95604766f5dac73973658eef782ee8b
F src/date.c fb1c99172017dcc8e237339132c91a21a0788584
F src/dbstat.c e637e7a7ff40ef32132a418c6fdf1cfb63aa27c7
-F src/delete.c fb64e308242aa09a47a874f5fd45aa00249208be
+F src/delete.c d14f86935c7ff120f04532af8332c2ca21a7af0c
F src/expr.c 3a76afcdac925294c39903b7002ddb9e5fd29863
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
F src/fkey.c 83e1baba999bed3144ea5a2143fc922edf51135f
@@ -343,25 +343,25 @@ F src/os.c 8fd25588eeba74068d41102d26810e216999b6c8
F src/os.h 3e57a24e2794a94d3cf2342c6d9a884888cd96bf
F src/os_common.h abdb9a191a367793268fe553d25bab894e986a0e
F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa
-F src/os_unix.c 76f493ed71c4154338049dee1bf6e47f69c74a55
-F src/os_win.c 40b3af7a47eb1107d0d69e592bec345a3b7b798a
+F src/os_unix.c fc93d55f96bb978f0b0168c6ea7d6fc60b0e172c
+F src/os_win.c 1716291e5ec2dbfc5a1fe0b32182030f1f7d8acf
F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca
-F src/pager.c 4784012f80b2197c61ff6eaf4f5c7026d93253fd
-F src/pager.h 6d435f563b3f7fcae4b84433b76a6ac2730036e2
+F src/pager.c 2fbeeba28f4e6d08a15bc106f36c43346a81f09e
+F src/pager.h ac213f8143ebfee6a8bfb91cf4ca02c9a83343c5
F src/parse.y f599aa5e871a493330d567ced93de696f61f48f7
F src/pcache.c 24be750c79272e0ca7b6e007bc94999700f3e5ef
F src/pcache.h 9968603796240cdf83da7e7bef76edf90619cea9
-F src/pcache1.c a0c0bb29f7bd720743a16a95eb5dedba3ade15bc
+F src/pcache1.c e822007159d53a7ea7aa040d6e28964ddb6de083
F src/pragma.c d71b813e67bf03f3116b9dd5164fbfd81ec673a2
F src/pragma.h 631a91c8b0e6ca8f051a1d8a4a0da4150e04620a
F src/prepare.c 82e5db1013846a819f198336fed72c44c974e7b1
F src/printf.c 0c4bcdd1c2e2521024f0a69cb5eb334f86b3652a
F src/random.c ba2679f80ec82c4190062d756f22d0c358180696
-F src/resolve.c 3126f7694b8ce0f97282d7dd3a5198b8fa18dce9
+F src/resolve.c 1954a0f01bf65d78d7d559aea3d5c67f33376d91
F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e
-F src/select.c c17613385bc6b095c421b1f30548814f5fd8a9b2
+F src/select.c 36ee14d729e182cd8b6796f980b7ab3fc9bcee72
F src/shell.c 2b29a6f5c1b431eb0d25196e249d7e69b68d5ef0
-F src/sqlite.h.in 6ee38de04d4836a0a5171482aa1655eb70aa4ff9
+F src/sqlite.h.in 627e991195047aebc49f3c895d458f9ac2805e4a
F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad
F src/sqlite3ext.h 64350bf36833a56ad675e27392a913f417c5c308
F src/sqliteInt.h 211b8080f46e7cda9f6df9ab590a7aec1b51d999
@@ -425,7 +425,7 @@ F src/vacuum.c 2ddd5cad2a7b9cef7f9e431b8c7771634c6b1701
F src/vdbe.c b61897b3e827e600f2a773031326471e49205fa5
F src/vdbe.h 67151895e779b35475c6c11b16be2ceb839066c8
F src/vdbeInt.h 42fa34502937071aabd3c0596575ba9776547353
-F src/vdbeapi.c 82973abfc02aaba46ec1020423ffcee66665ee45
+F src/vdbeapi.c f5eda36a5c85ef578957ab4311e8d9b1f51a3552
F src/vdbeaux.c 4cbd4cc79dad0e2c2b9996ae018d79a7330110f4
F src/vdbeblob.c 53ed7f38ab93922038bcfa17aae514dc47752f1e
F src/vdbemem.c 28ab8455ac490373798cf2c21def2c1287942551
@@ -436,9 +436,9 @@ F src/vxworks.h c18586c8edc1bddbc15c004fa16aeb1e1342b4fb
F src/wal.c 18b0ed49830cf04fe2d68224b41838a73ac6cd24
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
F src/walker.c 2e14d17f592d176b6dc879c33fbdec4fbccaa2ba
-F src/where.c 882fb44b36201fafc32dd7d59366f852806b7e70
+F src/where.c d5eed2584542e7f3bc78ddef7809a9d76d14d811
F src/whereInt.h 7892bb54cf9ca0ae5c7e6094491b94c9286dc647
-F src/wherecode.c 186b493599000e640203be0a441223b395dabd24
+F src/wherecode.c 7660e1ad16817a921b099af553f3e1349352d16f
F src/whereexpr.c 2473e4350e30f9b55d1c6a8f66ca23c689f23f1d
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd
@@ -550,7 +550,7 @@ F test/conflict2.test 0d3af4fb534fa1bd020c79960bb56e4d52655f09
F test/conflict3.test dec0634c0f31dec9a4b01c63063e939f0cd21b6b
F test/contrib01.test 2a1cbc0f2f48955d7d073f725765da6fbceda6b4
F test/corrupt.test 141c39ea650c1365e85a49e402fa05cb9617fb97
-F test/corrupt2.test 08cec1e5ffa68a3610306d6068f112d08bc9f090
+F test/corrupt2.test cb787825d761b0f869764d6990531382840de872
F test/corrupt3.test 4b548d0bbe2933bc81d3f54099a05fc4d28aff18
F test/corrupt4.test b99652079d542b21f4965f6248703b983e40fe80
F test/corrupt5.test 8ead52af76006f3286e9396cb41898018ccea107
@@ -560,7 +560,7 @@ F test/corrupt8.test 2399dfe40d2c0c63af86706e30f3e6302a8d0516
F test/corrupt9.test 730a3db08d4ab9aa43392ea30d9c2b4879cbff85
F test/corruptA.test 53e56dafd180addcdadb402244b8cb9771d2ba26
F test/corruptB.test 73a8d6c0b9833697ecf16b63e3c5c05c945b5dec
-F test/corruptC.test 3fcc0f73d2cf2d69befe2d96332b942426a6aae2
+F test/corruptC.test 0c46574f8d4f27ecc799b1b5c4cbf9b1817bce9a
F test/corruptD.test b3c205fac7952b1de645ce44bb02335cd9e3e040
F test/corruptE.test be8e5088c369fc7979c662cd644efdaafc0f7f6d
F test/corruptF.test be9fde98e4c93648f1ba52b74e5318edc8f59fe4
@@ -768,10 +768,11 @@ F test/fuzz2.test 76dc35b32b6d6f965259508508abce75a6c4d7e1
F test/fuzz3.test 53fabcd5f0f430f8b221282f6c12c4d0903c21eb
F test/fuzz_common.tcl a87dfbb88c2a6b08a38e9a070dabd129e617b45b
F test/fuzz_malloc.test 328f70aaca63adf29b4c6f06505ed0cf57ca7c26
-F test/fuzzcheck.c 79980bbc00e19ad44c3ba6699e643348572757a2
+F test/fuzzcheck.c b8eb7ee40f6d28548a0b028e0676293522f3427f
F test/fuzzdata1.db 7ee3227bad0e7ccdeb08a9e6822916777073c664
F test/fuzzdata2.db f03a420d3b822cc82e4f894ca957618fbe9c4973
F test/fuzzdata3.db 1d6044c33a114007f02b6e6846f1fa232f607bfd
+F test/fuzzdata4.db 1882f0055fb63214d8407ddc7aca9b0b1c59af21
F test/fuzzer1.test d4c52aaf3ef923da293a2653cfab33d02f718a36
F test/fuzzerfault.test 8792cd77fd5bce765b05d0c8e01b9edcf8af8536
F test/genesis.tcl 1e2e2e8e5cc4058549a154ff1892fe5c9de19f98
@@ -803,7 +804,7 @@ F test/index5.test 8621491915800ec274609e42e02a97d67e9b13e7
F test/index6.test 7102ec371414c42dfb1d5ca37eb4519aa9edc23a
F test/index7.test 9c6765a74fc3fcde7aebc5b3bd40d98df14a527c
F test/indexedby.test 9c4cd331224e57f79fbf411ae245e6272d415985
-F test/indexexpr1.test 4feec154aadacb033b41acc1760a18edc4c60470
+F test/indexexpr1.test 203c83a05accf6f2b748834192f3564321b8c0d8
F test/indexfault.test 31d4ab9a7d2f6e9616933eb079722362a883eb1d
F test/init.test 15c823093fdabbf7b531fe22cf037134d09587a7
F test/insert.test 38742b5e9601c8f8d76e9b7555f7270288c2d371
@@ -834,8 +835,8 @@ F test/journal3.test ff8af941f9e06161d3db1b46bb9f965ff0e7f307
F test/jrnlmode.test 7864d59cf7f6e552b9b99ba0f38acd167edc10fa
F test/jrnlmode2.test 81610545a4e6ed239ea8fa661891893385e23a1d
F test/jrnlmode3.test 556b447a05be0e0963f4311e95ab1632b11c9eaa
-F test/json101.test e20d2421c531db32fad59c5e06e80af0b1b002c8
-F test/json102.test 4e1403cb06481ab160cf471c3c139820498e0563
+F test/json101.test e8b50fbcdbf283cfafbc42632bf2c7dfa4541c46
+F test/json102.test 796b1c59894c6e0f38fc1a3acb0e690573b952a3
F test/keyword1.test 37ef6bba5d2ed5b07ecdd6810571de2956599dff
F test/lastinsert.test 42e948fd6442f07d60acbd15d33fb86473e0ef63
F test/laststmtchanges.test ae613f53819206b3222771828d024154d51db200
@@ -924,7 +925,7 @@ F test/orderby5.test 8f08a54836d21fb7c70245360751aedd1c2286fb
F test/orderby6.test 8b38138ab0972588240b3fca0985d2e400432859
F test/orderby7.test 3d1383d52ade5b9eb3a173b3147fdd296f0202da
F test/orderby8.test 23ef1a5d72bd3adcc2f65561c654295d1b8047bd
-F test/orderby9.test 88a330ea5fc7bed7e407b28beb0d2b79485ae2cc
+F test/orderby9.test 87fb9548debcc2cd141c5299002dd94672fa76a3
F test/oserror.test 14fec2796c2b6fe431c7823750e8a18a761176d7
F test/ovfl.test 4f7ca651cba5c059a12d8c67dddd49bec5747799
F test/pager1.test 1acbdb14c5952a72dd43129cabdbf69aaa3ed1fa
@@ -960,7 +961,7 @@ F test/rbu.test 168573d353cd0fd10196b87b0caa322c144ef736
F test/rdonly.test 64e2696c322e3538df0b1ed624e21f9a23ed9ff8
F test/regexp1.test 497ea812f264d12b6198d6e50a76be4a1973a9d8
F test/reindex.test 44edd3966b474468b823d481eafef0c305022254
-F test/releasetest.tcl 5af0ca3d6a12471ffd9993c3efc00a553dfb2d41
+F test/releasetest.tcl afdac5c3429dceb034295617c0a51df9954d467a
F test/resolver01.test f4022acafda7f4d40eca94dbf16bc5fc4ac30ceb
F test/rollback.test 458fe73eb3ffdfdf9f6ba3e9b7350a6220414dea
F test/rollback2.test fc14cf6d1a2b250d2735ef16124b971bce152f14
@@ -1047,9 +1048,9 @@ F test/speed4p.explain 6b5f104ebeb34a038b2f714150f51d01143e59aa
F test/speed4p.test 0e51908951677de5a969b723e03a27a1c45db38b
F test/speedtest1.c 857439869d1cb4db35e1c720ee9c2756eb9ea2a0
F test/spellfix.test 0597065ff57042df1f138e6a2611ae19c2698135
-F test/spellfix2.test e5f2bc1dae046dbdd8008f2a84ed7749ff9b325e
+F test/spellfix2.test 1ff48bb65b6198d21674ae24d19bb136e547585a
F test/sqldiff1.test 8f6bc7c6a5b3585d350d779c6078869ba402f8f5
-F test/sqllimits1.test e05786eaed7950ff6a2d00031d001d8a26131e68
+F test/sqllimits1.test 89b3d5aad05b99f707ee3786bdd4416dccf83304
F test/stat.test 8de91498c99f5298b303f70f1d1f3b9557af91bf
F test/statfault.test f525a7bf633e50afd027700e9a486090684b1ac1
F test/stmt.test 25d64e3dbf9a3ce89558667d7f39d966fe2a71b9
@@ -1062,7 +1063,7 @@ F test/superlock.test 1cde669f68d2dd37d6c9bd35eee1d95491ae3fc2
F test/sync.test a34cd43e98b7fb84eabbf38f7ed8f7349b3f3d85
F test/syscall.test d2fdaad713f103ac611fe7ef9b724c7b69f8149c
F test/sysfault.test fa776e60bf46bdd3ae69f0b73e46ee3977a58ae6
-F test/tabfunc01.test fa9d8dfc75747019e0be98d3b6ac68d18632d328
+F test/tabfunc01.test 83e63be7b6e3f67b6a03519c9c61bc68efb25f31
F test/table.test b708f3e5fa2542fa51dfab21fc07b36ea445cb2f
F test/tableapi.test 2674633fa95d80da917571ebdd759a14d9819126
F test/tableopts.test dba698ba97251017b7c80d738c198d39ab747930
@@ -1254,7 +1255,7 @@ F test/types.test bf816ce73c7dfcfe26b700c19f97ef4050d194ff
F test/types2.test 3555aacf8ed8dc883356e59efc314707e6247a84
F test/types3.test 99e009491a54f4dc02c06bdbc0c5eea56ae3e25a
F test/unique.test 93f8b2ef5ea51b9495f8d6493429b1fd0f465264
-F test/unique2.test 41e7f83c6827605991160a31380148a9fc5f1339
+F test/unique2.test 3674e9f2a3f1fbbfd4772ac74b7a97090d0f77d2
F test/unixexcl.test cd6c765f75e50e8e2c2ba763149e5d340ea19825
F test/unordered.test ca7adce0419e4ca0c50f039885e76ed2c531eda8
F test/update.test 6c68446b8a0a33d522a7c72b320934596a2d7d32
@@ -1288,7 +1289,7 @@ F test/vtab_err.test 0d4d8eb4def1d053ac7c5050df3024fd47a3fbd8
F test/vtab_shared.test ea8778d5b0df200adef2ca7c00c3c37d4375f772
F test/wal.test dbfc482e10c7263298833bb1fc60b3ac9d6340a1
F test/wal2.test 1f841d2048080d32f552942e333fd99ce541dada
-F test/wal3.test 2b5445e5da44780b9b44712f5a38523f7aeb0941
+F test/wal3.test 2ab8e490afe0164bfc89b185c8b2572e0d821f23
F test/wal4.test 4744e155cd6299c6bd99d3eab1c82f77db9cdb3c
F test/wal5.test 88b5d9a6a3d1532497ee9f4296f010d66f07e33c
F test/wal6.test 4421cd5a2fa99d29cc91ef12fb23bed171ed3a4c
@@ -1347,7 +1348,7 @@ F test/without_rowid2.test af260339f79d13cb220288b67cd287fbcf81ad99
F test/without_rowid3.test aad4f9d383e199349b6c7e508a778f7dff5dff79
F test/without_rowid4.test 4e08bcbaee0399f35d58b5581881e7a6243d458a
F test/without_rowid5.test 61256715b686359df48ca1742db50cc7e3e7b862
-F test/without_rowid6.test db0dbf03c49030aa3c1ba5f618620334bd2baf5f
+F test/without_rowid6.test 1f99644e6508447fb050f73697350c7ceca3392e
F test/wordcount.c 9915e06cb33d8ca8109b8700791afe80d305afda
F test/zeroblob.test 3857870fe681b8185654414a9bccfde80b62a0fa
F test/zerodamage.test cf6748bad89553cc1632be51a6f54e487e4039ac
@@ -1358,7 +1359,7 @@ F tool/diffdb.c 7524b1b5df217c20cd0431f6789851a4e0cb191b
F tool/extract.c 054069d81b095fbdc189a6f5d4466e40380505e2
F tool/fast_vacuum.c 5ba0d6f5963a0a63bdc42840f678bad75b2ebce1
F tool/fragck.tcl 5265a95126abcf6ab357f7efa544787e5963f439
-F tool/fuzzershell.c f2fc86dd22df654b28851b85019d3bd007361751
+F tool/fuzzershell.c 87cc3d6f00239d786d231954289f106131989cc7
F tool/genfkey.README cf68fddd4643bbe3ff8e31b8b6d8b0a1b85e20f4
F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5
F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce
@@ -1407,7 +1408,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
-P 22ce9218fb2bb56cc5dd4e32077a16f669250d5f 1d018c35b9e81982df036f5e62a4a42219b54e02
-R ba7adfa610b6d372707d43b6ef7bdad4
-U dan
-Z 579d0e0aee90abe69ff327b544da1baf
+P b7469c44be77358e02892a3abc696f7caa0dcd3b c6ab807b72ddfc1462f61aa91442b6fac04ace8a
+R 1b640a6d419521daa5b2a632ced07132
+U drh
+Z b4a9ac9211cc2ca2704bd7cc4c9b5b17
diff --git a/manifest.uuid b/manifest.uuid
index af7caece27..5cc71bdd0b 100644
--- a/manifest.uuid
+++ b/manifest.uuid
@@ -1 +1 @@
-b7469c44be77358e02892a3abc696f7caa0dcd3b
\ No newline at end of file
+c91065f8edb1e54076791716fc20d3fcfe3070dc
\ No newline at end of file
diff --git a/src/backup.c b/src/backup.c
index 94e578d9df..69e3c52822 100644
--- a/src/backup.c
+++ b/src/backup.c
@@ -769,6 +769,10 @@ int sqlite3BtreeCopyFile(Btree *pTo, Btree *pFrom){
b.pDest = pTo;
b.iNext = 1;
+#ifdef SQLITE_HAS_CODEC
+ sqlite3PagerAlignReserve(sqlite3BtreePager(pTo), sqlite3BtreePager(pFrom));
+#endif
+
/* 0x7FFFFFFF is the hard limit for the number of pages in a database
** file. By passing this as the number of pages to copy to
** sqlite3_backup_step(), we can guarantee that the copy finishes
diff --git a/src/btree.c b/src/btree.c
index 6e019aebd8..c7d6fabba6 100644
--- a/src/btree.c
+++ b/src/btree.c
@@ -8186,7 +8186,8 @@ int sqlite3BtreeDelete(BtCursor *pCur, int bPreserve){
if( rc==SQLITE_OK ){
if( bSkipnext ){
assert( bPreserve && pCur->iPage==iCellDepth );
- assert( pPage->nCell>0 && iCellIdx<=pPage->nCell );
+ assert( pPage==pCur->apPage[pCur->iPage] );
+ assert( (pPage->nCell>0 || CORRUPT_DB) && iCellIdx<=pPage->nCell );
pCur->eState = CURSOR_SKIPNEXT;
if( iCellIdx>=pPage->nCell ){
pCur->skipNext = -1;
@@ -8921,6 +8922,10 @@ static void checkList(
#endif
iPage = get4byte(pOvflData);
sqlite3PagerUnref(pOvflPage);
+
+ if( isFreeList && N<(iPage!=0) ){
+ checkAppendMsg(pCheck, "free-page count in header is too small");
+ }
}
}
#endif /* SQLITE_OMIT_INTEGRITY_CHECK */
diff --git a/src/delete.c b/src/delete.c
index 800298256f..914b3dfaef 100644
--- a/src/delete.c
+++ b/src/delete.c
@@ -415,6 +415,7 @@ void sqlite3DeleteFrom(
if( pWInfo==0 ) goto delete_from_cleanup;
eOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass);
assert( IsVirtual(pTab)==0 || eOnePass==ONEPASS_OFF );
+ assert( IsVirtual(pTab) || bComplex || eOnePass!=ONEPASS_OFF );
/* Keep track of the number of rows to be deleted */
if( db->flags & SQLITE_CountRows ){
diff --git a/src/os_unix.c b/src/os_unix.c
index 53a4fd31bd..fb2a8ca916 100644
--- a/src/os_unix.c
+++ b/src/os_unix.c
@@ -4660,7 +4660,8 @@ static void unixShmBarrier(
sqlite3_file *fd /* Database file holding the shared memory */
){
UNUSED_PARAMETER(fd);
- unixEnterMutex();
+ sqlite3MemoryBarrier(); /* compiler-defined memory barrier */
+ unixEnterMutex(); /* Also mutex, for redundancy */
unixLeaveMutex();
}
diff --git a/src/os_win.c b/src/os_win.c
index 41bd94098c..251107528b 100644
--- a/src/os_win.c
+++ b/src/os_win.c
@@ -3850,8 +3850,8 @@ static void winShmBarrier(
sqlite3_file *fd /* Database holding the shared memory */
){
UNUSED_PARAMETER(fd);
- /* MemoryBarrier(); // does not work -- do not know why not */
- winShmEnterMutex();
+ sqlite3MemoryBarrier(); /* compiler-defined memory barrier */
+ winShmEnterMutex(); /* Also mutex, for redundancy */
winShmLeaveMutex();
}
diff --git a/src/pager.c b/src/pager.c
index 2f7c330d60..399070af01 100644
--- a/src/pager.c
+++ b/src/pager.c
@@ -2116,6 +2116,20 @@ static void pagerReportSize(Pager *pPager){
# define pagerReportSize(X) /* No-op if we do not support a codec */
#endif
+#ifdef SQLITE_HAS_CODEC
+/*
+** Make sure the number of reserved bits is the same in the destination
+** pager as it is in the source. This comes up when a VACUUM changes the
+** number of reserved bits to the "optimal" amount.
+*/
+void sqlite3PagerAlignReserve(Pager *pDest, Pager *pSrc){
+ if( pDest->nReserve!=pSrc->nReserve ){
+ pDest->nReserve = pSrc->nReserve;
+ pagerReportSize(pDest);
+ }
+}
+#endif
+
/*
** Read a single page from either the journal file (if isMainJrnl==1) or
** from the sub-journal (if isMainJrnl==0) and playback that page.
diff --git a/src/pager.h b/src/pager.h
index e3b57f435e..99a7aebc78 100644
--- a/src/pager.h
+++ b/src/pager.h
@@ -118,6 +118,9 @@ int sqlite3PagerReadFileheader(Pager*, int, unsigned char*);
/* Functions used to configure a Pager object. */
void sqlite3PagerSetBusyhandler(Pager*, int(*)(void *), void *);
int sqlite3PagerSetPagesize(Pager*, u32*, int);
+#ifdef SQLITE_HAS_CODEC
+void sqlite3PagerAlignReserve(Pager*,Pager*);
+#endif
int sqlite3PagerMaxPageCount(Pager*, int);
void sqlite3PagerSetCachesize(Pager*, int);
void sqlite3PagerSetMmapLimit(Pager *, sqlite3_int64);
diff --git a/src/pcache1.c b/src/pcache1.c
index 00a0205f5a..ee6ac0b955 100644
--- a/src/pcache1.c
+++ b/src/pcache1.c
@@ -413,7 +413,7 @@ static PgHdr1 *pcache1AllocPage(PCache1 *pCache, int benignMalloc){
assert( pCache->pGroup==&pcache1.grp );
pcache1LeaveMutex(pCache->pGroup);
#endif
- if( benignMalloc ) sqlite3BeginBenignMalloc();
+ if( benignMalloc ){ sqlite3BeginBenignMalloc(); }
#ifdef SQLITE_PCACHE_SEPARATE_HEADER
pPg = pcache1Alloc(pCache->szPage);
p = sqlite3Malloc(sizeof(PgHdr1) + pCache->szExtra);
@@ -426,7 +426,7 @@ static PgHdr1 *pcache1AllocPage(PCache1 *pCache, int benignMalloc){
pPg = pcache1Alloc(pCache->szAlloc);
p = (PgHdr1 *)&((u8 *)pPg)[pCache->szPage];
#endif
- if( benignMalloc ) sqlite3EndBenignMalloc();
+ if( benignMalloc ){ sqlite3EndBenignMalloc(); }
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
pcache1EnterMutex(pCache->pGroup);
#endif
diff --git a/src/resolve.c b/src/resolve.c
index 2c4212ba7d..ac1706b595 100644
--- a/src/resolve.c
+++ b/src/resolve.c
@@ -355,8 +355,13 @@ static int lookupName(
/*
** Perhaps the name is a reference to the ROWID
*/
- if( cnt==0 && cntTab==1 && pMatch && sqlite3IsRowid(zCol)
- && VisibleRowid(pMatch->pTab) ){
+ if( cnt==0
+ && cntTab==1
+ && pMatch
+ && (pNC->ncFlags & NC_IdxExpr)==0
+ && sqlite3IsRowid(zCol)
+ && VisibleRowid(pMatch->pTab)
+ ){
cnt = 1;
pExpr->iColumn = -1; /* IMP: R-44911-55124 */
pExpr->affinity = SQLITE_AFF_INTEGER;
diff --git a/src/select.c b/src/select.c
index 0dea56ba12..a4aaa0ecaf 100644
--- a/src/select.c
+++ b/src/select.c
@@ -4267,9 +4267,12 @@ static int selectExpander(Walker *pWalker, Select *p){
pTab->nRef++;
#if !defined(SQLITE_OMIT_VIEW) || !defined (SQLITE_OMIT_VIRTUALTABLE)
if( pTab->pSelect || IsVirtual(pTab) ){
- /* We reach here if the named table is a really a view */
if( sqlite3ViewGetColumnNames(pParse, pTab) ) return WRC_Abort;
assert( pFrom->pSelect==0 );
+ if( pFrom->fg.isTabFunc && !IsVirtual(pTab) ){
+ sqlite3ErrorMsg(pParse, "'%s' is not a function", pTab->zName);
+ return WRC_Abort;
+ }
pFrom->pSelect = sqlite3SelectDup(db, pTab->pSelect, 0);
sqlite3SelectSetName(pFrom->pSelect, pTab->zName);
sqlite3WalkSelect(pWalker, pFrom->pSelect);
diff --git a/src/sqlite.h.in b/src/sqlite.h.in
index 8474020879..471b7f5261 100644
--- a/src/sqlite.h.in
+++ b/src/sqlite.h.in
@@ -3630,7 +3630,7 @@ const char *sqlite3_bind_parameter_name(sqlite3_stmt*, int);
**
** See also: [sqlite3_bind_blob|sqlite3_bind()],
** [sqlite3_bind_parameter_count()], and
-** [sqlite3_bind_parameter_index()].
+** [sqlite3_bind_parameter_name()].
*/
int sqlite3_bind_parameter_index(sqlite3_stmt*, const char *zName);
diff --git a/src/vdbeapi.c b/src/vdbeapi.c
index 9d2a76dccc..12546bdc8c 100644
--- a/src/vdbeapi.c
+++ b/src/vdbeapi.c
@@ -912,18 +912,19 @@ static const Mem *columnNullValue(void){
#endif
= {
/* .u = */ {0},
- /* .flags = */ MEM_Null,
- /* .enc = */ 0,
- /* .n = */ 0,
- /* .z = */ 0,
- /* .zMalloc = */ 0,
- /* .szMalloc = */ 0,
- /* .iPadding1 = */ 0,
- /* .db = */ 0,
- /* .xDel = */ 0,
+ /* .flags = */ (u16)MEM_Null,
+ /* .enc = */ (u8)0,
+ /* .eSubtype = */ (u8)0,
+ /* .n = */ (int)0,
+ /* .z = */ (char*)0,
+ /* .zMalloc = */ (char*)0,
+ /* .szMalloc = */ (int)0,
+ /* .uTemp = */ (u32)0,
+ /* .db = */ (sqlite3*)0,
+ /* .xDel = */ (void(*)(void*))0,
#ifdef SQLITE_DEBUG
- /* .pScopyFrom = */ 0,
- /* .pFiller = */ 0,
+ /* .pScopyFrom = */ (Mem*)0,
+ /* .pFiller = */ (void*)0,
#endif
};
return &nullMem;
diff --git a/src/where.c b/src/where.c
index 69b7c064e8..1e13cf0ed0 100644
--- a/src/where.c
+++ b/src/where.c
@@ -182,7 +182,7 @@ static WhereTerm *whereScanNext(WhereScan *pScan){
while( pScan->iEquiv<=pScan->nEquiv ){
iCur = pScan->aiCur[pScan->iEquiv-1];
iColumn = pScan->aiColumn[pScan->iEquiv-1];
- assert( iColumn!=(-2) || pScan->pIdxExpr!=0 );
+ if( iColumn==(-2) && pScan->pIdxExpr==0 ) return 0;
while( (pWC = pScan->pWC)!=0 ){
for(pTerm=pWC->a+k; knTerm; k++, pTerm++){
if( pTerm->leftCursor==iCur
@@ -193,10 +193,9 @@ static WhereTerm *whereScanNext(WhereScan *pScan){
){
if( (pTerm->eOperator & WO_EQUIV)!=0
&& pScan->nEquivaiCur)
+ && (pX = sqlite3ExprSkipCollate(pTerm->pExpr->pRight))->op==TK_COLUMN
){
int j;
- pX = sqlite3ExprSkipCollate(pTerm->pExpr->pRight);
- assert( pX->op==TK_COLUMN );
for(j=0; jnEquiv; j++){
if( pScan->aiCur[j]==pX->iTable
&& pScan->aiColumn[j]==pX->iColumn ){
diff --git a/src/wherecode.c b/src/wherecode.c
index 4fb6084018..77b8be4bee 100644
--- a/src/wherecode.c
+++ b/src/wherecode.c
@@ -65,7 +65,7 @@ static const char *explainIndexColumnName(Index *pIdx, int i){
**
** "a=? AND b>?"
*/
-static void explainIndexRange(StrAccum *pStr, WhereLoop *pLoop, Table *pTab){
+static void explainIndexRange(StrAccum *pStr, WhereLoop *pLoop){
Index *pIndex = pLoop->u.btree.pIndex;
u16 nEq = pLoop->u.btree.nEq;
u16 nSkip = pLoop->nSkip;
@@ -166,7 +166,7 @@ int sqlite3WhereExplainOneScan(
if( zFmt ){
sqlite3StrAccumAppend(&str, " USING ", 7);
sqlite3XPrintf(&str, 0, zFmt, pIdx->zName);
- explainIndexRange(&str, pLoop, pItem->pTab);
+ explainIndexRange(&str, pLoop);
}
}else if( (flags & WHERE_IPK)!=0 && (flags & WHERE_CONSTRAINT)!=0 ){
const char *zRangeOp;
@@ -514,8 +514,8 @@ static int codeAllEqualityTerms(
sqlite3VdbeJumpHere(v, j);
for(j=0; jaiColumn[j]>=0 );
- VdbeComment((v, "%s", pIdx->pTable->aCol[pIdx->aiColumn[j]].zName));
+ testcase( pIdx->aiColumn[j]==(-2) );
+ VdbeComment((v, "%s", explainIndexColumnName(pIdx, j)));
}
}
diff --git a/test/corrupt2.test b/test/corrupt2.test
index dc417339cd..9bd29cf90f 100644
--- a/test/corrupt2.test
+++ b/test/corrupt2.test
@@ -17,6 +17,7 @@
set testdir [file dirname $argv0]
source $testdir/tester.tcl
+set testprefix corrupt2
# 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).
@@ -558,4 +559,51 @@ ifcapable autovacuum {
}
}
+#-------------------------------------------------------------------------
+# Test that PRAGMA integrity_check detects cases where the freelist-count
+# header field is smaller than the actual number of pages on the freelist.
+#
+
+reset_db
+do_execsql_test 14.0 {
+ PRAGMA auto_vacuum = 0;
+ CREATE TABLE t1(x);
+ INSERT INTO t1 VALUES(randomblob(3500));
+ DELETE FROM t1;
+}
+
+do_execsql_test 14.1 {
+ PRAGMA integrity_check;
+ PRAGMA freelist_count;
+} {ok 3}
+
+# There are now 3 free pages. Modify the header-field so that it
+# (incorrectly) says that just 2 are free.
+do_test 14.2 {
+ db close
+ hexio_write test.db 36 [hexio_render_int32 2]
+ sqlite3 db test.db
+ execsql { PRAGMA freelist_count }
+} {2}
+
+do_execsql_test 14.3 {
+ PRAGMA integrity_check;
+} {{*** in database main ***
+Main freelist: free-page count in header is too small}}
+
+# Use 2 of the free pages on the free-list.
+#
+do_execsql_test 14.4 {
+ INSERT INTO t1 VALUES(randomblob(2500));
+ PRAGMA freelist_count;
+} {0}
+
+do_execsql_test 14.5 {
+ PRAGMA integrity_check;
+} {{*** in database main ***
+Page 3 is never used}}
+
+
+finish_test
+
finish_test
diff --git a/test/corruptC.test b/test/corruptC.test
index a7f93c46d2..80c3c09f61 100644
--- a/test/corruptC.test
+++ b/test/corruptC.test
@@ -189,7 +189,11 @@ do_test corruptC-2.7 {
catchsql {BEGIN; UPDATE t2 SET y='abcdef-uvwxyz'; ROLLBACK;}
} {1 {database disk image is malformed}}
+
# corruption (seed 179069)
+# Obsolete. With single-pass DELETE the corruption in the
+# main database is not detected.
+if 0 {
do_test corruptC-2.8 {
db close
forcecopy test.bu test.db
@@ -204,6 +208,7 @@ do_test corruptC-2.8 {
sqlite3 db test.db
catchsql {BEGIN; DELETE FROM t1 WHERE x>13; ROLLBACK;}
} {1 {database disk image is malformed}}
+}
# corruption (seed 170434)
#
diff --git a/test/fuzzcheck.c b/test/fuzzcheck.c
index c678e2af7a..4597891c3a 100644
--- a/test/fuzzcheck.c
+++ b/test/fuzzcheck.c
@@ -296,6 +296,38 @@ static void readfileFunc(
fclose(in);
}
+/*
+** Implementation of the "writefile(X,Y)" SQL function. The argument Y
+** is written into file X. The number of bytes written is returned. Or
+** NULL is returned if something goes wrong, such as being unable to open
+** file X for writing.
+*/
+static void writefileFunc(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ FILE *out;
+ const char *z;
+ sqlite3_int64 rc;
+ const char *zFile;
+
+ (void)argc;
+ zFile = (const char*)sqlite3_value_text(argv[0]);
+ if( zFile==0 ) return;
+ out = fopen(zFile, "wb");
+ if( out==0 ) return;
+ z = (const char*)sqlite3_value_blob(argv[1]);
+ if( z==0 ){
+ rc = 0;
+ }else{
+ rc = fwrite(z, 1, sqlite3_value_bytes(argv[1]), out);
+ }
+ fclose(out);
+ sqlite3_result_int64(context, rc);
+}
+
+
/*
** Load a list of Blob objects from the database
*/
@@ -751,6 +783,8 @@ static void showHelp(void){
"Options:\n"
" --cell-size-check Set the PRAGMA cell_size_check=ON\n"
" --dbid N Use only the database where dbid=N\n"
+" --export-db DIR Write databases to files(s) in DIR. Works with --dbid\n"
+" --export-sql DIR Write SQL to file(s) in DIR. Also works with --sqlid\n"
" --help Show this help text\n"
" -q Reduced output\n"
" --quiet Reduced output\n"
@@ -763,7 +797,7 @@ static void showHelp(void){
" --rebuild Rebuild and vacuum the database file\n"
" --result-trace Show the results of each SQL command\n"
" --sqlid N Use only SQL where sqlid=N\n"
-" --timeline N Abort if any single test case needs more than N seconds\n"
+" --timeout N Abort if any single test case needs more than N seconds\n"
" -v Increased output\n"
" --verbose Increased output\n"
);
@@ -799,6 +833,8 @@ int main(int argc, char **argv){
int sqlFuzz = 0; /* True for SQL fuzz testing. False for DB fuzz */
int iTimeout = 120; /* Default 120-second timeout */
int nMem = 0; /* Memory limit */
+ char *zExpDb = 0; /* Write Databases to files in this directory */
+ char *zExpSql = 0; /* Write SQL to files in this directory */
iBegin = timeOfDay();
#ifdef __unix__
@@ -818,6 +854,14 @@ int main(int argc, char **argv){
if( i>=argc-1 ) fatalError("missing arguments on %s", argv[i]);
onlyDbid = integerValue(argv[++i]);
}else
+ if( strcmp(z,"export-db")==0 ){
+ if( i>=argc-1 ) fatalError("missing arguments on %s", argv[i]);
+ zExpDb = argv[++i];
+ }else
+ if( strcmp(z,"export-sql")==0 ){
+ if( i>=argc-1 ) fatalError("missing arguments on %s", argv[i]);
+ zExpSql = argv[++i];
+ }else
if( strcmp(z,"help")==0 ){
showHelp();
return 0;
@@ -943,6 +987,50 @@ int main(int argc, char **argv){
sqlite3_close(db);
return 0;
}
+ if( zExpDb!=0 || zExpSql!=0 ){
+ sqlite3_create_function(db, "writefile", 2, SQLITE_UTF8, 0,
+ writefileFunc, 0, 0);
+ if( zExpDb!=0 ){
+ const char *zExDb =
+ "SELECT writefile(printf('%s/db%06d.db',?1,dbid),dbcontent),"
+ " dbid, printf('%s/db%06d.db',?1,dbid), length(dbcontent)"
+ " FROM db WHERE ?2<0 OR dbid=?2;";
+ rc = sqlite3_prepare_v2(db, zExDb, -1, &pStmt, 0);
+ if( rc ) fatalError("cannot prepare statement [%s]: %s",
+ zExDb, sqlite3_errmsg(db));
+ sqlite3_bind_text64(pStmt, 1, zExpDb, strlen(zExpDb),
+ SQLITE_STATIC, SQLITE_UTF8);
+ sqlite3_bind_int(pStmt, 2, onlyDbid);
+ while( sqlite3_step(pStmt)==SQLITE_ROW ){
+ printf("write db-%d (%d bytes) into %s\n",
+ sqlite3_column_int(pStmt,1),
+ sqlite3_column_int(pStmt,3),
+ sqlite3_column_text(pStmt,2));
+ }
+ sqlite3_finalize(pStmt);
+ }
+ if( zExpSql!=0 ){
+ const char *zExSql =
+ "SELECT writefile(printf('%s/sql%06d.txt',?1,sqlid),sqltext),"
+ " sqlid, printf('%s/sql%06d.txt',?1,sqlid), length(sqltext)"
+ " FROM xsql WHERE ?2<0 OR sqlid=?2;";
+ rc = sqlite3_prepare_v2(db, zExSql, -1, &pStmt, 0);
+ if( rc ) fatalError("cannot prepare statement [%s]: %s",
+ zExSql, sqlite3_errmsg(db));
+ sqlite3_bind_text64(pStmt, 1, zExpSql, strlen(zExpSql),
+ SQLITE_STATIC, SQLITE_UTF8);
+ sqlite3_bind_int(pStmt, 2, onlySqlid);
+ while( sqlite3_step(pStmt)==SQLITE_ROW ){
+ printf("write sql-%d (%d bytes) into %s\n",
+ sqlite3_column_int(pStmt,1),
+ sqlite3_column_int(pStmt,3),
+ sqlite3_column_text(pStmt,2));
+ }
+ sqlite3_finalize(pStmt);
+ }
+ sqlite3_close(db);
+ return 0;
+ }
/* Load all SQL script content and all initial database images from the
** source db
@@ -1039,6 +1127,12 @@ int main(int argc, char **argv){
}
rc = sqlite3_open_v2("main.db", &db, openFlags, zVfs);
if( rc ) fatalError("cannot open inmem database");
+#ifdef SQLITE_ENABLE_JSON1
+ {
+ extern int sqlite3_json_init(sqlite3*);
+ sqlite3_json_init(db);
+ }
+#endif
if( cellSzCkFlag ) runSql(db, "PRAGMA cell_size_check=ON", runFlags);
setAlarm(iTimeout);
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
diff --git a/test/fuzzdata4.db b/test/fuzzdata4.db
new file mode 100644
index 0000000000..b97ca104e7
Binary files /dev/null and b/test/fuzzdata4.db differ
diff --git a/test/indexexpr1.test b/test/indexexpr1.test
index 0c925c9f92..1945059f2b 100644
--- a/test/indexexpr1.test
+++ b/test/indexexpr1.test
@@ -218,5 +218,41 @@ do_execsql_test indexexpr1-510eqp {
SELECT substr(a,4,3) AS k FROM cnt, t5 WHERE k=printf('%03d',x);
} {/USING INDEX t5ax/}
+# Skip-scan on an indexed expression
+#
+do_execsql_test indexexpr1-600 {
+ DROP TABLE IF EXISTS t4;
+ CREATE TABLE t4(a,b,c,d,e,f,g,h,i);
+ CREATE INDEX t4all ON t4(a,b,cx;
} {}
-do_execsql_test json1-4.6 {
+do_execsql_test json101-4.6 {
SELECT x FROM j1 WHERE json_replace(x)<>x;
} {}
-do_execsql_test json1-4.7 {
+do_execsql_test json101-4.7 {
SELECT x FROM j1 WHERE json_set(x)<>x;
} {}
-do_execsql_test json1-4.8 {
+do_execsql_test json101-4.8 {
SELECT x FROM j1 WHERE json_insert(x)<>x;
} {}
@@ -302,6 +307,18 @@ do_execsql_test json-5.8 {
WHERE jx.value<>jx.atom AND type NOT IN ('array','object');
} {}
+do_execsql_test json-6.1 {
+ SELECT json_valid('{"a":55,"b":72,}');
+} {0}
+do_execsql_test json-6.2 {
+ SELECT json_valid('{"a":55,"b":72}');
+} {1}
+do_execsql_test json-6.3 {
+ SELECT json_valid('["a",55,"b",72,]');
+} {0}
+do_execsql_test json-6.4 {
+ SELECT json_valid('["a",55,"b",72]');
+} {1}
finish_test
diff --git a/test/json102.test b/test/json102.test
index da9fbd1b76..f40580da4e 100644
--- a/test/json102.test
+++ b/test/json102.test
@@ -278,4 +278,20 @@ do_execsql_test json102-1132 {
} {123}
} ;# end ifcapable vtab
+#-------------------------------------------------------------------------
+# Test that json_valid() correctly identifies non-ascii range
+# characters as non-whitespace.
+#
+do_execsql_test json102-1201 { SELECT json_valid(char(32) || '"xyz"') } 1
+do_execsql_test json102-1202 { SELECT json_valid(char(200) || '"xyz"') } 0
+
+# Off-by-one error in jsonAppendString()
+#
+for {set i 0} {$i<100} {incr i} {
+ set str abcdef[string repeat \" [expr {$i+50}]]uvwxyz
+ do_test json102-[format %d [expr {$i+1300}]] {
+ db eval {SELECT json_extract(json_array($::str),'$[0]')==$::str}
+ } {1}
+}
+
finish_test
diff --git a/test/orderby9.test b/test/orderby9.test
index c998c5054e..581951c795 100644
--- a/test/orderby9.test
+++ b/test/orderby9.test
@@ -27,6 +27,16 @@ do_execsql_test setup {
c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<100)
INSERT INTO t1 SELECT x FROM c;
}
+
+# Some versions of TCL are unable to [lsort -int] for
+# 64-bit integers. So we write our own comparison
+# routine.
+proc bigintcompare {a b} {
+ set x [expr {$a-$b}]
+ if {$x<0} {return -1}
+ if {$x>0} {return +1}
+ return 0
+}
do_test 1.0 {
set l1 {}
# If random() is only evaluated once and then reused for each row, then
@@ -34,19 +44,19 @@ do_test 1.0 {
# separately for the result set and the ORDER BY clause, then the output
# order will be random.
db eval {SELECT random() AS y FROM t1 ORDER BY 1;} {lappend l1 $y}
- expr {$l1==[lsort -int $l1]}
+ expr {$l1==[lsort -command bigintcompare $l1]}
} {1}
do_test 1.1 {
set l1 {}
db eval {SELECT random() AS y FROM t1 ORDER BY random();} {lappend l1 $y}
- expr {$l1==[lsort -int $l1]}
+ expr {$l1==[lsort -command bigintcompare $l1]}
} {1}
do_test 1.2 {
set l1 {}
db eval {SELECT random() AS y FROM t1 ORDER BY +random();} {lappend l1 $y}
- expr {$l1==[lsort -int $l1]}
+ expr {$l1==[lsort -command bigintcompare $l1]}
} {0}
finish_test
diff --git a/test/releasetest.tcl b/test/releasetest.tcl
index 55acd215e7..dde3f039d6 100644
--- a/test/releasetest.tcl
+++ b/test/releasetest.tcl
@@ -297,6 +297,7 @@ proc PUTS {args} {
puts [lindex $args 0]
puts $::LOG [lindex $args 0]
}
+ flush $::LOG
}
puts $LOG "$argv0 $argv"
set tm0 [clock format [clock seconds] -format {%Y-%m-%d %H:%M:%S} -gmt 1]
diff --git a/test/spellfix2.test b/test/spellfix2.test
index b4614a9e1f..e9d6c693b2 100644
--- a/test/spellfix2.test
+++ b/test/spellfix2.test
@@ -29,32 +29,35 @@ do_execsql_test 1.0 {
do_execsql_test 1.1 {
SELECT word, distance, matchlen FROM demo
- WHERE word MATCH 'amstedam*' AND top=3;
+ WHERE word MATCH 'amstedam*' AND top=3
+ ORDER BY +word;
} {
amsterdam 100 9
- amsterdammetje 100 9
amsterdamania 100 9
+ amsterdammetje 100 9
}
do_execsql_test 1.2 {
SELECT word, distance, matchlen FROM demo WHERE
- word MATCH 'amstedam*' AND top=3 AND distance <= 100;
+ word MATCH 'amstedam*' AND top=3 AND distance <= 100
+ ORDER BY +word;
} {
amsterdam 100 9
- amsterdammetje 100 9
amsterdamania 100 9
+ amsterdammetje 100 9
}
do_execsql_test 1.3 {
SELECT word, distance, matchlen FROM demo WHERE
- word MATCH 'amstedam*' AND distance <= 100;
+ word MATCH 'amstedam*' AND distance <= 100
+ ORDER BY +word;
} {
amsterdam 100 9
- amsterdammetje 100 9
amsterdamania 100 9
- amsterdamweg 100 9
- amsterdamsestraat 100 9
amsterdamlaan 100 9
+ amsterdammetje 100 9
+ amsterdamsestraat 100 9
+ amsterdamweg 100 9
}
do_test 1.4 {
@@ -111,4 +114,3 @@ do_execsql_test 1.7 {
finish_test
-
diff --git a/test/sqllimits1.test b/test/sqllimits1.test
index 39e3aedd8f..ec72723ebe 100644
--- a/test/sqllimits1.test
+++ b/test/sqllimits1.test
@@ -643,7 +643,8 @@ do_test sqllimits1-8.8 {
for {set i 0} {$i <= $SQLITE_LIMIT_COLUMN} {incr i} {
lappend cols "c$i"
}
- catchsql "CREATE VIEW v1 AS SELECT [join $cols ,] FROM t1;"
+ execsql "CREATE VIEW v1 AS SELECT [join $cols ,] FROM t1;"
+ catchsql {SELECT * FROM v1}
} {1 {too many columns in result set}}
do_test sqllimits1-8.9 {
@@ -652,9 +653,12 @@ do_test sqllimits1-8.9 {
for {set i 0} {$i < $SQLITE_LIMIT_COLUMN} {incr i} {
lappend cols "c$i"
}
+ execsql {DROP VIEW IF EXISTS v1}
catchsql "CREATE TABLE t2([join $cols ,])"
catchsql "CREATE VIEW v1 AS SELECT *, c1 AS o FROM t2;"
+ catchsql "SELECT * FROM v1"
} {1 {too many columns in result set}}
+
do_test sqllimits1-8.10 {
# ORDER BY columns
set cols [list]
diff --git a/test/tabfunc01.test b/test/tabfunc01.test
index 07b3c80442..5bd729b87d 100644
--- a/test/tabfunc01.test
+++ b/test/tabfunc01.test
@@ -55,6 +55,21 @@ do_execsql_test tabfunc01-1.10 {
SELECT rowid, * FROM generate_series(0,32,5) ORDER BY +value DESC;
} {7 30 6 25 5 20 4 15 3 10 2 5 1 0}
+do_execsql_test tabfunc01-1.20 {
+ CREATE VIEW v1(a,b) AS VALUES(1,2),(3,4);
+ SELECT * FROM v1;
+} {1 2 3 4}
+do_catchsql_test tabfunc01-1.21 {
+ SELECT * FROM v1(55);
+} {1 {'v1' is not a function}}
+do_execsql_test tabfunc01-1.22 {
+ CREATE VIEW v2(x) AS SELECT value FROM generate_series(1,5);
+ SELECT * FROM v2;
+} {1 2 3 4 5}
+do_catchsql_test tabfunc01-1.23 {
+ SELECT * FROM v2(55);
+} {1 {'v2' is not a function}}
+
do_execsql_test tabfunc01-2.1 {
CREATE TABLE t1(x);
INSERT INTO t1(x) VALUES(2),(3);
diff --git a/test/unique2.test b/test/unique2.test
index 6a320d4d7d..0ec0dd3db2 100644
--- a/test/unique2.test
+++ b/test/unique2.test
@@ -75,4 +75,12 @@ foreach {id sql} {
} {1 {UNIQUE constraint failed: t1.y, t1.z}}
}
+do_catchsql_test 13.1 {
+ CREATE TABLE err1(a,b,c,UNIQUE(rowid));
+} {1 {no such column: rowid}}
+do_catchsql_test 13.2 {
+ CREATE TABLE err1(a,b,c,PRIMARY KEY(rowid));
+} {1 {no such column: rowid}}
+
+
finish_test
diff --git a/test/wal3.test b/test/wal3.test
index 33bb285c53..bd312b349c 100644
--- a/test/wal3.test
+++ b/test/wal3.test
@@ -34,10 +34,6 @@ db func a_string a_string
# of test cases tests that nothing appears to go wrong when this is
# done.
#
-set ans 4056
-if {[info exists G(perm:name)] && $G(perm:name)=="memsubsys1"} {
- set ans 4251
-}
do_test wal3-1.0 {
execsql {
PRAGMA cache_size = 2000;
@@ -64,8 +60,12 @@ do_test wal3-1.0 {
COMMIT;
PRAGMA cache_size = 10;
}
- wal_frame_count test.db-wal 1024
-} $ans
+ set x [wal_frame_count test.db-wal 1024]
+ if {$::G(perm:name)=="memsubsys1"} {
+ if {$x==4251 || $x==4290} {set x 4056}
+ }
+ set x
+} 4056
for {set i 1} {$i < 50} {incr i} {
diff --git a/test/without_rowid6.test b/test/without_rowid6.test
index 8ca78ba63a..3f9fe415d8 100644
--- a/test/without_rowid6.test
+++ b/test/without_rowid6.test
@@ -113,5 +113,9 @@ do_execsql_test without_rowid6-520 {
PRAGMA index_list(t1);
} {/sqlite_autoindex_t1_1 1 pk/}
+do_catchsql_test without_rowid6-600 {
+ CREATE TABLE t6(a,b,c,PRIMARY KEY(a,rowid,b))WITHOUT ROWID;
+} {1 {no such column: rowid}}
+
finish_test
diff --git a/tool/fuzzershell.c b/tool/fuzzershell.c
index 2778c9d2f7..fa80b3561f 100644
--- a/tool/fuzzershell.c
+++ b/tool/fuzzershell.c
@@ -322,6 +322,7 @@ static void showHelp(void){
"Options:\n"
" --autovacuum Enable AUTOVACUUM mode\n"
" --database FILE Use database FILE instead of an in-memory database\n"
+" --disable-lookaside Turn off lookaside memory\n"
" --heap SZ MIN Memory allocator uses SZ bytes & min allocation MIN\n"
" --help Show this help text\n"
" --lookaside N SZ Configure lookaside for N slots of SZ bytes each\n"
@@ -457,6 +458,7 @@ int main(int argc, char **argv){
const char *zDbName = 0; /* Name of an on-disk database file to open */
iBegin = timeOfDay();
+ sqlite3_shutdown();
zFailCode = getenv("TEST_FAILURE");
g.zArgv0 = argv[0];
zPrompt = "";
@@ -473,6 +475,10 @@ int main(int argc, char **argv){
zDbName = argv[i+1];
i += 1;
}else
+ if( strcmp(z,"disable-lookaside")==0 ){
+ nLook = 1;
+ szLook = 0;
+ }else
if( strcmp(z, "f")==0 && i+1