aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlarrybr <larrybr@noemail.net>2021-05-19 19:55:10 +0000
committerlarrybr <larrybr@noemail.net>2021-05-19 19:55:10 +0000
commit4f878f33a981786a5bf3db3372a11cf690260de7 (patch)
treeb8c05ad24cf1596c5b8db1c3b4ae28cfa40ed3d8
parent3ec4861c000cc5b26520c248043c18299a749d99 (diff)
parent1f4f7c7a416801a4e195634b03650191a4a43c7a (diff)
downloadsqlite-4f878f33a981786a5bf3db3372a11cf690260de7.tar.gz
sqlite-4f878f33a981786a5bf3db3372a11cf690260de7.zip
merge from trunk
FossilOrigin-Name: 19ffe3cfe278a4046f32df56f75080c2377e4c44ad40a02d39db8e7701526204
-rw-r--r--Makefile.in8
-rw-r--r--Makefile.msc4
-rw-r--r--autoconf/Makefile.msc2
-rw-r--r--ext/fts3/fts3.c14
-rw-r--r--ext/fts5/fts5_index.c7
-rw-r--r--ext/fts5/test/fts5corrupt3.test129
-rw-r--r--ext/misc/cksumvfs.c14
-rw-r--r--ext/misc/decimal.c9
-rw-r--r--ext/misc/json1.c2
-rw-r--r--ext/rbu/rbu1.test5
-rw-r--r--ext/rbu/sqlite3rbu.c30
-rw-r--r--ext/session/sqlite3session.h17
-rw-r--r--main.mk6
-rw-r--r--manifest141
-rw-r--r--manifest.uuid2
-rw-r--r--src/alter.c2
-rw-r--r--src/attach.c2
-rw-r--r--src/btree.c54
-rw-r--r--src/build.c42
-rw-r--r--src/expr.c13
-rw-r--r--src/global.c2
-rw-r--r--src/main.c10
-rw-r--r--src/memdb.c345
-rw-r--r--src/os_unix.c16
-rw-r--r--src/pager.c4
-rw-r--r--src/parse.y2
-rw-r--r--src/resolve.c26
-rw-r--r--src/select.c23
-rw-r--r--src/shell.c.in32
-rw-r--r--src/sqlite.h.in51
-rw-r--r--src/sqliteInt.h12
-rw-r--r--src/tclsqlite.c4
-rw-r--r--src/test8.c6
-rw-r--r--src/test_config.c2
-rw-r--r--src/trigger.c80
-rw-r--r--src/vdbe.c98
-rw-r--r--src/vdbemem.c8
-rw-r--r--src/wal.c5
-rw-r--r--src/walker.c3
-rw-r--r--src/where.c26
-rw-r--r--src/whereInt.h5
-rw-r--r--src/wherecode.c36
-rw-r--r--src/whereexpr.c284
-rw-r--r--src/window.c15
-rw-r--r--test/alter4.test8
-rw-r--r--test/altertab.test49
-rw-r--r--test/corrupt4.test28
-rw-r--r--test/corruptN.test117
-rw-r--r--test/dbfuzz2.c3
-rw-r--r--test/exists2.test194
-rw-r--r--test/existsfault.test51
-rw-r--r--test/fuzzcheck.c4
-rw-r--r--test/fuzzdata8.dbbin2118656 -> 2260992 bytes
-rw-r--r--test/in6.test19
-rw-r--r--test/optfuzz.c1
-rwxr-xr-xtest/releasetest.tcl2
-rw-r--r--test/releasetest_data.tcl4
-rw-r--r--test/returning1.test94
-rw-r--r--test/threadtest5.c339
-rw-r--r--test/transitive1.test27
-rw-r--r--test/vtab1.test1
-rw-r--r--test/where9.test19
-rw-r--r--test/whereL.test8
-rw-r--r--test/window1.test71
-rw-r--r--test/window8.tcl70
-rw-r--r--test/window8.test71
-rw-r--r--test/without_rowid1.test13
-rw-r--r--tool/mkopcodeh.tcl11
-rw-r--r--tool/omittest.tcl1
69 files changed, 1830 insertions, 973 deletions
diff --git a/Makefile.in b/Makefile.in
index 981263921..f010cdaa1 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -616,12 +616,10 @@ SHELL_OPT += -DSQLITE_ENABLE_DBPAGE_VTAB
SHELL_OPT += -DSQLITE_ENABLE_DBSTAT_VTAB
SHELL_OPT += -DSQLITE_ENABLE_BYTECODE_VTAB
SHELL_OPT += -DSQLITE_ENABLE_OFFSET_SQL_FUNC
-SHELL_OPT += -DSQLITE_ENABLE_DESERIALIZE
FUZZERSHELL_OPT = -DSQLITE_ENABLE_JSON1
FUZZCHECK_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5 -DSQLITE_OSS_FUZZ
FUZZCHECK_OPT += -DSQLITE_MAX_MEMORY=50000000
FUZZCHECK_OPT += -DSQLITE_PRINTF_PRECISION_LIMIT=1000
-FUZZCHECK_OPT += -DSQLITE_ENABLE_DESERIALIZE
FUZZCHECK_OPT += -DSQLITE_ENABLE_FTS4
FUZZCHECK_OPT += -DSQLITE_ENABLE_FTS3_PARENTHESIS
#FUZZCHECK_OPT += -DSQLITE_ENABLE_FTS5
@@ -695,7 +693,6 @@ dbfuzz$(TEXE): $(TOP)/test/dbfuzz.c sqlite3.c sqlite3.h
DBFUZZ2_OPTS = \
-DSQLITE_THREADSAFE=0 \
-DSQLITE_OMIT_LOAD_EXTENSION \
- -DSQLITE_ENABLE_DESERIALIZE \
-DSQLITE_DEBUG \
-DSQLITE_ENABLE_DBSTAT_VTAB \
-DSQLITE_ENABLE_BYTECODE_VTAB \
@@ -1235,7 +1232,6 @@ TESTFIXTURE_FLAGS += -DSQLITE_DEFAULT_PAGE_SIZE=1024
TESTFIXTURE_FLAGS += -DSQLITE_ENABLE_STMTVTAB
TESTFIXTURE_FLAGS += -DSQLITE_ENABLE_DBPAGE_VTAB
TESTFIXTURE_FLAGS += -DSQLITE_ENABLE_BYTECODE_VTAB
-TESTFIXTURE_FLAGS += -DSQLITE_ENABLE_DESERIALIZE
TESTFIXTURE_FLAGS += -DSQLITE_CKSUMVFS_STATIC
TESTFIXTURE_SRC0 = $(TESTSRC2) libsqlite3.la
@@ -1431,6 +1427,9 @@ threadtest3$(TEXE): sqlite3.lo $(THREADTEST3_SRC)
threadtest: threadtest3$(TEXE)
./threadtest3$(TEXE)
+threadtest5: sqlite3.c $(TOP)/test/threadtest5.c
+ $(LTLINK) $(TOP)/test/threadtest5.c sqlite3.c -o $@ $(TLIBS)
+
releasetest:
$(TCLSH_CMD) $(TOP)/test/releasetest.tcl
@@ -1484,6 +1483,7 @@ clean:
rm -f sqldiff sqldiff.exe
rm -f dbhash dbhash.exe
rm -f fts5.* fts5parse.*
+ rm -f threadtest5
distclean: clean
rm -f config.h config.log config.status libtool Makefile sqlite3.pc
diff --git a/Makefile.msc b/Makefile.msc
index 3068815fb..394d342b6 100644
--- a/Makefile.msc
+++ b/Makefile.msc
@@ -367,7 +367,6 @@ OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_STMTVTAB=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DBPAGE_VTAB=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DBSTAT_VTAB=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_BYTECODE_VTAB=1
-OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DESERIALIZE=1
!ENDIF
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_COLUMN_METADATA=1
!ENDIF
@@ -1689,7 +1688,6 @@ FUZZDATA = \
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_FTS4=1
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_EXPLAIN_COMMENTS=1
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_OFFSET_SQL_FUNC=1
-SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_DESERIALIZE=1
!ENDIF
# <<mark>>
@@ -1698,7 +1696,6 @@ SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_DESERIALIZE=1
MPTESTER_COMPILE_OPTS = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5
FUZZERSHELL_COMPILE_OPTS = -DSQLITE_ENABLE_JSON1
FUZZCHECK_OPTS = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5 -DSQLITE_OSS_FUZZ -DSQLITE_MAX_MEMORY=50000000 -DSQLITE_PRINTF_PRECISION_LIMIT=1000
-FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_ENABLE_DESERIALIZE
FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_ENABLE_FTS4
FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_ENABLE_RTREE
FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_ENABLE_GEOPOLY
@@ -2392,7 +2389,6 @@ TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_ENABLE_STMTVTAB=1
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_ENABLE_DBPAGE_VTAB=1
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_ENABLE_BYTECODE_VTAB=1
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_ENABLE_JSON1=1
-TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_ENABLE_DESERIALIZE=1
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_CKSUMVFS_STATIC=1
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) $(TEST_CCONV_OPTS)
diff --git a/autoconf/Makefile.msc b/autoconf/Makefile.msc
index 1f177557a..40d0e8113 100644
--- a/autoconf/Makefile.msc
+++ b/autoconf/Makefile.msc
@@ -290,7 +290,6 @@ OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_STMTVTAB=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DBPAGE_VTAB=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DBSTAT_VTAB=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_BYTECODE_VTAB=1
-OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DESERIALIZE=1
!ENDIF
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_COLUMN_METADATA=1
!ENDIF
@@ -960,7 +959,6 @@ LIBRESOBJS =
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_FTS4=1
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_EXPLAIN_COMMENTS=1
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_OFFSET_SQL_FUNC=1
-SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_DESERIALIZE=1
!ENDIF
diff --git a/ext/fts3/fts3.c b/ext/fts3/fts3.c
index e1c8b49c0..9c5703d3f 100644
--- a/ext/fts3/fts3.c
+++ b/ext/fts3/fts3.c
@@ -1899,7 +1899,7 @@ static int fts3ScanInteriorNode(
char *zBuffer = 0; /* Buffer to load terms into */
i64 nAlloc = 0; /* Size of allocated buffer */
int isFirstTerm = 1; /* True when processing first term on page */
- sqlite3_int64 iChild; /* Block id of child node to descend to */
+ u64 iChild; /* Block id of child node to descend to */
int nBuffer = 0; /* Total term size */
/* Skip over the 'height' varint that occurs at the start of every
@@ -1915,8 +1915,8 @@ static int fts3ScanInteriorNode(
** table, then there are always 20 bytes of zeroed padding following the
** nNode bytes of content (see sqlite3Fts3ReadBlock() for details).
*/
- zCsr += sqlite3Fts3GetVarint(zCsr, &iChild);
- zCsr += sqlite3Fts3GetVarint(zCsr, &iChild);
+ zCsr += sqlite3Fts3GetVarintU(zCsr, &iChild);
+ zCsr += sqlite3Fts3GetVarintU(zCsr, &iChild);
if( zCsr>zEnd ){
return FTS_CORRUPT_VTAB;
}
@@ -1969,20 +1969,20 @@ static int fts3ScanInteriorNode(
*/
cmp = memcmp(zTerm, zBuffer, (nBuffer>nTerm ? nTerm : nBuffer));
if( piFirst && (cmp<0 || (cmp==0 && nBuffer>nTerm)) ){
- *piFirst = iChild;
+ *piFirst = (i64)iChild;
piFirst = 0;
}
if( piLast && cmp<0 ){
- *piLast = iChild;
+ *piLast = (i64)iChild;
piLast = 0;
}
iChild++;
};
- if( piFirst ) *piFirst = iChild;
- if( piLast ) *piLast = iChild;
+ if( piFirst ) *piFirst = (i64)iChild;
+ if( piLast ) *piLast = (i64)iChild;
finish_scan:
sqlite3_free(zBuffer);
diff --git a/ext/fts5/fts5_index.c b/ext/fts5/fts5_index.c
index 869d7a8b7..b66e9bece 100644
--- a/ext/fts5/fts5_index.c
+++ b/ext/fts5/fts5_index.c
@@ -431,7 +431,7 @@ struct Fts5SegIter {
int iLeafPgno; /* Current leaf page number */
Fts5Data *pLeaf; /* Current leaf data */
Fts5Data *pNextLeaf; /* Leaf page (iLeafPgno+1) */
- int iLeafOffset; /* Byte offset within current leaf */
+ i64 iLeafOffset; /* Byte offset within current leaf */
/* Next method */
void (*xNext)(Fts5Index*, Fts5SegIter*, int*);
@@ -1611,7 +1611,7 @@ static void fts5SegIterLoadNPos(Fts5Index *p, Fts5SegIter *pIter){
static void fts5SegIterLoadRowid(Fts5Index *p, Fts5SegIter *pIter){
u8 *a = pIter->pLeaf->p; /* Buffer to read data from */
- int iOff = pIter->iLeafOffset;
+ i64 iOff = pIter->iLeafOffset;
ASSERT_SZLEAF_OK(pIter->pLeaf);
if( iOff>=pIter->pLeaf->szLeaf ){
@@ -1644,7 +1644,7 @@ static void fts5SegIterLoadRowid(Fts5Index *p, Fts5SegIter *pIter){
*/
static void fts5SegIterLoadTerm(Fts5Index *p, Fts5SegIter *pIter, int nKeep){
u8 *a = pIter->pLeaf->p; /* Buffer to read data from */
- int iOff = pIter->iLeafOffset; /* Offset to read at */
+ i64 iOff = pIter->iLeafOffset; /* Offset to read at */
int nNew; /* Bytes of new data */
iOff += fts5GetVarint32(&a[iOff], nNew);
@@ -2072,7 +2072,6 @@ static void fts5SegIterNext(
** this block is particularly performance critical, so equivalent
** code is inlined. */
int nSz;
- assert( p->rc==SQLITE_OK );
assert_nc( pIter->iLeafOffset<=pIter->pLeaf->nn );
fts5FastGetVarint32(pIter->pLeaf->p, pIter->iLeafOffset, nSz);
pIter->bDel = (nSz & 0x0001);
diff --git a/ext/fts5/test/fts5corrupt3.test b/ext/fts5/test/fts5corrupt3.test
index 631cb2159..4796f2c48 100644
--- a/ext/fts5/test/fts5corrupt3.test
+++ b/ext/fts5/test/fts5corrupt3.test
@@ -14793,6 +14793,135 @@ do_catchsql_test 75.1 {
SELECT rowid, quote(matchinfo(t1,'pcxybs')) FROM t1 WHERE t1 MATCH 'e*';
} {1 {database disk image is malformed}}
+#-------------------------------------------------------------------------
+reset_db
+do_test 76.0 {
+ sqlite3 db {}
+ db deserialize [decode_hexdb {
+| size 40960 pagesize 4096 filename crash-03b68c01d30713.db
+| page 1 offset 0
+| 0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00 SQLite format 3.
+| 16: 10 00 01 01 00 40 20 20 00 00 00 00 00 00 00 0a .....@ ........
+| 32: 00 00 00 00 00 00 00 00 00 00 00 0d 00 00 00 04 ................
+| 96: 00 00 00 00 0d 00 00 00 0d 0b 6e 00 0f a3 0f 4c ..........n....L
+| 112: 0e e1 0e 81 0e 24 0d cc 0d 72 0d 1b 0c b0 0c 50 .....$...r.....P
+| 128: 0b f8 0b b3 0b 6e 01 00 00 00 00 00 00 00 00 00 .....n..........
+| 2912: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 43 0d ..............C.
+| 2928: 06 17 11 11 08 75 74 61 62 6c 65 74 34 74 34 43 .....utablet4t4C
+| 2944: 52 45 41 54 45 20 56 49 52 54 55 41 4c 20 54 41 REATE VIRTUAL TA
+| 2960: 42 4c 45 20 74 34 20 55 53 49 4e 47 20 66 74 73 BLE t4 USING fts
+| 2976: 35 76 6f 63 61 62 28 27 74 32 27 2c 20 27 72 6f 5vocab('t2', 'ro
+| 2992: 77 27 29 43 0c 06 17 11 11 08 75 74 61 62 6c 65 w')C......utable
+| 3008: 74 33 74 33 43 52 45 41 54 45 20 56 49 52 54 55 t3t3CREATE VIRTU
+| 3024: 41 4c 20 54 41 42 4c 45 20 74 33 20 55 53 49 4e AL TABLE t3 USIN
+| 3040: 47 20 66 74 73 35 76 6f 63 61 62 28 27 74 31 27 G fts5vocab('t1'
+| 3056: 2c 20 27 72 6f 77 27 29 56 0b 06 17 1f 1f 01 7d , 'row')V.......
+| 3072: 74 61 62 6c 65 74 32 5f 63 6f 6e 66 69 67 74 32 tablet2_configt2
+| 3088: 5f 63 6f 6e 66 69 67 0a 43 52 45 41 54 45 20 54 _config.CREATE T
+| 3104: 41 42 4c 45 20 27 74 32 5f 63 6f 6e 66 69 67 27 ABLE 't2_config'
+| 3120: 28 6b 20 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 (k PRIMARY KEY,
+| 3136: 76 29 20 57 49 54 48 4f 55 54 20 52 4f 57 49 44 v) WITHOUT ROWID
+| 3152: 5e 0a 07 17 21 21 01 81 07 74 61 62 6c 65 74 32 ^...!!...tablet2
+| 3168: 5f 63 6f 6e 74 65 6e 74 74 32 5f 63 6f 6e 74 65 _contentt2_conte
+| 3184: 6e 74 09 43 52 45 41 54 45 20 54 41 42 4c 45 20 nt.CREATE TABLE
+| 3200: 27 74 32 5f 63 6f 6e 74 65 6e 74 27 28 69 64 20 't2_content'(id
+| 3216: 49 4e 54 45 47 45 52 20 50 52 49 4d 41 52 59 20 INTEGER PRIMARY
+| 3232: 4b 45 59 2c 20 63 30 2c 20 63 31 2c 20 63 32 29 KEY, c0, c1, c2)
+| 3248: 69 09 07 17 19 19 01 81 2d 74 61 62 6c 65 74 32 i.......-tablet2
+| 3264: 5f 69 64 78 74 32 5f 69 64 78 08 43 52 45 41 54 _idxt2_idx.CREAT
+| 3280: 45 20 54 41 42 4c 45 20 27 74 32 5f 69 64 78 27 E TABLE 't2_idx'
+| 3296: 28 73 65 67 69 64 2c 20 74 65 72 6d 2c 20 70 67 (segid, term, pg
+| 3312: 6e 6f 2c 20 50 52 49 4d 41 52 59 20 4b 45 59 28 no, PRIMARY KEY(
+| 3328: 73 65 67 69 64 2c 20 74 65 72 6d 29 29 20 57 49 segid, term)) WI
+| 3344: 54 48 4f 55 54 20 52 4f 57 49 44 55 08 07 17 1b THOUT ROWIDU....
+| 3360: 1b 01 81 01 74 61 62 6c 65 74 32 5f 64 61 74 61 ....tablet2_data
+| 3376: 74 32 5f 64 61 74 61 07 43 52 45 41 54 45 20 54 t2_data.CREATE T
+| 3392: 41 42 4c 45 20 27 74 32 5f 64 61 74 61 27 28 69 ABLE 't2_data'(i
+| 3408: 64 20 49 4e 54 45 47 45 52 20 50 52 49 4d 41 52 d INTEGER PRIMAR
+| 3424: 59 20 4b 45 59 2c 20 62 6c 6f 63 6b 20 42 4c 4f Y KEY, block BLO
+| 3440: 42 29 58 07 07 17 11 11 08 81 1d 74 61 62 6c 65 B)X........table
+| 3456: 74 32 74 32 43 52 45 41 54 45 20 56 49 52 54 55 t2t2CREATE VIRTU
+| 3472: 41 4c 20 54 41 42 4c 45 20 74 32 20 55 53 49 4e AL TABLE t2 USIN
+| 3488: 47 20 66 74 73 35 28 27 61 27 2c 5b 62 5d 2c 22 G fts5('a',[b],.
+| 3504: 63 22 2c 64 65 74 61 69 6c 3d 6e 6f 6e 65 2c 63 c.,detail=none,c
+| 3520: 6f 6c 75 6d 6e 73 69 7a 65 3d 30 29 56 06 06 17 olumnsize=0)V...
+| 3536: 1f 1f 01 7d 74 61 62 6c 65 74 31 5f 63 6f 6e 66 ....tablet1_conf
+| 3552: 69 67 74 31 5f 63 6f 6e 66 69 67 06 43 52 45 41 igt1_config.CREA
+| 3568: 54 45 20 54 41 42 4c 45 20 27 74 31 5f 63 6f 6e TE TABLE 't1_con
+| 3584: 66 69 67 27 28 6b 20 50 52 49 4d 41 52 59 20 4b fig'(k PRIMARY K
+| 3600: 45 59 2c 20 76 29 20 57 49 54 48 4f 55 54 20 52 EY, v) WITHOUT R
+| 3616: 4f 57 49 44 5b 05 07 17 21 21 01 81 01 74 61 62 OWID[...!!...tab
+| 3632: 6c 65 74 31 5f 64 6f 63 73 69 7a 65 74 31 5f 64 let1_docsizet1_d
+| 3648: 6f 63 73 69 7a 65 05 43 52 45 41 54 45 20 54 41 ocsize.CREATE TA
+| 3664: 42 4c 45 20 27 74 31 5f 64 6f 63 73 69 7a 65 27 BLE 't1_docsize'
+| 3680: 28 69 64 20 49 4e 54 45 47 45 52 20 50 52 49 4d (id INTEGER PRIM
+| 3696: 41 52 59 20 4b 45 59 2c 20 73 7a 20 42 4c 4f 42 ARY KEY, sz BLOB
+| 3712: 29 5e 04 07 17 21 21 01 81 07 74 61 62 6c 65 74 )^...!!...tablet
+| 3728: 31 5f 63 6f 6e 74 65 6e 74 74 31 5f 63 6f 6e 74 1_contentt1_cont
+| 3744: 65 6e 74 04 43 52 45 41 54 45 20 54 41 42 4c 45 ent.CREATE TABLE
+| 3760: 20 27 74 31 5f 63 6f 6e 74 65 6e 74 27 28 69 64 't1_content'(id
+| 3776: 20 49 4e 54 45 47 45 52 20 50 52 49 4d 41 52 59 INTEGER PRIMARY
+| 3792: 20 4b 45 59 2c 20 63 30 2c 20 63 31 2c 20 63 32 KEY, c0, c1, c2
+| 3808: 29 69 03 07 17 19 19 01 81 2d 74 61 62 6c 65 74 )i.......-tablet
+| 3824: 31 5f 69 64 78 74 31 5f 69 64 78 03 43 52 45 41 1_idxt1_idx.CREA
+| 3840: 54 45 20 54 41 42 4c 45 20 27 74 31 5f 69 64 78 TE TABLE 't1_idx
+| 3856: 27 28 73 65 67 69 64 2c 20 74 65 72 6d 2c 20 70 '(segid, term, p
+| 3872: 67 6e 6f 2c 20 50 52 49 4d 41 52 59 20 4b 45 59 gno, PRIMARY KEY
+| 3888: 28 73 65 67 69 64 2c 20 74 65 72 6d 29 29 20 57 (segid, term)) W
+| 3904: 49 54 48 4f 55 54 20 52 4f 57 49 44 55 02 07 17 ITHOUT ROWIDU...
+| 3920: 1b 1b 01 81 01 74 61 62 6c 65 74 31 5f 64 61 74 .....tablet1_dat
+| 3936: 61 74 31 5f 64 61 74 61 02 43 52 45 41 54 45 20 at1_data.CREATE
+| 3952: 54 41 42 4c 45 20 27 74 31 5f 64 61 74 61 27 28 TABLE 't1_data'(
+| 3968: 69 64 20 49 4e 54 45 47 45 52 20 50 52 49 4d 41 id INTEGER PRIMA
+| 3984: 52 59 20 4b 45 59 2c 20 62 6c 6f 63 6b 20 42 4c RY KEY, block BL
+| 4000: 4f 42 29 5b 01 07 17 11 11 08 81 23 74 61 62 6c OB)[.......#tabl
+| 4016: 65 74 31 74 31 43 52 45 41 54 45 20 56 49 52 54 et1t1CREATE VIRT
+| 4032: 55 41 4c 20 54 41 42 4c 45 20 74 31 20 55 53 49 UAL TABLE t1 USI
+| 4048: 4e 47 20 66 74 73 35 28 61 2c 62 20 75 6e 69 65 NG fts5(a,b unie
+| 4064: 24 65 78 65 64 2c 63 2c 74 6f 6b 65 6e 69 7a 65 $exed,c,tokenize
+| 4080: 3d 22 70 6f 72 74 65 72 20 61 73 63 69 69 22 29 =.porter ascii.)
+| page 2 offset 4096
+| 0: 0d 0f 68 00 05 0f 13 00 0f e6 0f 13 0f a8 00 00 ..h.............
+| 3856: 00 00 00 15 0a 03 00 30 00 00 00 00 01 03 03 00 .......0........
+| 3872: 03 01 01 01 02 01 01 03 01 01 37 8c 80 80 80 80 ..........7.....
+| 3888: 01 03 00 74 00 20 68 20 69 0d 00 00 00 03 0f e8 ...t. h i.......
+| page 5 offset 16384
+| 4064: 00 00 00 00 00 00 00 00 06 03 03 00 12 03 00 00 ................
+| 4080: 60 20 30 d6 20 30 00 30 60 10 30 01 20 30 00 30 ` 0. 0.0`.0. 0.0
+| page 6 offset 20480
+| 0: a0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
+| 4080: 00 00 00 00 0b 03 1b 01 76 65 72 73 69 6f 6e 04 ........version.
+| page 7 offset 24576
+| 0: 0d 00 00 00 03 0f 9e 00 0f e6 0f ef 0f 9e 00 00 ................
+| 16: 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 ................
+| 3984: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 41 84 ..............A.
+| 4000: 80 80 80 80 01 04 00 81 06 00 00 00 34 02 30 61 ............4.0a
+| 4016: 01 00 ff ff ff ff ff ff ff ff ff 11 87 89 06 26 ...............&
+| 4032: 01 64 01 01 01 65 01 01 01 66 01 01 01 66 01 01 .d...e...f...f..
+| 4048: 01 01 01 68 01 01 01 01 01 69 01 01 01 04 01 56 ...h.....i.....V
+| 4064: 06 04 44 00 06 06 07 01 03 00 14 03 09 09 09 0f ..D.............
+| 4080: 0a 03 00 24 00 00 00 00 01 01 01 00 01 01 01 01 ...$............
+| page 8 offset 28672
+| 0: 0a 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 ................
+| 4080: 00 00 00 00 00 00 00 00 00 00 05 04 09 1c 01 02 ................
+| page 9 offset 32768
+| 0: 0d 00 00 00 9d 0f be 00 0f ea 0f d4 0f be 00 00 ................
+| 4016: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 14 03 ................
+| 4032: 05 00 17 17 17 61 20 62 20 63 67 20 68 20 69 67 .....a b cg h ig
+| 4048: 20 68 20 69 14 02 05 00 17 17 17 67 20 68 20 69 h i.......g h i
+| 4064: 61 20 62 20 63 67 20 68 20 69 14 01 04 ff 17 17 a b cg h i......
+| 4080: 17 61 20 62 20 63 64 20 65 20 66 67 20 68 20 69 .a b cd e fg h i
+| page 10 offset 36864
+| 0: 0a 00 00 00 01 0f f4 00 0f f4 00 00 00 00 00 01 ................
+| 4080: 00 00 00 00 0b 03 1b 01 76 65 72 73 69 6f 6e 04 ........version.
+| end crash-03b68c01d30713.db
+}]} {}
+
+
+do_catchsql_test 76.1 {
+ SELECT * FROM t4;
+} {1 {database disk image is malformed}}
+
sqlite3_fts5_may_be_corrupt 0
finish_test
diff --git a/ext/misc/cksumvfs.c b/ext/misc/cksumvfs.c
index 0f6b00f43..6994dc776 100644
--- a/ext/misc/cksumvfs.c
+++ b/ext/misc/cksumvfs.c
@@ -579,6 +579,18 @@ static int cksmFileControl(sqlite3_file *pFile, int op, void *pArg){
}else if( op==SQLITE_FCNTL_CKPT_START || op==SQLITE_FCNTL_CKPT_DONE ){
p->inCkpt = op==SQLITE_FCNTL_CKPT_START;
if( p->pPartner ) p->pPartner->inCkpt = p->inCkpt;
+ }else if( op==SQLITE_FCNTL_CKSM_FILE ){
+ /* This VFS needs to obtain a pointer to the corresponding database
+ ** file handle from within xOpen() calls to open wal files. To do this,
+ ** it uses the sqlite3_database_file_object() API to obtain a pointer
+ ** to the file-handle used by SQLite to access the db file. This is
+ ** fine if cksmvfs happens to be the top-level VFS, but not if there
+ ** are one or more wrapper VFS. To handle this case, this file-control
+ ** is used to extract the cksmvfs file-handle from any wrapper file
+ ** handle. */
+ sqlite3_file **ppFile = (sqlite3_file**)pArg;
+ *ppFile = (sqlite3_file*)p;
+ return SQLITE_OK;
}
rc = pFile->pMethods->xFileControl(pFile, op, pArg);
if( rc==SQLITE_OK && op==SQLITE_FCNTL_VFSNAME ){
@@ -688,6 +700,8 @@ static int cksmOpen(
if( rc ) goto cksm_open_done;
if( flags & SQLITE_OPEN_WAL ){
sqlite3_file *pDb = sqlite3_database_file_object(zName);
+ rc = pDb->pMethods->xFileControl(pDb, SQLITE_FCNTL_CKSM_FILE, (void*)&pDb);
+ assert( rc==SQLITE_OK );
p->pPartner = (CksmFile*)pDb;
assert( p->pPartner->pPartner==0 );
p->pPartner->pPartner = p;
diff --git a/ext/misc/decimal.c b/ext/misc/decimal.c
index a8d68ac72..37c6c2f52 100644
--- a/ext/misc/decimal.c
+++ b/ext/misc/decimal.c
@@ -459,10 +459,11 @@ static void decimalSubFunc(
Decimal *pA = decimal_new(context, argv[0], 0, 0);
Decimal *pB = decimal_new(context, argv[1], 0, 0);
UNUSED_PARAMETER(argc);
- if( pB==0 ) return;
- pB->sign = !pB->sign;
- decimal_add(pA, pB);
- decimal_result(context, pA);
+ if( pB ){
+ pB->sign = !pB->sign;
+ decimal_add(pA, pB);
+ decimal_result(context, pA);
+ }
decimal_free(pA);
decimal_free(pB);
}
diff --git a/ext/misc/json1.c b/ext/misc/json1.c
index 76c6e40f8..41ff01db4 100644
--- a/ext/misc/json1.c
+++ b/ext/misc/json1.c
@@ -299,7 +299,7 @@ static void jsonAppendSeparator(JsonString *p){
*/
static void jsonAppendString(JsonString *p, const char *zIn, u32 N){
u32 i;
- if( (N+p->nUsed+2 >= p->nAlloc) && jsonGrow(p,N+2)!=0 ) return;
+ if( zIn==0 || ((N+p->nUsed+2 >= p->nAlloc) && jsonGrow(p,N+2)!=0) ) return;
p->zBuf[p->nUsed++] = '"';
for(i=0; i<N; i++){
unsigned char c = ((unsigned const char*)zIn)[i];
diff --git a/ext/rbu/rbu1.test b/ext/rbu/rbu1.test
index 7ec075b7e..9237dbcea 100644
--- a/ext/rbu/rbu1.test
+++ b/ext/rbu/rbu1.test
@@ -132,6 +132,11 @@ foreach {tn3 create_vfs destroy_vfs} {
} {
sqlite3rbu_destroy_vfs myrbu
}
+ 3 {
+ sqlite3_register_cksumvfs
+ } {
+ sqlite3_unregister_cksumvfs
+ }
} {
eval $create_vfs
diff --git a/ext/rbu/sqlite3rbu.c b/ext/rbu/sqlite3rbu.c
index c5f809848..1a13b6c4a 100644
--- a/ext/rbu/sqlite3rbu.c
+++ b/ext/rbu/sqlite3rbu.c
@@ -1620,7 +1620,9 @@ char *rbuVacuumIndexStart(
zSep = "";
for(iCol=0; iCol<pIter->nCol; iCol++){
const char *zQuoted = (const char*)sqlite3_column_text(pSel, iCol);
- if( zQuoted[0]=='N' ){
+ if( zQuoted==0 ){
+ p->rc = SQLITE_NOMEM;
+ }else if( zQuoted[0]=='N' ){
bFailed = 1;
break;
}
@@ -4992,28 +4994,14 @@ static int rbuVfsOpen(
rbu_file *pDb = rbuFindMaindb(pRbuVfs, zName, 0);
if( pDb ){
if( pDb->pRbu && pDb->pRbu->eStage==RBU_STAGE_OAL ){
- /* This call is to open a *-wal file. Intead, open the *-oal. This
- ** code ensures that the string passed to xOpen() is terminated by a
- ** pair of '\0' bytes in case the VFS attempts to extract a URI
- ** parameter from it. */
- const char *zBase = zName;
- size_t nCopy;
- char *zCopy;
+ /* This call is to open a *-wal file. Intead, open the *-oal. */
+ size_t nOpen;
if( rbuIsVacuum(pDb->pRbu) ){
- zBase = sqlite3_db_filename(pDb->pRbu->dbRbu, "main");
- zBase = sqlite3_filename_wal(zBase);
- }
- nCopy = strlen(zBase);
- zCopy = sqlite3_malloc64(nCopy+2);
- if( zCopy ){
- memcpy(zCopy, zBase, nCopy);
- zCopy[nCopy-3] = 'o';
- zCopy[nCopy] = '\0';
- zCopy[nCopy+1] = '\0';
- zOpen = (const char*)(pFd->zDel = zCopy);
- }else{
- rc = SQLITE_NOMEM;
+ zOpen = sqlite3_db_filename(pDb->pRbu->dbRbu, "main");
+ zOpen = sqlite3_filename_wal(zOpen);
}
+ nOpen = strlen(zOpen);
+ ((char*)zOpen)[nOpen-3] = 'o';
pFd->pRbu = pDb->pRbu;
}
pDb->pWalFd = pFd;
diff --git a/ext/session/sqlite3session.h b/ext/session/sqlite3session.h
index e4aed9a25..10d013390 100644
--- a/ext/session/sqlite3session.h
+++ b/ext/session/sqlite3session.h
@@ -86,14 +86,11 @@ void sqlite3session_delete(sqlite3_session *pSession);
** This method is used to configure a session object after it has been
** created. At present the only valid value for the second parameter is
** [SQLITE_SESSION_OBJCONFIG_SIZE].
-*/
-int sqlite3session_object_config(sqlite3_session*, int op, void *pArg);
-
-/*
-** CAPI3REF: Arguments for sqlite3session_object_config()
+**
+** Arguments for sqlite3session_object_config()
**
** The following values may passed as the the 4th parameter to
-** [sqlite3session_object_config].
+** sqlite3session_object_config().
**
** <dt>SQLITE_SESSION_OBJCONFIG_SIZE <dd>
** This option is used to set, clear or query the flag that enables
@@ -109,6 +106,10 @@ int sqlite3session_object_config(sqlite3_session*, int op, void *pArg);
** It is an error (SQLITE_MISUSE) to attempt to modify this setting after
** the first table has been attached to the session object.
*/
+int sqlite3session_object_config(sqlite3_session*, int op, void *pArg);
+
+/*
+*/
#define SQLITE_SESSION_OBJCONFIG_SIZE 1
/*
@@ -356,11 +357,11 @@ int sqlite3session_changeset(
/*
** CAPI3REF: Return An Upper-limit For The Size Of The Changeset
-** METHOD: sqlite3session_changeset_size()
+** METHOD: sqlite3_session
**
** By default, this function always returns 0. For it to return
** a useful result, the sqlite3_session object must have been configured
-** to enable this API using [sqlite3session_object_config()] with the
+** to enable this API using sqlite3session_object_config() with the
** SQLITE_SESSION_OBJCONFIG_SIZE verb.
**
** When enabled, this function returns an upper limit, in bytes, for the size
diff --git a/main.mk b/main.mk
index 43b956a12..d8b44f419 100644
--- a/main.mk
+++ b/main.mk
@@ -539,7 +539,6 @@ FUZZERSHELL_OPT = -DSQLITE_ENABLE_JSON1
FUZZCHECK_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5
FUZZCHECK_OPT += -DSQLITE_MAX_MEMORY=50000000
FUZZCHECK_OPT += -DSQLITE_PRINTF_PRECISION_LIMIT=1000
-FUZZCHECK_OPT += -DSQLITE_ENABLE_DESERIALIZE
FUZZCHECK_OPT += -DSQLITE_ENABLE_FTS4
FUZZCHECK_OPT += -DSQLITE_ENABLE_RTREE
FUZZCHECK_OPT += -DSQLITE_ENABLE_GEOPOLY
@@ -592,7 +591,6 @@ dbfuzz$(EXE): $(TOP)/test/dbfuzz.c sqlite3.c sqlite3.h
DBFUZZ2_OPTS = \
-DSQLITE_THREADSAFE=0 \
-DSQLITE_OMIT_LOAD_EXTENSION \
- -DSQLITE_ENABLE_DESERIALIZE \
-DSQLITE_DEBUG \
-DSQLITE_ENABLE_DBSTAT_VTAB \
-DSQLITE_ENABLE_BYTECODE_VTAB \
@@ -1081,6 +1079,9 @@ rbu$(EXE): $(TOP)/ext/rbu/rbu.c $(TOP)/ext/rbu/sqlite3rbu.c sqlite3.o
loadfts: $(TOP)/tool/loadfts.c libsqlite3.a
$(TCC) $(TOP)/tool/loadfts.c libsqlite3.a -o loadfts $(THREADLIB)
+threadtest5: $(TOP)/test/threadtest5.c libsqlite3.a
+ $(TCC) $(TOP)/test/threadtest5.c libsqlite3.a -o threadtest5 $(THREADLIB)
+
# This target will fail if the SQLite amalgamation contains any exported
# symbols that do not begin with "sqlite3_". It is run as part of the
# releasetest.tcl script.
@@ -1143,3 +1144,4 @@ clean:
rm -f sqldiff sqldiff.exe
rm -f fts5.* fts5parse.*
rm -f lsm.h lsm1.c
+ rm -f threadtest5
diff --git a/manifest b/manifest
index e45c8dc25..231f1fbf9 100644
--- a/manifest
+++ b/manifest
@@ -1,11 +1,11 @@
-C merge\slatest\strunk
-D 2021-04-27T04:47:27.151
+C merge\sfrom\strunk
+D 2021-05-19T19:55:10.206
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
-F Makefile.in 3f76d8a9b0e78aa7b627ad56cab35908d99909de51dcb90b1e6a29eb4fd4394a
+F Makefile.in 30c6d39386246695e951a676973e0bf57aabbd1e37024c07e657af89dd332555
F Makefile.linux-gcc f609543700659711fbd230eced1f01353117621dccae7b9fb70daa64236c5241
-F Makefile.msc 231cf3fbc7bab3cc1801b3bf6a006098e9dfeca00d4d0910aad74795d0f94d5f
+F Makefile.msc 6443729ba6a013a0fea4f999b22e54760f36e73c2e691554f0c4bfa1dbe4d070
F README.md 2a71913f398ecac5f3e10945fcf438aed425c2e9ed9874de561156ba77fb7023
F VERSION 8c392f6d70d82e513a0eac622bdf23c43df3e084cb630288beba8cef3012c812
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
@@ -15,7 +15,7 @@ F art/sqlite370.jpg d512473dae7e378a67e28ff96a34da7cb331def2
F autoconf/INSTALL 83e4a25da9fd053c7b3665eaaaf7919707915903
F autoconf/Makefile.am a8d1d24affe52ebf8d7ddcf91aa973fa0316618ab95bb68c87cabf8faf527dc8
F autoconf/Makefile.fallback 22fe523eb36dfce31e0f6349f782eb084e86a5620b2b0b4f84a2d6133f53f5ac
-F autoconf/Makefile.msc ebe7e66edbb2f453593cbde186d1a0fa0dcd8cae9977febcae27aef1dab5678d
+F autoconf/Makefile.msc d146a08ebbdf7f881ba600a49cd8dce40c4c807addcdb4b9b6a507e4b40ce837
F autoconf/README.first 6c4f34fe115ff55d4e8dbfa3cecf04a0188292f7
F autoconf/README.txt 4f04b0819303aabaa35fff5f7b257fb0c1ef95f1
F autoconf/configure.ac a8ba2a9e61216f5093d44f3b7d2cb8fe1890d6b7dc330a02f802d8efaa1fdc79
@@ -84,7 +84,7 @@ F ext/fts3/README.content b9078d0843a094d86af0d48dffbff13c906702b4c3558012e67b9c
F ext/fts3/README.syntax a19711dc5458c20734b8e485e75fb1981ec2427a
F ext/fts3/README.tokenizers b92bdeb8b46503f0dd301d364efc5ef59ef9fa8e2758b8e742f39fa93a2e422d
F ext/fts3/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d
-F ext/fts3/fts3.c 1d80d0a1e53ce5e7316e1379969c842079c46237369e131fd378288e64ebbf5f
+F ext/fts3/fts3.c 95f55e24550c01c2a325d09c9ea8fdff61e923a4675f8545b28bf3c470e57dfb
F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe
F ext/fts3/fts3Int.h bde280294d56ff50ee29d03e5140f0b6953b44d1c969bb5831e8ae85e3e76715
F ext/fts3/fts3_aux.c 1af58af8f2b00a49f4fb1c2602f8da2054ad60076f46c8ebf85c5410eccccb65
@@ -119,7 +119,7 @@ F ext/fts5/fts5_buffer.c 5a5fe0159752c0fb0a5a93c722e9db2662822709490769d482b76a6
F ext/fts5/fts5_config.c 8336d0ff6db0933f63cfec8ae0ab76e68393259cbccc0b46e1f79f7fa1842ff3
F ext/fts5/fts5_expr.c 9462249a3bb82d0e49b163500f9d2197c2e4cd95bf440a9bbfc3906b22ea1e1b
F ext/fts5/fts5_hash.c 1aa93c9b5f461afba66701ee226297dc78402b3bdde81e90a10de5fe3df14959
-F ext/fts5/fts5_index.c 345824b780672465f786a65f348321f1e100880961e682273230eba65b795b62
+F ext/fts5/fts5_index.c 222b5e56f51139ca5400985e26ea9971165901c7a45a2c17499bd2be3695c697
F ext/fts5/fts5_main.c f497ca97cb2802311ec93733b595762dc5b044ce3c6c8ce5fb3e871dd3fccd5d
F ext/fts5/fts5_storage.c 58ba71e6cd3d43a5735815e7956ee167babb4d2cbfe206905174792af4d09d75
F ext/fts5/fts5_tcl.c b1445cbe69908c411df8084a10b2485500ac70a9c747cdc8cda175a3da59d8ae
@@ -160,7 +160,7 @@ F ext/fts5/test/fts5connect.test 08030168fc96fc278fa81f28654fb7e90566f33aff269c0
F ext/fts5/test/fts5content.test 213506436fb2c87567b8e31f6d43ab30aab99354cec74ed679f22aad0cdbf283
F ext/fts5/test/fts5corrupt.test 77ae6f41a7eba10620efb921cf7dbe218b0ef232b04519deb43581cb17a57ebe
F ext/fts5/test/fts5corrupt2.test 7453752ba12ce91690c469a6449d412561cc604b1dec994e16ab132952e7805f
-F ext/fts5/test/fts5corrupt3.test 04dde67b3ecff4206a86e02d082b41a5706c88238f0bee139d950dc5c74bbba6
+F ext/fts5/test/fts5corrupt3.test 7748c28d0a0c8f00e7741a097df7c76eed207b5443908621dd1ce1dd23b84a07
F ext/fts5/test/fts5corrupt4.test f4c08e2182a48d8b70975fd869ee5391855c06d8a0ff87b6a2529e7c5a88a1d3
F ext/fts5/test/fts5delete.test 619295b20dbc1d840b403ee07c878f52378849c3c02e44f2ee143b3e978a0aa7
F ext/fts5/test/fts5detail.test 31b240dbf6d44ac3507e2f8b65f29fdc12465ffd531212378c7ce1066766f54e
@@ -291,21 +291,21 @@ F ext/misc/blobio.c a867c4c4617f6ec223a307ebfe0eabb45e0992f74dd47722b96f3e631c0e
F ext/misc/btreeinfo.c d28ce349b40054eaa9473e835837bad7a71deec33ba13e39f963d50933bfa0f9
F ext/misc/carray.c b75a0f207391038bf1540d3372f482a95c3613511c7c474db51ede1196321c7c
F ext/misc/carray.h de74ac70b2338f416723f7d538026e8ec0b7f1d388319f8f140c9a4d7677f02e
-F ext/misc/cksumvfs.c 8dc4e1b718e374bed3a9b5c0a08da2922438002e33267311697768e06217b983
+F ext/misc/cksumvfs.c 2c6b07714f3be6c1200671c53aa781a86d2c472c0fcb2fff520375362eb94303
F ext/misc/closure.c dbfd8543b2a017ae6b1a5843986b22ddf99ff126ec9634a2f4047cd14c85c243
F ext/misc/completion.c 6dafd7f4348eecc7be9e920d4b419d1fb2af75d938cd9c59a20cfe8beb2f22b9
F ext/misc/compress.c 3354c77a7c8e86e07d849916000cdac451ed96500bfb5bd83b20eb61eee012c9
F ext/misc/csv.c 53b3338d4fa812eda51a2637df30233a4dae16b964ee5666e2051b9672ed8bb4
F ext/misc/dbdata.c e316fba936571584e55abd5b974a32a191727a6b746053a0c9d439bd2cf93940
F ext/misc/dbdump.c b8592f6f2da292c62991a13864a60d6c573c47a9cc58362131b9e6a64f823e01
-F ext/misc/decimal.c 3ddbf8162015be4d5ec2395dee4538f1e638bb517174bb148274b132df6e1d08
+F ext/misc/decimal.c 09f967dcf4a1ee35a76309829308ec278d3648168733f4a1147820e11ebefd12
F ext/misc/eval.c 04bc9aada78c888394204b4ed996ab834b99726fb59603b0ee3ed6e049755dc1
F ext/misc/explain.c 0086fab288d4352ea638cf40ac382aad3b0dc5e845a1ea829a694c015fd970fe
F ext/misc/fileio.c 9b69e25da3b51d4a1d905a464ccb96709792ad627a742ba09215bc0d1447e7bd
F ext/misc/fossildelta.c 1240b2d3e52eab1d50c160c7fe1902a9bd210e052dc209200a750bbf885402d5
F ext/misc/fuzzer.c eae560134f66333e9e1ca4c8ffea75df42056e2ce8456734565dbe1c2a92bf3d
F ext/misc/ieee754.c cd6ab89f85fda8a020559b3f4d03001a8a62dd856beda5af3f558621d12be913
-F ext/misc/json1.c 332c285db81a3757c278d725e5dafd7afeab6232240c679fbdc087683923eb85
+F ext/misc/json1.c 2c5c0dbc7fa303f0213f008e5878db9f0e5875fe8ff59a7c2d9f235b18e323a7
F ext/misc/memstat.c 3017a0832c645c0f8c773435620d663855f04690172316bd127270d1a7523d4d
F ext/misc/memtrace.c 7c0d115d2ef716ad0ba632c91e05bd119cb16c1aedf3bec9f06196ead2d5537b
F ext/misc/memvfs.c ab36f49e02ebcdf85a1e08dc4d8599ea8f343e073ac9e0bca18a98b7e1ec9567
@@ -340,7 +340,7 @@ F ext/misc/wholenumber.c a838d1bea913c514ff316c69695efbb49ea3b8cb37d22afc57f73b6
F ext/misc/zipfile.c acbad31bd9c9ec3540fa72b2e3fcd6f757eb33117d51528c0e13d0da5c836908
F ext/misc/zorder.c b0ff58fa643afa1d846786d51ea8d5c4b6b35aa0254ab5a82617db92f3adda64
F ext/rbu/rbu.c b880ca5cb857d6d6f52e72eb7397813058ef48c78c5402cd04ff2b6b5437f622
-F ext/rbu/rbu1.test 221d9c18a5e600ac9ac6b1810d99d9f99163a7909ba61597876ab6e4d4beb3d6
+F ext/rbu/rbu1.test c62904bd9526dcdc3496a21199aaf14ae191bbadbf67f076bf16be6b3f2115c2
F ext/rbu/rbu10.test 0a201c32202143f23c81c0144503da339786fc20acb7a2fda11601b65659f314
F ext/rbu/rbu11.test 5c834cf491086b45e071eabf71f708febc143e86a384a92de69e0b1a4cace144
F ext/rbu/rbu12.test 29f8b2118f6c96fac3755bd6d2b55c2db24f878b1f11fbfbe294f3a230a3dcdc
@@ -379,7 +379,7 @@ F ext/rbu/rbuvacuum.test 55e101e90168c2b31df6c9638fe73dc7f7cc666b6142266d1563697
F ext/rbu/rbuvacuum2.test b8e5b51dc8b2c0153373d024c0936be3f66f9234acbd6d0baab0869d56b14e6b
F ext/rbu/rbuvacuum3.test 8addd82e4b83b4c93fa47428eae4fd0dbf410f8512c186f38e348feb49ba03dc
F ext/rbu/rbuvacuum4.test a78898e438a44803eb2bc897ba3323373c9f277418e2d6d76e90f2f1dbccfd10
-F ext/rbu/sqlite3rbu.c e6531884442b72f9e0ba47036fb5c4641ea817ff659a642b3984c10b8535b0fd
+F ext/rbu/sqlite3rbu.c badb52388467f58e67ef104c5276d1ac68b316a30f8ccb2f74eac733625ae236
F ext/rbu/sqlite3rbu.h 1dc88ab7bd32d0f15890ea08d23476c4198d3da3056985403991f8c9cd389812
F ext/rbu/test_rbu.c 03f6f177096a5f822d68d8e4069ad8907fe572c62ff2d19b141f59742821828a
F ext/repair/README.md 92f5e8aae749a4dae14f02eea8e1bb42d4db2b6ce5e83dbcdd6b1446997e0c15
@@ -457,7 +457,7 @@ F ext/session/sessionsize.test 6f644aff31c7f1e4871e9ff3542766e18da68fc7e587b83a3
F ext/session/sessionstat1.test 218d351cf9fcd6648f125a26b607b140310160184723c2666091b54450a68fb5
F ext/session/sessionwor.test 6fd9a2256442cebde5b2284936ae9e0d54bde692d0f5fd009ecef8511f4cf3fc
F ext/session/sqlite3session.c 703634ca25b4b903ae8ec25045802a8c8deca36a65d2b993c4bc8888f6d6c7ee
-F ext/session/sqlite3session.h 4c299467627cd27ac31fcbd062274da676d0c471be22f1255867f30f4f832b9a
+F ext/session/sqlite3session.h 0907de79bc13a2e3af30a6dc29acc60792a3eaf7d33d44cf52500d0f3c2b2171
F ext/session/test_session.c f433f68a8a8c64b0f5bc74dc725078f12483301ad4ae8375205eef790274a787
F ext/userauth/sqlite3userauth.h 7f3ea8c4686db8e40b0a0e7a8e0b00fac13aa7a3
F ext/userauth/user-auth.txt e6641021a9210364665fe625d067617d03f27b04
@@ -465,7 +465,7 @@ F ext/userauth/userauth.c 7f00cded7dcaa5d47f54539b290a43d2e59f4b1eb5f447545fa865
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60
-F main.mk 71abdbb39dbc530f436f7095d2c0504140d513142a6a552602fb55c8156fd854
+F main.mk d1654e2923a7195603a7d6564dabe037a3a20ea5b3817002db534ffc4ad8cecf
F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83
F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
@@ -477,17 +477,17 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca
F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
-F src/alter.c 6c62a47364d4eb142de6b0aa8a21e83450ad115ca5c2100f031af171777af068
+F src/alter.c df53c39fd4f32528fc7ad8188b3bf2b506e1a8b3bb975b14f16a1bc6e901950f
F src/analyze.c 01c6c6765cb4d40b473b71d85535093730770bb186f2f473abac25f07fcdee5c
-F src/attach.c a7d1a7df69f053951ec1665e5894c61184fda3f677323762f1c3679ebd27d5c7
+F src/attach.c 42774f1f26f6970aef07a206f0afa5d73fea5d2bb84d5a8f687a7f56f00f2a3a
F src/auth.c 08954fdc4cc2da5264ba5b75cfd90b67a6fc7d1710a02ccf917c38eadec77853
F src/backup.c 3014889fa06e20e6adfa0d07b60097eec1f6e5b06671625f476a714d2356513d
F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33
F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6
-F src/btree.c 0555f7e97ede886ac3d7aaec363b44498c9716dd45f3f0484de31eb90e30a37e
+F src/btree.c 51ba86095316fceb3e25bc61617d673d84627e79f4ace83f8722910f33eedef3
F src/btree.h 096cc53baa58be22b02c896d1cf933c38cfc6d65f9253c1367ece8cc88a24de5
F src/btreeInt.h 7bc15a24a02662409ebcd6aeaa1065522d14b7fda71573a2b0568b458f514ae0
-F src/build.c f4072218dacf42f45b733d1a9a98b3a4d7b8c676a7e5d8ff17d70b60aff687ae
+F src/build.c 4e13b92f77d3f6dc1285c3636a2ba7c6af5cbb793e52075a762fbcebcd36e968
F src/callback.c d0b853dd413255d2e337b34545e54d888ea02f20da5ad0e63585b389624c4a6c
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
F src/ctime.c fbc6243075128ddf187ec469a6d178ebd58bb6eae8e3ba191446fa18cffb17c3
@@ -495,11 +495,11 @@ F src/date.c e0632f335952b32401482d099321bbf12716b29d6e72836b53ae49683ebae4bf
F src/dbpage.c 8a01e865bf8bc6d7b1844b4314443a6436c07c3efe1d488ed89e81719047833a
F src/dbstat.c 3aa79fc3aed7ce906e4ea6c10e85d657299e304f6049861fe300053ac57de36c
F src/delete.c 73f57a9a183532c344a3135cf8f2a5589376e39183e0b5f562d6b61b2af0f4d8
-F src/expr.c 70e2cf6e270bb97ab6602336c82060bee0720cd887483f85c645ac1df97d4a34
+F src/expr.c 1d5171fe602cd56ab8b9c9ecbd48d9917e6020cafd6bd87ceac5949e8a1ed2d8
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
F src/fkey.c e9063648396c58778f77583a678342fe4a9bc82436bf23c5f9f444f2df0fdaa4
F src/func.c 88fd711754a7241cb9f8eb1391370fd0c0cea756b3358efa274c5d1efd59af93
-F src/global.c 56d6762a3a44495ab035e2d3185eeccbc98579e18c06038e1bb9af346105bc84
+F src/global.c 25ba4d58476f6be29bba9d9d14f7f146b78476d3a4d75ebb8c3b736328afe0f9
F src/hash.c 8d7dda241d0ebdafb6ffdeda3149a412d7df75102cecfc1021c98d6219823b19
F src/hash.h 9d56a9079d523b648774c1784b74b89bd93fac7b365210157482e4319a468f38
F src/hwtime.h cb1d7e3e1ed94b7aa6fde95ae2c2daccc3df826be26fc9ed7fd90d1750ae6144
@@ -507,14 +507,14 @@ F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
F src/insert.c 2189e0e596010a0dc5405d9f14f78db1ee2fa71138c931f5b6ea96610b95bfc1
F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
F src/loadext.c 8c9c8cd2bd8eecdb06d9b6e89de7e9e65bae45cc8fc33609cc74023a5c296067
-F src/main.c 7db30c6293bb86c45c11638b1de38419e663623b549c74959be6981e7731eb5e
+F src/main.c 2b2044221a10e7c5f49a98f50563ce9a944511241ba5946d1754dcc2a7437a07
F src/malloc.c c1af4ac5a463648cd2953fd4ac679b3ba9022ce5ec794a60806150ad69dfd33a
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de
F src/mem2.c b93b8762ab999a29ae7751532dadf0a1ac78040308a5fb1d17fcc365171d67eb
F src/mem3.c 30301196cace2a085cbedee1326a49f4b26deff0af68774ca82c1f7c06fda4f6
F src/mem5.c 9bf955937b07f8c32541c8a9991f33ce3173d944
-F src/memdb.c eab3c87582a99de1589703e393b0238881c9a16511dc5a29009e84042a5e9f25
+F src/memdb.c f6ce717b26cd51a24cda62fce611b4b72b3db367113374aa498e489a69470715
F src/memjournal.c 431c70a111223a8a6e2e7e9f014afc6c88d818d357d866afc563195f2277d50e
F src/msvc.h 3a15918220367a8876be3fa4f2abe423a861491e84b864fb2b7426bf022a28f8
F src/mutex.c 5e3409715552348732e97b9194abe92fdfcd934cfb681df4ba0ab87ac6c18d25
@@ -527,12 +527,12 @@ F src/os.c 6e94cd64b134c9317e52ad534117578e3df66ec180d70dbf4b1d7eb1db8e5a5d
F src/os.h 48388821692e87da174ea198bf96b1b2d9d83be5dfc908f673ee21fafbe0d432
F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85
F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586
-F src/os_unix.c b5b7475bd1a8f1b83b6173a81f4fe50f9e077ccbacb62ce2fe7a5cb89916bce1
+F src/os_unix.c efa60c1cb54dba767abbba3c6dd67d3df5ef8aa26e2e499c37f055f56a374068
F src/os_win.c 77d39873836f1831a9b0b91894fec45ab0e9ca8e067dc8c549e1d1eca1566fe9
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
-F src/pager.c 0c84ba222cc58825098ae7d693db85c69f1700ba2a74d9d395033337a511b4e6
+F src/pager.c 95c255256b13827caf038c8f963d334784073f38ab6ef9d70371d9d04f3c43e0
F src/pager.h 4bf9b3213a4b2bebbced5eaa8b219cf25d4a82f385d093cd64b7e93e5285f66f
-F src/parse.y 77039cf996d9cde8ee1e947ad9284566c30e48cc227766a7be1d475ec7aed9dd
+F src/parse.y ac294bd2891c4310b0b23a67ea3bbca2d0bf5b7662c4444b6517c3986be4a437
F src/pcache.c 385ff064bca69789d199a98e2169445dc16e4291fa807babd61d4890c3b34177
F src/pcache.h 4f87acd914cef5016fae3030343540d75f5b85a1877eed1a2a19b9f284248586
F src/pcache1.c 388304fd2d91c39591080b5e0f3c62cfba87db20370e7e0554062bfb29740e9f
@@ -541,18 +541,18 @@ F src/pragma.h 8dc78ab7e9ec6ce3ded8332810a2066f1ef6267e2e03cd7356ee00276125c6cf
F src/prepare.c d778af9986f3b0107c5b255dcfe2696e8e99e00fb77c5115bbfea4e92c3302e7
F src/printf.c 78fabb49b9ac9a12dd1c89d744abdc9b67fd3205e62967e158f78b965a29ec4b
F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
-F src/resolve.c c38bbb89d7ba7a8673ec4f59b63e0980eb859c39ff2acc5df8b3d0f2dcd33115
+F src/resolve.c 40e216d9a72e52841a9c8e0aec7d367bade8e2df17b804653b539b20c1ab5660
F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92
-F src/select.c 57dbb27e0d0cb2438487c797365a4c17294d0df3c25c970ca87f123105f33ed0
-F src/shell.c.in 9320b476fde0f7c46700e5695b69b435f1e46843a1513cdd187ac426cdbee016
-F src/sqlite.h.in 372554fcd1e1ed25ba44a316e8abdaad712470b7dcfa185ece54f51b10fbde10
+F src/select.c 09acd5a12c4229238919e38816d0d5c90b24015ef495afb825dc1b3f2a8cf18a
+F src/shell.c.in 1b32ba2918ede13b68df47c7b92b72ba0d06e68d384e78bb9d7456527271d400
+F src/sqlite.h.in 5c950066775ca9efdaa49077c05d38d0bef6418f3bd07d2dce0210f1d2f3c326
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h 61b38c073d5e1e96a3d45271b257aef27d0d13da2bea5347692ae579475cd95e
-F src/sqliteInt.h a00cc0642e2a4e26367313dc553781253e278a0e571e7211cc56245a8db3e0e7
+F src/sqliteInt.h 16d132f4380f9f4ebf9db6b803ddde641aa2c917964b028404d09459cf83533f
F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a31657
F src/status.c 4b8bc2a6905163a38b739854a35b826c737333fab5b1f8e03fa7eb9a4799c4c1
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
-F src/tclsqlite.c 986b6391f02cd9b53c1d688be55899f6ffddeb8e8014cd83c1b73ff912579a71
+F src/tclsqlite.c 97645e4a15dde6a6ad6de8d81057ff9869413b866015a89e208fedacd709493e
F src/test1.c 2100f4c28bae21ce83a9a0c5ec6827efd0e15d11b93b569b614daa5654b3fcf6
F src/test2.c 3efb99ab7f1fc8d154933e02ae1378bac9637da5
F src/test3.c 61798bb0d38b915067a8c8e03f5a534b431181f802659a6616f9b4ff7d872644
@@ -560,7 +560,7 @@ F src/test4.c 7c4420e01c577b5c4add2cb03119743b1a357543d347773b9e717195ea967159
F src/test5.c 328aae2c010c57a9829d255dc099d6899311672d
F src/test6.c ae73a3a42bbc982fb9e301b84d30bda65a307be48c6dff20aba1461e17a9b0ce
F src/test7.c 5612e9aecf934d6df7bba6ce861fdf5ba5456010
-F src/test8.c 7fb971777c2c79c734bb52757191d68d4af659b8de9b4a071be3f527a9d19a02
+F src/test8.c 0c856d6ff6b0d2ff6696addc467a15ed17c6910f14475302cd5b3b4e54406161
F src/test9.c 12e5ba554d2d1cbe0158f6ab3f7ffcd7a86ee4e5
F src/test_async.c 195ab49da082053fdb0f949c114b806a49ca770a
F src/test_autoext.c 915d245e736652a219a907909bb6710f0d587871
@@ -568,7 +568,7 @@ F src/test_backup.c bf5da90c9926df0a4b941f2d92825a01bbe090a0
F src/test_bestindex.c 78809f11026f18a93fcfd798d9479cba37e1201c830260bf1edc674b2fa9b857
F src/test_blob.c ae4a0620b478548afb67963095a7417cd06a4ec0a56adb453542203bfdcb31ce
F src/test_btree.c 8b2dc8b8848cf3a4db93f11578f075e82252a274
-F src/test_config.c 842ddde1f1d32c12f1651a77e51d6ccdb84697d5023be352c54683db930e9702
+F src/test_config.c 9c8e12823c46082a01765addf43be9309889f4e9dfb5a512a6c974e1c4efb413
F src/test_delete.c e2fe07646dff6300b48d49b2fee2fe192ed389e834dd635e3b3bac0ce0bf9f8f
F src/test_demovfs.c 86142ba864d4297d54c5b2e972e74f3141ae4b30f05b3a95824184ed2d3d7f91
F src/test_devsym.c aff2255ea290d7718da08af30cdf18e470ff7325a5eff63e0057b1496ed66593
@@ -609,32 +609,32 @@ F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
F src/tokenize.c bae853ad129d1129c063de8630a3e99e306283bc40146f359b1bb91be2c08f1e
F src/treeview.c e483aeedf6f207000db1f90eb6abd816350493314c30e8749d319bdb9ab3b08c
-F src/trigger.c f8493674f5c8f103c1a2cd0616af9dca85c7058450f9fe47cacd15cf5d512d52
+F src/trigger.c e0fd347b2571a2d956318cdc6d011ccca7ce862d10a0ca04188a37920ef5440c
F src/update.c b3abdaf4a314bbed238da69a6ca54c0f21262119389b412ee5778fffe62dd3cc
F src/upsert.c df8f1727d62b5987c4fd302cd4d7c0c84ae57cd65683c5a34a740dfe24039235
F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0
F src/util.c 41c7a72da1df47864faa378a1c720b38adb288c6838cb6be5594511b6287a048
F src/vacuum.c 492422c1463c076473bae1858799c7a0a5fe87a133d1223239447c422cd26286
-F src/vdbe.c ff3ccdd969774e6ce821b54d076286c84137e2f0e6387b1133bafbaa7470f749
+F src/vdbe.c 74491791630743ef5215a90e6ec94c0965577b9b7086b2180d2c7fa0954317a8
F src/vdbe.h 25dabb25c7e157b84e59260cfb5b466c3ac103ede9f36f4db371332c47601abe
F src/vdbeInt.h 58980223a32495ad059d10581b83e133abdc77248b1bab85c080cab8a13bd819
F src/vdbeapi.c d9e99daf59fec928986838b3389a7337e82fec6b3b5de30206cb99fb4661b94e
F src/vdbeaux.c 065a10392378109f08435bd50d03dff315e384cde2831d6b8dbaec05f33b10af
F src/vdbeblob.c c6b8db50b227f66fb404215732068df76485b5b433e5f9d4d9ac27410b218193
-F src/vdbemem.c 947f2a65910edb4014dc981d33e414a68c51f169f9df8c4c493a0ba840b6eb1f
+F src/vdbemem.c 175c73ced03edbb0f6567a41c8032afaeb83372090fa7bddfc88a67e28da2b8a
F src/vdbesort.c f5b5e473a7cee44e47a94817b042fd7172cf3aa2c0a7928a8339d612bcfdec5a
F src/vdbetrace.c 666c6fd9f1b62be6999e072a45b913e3c2c3518bc60dfd4d54fe304130acb724
F src/vdbevtab.c f99b275366c5fc5e2d99f734729880994ab9500bdafde7fae3b02d562b9d323c
F src/vtab.c b928405ccb66040fc6c3a11eaa93ddb02cbf20f9ab6860b301b222b9b50dc089
F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
-F src/wal.c 69e770e96fd56cc21608992bf2c6f1f3dc5cf2572d0495c6a643b06c3a679f14
+F src/wal.c c8ec20a1ca161d5635a4f19c2a4efec2e006e19a8a61f272bf6bce1c80ab7436
F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a
-F src/walker.c 6e540867a30d81e00205995fa2dc0e3d25365a7402251c9fd5d19aa4ff5e60b6
-F src/where.c 22705995adaa97f7fb9163f31b9277c457d6995dcb0c4fcf52d1b317d9594d1f
-F src/whereInt.h 446e5e8018f83358ef917cf32d8e6a86dc8430113d0b17e720f1839d3faa44c4
-F src/wherecode.c 992bf0d7520bffd345472fb9bc83a1ca0134e46d9e904879bb21e1e77957fcc3
-F src/whereexpr.c d8cafcf6781cf871082f04d7540862cf0fe30cb381dd1b2145a380376364fe8e
-F src/window.c 35b14e7a53fe0472b42679919c474de3a5b5c1615fe90a2c41431f37e4ede1be
+F src/walker.c 7342becedf3f8a26f9817f08436bdf8b56ad69af83705f6b9320a0ad3092c2ac
+F src/where.c 32f41c3c93c6785e0077e3a2cdc669c3ccfe70173787847be77f294c18fc7dc3
+F src/whereInt.h 9248161dd004f625ce5d3841ca9b99fed3fc8d61522cf76340fc5217dbe1375b
+F src/wherecode.c 110ed13049e0f1dc27e9dd942eb870417b36480cb7819302f5804cbcf9330b0e
+F src/whereexpr.c 5a9c9f5d2dac4bcdcaae3035034b4667523f731df228e0bb1d4efc669efa9da5
+F src/window.c ce5e73ab88a8527d268673906bf89cbe58c61bca8d54d38ed8c33c3220a276ee
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/affinity2.test ce1aafc86e110685b324e9a763eab4f2a73f737842ec3b687bd965867de90627
F test/affinity3.test eecb0dabee4b7765a8465439d5e99429279ffba23ca74a7eae270a452799f9e7
@@ -645,7 +645,7 @@ F test/all.test 2ecb8bbd52416642e41c9081182a8df05d42c75637afd4488aace78cc4b69e13
F test/alter.test f53d8a4ecd35f051c07e54a36beec5d0a30d30a9d98bc723f6cde6afbfb3c5ca
F test/alter2.test a966ccfcddf9ce0a4e0e6ff1aca9e6e7948e0e242cd7e43fc091948521807687
F test/alter3.test e487958dec7932453e0b83baf21d6b1e71d5e7d9a55bc20eadfa62a51ddffc29
-F test/alter4.test dfd6086faf461b27ca2d2999848dcd207edf23352fc1592d0005c0844f3f08cf
+F test/alter4.test 716caa071dd8a3c6d57225778d15d3c3cbf5e34b2e84ae44199aeb2bbf50a707
F test/alterauth.test 63442ba61ceb0c1eeb63aac1f4f5cebfa509d352276059d27106ae256bafc959
F test/alterauth2.test 381b1ab603c9ef96314a3158528ea17f7964449385a28eeaf8191120b2e24a8d
F test/altercol.test b11fa1b131e80ab5b6ecfb3b725fb0419c14ca6efba5adb57aeabfc9baa0c8f3
@@ -657,7 +657,7 @@ F test/altermalloc.test 167a47de41b5c638f5f5c6efb59784002b196fff70f98d9b4ed3cd74
F test/altermalloc2.test fa7b1c1139ea39b8dec407cf1feb032ca8e0076bd429574969b619175ad0174b
F test/altermalloc3.test 059841a3de6b6780efd9f0b30bf1d9b4443c555f68d39975cbcac2583167b239
F test/alterqf.test 67568ad152db8c1187b15633b801242cf960f1beafc51261a3d1725d910baeb2
-F test/altertab.test 2591f93cc1c5ac1f1854b096ffdfe10caf0a8bcdfc8f830bdc9a554e08e6dd6d
+F test/altertab.test c7966d92e4da535050b911e1e9972ecb3a5befb0b2d22026b132cf5003d43dec
F test/altertab2.test b0d62f323ca5dab42b0bc028c52e310ebdd13e655e8fac070fe622bad7852c2b
F test/altertab3.test 2b82fa2236a3a91553d53ae5555d8e723c7eec174c41f1fa62ff497355398479
F test/amatch1.test b5ae7065f042b7f4c1c922933f4700add50cdb9f
@@ -782,7 +782,7 @@ F test/contrib01.test 2a1cbc0f2f48955d7d073f725765da6fbceda6b4
F test/corrupt.test d7cb0300e4a297147b6a05e92a1684bc8973635c3bcaa3d66e983c9cbdbf47a3
F test/corrupt2.test bb50042cf9a1f1023d73af325d47eb02a6bb11e3c52f8812644b220c5d4bca35
F test/corrupt3.test 2520432b1fbf99994841e69804a3c59fb828183f4d09b85a1631bc7adca17e31
-F test/corrupt4.test 04965221ecd005901923fdc57f26811fa07178074b0672e50ea424c21638c708
+F test/corrupt4.test b5ae41607e8d17d9c1f3e94fdb572ce061ed3beeebdb46fb3a348181b8c8a097
F test/corrupt5.test 387be3250795e2a86e6234745558b80efb248a357d0cd8e53bce75c7463f545d
F test/corrupt6.test fc6a891716139665dae0073b6945e3670bf92568
F test/corrupt7.test b036f94bda4b0b23a2919bf717046ce9ecca4543
@@ -801,7 +801,7 @@ F test/corruptJ.test 4d5ccc4bf959464229a836d60142831ef76a5aa4
F test/corruptK.test 5b4212fe346699831c5ad559a62c54e11c0611bdde1ea8423a091f9c01aa32af
F test/corruptL.test df132ba9ffd6fa15038380b4154998b9904ab8f1ea78400d7da53c920cb3b13d
F test/corruptM.test 7d574320e08c1b36caa3e47262061f186367d593a7e305d35f15289cc2c3e067
-F test/corruptN.test 7a8a8399f57cdc6a189f275230300ccbb2b31a5aea8399070251beeebe2cc02b
+F test/corruptN.test f56e3417fe9a444efd765ae55acbe65595d7b8f747785fe0fd785dbdc424932a
F test/cost.test b11cdbf9f11ffe8ef99c9881bf390e61fe92baf2182bad1dbe6de59a7295c576
F test/count.test 5364003488249957750a5f15ee42ca1cd7b100b1131c2dc71fff266a1250bf55
F test/countofview.test e17d6e6688cf74f22783c9ec6e788c0790ee4fbbaee713affd00b1ac0bb39b86
@@ -829,7 +829,7 @@ F test/dbdata.test 042f49acff3438f940eeba5868d3af080ae64ddf26ae78f80c92bec3ca7d8
F test/dbfuzz.c 73047c920d6210e5912c87cdffd9a1c281d4252e
F test/dbfuzz001.test 55e1a3504f8dea84155e09912fe3b1c3ad77e0b1a938ec42ca03b8e51b321e30
F test/dbfuzz2-seed1.db e6225c6f3d7b63f9c5b6867146a5f329d997ab105bee64644dc2b3a2f2aebaee
-F test/dbfuzz2.c db2a1710c0d30d38e1352ee1b52b717fcb224c8caacc6f10909ef540f73cc9e8
+F test/dbfuzz2.c 4b3c12de4d98b1b2d908ab03d217d4619e47c8b23d5e67f8a6f2b1bdee7cae23
F test/dbpage.test 650234ba683b9d82b899c6c51439819787e7609f17a0cc40e0080a7b6443bc38
F test/dbstatus.test 4a4221a883025ffd39696b3d1b3910b928fb097d77e671351acb35f3aed42759
F test/dbstatus2.test f5fe0afed3fa45e57cfa70d1147606c20d2ba23feac78e9a172f2fe8ab5b78ef
@@ -884,8 +884,6 @@ F test/exclusive.test 7ff63be7503990921838d5c9f77f6e33e68e48ed1a9d48cd28745bf650
F test/exclusive2.test 984090e8e9d1b331d2e8111daf6e5d61dda0bef7
F test/exec.test e949714dc127eaa5ecc7d723efec1ec27118fdd7
F test/exists.test 79a75323c78f02bbe9c251ea502a092f9ef63dac
-F test/exists2.test 92d563a97019a70f7adcbe3cbaab16f9fc696affbf0f9ede1796ea5f7cc5a3ac
-F test/existsfault.test 72a0036c1424d9204d49f4d976c3277a1b8bb2eed3c67aa124ba2df2f1331c7c
F test/expr.test 26cd01e8485bc48c8aa6a1add598e9ce1e706b4eb4f3f554e0b0223022e8c2cf
F test/expr2.test c27327ae9c017a7ff6280123f67aff496f912da74d78c888926d68b46ec75fd8
F test/exprfault.test 497cc0b8fe6a677f49b55cb485e040f709ec2834b84f25912fe9c2dfeeda33db
@@ -1049,7 +1047,7 @@ F test/fuzz3.test 9c813e6613b837cb7a277b0383cd66bfa07042b4cf0317157c35852f30043c
F test/fuzz4.test c229bcdb45518a89e1d208a21343e061503460ac69fae1539320a89f572eb634
F test/fuzz_common.tcl b7197de6ed1ee8250a4f82d67876f4561b42ee8cbbfc6160dcb66331bad3f830
F test/fuzz_malloc.test f348276e732e814802e39f042b1f6da6362a610af73a528d8f76898fde6b22f2
-F test/fuzzcheck.c 59bcbb5f5c6dcec4f6f5c4e4456b5dc7211ea893f2204c80ceb4277bba83fb9b
+F test/fuzzcheck.c c51cdb34e926d0a6551624aa1f04c456c29317b5457855d64391917d9b4c2aff
F test/fuzzdata1.db d36e88741b4f23bcbaaf55b006290669d03c6c891cf13c7b3a53bc1b097b693f
F test/fuzzdata2.db 128b3feeb78918d075c9b14b48610145a0dd4c8d6f1ca7c2870c7e425f5bf31f
F test/fuzzdata3.db c6586d3e3cef0fbc18108f9bb649aa77bfc38aba
@@ -1057,7 +1055,7 @@ F test/fuzzdata4.db b502c7d5498261715812dd8b3c2005bad08b3a26e6489414bd13926cd3e4
F test/fuzzdata5.db e35f64af17ec48926481cfaf3b3855e436bd40d1cfe2d59a9474cb4b748a52a5
F test/fuzzdata6.db 92a80e4afc172c24f662a10a612d188fb272de4a9bd19e017927c95f737de6d7
F test/fuzzdata7.db 0166b56fd7a6b9636a1d60ef0a060f86ddaecf99400a666bb6e5bbd7199ad1f2
-F test/fuzzdata8.db 00e053a6a486be9edf2d6bae8f3911ca7e2cc27aa32291d1c8258130e9eb9eb3
+F test/fuzzdata8.db 5e616432bbdd9b27014463545cae06797790645021fbc650d28c994b4f02a6f5
F test/fuzzer1.test 3d4c4b7e547aba5e5511a2991e3e3d07166cfbb8
F test/fuzzer2.test a85ef814ce071293bce1ad8dffa217cbbaad4c14
F test/fuzzerfault.test f64c4aef4c9e9edf1d6dc0d3f1e65dcc81e67c996403c88d14f09b74807a42bc
@@ -1077,7 +1075,7 @@ F test/in2.test 5d4c61d17493c832f7d2d32bef785119e87bde75
F test/in3.test 3cbf58c87f4052cee3a58b37b6389777505aa0c0
F test/in4.test cd08375ba470b248c3dc4ab30fd5dbcb682deafe3862d8249ba0ad6a11dd25ea
F test/in5.test b32ce7f4a93f44c5dee94af16886d922cc16ebe33c8e1765c73d4049d0f4b40f
-F test/in6.test 8562d0945195cab3cc4ab3794e9118e72cb44c43f785c2b04d48a9d06ca6b4ec
+F test/in6.test f5f40d6816a8bb7c784424b58a10ac38efb76ab29127a2c17399e0cbeeda0e4b
F test/incrblob.test c9b96afc292aeff43d6687bcb09b0280aa599822
F test/incrblob2.test a494c9e848560039a23974b9119cfc2cf3ad3bd15cc2694ee6367ae537ef8f1f
F test/incrblob3.test d8d036fde015d4a159cd3cbae9d29003b37227a4
@@ -1239,7 +1237,7 @@ F test/offset1.test f06b83657bcf26f9ce805e67450e189e282143b2
F test/openv2.test 0d3040974bf402e19b7df4b783e447289d7ab394
F test/optfuzz-db01.c 9f2fa80b8f84ebbf1f2e8b13421a4e0477fe300f6686fbd76cac1d2db66e0fdc
F test/optfuzz-db01.txt 21f6bdeadc701cf11528276e2a55c70bfcb846ba42df327f979bd9e7b6ce7041
-F test/optfuzz.c 50e330304eb1992e15ddd11f3daaad9bcc0d9aaad09cb2bcc77f9515df2e88b1
+F test/optfuzz.c 690430a0bf0ad047d5a168bf52b05b2ee97aedaad8c14337e9eb5050faa64994
F test/orderby1.test a4bba04b9c60a21e53486fbc173a596b29641a3b3a57a0f26a1cbef1360358e9
F test/orderby2.test bc11009f7cd99d96b1b11e57b199b00633eb5b04
F test/orderby3.test 8619d06a3debdcd80a27c0fdea5c40b468854b99
@@ -1295,11 +1293,11 @@ F test/recover.test ccb8c2623902a92ebb76770edd075cb4f75a4760bb7afde38026572c6e79
F test/regexp1.test 497ea812f264d12b6198d6e50a76be4a1973a9d8
F test/regexp2.test 40e894223b3d6672655481493f1be12012f2b33c
F test/reindex.test cd9d6021729910ece82267b4f5e1b5ac2911a7566c43b43c176a6a4732e2118d
-F test/releasetest.tcl 8dcfc21d6b4a4a1d9a8503de0a94800d129ec8f03ef53d6e68b79ef78a786acd x
-F test/releasetest_data.tcl a864d27370e812c34a05224d6144ca082463906d5a4651782ad3b43712ab166a
+F test/releasetest.tcl 6f803ef0b896f8f3f4c26eb072c0399963a5987a509a64d45f5dfbc1ebae2951 x
+F test/releasetest_data.tcl f88ed29aa18366ed3956ace36c96ec6868ef5b9ee04cc05d32f4d81031e19e28
F test/resetdb.test 8062cf10a09d8c048f8de7711e94571c38b38168db0e5877ba7561789e5eeb2b
F test/resolver01.test f4022acafda7f4d40eca94dbf16bc5fc4ac30ceb
-F test/returning1.test 99012dc464860e1502153276d5e5c2bee32c53d3a866dcfc09b39932048e2276
+F test/returning1.test 52b4ed60f104a4ce85b38417e5319b2078b2b908c71a768d539cee3c0ce8bdc9
F test/rollback.test 06680159bc6746d0f26276e339e3ae2f951c64812468308838e0a3362d911eaa
F test/rollback2.test 3f3a4e20401825017df7e7671e9f31b6de5fae5620c2b9b49917f52f8c160a8f
F test/rollbackfault.test 0e646aeab8840c399cfbfa43daab46fd609cf04a
@@ -1465,6 +1463,7 @@ F test/threadtest1.c 6029d9c5567db28e6dc908a0c63099c3ba6c383b
F test/threadtest2.c a70a8e94bef23339d34226eb9521015ef99f4df8
F test/threadtest3.c e63013af10cf236c7610eb06d33bde08c861806dc64be811940ff4d9ddd34a4f
F test/threadtest4.c c1e67136ceb6c7ec8184e56ac61db28f96bd2925
+F test/threadtest5.c 9b4d782c58d8915d7e955ff8051f3d03628bda0d33b82971ea8c0f2f2808c421
F test/time-wordcount.sh 8e0b0f8109367827ad5d58f5cc849705731e4b90
F test/tkt-02a8e81d44.test 6c80d9c7514e2a42d4918bf87bf6bc54f379110c
F test/tkt-18458b1a.test 6a62cb1ee50fa3c620da59e3a6f531eb38fceaf7e2166203816b724524e6f1d6
@@ -1617,7 +1616,7 @@ F test/trace3.test ae2004df24b585fed9046cc0bae4601762bc6fc4aa321d475f1350bba5047
F test/trans.test 45f6f9ab6f66a7b5744f1caac06b558f95da62501916906cf55586a896f9f439
F test/trans2.test 62bd045bfc7a1c14c5ba83ba64d21ade31583f76
F test/trans3.test 91a100e5412b488e22a655fe423a14c26403ab94
-F test/transitive1.test 239eec5343388983f112c16d666aa89960cd85302b6af6cd8408ce8edb7b3316
+F test/transitive1.test 06bcfeeb2ed719abf6ae582f9f65a6b07642dd1363fa648ae9a74a35e83a825c
F test/trigger1.test d30cd09ae8ac365a088f09daba583cc5c0b8fc7d4e1d70809d0b4be3bf6ae2ab
F test/trigger2.test 6e35bd7321c49e63d540aee980eb95dec63e1d1caca175224101045bcc80871f
F test/trigger3.test aa640bb2bbb03edd5ff69c055117ea088f121945
@@ -1682,7 +1681,7 @@ F test/vacuummem.test 7b42abb3208bd82dd23a7536588396f295a314f2
F test/varint.test bbce22cda8fc4d135bcc2b589574be8410614e62
F test/veryquick.test 57ab846bacf7b90cf4e9a672721ea5c5b669b661
F test/view.test ea88361d5e9bc8eabf9f573185a16aea73a885be9b6c6a95ae84908913416a80
-F test/vtab1.test c5d9e90ed02bcacd776dcbb7360199d290f7f53c26b484ddece543060c54319f
+F test/vtab1.test 99c0c13b5336ca7f87f137459de144b2f396bb8563fbd602e46bfaa425e3d8cc
F test/vtab2.test 14d4ab26cee13ba6cf5c5601b158e4f57552d3b055cdd9406cf7f711e9c84082
F test/vtab3.test b45f47d20f225ccc9c28dc915d92740c2dee311e
F test/vtab4.test 8e73ed268f3d596bc3590f45fc948fb40f28e9c3
@@ -1750,7 +1749,7 @@ F test/where5.test fdf66f96d29a064b63eb543e28da4dfdccd81ad2
F test/where6.test 5da5a98cec820d488e82708301b96cb8c18a258b
F test/where7.test ab41d53ce8f2a6919ea3d5b13cd1153c1375a8e3ddaa129b81781f9033981383
F test/where8.test 461ca40265ed996a6305da99bb024b0e41602bb586acf544c08f95922358e49f
-F test/where9.test b1942ed1d4c4632ea99e135691371f33803428ee4092a462280338ab3347f916
+F test/where9.test 1ffb75edc50a8faa6e7bd77f8221d783febb00b44b0bdb32fb48cec6e38eca95
F test/whereA.test 9d1077b117f1b68d5f739d94f36956c36cf995eb87bb19b77b2e81af020edd20
F test/whereB.test 0def95db3bdec220a731c7e4bec5930327c1d8c5
F test/whereC.test cae295158703cb3fc23bf1a108a9ab730efff0f6
@@ -1762,7 +1761,7 @@ F test/whereH.test e4b07f7a3c2f5d31195cd33710054c78667573b2
F test/whereI.test c4bb7e2ca56d49bd8ab5c7bd085b8b83e353922b46904d68aefb3c7468643581
F test/whereJ.test fc05e374cc9f2dc204148d6c06822c380ad388895fe97a6d335b94a26a08aecf
F test/whereK.test 0270ab7f04ba5436fb9156d31d642a1c82727f4c4bfe5ba90d435c78cf44684a
-F test/whereL.test 7717caf61ff4b09d05ddd2978701c4cf5661408bd4dce31d38eff482f60f44f3
+F test/whereL.test 50171e3ec00b4c8ad5ec773119a35d9e9642cec45154b44c366d628326479f4d
F test/wherefault.test 6cf2a9c5712952d463d3f45ebee7f6caf400984df51a195d884cfb7eb0e837a7
F test/wherelfault.test 9012e4ef5259058b771606616bd007af5d154e64cc25fa9fd4170f6411db44e3
F test/wherelimit.test afb46397c6d7e964e6e294ba3569864a0c570fe3807afc634236c2b752372f31
@@ -1771,7 +1770,7 @@ F test/win32heap.test 10fd891266bd00af68671e702317726375e5407561d859be1aa04696f2
F test/win32lock.test fbf107c91d8f5512be5a5b87c4c42ab9fdd54972
F test/win32longpath.test 4baffc3acb2e5188a5e3a895b2b543ed09e62f7c72d713c1feebf76222fe9976
F test/win32nolock.test ac4f08811a562e45a5755e661f45ca85892bdbbc
-F test/window1.test 54e160bdeb8b06fb3b97993e0eec45ee4c3294f39ad63007c921c40961298815
+F test/window1.test 7cb66f49d30d89ca9d28dc20f7f1d85229365651e8e6211f7da1448740866511
F test/window2.tcl 492c125fa550cda1dd3555768a2303b3effbeceee215293adf8871efc25f1476
F test/window2.test e466a88bd626d66edc3d352d7d7e1d5531e0079b549ba44efb029d1fbff9fd3c
F test/window3.tcl acea6e86a4324a210fd608d06741010ca83ded9fde438341cb978c49928faf03
@@ -1782,8 +1781,8 @@ F test/window5.test d328dd18221217c49c144181975eea17339eaeaf0e9aa558cee3afb84652
F test/window6.test f8d674254b23289cc17c84d79dec7eda7caa1dfb7836c43122cfdf3640d1df32
F test/window7.tcl 6a1210f05d40ec89c22960213a22cd3f98d4e2f2eb20646c83c8c30d4d76108f
F test/window7.test 1d31276961ae7801edc72173edaf7593e3cbc79c06d1f1f09e20d8418af403cd
-F test/window8.tcl f2711aa3571e4e6b0dad98db8d95fd6cb8d9db0c92bbdf535f153b07606a1ce2
-F test/window8.test c4331b27a6f66d69fa8f8bab10cc731db1a81d293ae108a68f7c3487fa94e65b
+F test/window8.tcl 5e02e41d9d9a80f597063aed1a381eb19d1d0ef677a4f0df352c5365cf23f79c
+F test/window8.test 4ab16817414af0c904abe2ebdf88eb6c2b00058b84f9748c6174ff11fc45f1ed
F test/window9.test 349c71eab4288a1ffc19e2f65872ec2c37e6cf8a1dda2ad300364b7450ae4836
F test/windowA.test 6d63dc1260daa17141a55007600581778523a8b420629f1282d2acfc36af23be
F test/windowB.test 6e601f8178ba8ba28b2f19e74fe613815084bb4a8d2ad942defc7d42e191e521
@@ -1798,7 +1797,7 @@ F test/with4.test 257be66c0c67fee1defbbac0f685c3465e2cad037f21ce65f23f86084f1982
F test/with5.test 6248213c41fab36290b5b73aa3f937309dfba337004d9d8434c3fabc8c7d4be8
F test/with6.test 661d7e416bef6c0a2556b2c9f0c8178a5b15932bed65246abed99723a8d4e7c0
F test/withM.test 693b61765f2b387b5e3e24a4536e2e82de15ff64
-F test/without_rowid1.test e4034c0849ccc2e8bb749c69f15bd69bb9fcf8fe77e8d17ce02369604242fe83
+F test/without_rowid1.test 6abc5d497f634520944dac0a89a6c240a48d2ee0f8353356a750eb70dc1db41a
F test/without_rowid2.test af260339f79d13cb220288b67cd287fbcf81ad99
F test/without_rowid3.test 39ab0dd773eaa62e59b17093f875327630f54c4145458f6d2b053d68d4b2f67b
F test/without_rowid4.test 4e08bcbaee0399f35d58b5581881e7a6243d458a
@@ -1845,7 +1844,7 @@ F tool/mkctimec.tcl 6469850ad5e9f9173046da7569a0a6f40c5b21316406b70aaa029b357bc8
F tool/mkkeywordhash.c 08b6e4d7a482a7f37a9a0032e7ba968e26624a027b6b2e9ba589be6f5e3d8c2c
F tool/mkmsvcmin.tcl 6ecab9fe22c2c8de4d82d4c46797bda3d2deac8e763885f5a38d0c44a895ab33
F tool/mkopcodec.tcl d1b6362bd3aa80d5520d4d6f3765badf01f6c43c
-F tool/mkopcodeh.tcl 352a4319c0ad869eb26442bf7c3b015aa15594c21f1cce5a6420dbe999367c21
+F tool/mkopcodeh.tcl acc798757e2c60e4b6e16745505b9595fca76c206815c8ada576a136cf3608ed
F tool/mkopts.tcl 680f785fdb09729fd9ac50632413da4eadbdf9071535e3f26d03795828ab07fa
F tool/mkpragmatab.tcl ae5585ae76ca26e4d6ccd5ea9cdebaf5efefb318bf989497a0e846cd711d9ab1
F tool/mkshellc.tcl 70a9978e363b0f3280ca9ce1c46d72563ff479c1930a12a7375e3881b7325712
@@ -1857,7 +1856,7 @@ F tool/mksqlite3h.tcl 1f5e4a1dbbbc43c83cc6e74fe32c6c620502240b66c7c0f33a51378e78
F tool/mksqlite3internalh.tcl eb994013e833359137eb53a55acdad0b5ae1049b
F tool/mkvsix.tcl b9e0777a213c23156b6542842c238479e496ebf5
F tool/offsets.c 8ed2b344d33f06e71366a9b93ccedaa38c096cc1dbd4c3c26ad08c6115285845
-F tool/omittest.tcl 38c3e409ae0070df177ca49164f5ed19ad4f3d5b574ee3272d521a94b59bdb84
+F tool/omittest.tcl 3d222272b1d840b4e3d67bff0cb743ce3f633faddadb3702b2056b726775db8f
F tool/opcodesum.tcl 740ed206ba8c5040018988129abbf3089a0ccf4a
F tool/pagesig.c ff0ca355fd3c2398e933da5e22439bbff89b803b
F tool/replace.tcl 60f91e8dd06ab81f74d213ecbd9c9945f32ac048
@@ -1914,7 +1913,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 830b0b1c49aaca53a40e5a4ca9a11351d697a980c7bf80379e32f0646738d566 7e18e114b245d17aa259ea9ab42752ccc9ad5303bbac8d8e46928dd10319f545
-R 05bf1168d4e82946cb66360ad9e9f04a
+P 3ff228249adf2da345d3e19e9af3e23d1354f6b9a35ddbe9864e1a07716d871c 4e81ea3b15fb3fce5f31b77273639e748a735ab0970620e564e9a5c977b24a1a
+R ea5c2f2d0e31f28da39a2a85c2aa9d20
U larrybr
-Z 638e936d637dceb5113ec52daa047f9b
+Z aa5a2c613a1eb5b66660089c16f7322a
diff --git a/manifest.uuid b/manifest.uuid
index e45b76698..e1633a619 100644
--- a/manifest.uuid
+++ b/manifest.uuid
@@ -1 +1 @@
-3ff228249adf2da345d3e19e9af3e23d1354f6b9a35ddbe9864e1a07716d871c \ No newline at end of file
+19ffe3cfe278a4046f32df56f75080c2377e4c44ad40a02d39db8e7701526204 \ No newline at end of file
diff --git a/src/alter.c b/src/alter.c
index 32a472943..047b407e5 100644
--- a/src/alter.c
+++ b/src/alter.c
@@ -835,7 +835,7 @@ static int renameUnmapSelectCb(Walker *pWalker, Select *p){
Parse *pParse = pWalker->pParse;
int i;
if( pParse->nErr ) return WRC_Abort;
- if( NEVER(p->selFlags & SF_View) ) return WRC_Prune;
+ if( p->selFlags & SF_View ) return WRC_Prune;
if( ALWAYS(p->pEList) ){
ExprList *pList = p->pEList;
for(i=0; i<pList->nExpr; i++){
diff --git a/src/attach.c b/src/attach.c
index dcfa4910d..6d178b6ba 100644
--- a/src/attach.c
+++ b/src/attach.c
@@ -95,7 +95,7 @@ static void attachFunc(
if( zFile==0 ) zFile = "";
if( zName==0 ) zName = "";
-#ifdef SQLITE_ENABLE_DESERIALIZE
+#ifndef SQLITE_OMIT_DESERIALIZE
# define REOPEN_AS_MEMDB(db) (db->init.reopenMemdb)
#else
# define REOPEN_AS_MEMDB(db) (0)
diff --git a/src/btree.c b/src/btree.c
index 80b955682..300bb361e 100644
--- a/src/btree.c
+++ b/src/btree.c
@@ -547,7 +547,7 @@ static void invalidateIncrblobCursors(
int isClearTable /* True if all rows are being deleted */
){
BtCursor *p;
- if( pBtree->hasIncrblobCur==0 ) return;
+ assert( pBtree->hasIncrblobCur );
assert( sqlite3BtreeHoldsMutex(pBtree) );
pBtree->hasIncrblobCur = 0;
for(p=pBtree->pBt->pCursor; p; p=p->pNext){
@@ -6419,10 +6419,9 @@ static void freePage(MemPage *pPage, int *pRC){
}
/*
-** Free any overflow pages associated with the given Cell. Store
-** size information about the cell in pInfo.
+** Free the overflow pages associated with the given Cell.
*/
-static int clearCell(
+static SQLITE_NOINLINE int clearCellOverflow(
MemPage *pPage, /* The page that contains the Cell */
unsigned char *pCell, /* First byte of the Cell */
CellInfo *pInfo /* Size information about the cell */
@@ -6434,10 +6433,7 @@ static int clearCell(
u32 ovflPageSize;
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
- pPage->xParseCell(pPage, pCell, pInfo);
- if( pInfo->nLocal==pInfo->nPayload ){
- return SQLITE_OK; /* No overflow pages. Return without doing anything */
- }
+ assert( pInfo->nLocal!=pInfo->nPayload );
testcase( pCell + pInfo->nSize == pPage->aDataEnd );
testcase( pCell + (pInfo->nSize-1) == pPage->aDataEnd );
if( pCell + pInfo->nSize > pPage->aDataEnd ){
@@ -6493,6 +6489,21 @@ static int clearCell(
return SQLITE_OK;
}
+/* Call xParseCell to compute the size of a cell. If the cell contains
+** overflow, then invoke cellClearOverflow to clear out that overflow.
+** STore the result code (SQLITE_OK or some error code) in rc.
+**
+** Implemented as macro to force inlining for performance.
+*/
+#define BTREE_CLEAR_CELL(rc, pPage, pCell, sInfo) \
+ pPage->xParseCell(pPage, pCell, &sInfo); \
+ if( sInfo.nLocal!=sInfo.nPayload ){ \
+ rc = clearCellOverflow(pPage, pCell, &sInfo); \
+ }else{ \
+ rc = SQLITE_OK; \
+ }
+
+
/*
** Create the byte sequence used to represent a cell on page pPage
** and write that byte sequence into pCell[]. Overflow pages are
@@ -7168,7 +7179,9 @@ static int pageFreeArray(
}
pFree = pCell;
szFree = sz;
- if( pFree+sz>pEnd ) return 0;
+ if( pFree+sz>pEnd ){
+ return 0;
+ }
}else{
pFree = pCell;
szFree += sz;
@@ -8144,6 +8157,7 @@ static int balance_nonroot(
u8 *pCell;
u8 *pTemp;
int sz;
+ u8 *pSrcEnd;
MemPage *pNew = apNew[i];
j = cntNew[i];
@@ -8187,6 +8201,12 @@ static int balance_nonroot(
iOvflSpace += sz;
assert( sz<=pBt->maxLocal+23 );
assert( iOvflSpace <= (int)pBt->pageSize );
+ for(k=0; b.ixNx[k]<=i && ALWAYS(k<NB*2); k++){}
+ pSrcEnd = b.apEnd[k];
+ if( SQLITE_WITHIN(pSrcEnd, pCell, pCell+sz) ){
+ rc = SQLITE_CORRUPT_BKPT;
+ goto balance_cleanup;
+ }
insertCell(pParent, nxDiv+i, pCell, sz, pTemp, pNew->pgno, &rc);
if( rc!=SQLITE_OK ) goto balance_cleanup;
assert( sqlite3PagerIswriteable(pParent->pDbPage) );
@@ -8743,7 +8763,9 @@ int sqlite3BtreeInsert(
assert( pX->pKey==0 );
/* If this is an insert into a table b-tree, invalidate any incrblob
** cursors open on the row being replaced */
- invalidateIncrblobCursors(p, pCur->pgnoRoot, pX->nKey, 0);
+ if( p->hasIncrblobCur ){
+ invalidateIncrblobCursors(p, pCur->pgnoRoot, pX->nKey, 0);
+ }
/* If BTREE_SAVEPOSITION is set, the cursor must already be pointing
** to a row with the same key as the new entry being inserted.
@@ -8877,7 +8899,7 @@ int sqlite3BtreeInsert(
if( !pPage->leaf ){
memcpy(newCell, oldCell, 4);
}
- rc = clearCell(pPage, oldCell, &info);
+ BTREE_CLEAR_CELL(rc, pPage, oldCell, info);
testcase( pCur->curFlags & BTCF_ValidOvfl );
invalidateOverflowCache(pCur);
if( info.nSize==szNew && info.nLocal==info.nPayload
@@ -9170,7 +9192,7 @@ int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){
/* If this is a delete operation to remove a row from a table b-tree,
** invalidate any incrblob cursors open on the row being deleted. */
- if( pCur->pKeyInfo==0 ){
+ if( pCur->pKeyInfo==0 && p->hasIncrblobCur ){
invalidateIncrblobCursors(p, pCur->pgnoRoot, pCur->info.nKey, 0);
}
@@ -9179,7 +9201,7 @@ int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){
** itself from within the page. */
rc = sqlite3PagerWrite(pPage->pDbPage);
if( rc ) return rc;
- rc = clearCell(pPage, pCell, &info);
+ BTREE_CLEAR_CELL(rc, pPage, pCell, info);
dropCell(pPage, iCellIdx, info.nSize, &rc);
if( rc ) return rc;
@@ -9466,7 +9488,7 @@ static int clearDatabasePage(
rc = clearDatabasePage(pBt, get4byte(pCell), 1, pnChange);
if( rc ) goto cleardatabasepage_out;
}
- rc = clearCell(pPage, pCell, &info);
+ BTREE_CLEAR_CELL(rc, pPage, pCell, info);
if( rc ) goto cleardatabasepage_out;
}
if( !pPage->leaf ){
@@ -9514,7 +9536,9 @@ int sqlite3BtreeClearTable(Btree *p, int iTable, int *pnChange){
/* Invalidate all incrblob cursors open on table iTable (assuming iTable
** is the root of a table b-tree - if it is not, the following call is
** a no-op). */
- invalidateIncrblobCursors(p, (Pgno)iTable, 0, 1);
+ if( p->hasIncrblobCur ){
+ invalidateIncrblobCursors(p, (Pgno)iTable, 0, 1);
+ }
rc = clearDatabasePage(pBt, (Pgno)iTable, 0, pnChange);
}
sqlite3BtreeLeave(p);
diff --git a/src/build.c b/src/build.c
index 47b0d5693..25954b4d4 100644
--- a/src/build.c
+++ b/src/build.c
@@ -46,7 +46,7 @@ struct TableLock {
** code to make the lock occur is generated by a later call to
** codeTableLocks() which occurs during sqlite3FinishCoding().
*/
-void sqlite3TableLock(
+static SQLITE_NOINLINE void lockTable(
Parse *pParse, /* Parsing context */
int iDb, /* Index of the database containing the table to lock */
Pgno iTab, /* Root page number of the table to be locked */
@@ -59,8 +59,6 @@ void sqlite3TableLock(
TableLock *p;
assert( iDb>=0 );
- if( iDb==1 ) return;
- if( !sqlite3BtreeSharable(pParse->db->aDb[iDb].pBt) ) return;
pToplevel = sqlite3ParseToplevel(pParse);
for(i=0; i<pToplevel->nTableLock; i++){
p = &pToplevel->aTableLock[i];
@@ -84,6 +82,17 @@ void sqlite3TableLock(
sqlite3OomFault(pToplevel->db);
}
}
+void sqlite3TableLock(
+ Parse *pParse, /* Parsing context */
+ int iDb, /* Index of the database containing the table to lock */
+ Pgno iTab, /* Root page number of the table to be locked */
+ u8 isWriteLock, /* True for a write lock */
+ const char *zName /* Name of the table to be locked */
+){
+ if( iDb==1 ) return;
+ if( !sqlite3BtreeSharable(pParse->db->aDb[iDb].pBt) ) return;
+ lockTable(pParse, iDb, iTab, isWriteLock, zName);
+}
/*
** Code an OP_TableLock instruction for each table locked by the
@@ -1049,6 +1058,22 @@ i16 sqlite3TableColumnToStorage(Table *pTab, i16 iCol){
#endif
/*
+** Insert a single OP_JournalMode query opcode in order to force the
+** prepared statement to return false for sqlite3_stmt_readonly(). This
+** is used by CREATE TABLE IF NOT EXISTS and similar if the table already
+** exists, so that the prepared statement for CREATE TABLE IF NOT EXISTS
+** will return false for sqlite3_stmt_readonly() even if that statement
+** is a read-only no-op.
+*/
+static void sqlite3ForceNotReadOnly(Parse *pParse){
+ int iReg = ++pParse->nMem;
+ Vdbe *v = sqlite3GetVdbe(pParse);
+ if( v ){
+ sqlite3VdbeAddOp3(v, OP_JournalMode, 0, iReg, PAGER_JOURNALMODE_QUERY);
+ }
+}
+
+/*
** Begin constructing a new table representation in memory. This is
** the first of several action routines that get called in response
** to a CREATE TABLE statement. In particular, this routine is called
@@ -1147,6 +1172,7 @@ void sqlite3StartTable(
}else{
assert( !db->init.busy || CORRUPT_DB );
sqlite3CodeVerifySchema(pParse, iDb);
+ sqlite3ForceNotReadOnly(pParse);
}
goto begin_table_error;
}
@@ -1323,6 +1349,7 @@ void sqlite3AddReturning(Parse *pParse, ExprList *pList){
pRet->retTrig.tr_tm = TRIGGER_AFTER;
pRet->retTrig.bReturning = 1;
pRet->retTrig.pSchema = db->aDb[1].pSchema;
+ pRet->retTrig.pTabSchema = db->aDb[1].pSchema;
pRet->retTrig.step_list = &pRet->retTStep;
pRet->retTStep.op = TK_RETURNING;
pRet->retTStep.pTrig = &pRet->retTrig;
@@ -3196,7 +3223,10 @@ void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView, int noErr){
if( noErr ) db->suppressErr--;
if( pTab==0 ){
- if( noErr ) sqlite3CodeVerifyNamedSchema(pParse, pName->a[0].zDatabase);
+ if( noErr ){
+ sqlite3CodeVerifyNamedSchema(pParse, pName->a[0].zDatabase);
+ sqlite3ForceNotReadOnly(pParse);
+ }
goto exit_drop_table;
}
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
@@ -3766,6 +3796,7 @@ void sqlite3CreateIndex(
}else{
assert( !db->init.busy );
sqlite3CodeVerifySchema(pParse, iDb);
+ sqlite3ForceNotReadOnly(pParse);
}
goto exit_create_index;
}
@@ -4246,7 +4277,7 @@ void sqlite3DefaultRowEst(Index *pIdx){
if( x<99 ){
pIdx->pTable->nRowLogEst = x = 99;
}
- if( pIdx->pPartIdxWhere!=0 ) x -= 10; assert( 10==sqlite3LogEst(2) );
+ if( pIdx->pPartIdxWhere!=0 ){ x -= 10; assert( 10==sqlite3LogEst(2) ); }
a[0] = x;
/* Estimate that a[1] is 10, a[2] is 9, a[3] is 8, a[4] is 7, a[5] is
@@ -4284,6 +4315,7 @@ void sqlite3DropIndex(Parse *pParse, SrcList *pName, int ifExists){
sqlite3ErrorMsg(pParse, "no such index: %S", pName->a);
}else{
sqlite3CodeVerifyNamedSchema(pParse, pName->a[0].zDatabase);
+ sqlite3ForceNotReadOnly(pParse);
}
pParse->checkSchema = 1;
goto exit_drop_index;
diff --git a/src/expr.c b/src/expr.c
index 140260931..7a2df30fd 100644
--- a/src/expr.c
+++ b/src/expr.c
@@ -95,18 +95,7 @@ Expr *sqlite3ExprAddCollateToken(
const Token *pCollName, /* Name of collating sequence */
int dequote /* True to dequote pCollName */
){
- assert( pExpr!=0 || pParse->db->mallocFailed );
- if( pExpr==0 ) return 0;
- if( pExpr->op==TK_VECTOR ){
- ExprList *pList = pExpr->x.pList;
- if( ALWAYS(pList!=0) ){
- int i;
- for(i=0; i<pList->nExpr; i++){
- pList->a[i].pExpr = sqlite3ExprAddCollateToken(pParse,pList->a[i].pExpr,
- pCollName, dequote);
- }
- }
- }else if( pCollName->n>0 ){
+ if( pCollName->n>0 ){
Expr *pNew = sqlite3ExprAlloc(pParse->db, TK_COLLATE, pCollName, dequote);
if( pNew ){
pNew->pLeft = pExpr;
diff --git a/src/global.c b/src/global.c
index 10c368f72..4648c26d9 100644
--- a/src/global.c
+++ b/src/global.c
@@ -279,7 +279,7 @@ SQLITE_WSD struct Sqlite3Config sqlite3Config = {
0, /* xVdbeBranch */
0, /* pVbeBranchArg */
#endif
-#ifdef SQLITE_ENABLE_DESERIALIZE
+#ifndef SQLITE_OMIT_DESERIALIZE
SQLITE_MEMDB_DEFAULT_MAXSIZE, /* mxMemdbSize */
#endif
#ifndef SQLITE_UNTESTABLE
diff --git a/src/main.c b/src/main.c
index 35641657e..bd92f7661 100644
--- a/src/main.c
+++ b/src/main.c
@@ -305,7 +305,7 @@ int sqlite3_initialize(void){
sqlite3GlobalConfig.isPCacheInit = 1;
rc = sqlite3OsInit();
}
-#ifdef SQLITE_ENABLE_DESERIALIZE
+#ifndef SQLITE_OMIT_DESERIALIZE
if( rc==SQLITE_OK ){
rc = sqlite3MemdbInit();
}
@@ -720,12 +720,12 @@ int sqlite3_config(int op, ...){
}
#endif /* SQLITE_ENABLE_SORTER_REFERENCES */
-#ifdef SQLITE_ENABLE_DESERIALIZE
+#ifndef SQLITE_OMIT_DESERIALIZE
case SQLITE_CONFIG_MEMDB_MAXSIZE: {
sqlite3GlobalConfig.mxMemdbSize = va_arg(ap, sqlite3_int64);
break;
}
-#endif /* SQLITE_ENABLE_DESERIALIZE */
+#endif /* SQLITE_OMIT_DESERIALIZE */
default: {
rc = SQLITE_ERROR;
@@ -1884,6 +1884,10 @@ int sqlite3CreateFunc(
}else{
sqlite3ExpirePreparedStatements(db, 0);
}
+ }else if( xSFunc==0 && xFinal==0 ){
+ /* Trying to delete a function that does not exist. This is a no-op.
+ ** https://sqlite.org/forum/forumpost/726219164b */
+ return SQLITE_OK;
}
p = sqlite3FindFunction(db, zFunctionName, nArg, (u8)enc, 1);
diff --git a/src/memdb.c b/src/memdb.c
index b25e13cbc..965ec36d4 100644
--- a/src/memdb.c
+++ b/src/memdb.c
@@ -17,32 +17,89 @@
** sqlite3_deserialize().
*/
#include "sqliteInt.h"
-#ifdef SQLITE_ENABLE_DESERIALIZE
+#ifndef SQLITE_OMIT_DESERIALIZE
/*
** Forward declaration of objects used by this utility
*/
typedef struct sqlite3_vfs MemVfs;
typedef struct MemFile MemFile;
+typedef struct MemStore MemStore;
/* Access to a lower-level VFS that (might) implement dynamic loading,
** access to randomness, etc.
*/
#define ORIGVFS(p) ((sqlite3_vfs*)((p)->pAppData))
-/* An open file */
-struct MemFile {
- sqlite3_file base; /* IO methods */
+/* Storage for a memdb file.
+**
+** An memdb object can be shared or separate. Shared memdb objects can be
+** used by more than one database connection. Mutexes are used by shared
+** memdb objects to coordinate access. Separate memdb objects are only
+** connected to a single database connection and do not require additional
+** mutexes.
+**
+** Shared memdb objects have .zFName!=0 and .pMutex!=0. They are created
+** using "file:/name?vfs=memdb". The first character of the name must be
+** "/" or else the object will be a separate memdb object. All shared
+** memdb objects are stored in memdb_g.apMemStore[] in an arbitrary order.
+**
+** Separate memdb objects are created using a name that does not begin
+** with "/" or using sqlite3_deserialize().
+**
+** Access rules for shared MemStore objects:
+**
+** * .zFName is initialized when the object is created and afterwards
+** is unchanged until the object is destroyed. So it can be accessed
+** at any time as long as we know the object is not being destroyed,
+** which means while either the SQLITE_MUTEX_STATIC_VFS1 or
+** .pMutex is held or the object is not part of memdb_g.apMemStore[].
+**
+** * Can .pMutex can only be changed while holding the
+** SQLITE_MUTEX_STATIC_VFS1 mutex or while the object is not part
+** of memdb_g.apMemStore[].
+**
+** * Other fields can only be changed while holding the .pMutex mutex
+** or when the .nRef is less than zero and the object is not part of
+** memdb_g.apMemStore[].
+**
+** * The .aData pointer has the added requirement that it can can only
+** be changed (for resizing) when nMmap is zero.
+**
+*/
+struct MemStore {
sqlite3_int64 sz; /* Size of the file */
sqlite3_int64 szAlloc; /* Space allocated to aData */
sqlite3_int64 szMax; /* Maximum allowed size of the file */
unsigned char *aData; /* content of the file */
+ sqlite3_mutex *pMutex; /* Used by shared stores only */
int nMmap; /* Number of memory mapped pages */
unsigned mFlags; /* Flags */
+ int nRdLock; /* Number of readers */
+ int nWrLock; /* Number of writers. (Always 0 or 1) */
+ int nRef; /* Number of users of this MemStore */
+ char *zFName; /* The filename for shared stores */
+};
+
+/* An open file */
+struct MemFile {
+ sqlite3_file base; /* IO methods */
+ MemStore *pStore; /* The storage */
int eLock; /* Most recent lock against this file */
};
/*
+** File-scope variables for holding the memdb files that are accessible
+** to multiple database connections in separate threads.
+**
+** Must hold SQLITE_MUTEX_STATIC_VFS1 to access any part of this object.
+*/
+static struct MemFS {
+ int nMemStore; /* Number of shared MemStore objects */
+ MemStore **apMemStore; /* Array of all shared MemStore objects */
+} memdb_g;
+
+/*
** Methods for MemFile
*/
static int memdbClose(sqlite3_file*);
@@ -95,7 +152,10 @@ static sqlite3_vfs memdb_vfs = {
memdbSleep, /* xSleep */
0, /* memdbCurrentTime, */ /* xCurrentTime */
memdbGetLastError, /* xGetLastError */
- memdbCurrentTimeInt64 /* xCurrentTimeInt64 */
+ memdbCurrentTimeInt64, /* xCurrentTimeInt64 */
+ 0, /* xSetSystemCall */
+ 0, /* xGetSystemCall */
+ 0, /* xNextSystemCall */
};
static const sqlite3_io_methods memdb_io_methods = {
@@ -120,19 +180,67 @@ static const sqlite3_io_methods memdb_io_methods = {
memdbUnfetch /* xUnfetch */
};
+/*
+** Enter/leave the mutex on a MemStore
+*/
+#if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE==0
+static void memdbEnter(MemStore *p){
+ UNUSED_PARAMETER(p);
+}
+static void memdbLeave(MemStore *p){
+ UNUSED_PARAMETER(p);
+}
+#else
+static void memdbEnter(MemStore *p){
+ sqlite3_mutex_enter(p->pMutex);
+}
+static void memdbLeave(MemStore *p){
+ sqlite3_mutex_leave(p->pMutex);
+}
+#endif
+
/*
** Close an memdb-file.
-**
-** The pData pointer is owned by the application, so there is nothing
-** to free. Unless the SQLITE_DESERIALIZE_FREEONCLOSE flag is set,
-** in which case we own the pData pointer and need to free it.
+** Free the underlying MemStore object when its refcount drops to zero
+** or less.
*/
static int memdbClose(sqlite3_file *pFile){
- MemFile *p = (MemFile *)pFile;
- if( p->mFlags & SQLITE_DESERIALIZE_FREEONCLOSE ){
- sqlite3_free(p->aData);
+ MemStore *p = ((MemFile*)pFile)->pStore;
+ if( p->zFName ){
+ int i;
+#ifndef SQLITE_MUTEX_OMIT
+ sqlite3_mutex *pVfsMutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1);
+#endif
+ sqlite3_mutex_enter(pVfsMutex);
+ for(i=0; ALWAYS(i<memdb_g.nMemStore); i++){
+ if( memdb_g.apMemStore[i]==p ){
+ memdbEnter(p);
+ if( p->nRef==1 ){
+ memdb_g.apMemStore[i] = memdb_g.apMemStore[--memdb_g.nMemStore];
+ if( memdb_g.nMemStore==0 ){
+ sqlite3_free(memdb_g.apMemStore);
+ memdb_g.apMemStore = 0;
+ }
+ }
+ break;
+ }
+ }
+ sqlite3_mutex_leave(pVfsMutex);
+ }else{
+ memdbEnter(p);
+ }
+ p->nRef--;
+ if( p->nRef<=0 ){
+ if( p->mFlags & SQLITE_DESERIALIZE_FREEONCLOSE ){
+ sqlite3_free(p->aData);
+ }
+ memdbLeave(p);
+ sqlite3_mutex_free(p->pMutex);
+ sqlite3_free(p);
+ }else{
+ memdbLeave(p);
}
return SQLITE_OK;
}
@@ -146,20 +254,23 @@ static int memdbRead(
int iAmt,
sqlite_int64 iOfst
){
- MemFile *p = (MemFile *)pFile;
+ MemStore *p = ((MemFile*)pFile)->pStore;
+ memdbEnter(p);
if( iOfst+iAmt>p->sz ){
memset(zBuf, 0, iAmt);
if( iOfst<p->sz ) memcpy(zBuf, p->aData+iOfst, p->sz - iOfst);
+ memdbLeave(p);
return SQLITE_IOERR_SHORT_READ;
}
memcpy(zBuf, p->aData+iOfst, iAmt);
+ memdbLeave(p);
return SQLITE_OK;
}
/*
** Try to enlarge the memory allocation to hold at least sz bytes
*/
-static int memdbEnlarge(MemFile *p, sqlite3_int64 newSz){
+static int memdbEnlarge(MemStore *p, sqlite3_int64 newSz){
unsigned char *pNew;
if( (p->mFlags & SQLITE_DESERIALIZE_RESIZEABLE)==0 || p->nMmap>0 ){
return SQLITE_FULL;
@@ -185,19 +296,27 @@ static int memdbWrite(
int iAmt,
sqlite_int64 iOfst
){
- MemFile *p = (MemFile *)pFile;
- if( NEVER(p->mFlags & SQLITE_DESERIALIZE_READONLY) ) return SQLITE_READONLY;
+ MemStore *p = ((MemFile*)pFile)->pStore;
+ memdbEnter(p);
+ if( NEVER(p->mFlags & SQLITE_DESERIALIZE_READONLY) ){
+ /* Can't happen: memdbLock() will return SQLITE_READONLY before
+ ** reaching this point */
+ memdbLeave(p);
+ return SQLITE_IOERR_WRITE;
+ }
if( iOfst+iAmt>p->sz ){
int rc;
if( iOfst+iAmt>p->szAlloc
&& (rc = memdbEnlarge(p, iOfst+iAmt))!=SQLITE_OK
){
+ memdbLeave(p);
return rc;
}
if( iOfst>p->sz ) memset(p->aData+p->sz, 0, iOfst-p->sz);
p->sz = iOfst+iAmt;
}
memcpy(p->aData+iOfst, z, iAmt);
+ memdbLeave(p);
return SQLITE_OK;
}
@@ -209,16 +328,24 @@ static int memdbWrite(
** the size of a file, never to increase the size.
*/
static int memdbTruncate(sqlite3_file *pFile, sqlite_int64 size){
- MemFile *p = (MemFile *)pFile;
- if( NEVER(size>p->sz) ) return SQLITE_FULL;
- p->sz = size;
- return SQLITE_OK;
+ MemStore *p = ((MemFile*)pFile)->pStore;
+ int rc = SQLITE_OK;
+ memdbEnter(p);
+ if( NEVER(size>p->sz) ){
+ rc = SQLITE_FULL;
+ }else{
+ p->sz = size;
+ }
+ memdbLeave(p);
+ return rc;
}
/*
** Sync an memdb-file.
*/
static int memdbSync(sqlite3_file *pFile, int flags){
+ UNUSED_PARAMETER(pFile);
+ UNUSED_PARAMETER(flags);
return SQLITE_OK;
}
@@ -226,8 +353,10 @@ static int memdbSync(sqlite3_file *pFile, int flags){
** Return the current file-size of an memdb-file.
*/
static int memdbFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
- MemFile *p = (MemFile *)pFile;
+ MemStore *p = ((MemFile*)pFile)->pStore;
+ memdbEnter(p);
*pSize = p->sz;
+ memdbLeave(p);
return SQLITE_OK;
}
@@ -235,19 +364,48 @@ static int memdbFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
** Lock an memdb-file.
*/
static int memdbLock(sqlite3_file *pFile, int eLock){
- MemFile *p = (MemFile *)pFile;
- if( eLock>SQLITE_LOCK_SHARED
- && (p->mFlags & SQLITE_DESERIALIZE_READONLY)!=0
- ){
- return SQLITE_READONLY;
+ MemFile *pThis = (MemFile*)pFile;
+ MemStore *p = pThis->pStore;
+ int rc = SQLITE_OK;
+ if( eLock==pThis->eLock ) return SQLITE_OK;
+ memdbEnter(p);
+ if( eLock>SQLITE_LOCK_SHARED ){
+ if( p->mFlags & SQLITE_DESERIALIZE_READONLY ){
+ rc = SQLITE_READONLY;
+ }else if( pThis->eLock<=SQLITE_LOCK_SHARED ){
+ if( p->nWrLock ){
+ rc = SQLITE_BUSY;
+ }else{
+ p->nWrLock = 1;
+ }
+ }
+ }else if( eLock==SQLITE_LOCK_SHARED ){
+ if( pThis->eLock > SQLITE_LOCK_SHARED ){
+ assert( p->nWrLock==1 );
+ p->nWrLock = 0;
+ }else if( p->nWrLock ){
+ rc = SQLITE_BUSY;
+ }else{
+ p->nRdLock++;
+ }
+ }else{
+ assert( eLock==SQLITE_LOCK_NONE );
+ if( pThis->eLock>SQLITE_LOCK_SHARED ){
+ assert( p->nWrLock==1 );
+ p->nWrLock = 0;
+ }
+ assert( p->nRdLock>0 );
+ p->nRdLock--;
}
- p->eLock = eLock;
- return SQLITE_OK;
+ if( rc==SQLITE_OK ) pThis->eLock = eLock;
+ memdbLeave(p);
+ return rc;
}
-#if 0 /* Never used because memdbAccess() always returns false */
+#if 0
/*
-** Check if another file-handle holds a RESERVED lock on an memdb-file.
+** This interface is only used for crash recovery, which does not
+** occur on an in-memory database.
*/
static int memdbCheckReservedLock(sqlite3_file *pFile, int *pResOut){
*pResOut = 0;
@@ -255,12 +413,14 @@ static int memdbCheckReservedLock(sqlite3_file *pFile, int *pResOut){
}
#endif
+
/*
** File control method. For custom operations on an memdb-file.
*/
static int memdbFileControl(sqlite3_file *pFile, int op, void *pArg){
- MemFile *p = (MemFile *)pFile;
+ MemStore *p = ((MemFile*)pFile)->pStore;
int rc = SQLITE_NOTFOUND;
+ memdbEnter(p);
if( op==SQLITE_FCNTL_VFSNAME ){
*(char**)pArg = sqlite3_mprintf("memdb(%p,%lld)", p->aData, p->sz);
rc = SQLITE_OK;
@@ -278,6 +438,7 @@ static int memdbFileControl(sqlite3_file *pFile, int op, void *pArg){
*(sqlite3_int64*)pArg = iLimit;
rc = SQLITE_OK;
}
+ memdbLeave(p);
return rc;
}
@@ -294,6 +455,7 @@ static int memdbSectorSize(sqlite3_file *pFile){
** Return the device characteristic flags supported by an memdb-file.
*/
static int memdbDeviceCharacteristics(sqlite3_file *pFile){
+ UNUSED_PARAMETER(pFile);
return SQLITE_IOCAP_ATOMIC |
SQLITE_IOCAP_POWERSAFE_OVERWRITE |
SQLITE_IOCAP_SAFE_APPEND |
@@ -307,20 +469,26 @@ static int memdbFetch(
int iAmt,
void **pp
){
- MemFile *p = (MemFile *)pFile;
+ MemStore *p = ((MemFile*)pFile)->pStore;
+ memdbEnter(p);
if( iOfst+iAmt>p->sz ){
*pp = 0;
}else{
p->nMmap++;
*pp = (void*)(p->aData + iOfst);
}
+ memdbLeave(p);
return SQLITE_OK;
}
/* Release a memory-mapped page */
static int memdbUnfetch(sqlite3_file *pFile, sqlite3_int64 iOfst, void *pPage){
- MemFile *p = (MemFile *)pFile;
+ MemStore *p = ((MemFile*)pFile)->pStore;
+ UNUSED_PARAMETER(iOfst);
+ UNUSED_PARAMETER(pPage);
+ memdbEnter(p);
p->nMmap--;
+ memdbLeave(p);
return SQLITE_OK;
}
@@ -330,20 +498,79 @@ static int memdbUnfetch(sqlite3_file *pFile, sqlite3_int64 iOfst, void *pPage){
static int memdbOpen(
sqlite3_vfs *pVfs,
const char *zName,
- sqlite3_file *pFile,
+ sqlite3_file *pFd,
int flags,
int *pOutFlags
){
- MemFile *p = (MemFile*)pFile;
+ MemFile *pFile = (MemFile*)pFd;
+ MemStore *p = 0;
+ int szName;
if( (flags & SQLITE_OPEN_MAIN_DB)==0 ){
- return ORIGVFS(pVfs)->xOpen(ORIGVFS(pVfs), zName, pFile, flags, pOutFlags);
+ return ORIGVFS(pVfs)->xOpen(ORIGVFS(pVfs), zName, pFd, flags, pOutFlags);
}
- memset(p, 0, sizeof(*p));
- p->mFlags = SQLITE_DESERIALIZE_RESIZEABLE | SQLITE_DESERIALIZE_FREEONCLOSE;
+ memset(pFile, 0, sizeof(*p));
+ szName = sqlite3Strlen30(zName);
+ if( szName>1 && zName[0]=='/' ){
+ int i;
+#ifndef SQLITE_MUTEX_OMIT
+ sqlite3_mutex *pVfsMutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1);
+#endif
+ sqlite3_mutex_enter(pVfsMutex);
+ for(i=0; i<memdb_g.nMemStore; i++){
+ if( strcmp(memdb_g.apMemStore[i]->zFName,zName)==0 ){
+ p = memdb_g.apMemStore[i];
+ break;
+ }
+ }
+ if( p==0 ){
+ MemStore **apNew;
+ p = sqlite3Malloc( sizeof(*p) + szName + 3 );
+ if( p==0 ){
+ sqlite3_mutex_leave(pVfsMutex);
+ return SQLITE_NOMEM;
+ }
+ apNew = sqlite3Realloc(memdb_g.apMemStore,
+ sizeof(apNew[0])*(memdb_g.nMemStore+1) );
+ if( apNew==0 ){
+ sqlite3_free(p);
+ sqlite3_mutex_leave(pVfsMutex);
+ return SQLITE_NOMEM;
+ }
+ apNew[memdb_g.nMemStore++] = p;
+ memdb_g.apMemStore = apNew;
+ memset(p, 0, sizeof(*p));
+ p->mFlags = SQLITE_DESERIALIZE_RESIZEABLE|SQLITE_DESERIALIZE_FREEONCLOSE;
+ p->szMax = sqlite3GlobalConfig.mxMemdbSize;
+ p->zFName = (char*)&p[1];
+ memcpy(p->zFName, zName, szName+1);
+ p->pMutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
+ if( p->pMutex==0 ){
+ memdb_g.nMemStore--;
+ sqlite3_free(p);
+ sqlite3_mutex_leave(pVfsMutex);
+ return SQLITE_NOMEM;
+ }
+ p->nRef = 1;
+ memdbEnter(p);
+ }else{
+ memdbEnter(p);
+ p->nRef++;
+ }
+ sqlite3_mutex_leave(pVfsMutex);
+ }else{
+ p = sqlite3Malloc( sizeof(*p) );
+ if( p==0 ){
+ return SQLITE_NOMEM;
+ }
+ memset(p, 0, sizeof(*p));
+ p->mFlags = SQLITE_DESERIALIZE_RESIZEABLE | SQLITE_DESERIALIZE_FREEONCLOSE;
+ p->szMax = sqlite3GlobalConfig.mxMemdbSize;
+ }
+ pFile->pStore = p;
assert( pOutFlags!=0 ); /* True because flags==SQLITE_OPEN_MAIN_DB */
*pOutFlags = flags | SQLITE_OPEN_MEMORY;
- pFile->pMethods = &memdb_io_methods;
- p->szMax = sqlite3GlobalConfig.mxMemdbSize;
+ pFd->pMethods = &memdb_io_methods;
+ memdbLeave(p);
return SQLITE_OK;
}
@@ -371,6 +598,9 @@ static int memdbAccess(
int flags,
int *pResOut
){
+ UNUSED_PARAMETER(pVfs);
+ UNUSED_PARAMETER(zPath);
+ UNUSED_PARAMETER(flags);
*pResOut = 0;
return SQLITE_OK;
}
@@ -386,6 +616,7 @@ static int memdbFullPathname(
int nOut,
char *zOut
){
+ UNUSED_PARAMETER(pVfs);
sqlite3_snprintf(nOut, zOut, "%s", zPath);
return SQLITE_OK;
}
@@ -458,9 +689,14 @@ static int memdbCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *p){
*/
static MemFile *memdbFromDbSchema(sqlite3 *db, const char *zSchema){
MemFile *p = 0;
+ MemStore *pStore;
int rc = sqlite3_file_control(db, zSchema, SQLITE_FCNTL_FILE_POINTER, &p);
if( rc ) return 0;
if( p->base.pMethods!=&memdb_io_methods ) return 0;
+ pStore = p->pStore;
+ memdbEnter(pStore);
+ if( pStore->zFName!=0 ) p = 0;
+ memdbLeave(pStore);
return p;
}
@@ -496,12 +732,14 @@ unsigned char *sqlite3_serialize(
if( piSize ) *piSize = -1;
if( iDb<0 ) return 0;
if( p ){
- if( piSize ) *piSize = p->sz;
+ MemStore *pStore = p->pStore;
+ assert( pStore->pMutex==0 );
+ if( piSize ) *piSize = pStore->sz;
if( mFlags & SQLITE_SERIALIZE_NOCOPY ){
- pOut = p->aData;
+ pOut = pStore->aData;
}else{
- pOut = sqlite3_malloc64( p->sz );
- if( pOut ) memcpy(pOut, p->aData, p->sz);
+ pOut = sqlite3_malloc64( pStore->sz );
+ if( pOut ) memcpy(pOut, pStore->aData, pStore->sz);
}
return pOut;
}
@@ -595,15 +833,16 @@ int sqlite3_deserialize(
if( p==0 ){
rc = SQLITE_ERROR;
}else{
- p->aData = pData;
+ MemStore *pStore = p->pStore;
+ pStore->aData = pData;
pData = 0;
- p->sz = szDb;
- p->szAlloc = szBuf;
- p->szMax = szBuf;
- if( p->szMax<sqlite3GlobalConfig.mxMemdbSize ){
- p->szMax = sqlite3GlobalConfig.mxMemdbSize;
+ pStore->sz = szDb;
+ pStore->szAlloc = szBuf;
+ pStore->szMax = szBuf;
+ if( pStore->szMax<sqlite3GlobalConfig.mxMemdbSize ){
+ pStore->szMax = sqlite3GlobalConfig.mxMemdbSize;
}
- p->mFlags = mFlags;
+ pStore->mFlags = mFlags;
rc = SQLITE_OK;
}
@@ -622,7 +861,7 @@ end_deserialize:
*/
int sqlite3MemdbInit(void){
sqlite3_vfs *pLower = sqlite3_vfs_find(0);
- int sz = pLower->szOsFile;
+ unsigned int sz = pLower->szOsFile;
memdb_vfs.pAppData = pLower;
/* The following conditional can only be true when compiled for
** Windows x86 and SQLITE_MAX_MMAP_SIZE=0. We always leave
@@ -632,4 +871,4 @@ int sqlite3MemdbInit(void){
memdb_vfs.szOsFile = sz;
return sqlite3_vfs_register(&memdb_vfs, 0);
}
-#endif /* SQLITE_ENABLE_DESERIALIZE */
+#endif /* SQLITE_OMIT_DESERIALIZE */
diff --git a/src/os_unix.c b/src/os_unix.c
index adc89f5a7..750b3e170 100644
--- a/src/os_unix.c
+++ b/src/os_unix.c
@@ -8067,6 +8067,22 @@ int sqlite3_os_init(void){
sqlite3_vfs_register(&aVfs[i], i==0);
}
unixBigLock = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1);
+
+ /* Validate lock assumptions */
+ assert( SQLITE_SHM_NLOCK==8 ); /* Number of available locks */
+ assert( UNIX_SHM_BASE==120 ); /* Start of locking area */
+ /* Locks:
+ ** WRITE UNIX_SHM_BASE 120
+ ** CKPT UNIX_SHM_BASE+1 121
+ ** RECOVER UNIX_SHM_BASE+2 122
+ ** READ-0 UNIX_SHM_BASE+3 123
+ ** READ-1 UNIX_SHM_BASE+4 124
+ ** READ-2 UNIX_SHM_BASE+5 125
+ ** READ-3 UNIX_SHM_BASE+6 126
+ ** READ-4 UNIX_SHM_BASE+7 127
+ ** DMS UNIX_SHM_BASE+8 128
+ */
+ assert( UNIX_SHM_DMS==128 ); /* Byte offset of the deadman-switch */
return SQLITE_OK;
}
diff --git a/src/pager.c b/src/pager.c
index 3550a13e2..12a78cde8 100644
--- a/src/pager.c
+++ b/src/pager.c
@@ -4665,7 +4665,7 @@ int sqlite3PagerOpen(
int rc = SQLITE_OK; /* Return code */
int tempFile = 0; /* True for temp files (incl. in-memory files) */
int memDb = 0; /* True if this is an in-memory file */
-#ifdef SQLITE_ENABLE_DESERIALIZE
+#ifndef SQLITE_OMIT_DESERIALIZE
int memJM = 0; /* Memory journal mode */
#else
# define memJM 0
@@ -4869,7 +4869,7 @@ int sqlite3PagerOpen(
int fout = 0; /* VFS flags returned by xOpen() */
rc = sqlite3OsOpen(pVfs, pPager->zFilename, pPager->fd, vfsFlags, &fout);
assert( !memDb );
-#ifdef SQLITE_ENABLE_DESERIALIZE
+#ifndef SQLITE_OMIT_DESERIALIZE
memJM = (fout&SQLITE_OPEN_MEMORY)!=0;
#endif
readOnly = (fout&SQLITE_OPEN_READONLY)!=0;
diff --git a/src/parse.y b/src/parse.y
index 5b3228bff..d29d861e7 100644
--- a/src/parse.y
+++ b/src/parse.y
@@ -193,7 +193,7 @@ ifnotexists(A) ::= . {A = 0;}
ifnotexists(A) ::= IF NOT EXISTS. {A = 1;}
%type temp {int}
%ifndef SQLITE_OMIT_TEMPDB
-temp(A) ::= TEMP. {A = 1;}
+temp(A) ::= TEMP. {A = pParse->db->init.busy==0;}
%endif SQLITE_OMIT_TEMPDB
temp(A) ::= . {A = 0;}
create_table_args ::= LP columnlist conslist_opt(X) RP(E) table_options(F). {
diff --git a/src/resolve.c b/src/resolve.c
index 4f5c5b961..d5cec3550 100644
--- a/src/resolve.c
+++ b/src/resolve.c
@@ -1715,6 +1715,19 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
}
}
+#ifndef SQLITE_OMIT_WINDOWFUNC
+ if( IN_RENAME_OBJECT ){
+ Window *pWin;
+ for(pWin=p->pWinDefn; pWin; pWin=pWin->pNextWin){
+ if( sqlite3ResolveExprListNames(&sNC, pWin->pOrderBy)
+ || sqlite3ResolveExprListNames(&sNC, pWin->pPartition)
+ ){
+ return WRC_Abort;
+ }
+ }
+ }
+#endif
+
/* The ORDER BY and GROUP BY clauses may not refer to terms in
** outer queries
*/
@@ -1771,19 +1784,6 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
}
}
-#ifndef SQLITE_OMIT_WINDOWFUNC
- if( IN_RENAME_OBJECT ){
- Window *pWin;
- for(pWin=p->pWinDefn; pWin; pWin=pWin->pNextWin){
- if( sqlite3ResolveExprListNames(&sNC, pWin->pOrderBy)
- || sqlite3ResolveExprListNames(&sNC, pWin->pPartition)
- ){
- return WRC_Abort;
- }
- }
- }
-#endif
-
/* If this is part of a compound SELECT, check that it has the right
** number of expressions in the select list. */
if( p->pNext && p->pEList->nExpr!=p->pNext->pEList->nExpr ){
diff --git a/src/select.c b/src/select.c
index 570c92b03..aeb63d99d 100644
--- a/src/select.c
+++ b/src/select.c
@@ -1955,7 +1955,7 @@ static void generateColumnTypes(
** then the result column name with the table name
** prefix, ex: TABLE.COLUMN. Otherwise use zSpan.
*/
-static void generateColumnNames(
+void sqlite3GenerateColumnNames(
Parse *pParse, /* Parser context */
Select *pSelect /* Generate column names for this SELECT statement */
){
@@ -2045,7 +2045,7 @@ static void generateColumnNames(
** and will break if those assumptions changes. Hence, use extreme caution
** when modifying this routine to avoid breaking legacy.
**
-** See Also: generateColumnNames()
+** See Also: sqlite3GenerateColumnNames()
*/
int sqlite3ColumnsFromExprList(
Parse *pParse, /* Parsing context */
@@ -2748,6 +2748,7 @@ static int multiSelect(
pPrior->iLimit = p->iLimit;
pPrior->iOffset = p->iOffset;
pPrior->pLimit = p->pLimit;
+ SELECTTRACE(1, pParse, p, ("multiSelect UNION ALL left...\n"));
rc = sqlite3Select(pParse, pPrior, &dest);
pPrior->pLimit = 0;
if( rc ){
@@ -2765,6 +2766,7 @@ static int multiSelect(
}
}
ExplainQueryPlan((pParse, 1, "UNION ALL"));
+ SELECTTRACE(1, pParse, p, ("multiSelect UNION ALL right...\n"));
rc = sqlite3Select(pParse, p, &dest);
testcase( rc!=SQLITE_OK );
pDelete = p->pPrior;
@@ -2817,6 +2819,7 @@ static int multiSelect(
*/
assert( !pPrior->pOrderBy );
sqlite3SelectDestInit(&uniondest, priorOp, unionTab);
+ SELECTTRACE(1, pParse, p, ("multiSelect EXCEPT/UNION left...\n"));
rc = sqlite3Select(pParse, pPrior, &uniondest);
if( rc ){
goto multi_select_end;
@@ -2836,6 +2839,7 @@ static int multiSelect(
uniondest.eDest = op;
ExplainQueryPlan((pParse, 1, "%s USING TEMP B-TREE",
sqlite3SelectOpName(p->op)));
+ SELECTTRACE(1, pParse, p, ("multiSelect EXCEPT/UNION right...\n"));
rc = sqlite3Select(pParse, p, &uniondest);
testcase( rc!=SQLITE_OK );
assert( p->pOrderBy==0 );
@@ -2896,6 +2900,7 @@ static int multiSelect(
/* Code the SELECTs to our left into temporary table "tab1".
*/
sqlite3SelectDestInit(&intersectdest, SRT_Union, tab1);
+ SELECTTRACE(1, pParse, p, ("multiSelect INTERSECT left...\n"));
rc = sqlite3Select(pParse, pPrior, &intersectdest);
if( rc ){
goto multi_select_end;
@@ -2912,6 +2917,7 @@ static int multiSelect(
intersectdest.iSDParm = tab2;
ExplainQueryPlan((pParse, 1, "%s USING TEMP B-TREE",
sqlite3SelectOpName(p->op)));
+ SELECTTRACE(1, pParse, p, ("multiSelect INTERSECT right...\n"));
rc = sqlite3Select(pParse, p, &intersectdest);
testcase( rc!=SQLITE_OK );
pDelete = p->pPrior;
@@ -4469,7 +4475,7 @@ static void constInsert(
*/
static void findConstInWhere(WhereConst *pConst, Expr *pExpr){
Expr *pRight, *pLeft;
- if( pExpr==0 ) return;
+ if( NEVER(pExpr==0) ) return;
if( ExprHasProperty(pExpr, EP_FromJoin) ) return;
if( pExpr->op==TK_AND ){
findConstInWhere(pConst, pExpr->pRight);
@@ -5213,7 +5219,7 @@ static int resolveFromTermToCte(
** sqlite3SelectExpand() when walking a SELECT tree to resolve table
** names and other FROM clause elements.
*/
-static void selectPopWith(Walker *pWalker, Select *p){
+void sqlite3SelectPopWith(Walker *pWalker, Select *p){
Parse *pParse = pWalker->pParse;
if( OK_IF_ALWAYS_TRUE(pParse->pWith) && p->pPrior==0 ){
With *pWith = findRightmost(p)->pWith;
@@ -5223,8 +5229,6 @@ static void selectPopWith(Walker *pWalker, Select *p){
}
}
}
-#else
-#define selectPopWith 0
#endif
/*
@@ -5611,7 +5615,7 @@ static void sqlite3SelectExpand(Parse *pParse, Select *pSelect){
sqlite3WalkSelect(&w, pSelect);
}
w.xSelectCallback = selectExpander;
- w.xSelectCallback2 = selectPopWith;
+ w.xSelectCallback2 = sqlite3SelectPopWith;
w.eCode = 0;
sqlite3WalkSelect(&w, pSelect);
}
@@ -6198,7 +6202,7 @@ int sqlite3Select(
}
if( pDest->eDest==SRT_Output ){
- generateColumnNames(pParse, p);
+ sqlite3GenerateColumnNames(pParse, p);
}
#ifndef SQLITE_OMIT_WINDOWFUNC
@@ -6328,7 +6332,8 @@ int sqlite3Select(
** as the equivalent optimization will be handled by query planner in
** sqlite3WhereBegin().
*/
- if( pTabList->nSrc>1
+ if( p->pWhere!=0
+ && p->pWhere->op==TK_AND
&& OptimizationEnabled(db, SQLITE_PropagateConst)
&& propagateConstants(pParse, p)
){
diff --git a/src/shell.c.in b/src/shell.c.in
index b3cc0599b..462cd717b 100644
--- a/src/shell.c.in
+++ b/src/shell.c.in
@@ -3978,8 +3978,8 @@ static const char *(azHelp[]) = {
".open ?OPTIONS? ?FILE? Close existing database and reopen FILE",
" Options:",
" --append Use appendvfs to append database to the end of FILE",
-#ifdef SQLITE_ENABLE_DESERIALIZE
- " --deserialize Load into memory useing sqlite3_deserialize()",
+#ifndef SQLITE_OMIT_DESERIALIZE
+ " --deserialize Load into memory using sqlite3_deserialize()",
" --hexdb Load the output of \"dbtotxt\" as an in-memory db",
" --maxsize N Maximum size for --hexdb or --deserialized database",
#endif
@@ -4300,7 +4300,7 @@ int deduceDatabaseType(const char *zName, int dfltZip){
return rc;
}
-#ifdef SQLITE_ENABLE_DESERIALIZE
+#ifndef SQLITE_OMIT_DESERIALIZE
/*
** Reconstruct an in-memory database using the output from the "dbtotxt"
** program. Read content from the file in p->zDbFilename. If p->zDbFilename
@@ -4389,7 +4389,7 @@ readHexDb_error:
utf8_printf(stderr,"Error on line %d of --hexdb input\n", nLine);
return 0;
}
-#endif /* SQLITE_ENABLE_DESERIALIZE */
+#endif /* SQLITE_OMIT_DESERIALIZE */
/*
** Scalar function "shell_int32". The first argument to this function
@@ -4650,7 +4650,7 @@ static void open_db(ShellState *p, int openFlags){
sqlite3_exec(p->db, zSql, 0, 0, 0);
sqlite3_free(zSql);
}
-#ifdef SQLITE_ENABLE_DESERIALIZE
+#ifndef SQLITE_OMIT_DESERIALIZE
else
if( p->openMode==SHELL_OPEN_DESERIALIZE || p->openMode==SHELL_OPEN_HEXDB ){
int rc;
@@ -6717,6 +6717,7 @@ static void shellExec(sqlite3 *db, int *pRc, const char *zSql){
if( rc!=SQLITE_OK ){
raw_printf(stderr, "SQL error: %s\n", zErr);
}
+ sqlite3_free(zErr);
*pRc = rc;
}
}
@@ -8021,7 +8022,6 @@ static int do_meta_command(char *zLine, ShellState *p){
if( c=='f' && strncmp(azArg[0], "fullschema", n)==0 ){
ShellState data;
- char *zErrMsg = 0;
int doStats = 0;
memcpy(&data, p, sizeof(data));
data.showHeader = 0;
@@ -8043,7 +8043,7 @@ static int do_meta_command(char *zLine, ShellState *p){
" SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_schema) "
"WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%' "
"ORDER BY rowid",
- callback, &data, &zErrMsg
+ callback, &data, 0
);
if( rc==SQLITE_OK ){
sqlite3_stmt *pStmt;
@@ -8059,12 +8059,12 @@ static int do_meta_command(char *zLine, ShellState *p){
}else{
raw_printf(p->out, "ANALYZE sqlite_schema;\n");
sqlite3_exec(p->db, "SELECT 'ANALYZE sqlite_schema'",
- callback, &data, &zErrMsg);
+ callback, &data, 0);
data.cMode = data.mode = MODE_Insert;
data.zDestTable = "sqlite_stat1";
- shell_exec(&data, "SELECT * FROM sqlite_stat1", &zErrMsg);
+ shell_exec(&data, "SELECT * FROM sqlite_stat1", 0);
data.zDestTable = "sqlite_stat4";
- shell_exec(&data, "SELECT * FROM sqlite_stat4", &zErrMsg);
+ shell_exec(&data, "SELECT * FROM sqlite_stat4", 0);
raw_printf(p->out, "ANALYZE sqlite_schema;\n");
}
}else
@@ -8712,14 +8712,14 @@ static int do_meta_command(char *zLine, ShellState *p){
p->openMode = SHELL_OPEN_READONLY;
}else if( optionMatch(z, "nofollow") ){
p->openFlags |= SQLITE_OPEN_NOFOLLOW;
-#ifdef SQLITE_ENABLE_DESERIALIZE
+#ifndef SQLITE_OMIT_DESERIALIZE
}else if( optionMatch(z, "deserialize") ){
p->openMode = SHELL_OPEN_DESERIALIZE;
}else if( optionMatch(z, "hexdb") ){
p->openMode = SHELL_OPEN_HEXDB;
}else if( optionMatch(z, "maxsize") && iName+1<nArg ){
p->szMax = integerValue(azArg[++iName]);
-#endif /* SQLITE_ENABLE_DESERIALIZE */
+#endif /* SQLITE_OMIT_DESERIALIZE */
}else if( z[0]=='-' ){
utf8_printf(stderr, "unknown option: %s\n", z);
rc = 1;
@@ -10703,7 +10703,7 @@ static const char zOptions[] =
" -column set output mode to 'column'\n"
" -cmd COMMAND run \"COMMAND\" before reading stdin\n"
" -csv set output mode to 'csv'\n"
-#if defined(SQLITE_ENABLE_DESERIALIZE)
+#if !defined(SQLITE_OMIT_DESERIALIZE)
" -deserialize open the database using sqlite3_deserialize()\n"
#endif
" -echo print commands before execution\n"
@@ -10720,7 +10720,7 @@ static const char zOptions[] =
" -list set output mode to 'list'\n"
" -lookaside SIZE N use N entries of SZ bytes for lookaside memory\n"
" -markdown set output mode to 'markdown'\n"
-#if defined(SQLITE_ENABLE_DESERIALIZE)
+#if !defined(SQLITE_OMIT_DESERIALIZE)
" -maxsize N maximum size for a --deserialize database\n"
#endif
" -memtrace trace all memory allocations and deallocations\n"
@@ -11050,7 +11050,7 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
#endif
}else if( strcmp(z,"-append")==0 ){
data.openMode = SHELL_OPEN_APPENDVFS;
-#ifdef SQLITE_ENABLE_DESERIALIZE
+#ifndef SQLITE_OMIT_DESERIALIZE
}else if( strcmp(z,"-deserialize")==0 ){
data.openMode = SHELL_OPEN_DESERIALIZE;
}else if( strcmp(z,"-maxsize")==0 && i+1<argc ){
@@ -11167,7 +11167,7 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
#endif
}else if( strcmp(z,"-append")==0 ){
data.openMode = SHELL_OPEN_APPENDVFS;
-#ifdef SQLITE_ENABLE_DESERIALIZE
+#ifndef SQLITE_OMIT_DESERIALIZE
}else if( strcmp(z,"-deserialize")==0 ){
data.openMode = SHELL_OPEN_DESERIALIZE;
}else if( strcmp(z,"-maxsize")==0 && i+1<argc ){
diff --git a/src/sqlite.h.in b/src/sqlite.h.in
index 56f23f2b0..ef452e324 100644
--- a/src/sqlite.h.in
+++ b/src/sqlite.h.in
@@ -1141,6 +1141,10 @@ struct sqlite3_io_methods {
** other process. This opcode cannot be used to detect transactions opened
** by clients within the current process, only within other processes.
** </ul>
+**
+** <li>[[SQLITE_FCNTL_CKSM_FILE]]
+** Used by the cksmvfs VFS module only.
+** </ul>
*/
#define SQLITE_FCNTL_LOCKSTATE 1
#define SQLITE_FCNTL_GET_LOCKPROXYFILE 2
@@ -1180,8 +1184,8 @@ struct sqlite3_io_methods {
#define SQLITE_FCNTL_CKPT_DONE 37
#define SQLITE_FCNTL_RESERVE_BYTES 38
#define SQLITE_FCNTL_CKPT_START 39
-
#define SQLITE_FCNTL_EXTERNAL_READER 40
+#define SQLITE_FCNTL_CKSM_FILE 41
/* deprecated names */
#define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE
@@ -4194,6 +4198,15 @@ const char *sqlite3_normalized_sql(sqlite3_stmt *pStmt);
** [BEGIN] merely sets internal flags, but the [BEGIN|BEGIN IMMEDIATE] and
** [BEGIN|BEGIN EXCLUSIVE] commands do touch the database and so
** sqlite3_stmt_readonly() returns false for those commands.
+**
+** ^This routine returns false if there is any possibility that the
+** statement might change the database file. ^A false return does
+** not guarantee that the statement will change the database file.
+** ^For example, an UPDATE statement might have a WHERE clause that
+** makes it a no-op, but the sqlite3_stmt_readonly() result would still
+** be false. ^Similarly, a CREATE TABLE IF NOT EXISTS statement is a
+** read-only no-op if the table already exists, but
+** sqlite3_stmt_readonly() still returns false for such a statement.
*/
int sqlite3_stmt_readonly(sqlite3_stmt *pStmt);
@@ -4363,18 +4376,22 @@ typedef struct sqlite3_context sqlite3_context;
** contain embedded NULs. The result of expressions involving strings
** with embedded NULs is undefined.
**
-** ^The fifth argument to the BLOB and string binding interfaces
-** is a destructor used to dispose of the BLOB or
-** string after SQLite has finished with it. ^The destructor is called
-** to dispose of the BLOB or string even if the call to the bind API fails,
-** except the destructor is not called if the third parameter is a NULL
-** pointer or the fourth parameter is negative.
-** ^If the fifth argument is
-** the special value [SQLITE_STATIC], then SQLite assumes that the
-** information is in static, unmanaged space and does not need to be freed.
-** ^If the fifth argument has the value [SQLITE_TRANSIENT], then
-** SQLite makes its own private copy of the data immediately, before
-** the sqlite3_bind_*() routine returns.
+** ^The fifth argument to the BLOB and string binding interfaces controls
+** or indicates the lifetime of the object referenced by the third parameter.
+** ^These three options exist:
+** ^(1) A destructor to dispose of the BLOB or string after SQLite has finished
+** with it may be passed. ^It is called to dispose of the BLOB or string even
+** if the call to the bind API fails, except the destructor is not called if
+** the third parameter is a NULL pointer or the fourth parameter is negative.
+** ^(2) The special constant, [SQLITE_STATIC], may be passsed to indicate that
+** the application remains responsible for disposing of the object. ^In this
+** case, the object and the provided pointer to it must remain valid until
+** either the prepared statement is finalized or the same SQL parameter is
+** bound to something else, whichever occurs sooner.
+** ^(3) The constant, [SQLITE_TRANSIENT], may be passed to indicate that the
+** object is to be copied prior to the return from sqlite3_bind_*(). ^The
+** object and pointer to it must remain valid until then. ^SQLite will then
+** manage the lifetime of its private copy.
**
** ^The sixth argument to sqlite3_bind_text64() must be one of
** [SQLITE_UTF8], [SQLITE_UTF16], [SQLITE_UTF16BE], or [SQLITE_UTF16LE]
@@ -9814,8 +9831,8 @@ SQLITE_EXPERIMENTAL int sqlite3_snapshot_recover(sqlite3 *db, const char *zDb);
** SQLITE_SERIALIZE_NOCOPY bit is omitted from argument F if a memory
** allocation error occurs.
**
-** This interface is only available if SQLite is compiled with the
-** [SQLITE_ENABLE_DESERIALIZE] option.
+** This interface is omitted if SQLite is compiled with the
+** [SQLITE_OMIT_DESERIALIZE] option.
*/
unsigned char *sqlite3_serialize(
sqlite3 *db, /* The database connection */
@@ -9866,8 +9883,8 @@ unsigned char *sqlite3_serialize(
** SQLITE_DESERIALIZE_FREEONCLOSE bit is set in argument F, then
** [sqlite3_free()] is invoked on argument P prior to returning.
**
-** This interface is only available if SQLite is compiled with the
-** [SQLITE_ENABLE_DESERIALIZE] option.
+** This interface is omitted if SQLite is compiled with the
+** [SQLITE_OMIT_DESERIALIZE] option.
*/
int sqlite3_deserialize(
sqlite3 *db, /* The database connection */
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index b8b6b340d..7eafdd2b4 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -1731,7 +1731,6 @@ struct sqlite3 {
#define SQLITE_SkipScan 0x00004000 /* Skip-scans */
#define SQLITE_PropagateConst 0x00008000 /* The constant propagation opt */
#define SQLITE_MinMaxOpt 0x00010000 /* The min/max optimization */
-#define SQLITE_ExistsToIN 0x00020000 /* The EXISTS-to-IN optimization */
#define SQLITE_AllOpts 0xffffffff /* All optimizations */
/*
@@ -3794,7 +3793,7 @@ struct Sqlite3Config {
void (*xVdbeBranch)(void*,unsigned iSrcLine,u8 eThis,u8 eMx); /* Callback */
void *pVdbeBranchArg; /* 1st argument */
#endif
-#ifdef SQLITE_ENABLE_DESERIALIZE
+#ifndef SQLITE_OMIT_DESERIALIZE
sqlite3_int64 mxMemdbSize; /* Default max memdb size */
#endif
#ifndef SQLITE_UNTESTABLE
@@ -3887,6 +3886,12 @@ void sqlite3WalkWinDefnDummyCallback(Walker*,Select*);
void sqlite3SelectWalkAssert2(Walker*, Select*);
#endif
+#ifndef SQLITE_OMIT_CTE
+void sqlite3SelectPopWith(Walker*, Select*);
+#else
+# define sqlite3SelectPopWith 0
+#endif
+
/*
** Return code from the parse-tree walking primitives and their
** callbacks.
@@ -4312,6 +4317,7 @@ void sqlite3ResetOneSchema(sqlite3*,int);
void sqlite3CollapseDatabaseArray(sqlite3*);
void sqlite3CommitInternalChanges(sqlite3*);
void sqlite3DeleteColumnNames(sqlite3*,Table*);
+void sqlite3GenerateColumnNames(Parse *pParse, Select *pSelect);
int sqlite3ColumnsFromExprList(Parse*,ExprList*,i16*,Column**);
void sqlite3SelectAddColumnTypeAndCollation(Parse*,Table*,Select*,char);
Table *sqlite3ResultSetOfSelect(Parse*,Select*,char);
@@ -4690,7 +4696,7 @@ int sqlite3TwoPartName(Parse *, Token *, Token *, Token **);
const char *sqlite3ErrName(int);
#endif
-#ifdef SQLITE_ENABLE_DESERIALIZE
+#ifndef SQLITE_OMIT_DESERIALIZE
int sqlite3MemdbInit(void);
#endif
diff --git a/src/tclsqlite.c b/src/tclsqlite.c
index d80c25251..2206bca32 100644
--- a/src/tclsqlite.c
+++ b/src/tclsqlite.c
@@ -2600,7 +2600,7 @@ static int SQLITE_TCLAPI DbObjCmd(
** Reopen DATABASE (default "main") using the content in $VALUE
*/
case DB_DESERIALIZE: {
-#ifndef SQLITE_ENABLE_DESERIALIZE
+#ifdef SQLITE_OMIT_DESERIALIZE
Tcl_AppendResult(interp, "MEMDB not available in this build",
(char*)0);
rc = TCL_ERROR;
@@ -3167,7 +3167,7 @@ deserialize_error:
** Return a serialization of a database.
*/
case DB_SERIALIZE: {
-#ifndef SQLITE_ENABLE_DESERIALIZE
+#ifdef SQLITE_OMIT_DESERIALIZE
Tcl_AppendResult(interp, "MEMDB not available in this build",
(char*)0);
rc = TCL_ERROR;
diff --git a/src/test8.c b/src/test8.c
index f984c2e5f..7a532346e 100644
--- a/src/test8.c
+++ b/src/test8.c
@@ -389,6 +389,7 @@ static int echoDestructor(sqlite3_vtab *pVtab){
typedef struct EchoModule EchoModule;
struct EchoModule {
Tcl_Interp *interp;
+ sqlite3 *db;
};
/*
@@ -1352,6 +1353,9 @@ extern int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb);
extern const char *sqlite3ErrName(int);
static void moduleDestroy(void *p){
+ EchoModule *pMod = (EchoModule*)p;
+ sqlite3_create_function(pMod->db, "function_that_does_not_exist_0982ma98",
+ SQLITE_ANY, 1, 0, 0, 0, 0);
sqlite3_free(p);
}
@@ -1376,6 +1380,7 @@ static int SQLITE_TCLAPI register_echo_module(
/* Virtual table module "echo" */
pMod = sqlite3_malloc(sizeof(EchoModule));
pMod->interp = interp;
+ pMod->db = db;
rc = sqlite3_create_module_v2(
db, "echo", &echoModule, (void*)pMod, moduleDestroy
);
@@ -1384,6 +1389,7 @@ static int SQLITE_TCLAPI register_echo_module(
if( rc==SQLITE_OK ){
pMod = sqlite3_malloc(sizeof(EchoModule));
pMod->interp = interp;
+ pMod->db = db;
rc = sqlite3_create_module_v2(db, "echo_v2",
&echoModuleV2, (void*)pMod, moduleDestroy
);
diff --git a/src/test_config.c b/src/test_config.c
index 5bf6ad63e..86e4df38f 100644
--- a/src/test_config.c
+++ b/src/test_config.c
@@ -155,7 +155,7 @@ static void set_options(Tcl_Interp *interp){
Tcl_SetVar2(interp, "sqlite_options", "hiddencolumns", "0", TCL_GLOBAL_ONLY);
#endif
-#ifdef SQLITE_ENABLE_DESERIALIZE
+#ifndef SQLITE_OMIT_DESERIALIZE
Tcl_SetVar2(interp, "sqlite_options", "deserialize", "1", TCL_GLOBAL_ONLY);
#else
Tcl_SetVar2(interp, "sqlite_options", "deserialize", "0", TCL_GLOBAL_ONLY);
diff --git a/src/trigger.c b/src/trigger.c
index 578d1e42e..90e6ef4a7 100644
--- a/src/trigger.c
+++ b/src/trigger.c
@@ -57,33 +57,41 @@ Trigger *sqlite3TriggerList(Parse *pParse, Table *pTab){
}
pTmpSchema = pParse->db->aDb[1].pSchema;
p = sqliteHashFirst(&pTmpSchema->trigHash);
- if( p==0 ){
- return pTab->pTrigger;
- }
pList = pTab->pTrigger;
- if( pTmpSchema!=pTab->pSchema ){
- while( p ){
- Trigger *pTrig = (Trigger *)sqliteHashData(p);
- if( pTrig->pTabSchema==pTab->pSchema
- && 0==sqlite3StrICmp(pTrig->table, pTab->zName)
- ){
- pTrig->pNext = pList;
- pList = pTrig;
- }else if( pTrig->op==TK_RETURNING
+ while( p ){
+ Trigger *pTrig = (Trigger *)sqliteHashData(p);
+ if( pTrig->pTabSchema==pTab->pSchema
+ && pTrig->table
+ && 0==sqlite3StrICmp(pTrig->table, pTab->zName)
+ && pTrig->pTabSchema!=pTmpSchema
+ ){
+ pTrig->pNext = pList;
+ pList = pTrig;
+ }else if( pTrig->op==TK_RETURNING
#ifndef SQLITE_OMIT_VIRTUALTABLE
- && pParse->db->pVtabCtx==0
+ && pParse->db->pVtabCtx==0
#endif
- ){
- assert( pParse->bReturning );
- assert( &(pParse->u1.pReturning->retTrig) == pTrig );
- pTrig->table = pTab->zName;
- pTrig->pTabSchema = pTab->pSchema;
- pTrig->pNext = pList;
- pList = pTrig;
- }
- p = sqliteHashNext(p);
+ ){
+ assert( pParse->bReturning );
+ assert( &(pParse->u1.pReturning->retTrig) == pTrig );
+ pTrig->table = pTab->zName;
+ pTrig->pTabSchema = pTab->pSchema;
+ pTrig->pNext = pList;
+ pList = pTrig;
+ }
+ p = sqliteHashNext(p);
+ }
+#if 0
+ if( pList ){
+ Trigger *pX;
+ printf("Triggers for %s:", pTab->zName);
+ for(pX=pList; pX; pX=pX->pNext){
+ printf(" %s", pX->zName);
}
+ printf("\n");
+ fflush(stdout);
}
+#endif
return pList;
}
@@ -887,15 +895,6 @@ static ExprList *sqlite3ExpandReturning(
}
}
}
- if( !db->mallocFailed ){
- Vdbe *v = pParse->pVdbe;
- assert( v!=0 );
- sqlite3VdbeSetNumCols(v, pNew->nExpr);
- for(i=0; i<pNew->nExpr; i++){
- sqlite3VdbeSetColName(v, i, COLNAME_NAME, pNew->a[i].zEName,
- SQLITE_TRANSIENT);
- }
- }
return pNew;
}
@@ -911,13 +910,27 @@ static void codeReturningTrigger(
int regIn /* The first in an array of registers */
){
Vdbe *v = pParse->pVdbe;
+ sqlite3 *db = pParse->db;
ExprList *pNew;
Returning *pReturning;
+ Select sSelect;
+ SrcList sFrom;
assert( v!=0 );
assert( pParse->bReturning );
pReturning = pParse->u1.pReturning;
assert( pTrigger == &(pReturning->retTrig) );
+ memset(&sSelect, 0, sizeof(sSelect));
+ memset(&sFrom, 0, sizeof(sFrom));
+ sSelect.pEList = sqlite3ExprListDup(db, pReturning->pReturnEL, 0);
+ sSelect.pSrc = &sFrom;
+ sFrom.nSrc = 1;
+ sFrom.a[0].pTab = pTab;
+ sqlite3SelectPrep(pParse, &sSelect, 0);
+ if( db->mallocFailed==0 && pParse->nErr==0 ){
+ sqlite3GenerateColumnNames(pParse, &sSelect);
+ }
+ sqlite3ExprListDelete(db, sSelect.pEList);
pNew = sqlite3ExpandReturning(pParse, pReturning->pReturnEL, pTab);
if( pNew ){
NameContext sNC;
@@ -938,13 +951,14 @@ static void codeReturningTrigger(
pParse->nMem += nCol+2;
pReturning->iRetReg = reg;
for(i=0; i<nCol; i++){
- sqlite3ExprCodeFactorable(pParse, pNew->a[i].pExpr, reg+i);
+ Expr *pCol = pNew->a[i].pExpr;
+ sqlite3ExprCodeFactorable(pParse, pCol, reg+i);
}
sqlite3VdbeAddOp3(v, OP_MakeRecord, reg, i, reg+i);
sqlite3VdbeAddOp2(v, OP_NewRowid, pReturning->iRetCur, reg+i+1);
sqlite3VdbeAddOp3(v, OP_Insert, pReturning->iRetCur, reg+i, reg+i+1);
}
- sqlite3ExprListDelete(pParse->db, pNew);
+ sqlite3ExprListDelete(db, pNew);
pParse->eTriggerOp = 0;
pParse->pTriggerTab = 0;
}
diff --git a/src/vdbe.c b/src/vdbe.c
index c34ea7245..54588b2a1 100644
--- a/src/vdbe.c
+++ b/src/vdbe.c
@@ -275,18 +275,36 @@ static VdbeCursor *allocateCursor(
sqlite3VdbeFreeCursor(p, p->apCsr[iCur]);
p->apCsr[iCur] = 0;
}
- if( SQLITE_OK==sqlite3VdbeMemClearAndResize(pMem, nByte) ){
- p->apCsr[iCur] = pCx = (VdbeCursor*)pMem->z;
- memset(pCx, 0, offsetof(VdbeCursor,pAltCursor));
- pCx->eCurType = eCurType;
- pCx->iDb = iDb;
- pCx->nField = nField;
- pCx->aOffset = &pCx->aType[nField];
- if( eCurType==CURTYPE_BTREE ){
- pCx->uc.pCursor = (BtCursor*)
- &pMem->z[ROUND8(sizeof(VdbeCursor))+2*sizeof(u32)*nField];
- sqlite3BtreeCursorZero(pCx->uc.pCursor);
+
+ /* There used to be a call to sqlite3VdbeMemClearAndResize() to make sure
+ ** the pMem used to hold space for the cursor has enough storage available
+ ** in pMem->zMalloc. But for the special case of the aMem[] entries used
+ ** to hold cursors, it is faster to in-line the logic. */
+ assert( pMem->flags==MEM_Undefined );
+ assert( (pMem->flags & MEM_Dyn)==0 );
+ assert( pMem->szMalloc==0 || pMem->z==pMem->zMalloc );
+ if( pMem->szMalloc<nByte ){
+ if( pMem->szMalloc>0 ){
+ sqlite3DbFreeNN(pMem->db, pMem->zMalloc);
+ }
+ pMem->z = pMem->zMalloc = sqlite3DbMallocRaw(pMem->db, nByte);
+ if( pMem->zMalloc==0 ){
+ pMem->szMalloc = 0;
+ return 0;
}
+ pMem->szMalloc = nByte;
+ }
+
+ p->apCsr[iCur] = pCx = (VdbeCursor*)pMem->zMalloc;
+ memset(pCx, 0, offsetof(VdbeCursor,pAltCursor));
+ pCx->eCurType = eCurType;
+ pCx->iDb = iDb;
+ pCx->nField = nField;
+ pCx->aOffset = &pCx->aType[nField];
+ if( eCurType==CURTYPE_BTREE ){
+ pCx->uc.pCursor = (BtCursor*)
+ &pMem->z[ROUND8(sizeof(VdbeCursor))+2*sizeof(u32)*nField];
+ sqlite3BtreeCursorZero(pCx->uc.pCursor);
}
return pCx;
}
@@ -574,6 +592,11 @@ static void registerTrace(int iReg, Mem *p){
printf("\n");
sqlite3VdbeCheckMemInvariants(p);
}
+/**/ void sqlite3PrintMem(Mem *pMem){
+ memTracePrint(pMem);
+ printf("\n");
+ fflush(stdout);
+}
#endif
#ifdef SQLITE_DEBUG
@@ -2021,6 +2044,31 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
pIn3 = &aMem[pOp->p3];
flags1 = pIn1->flags;
flags3 = pIn3->flags;
+ if( (flags1 & flags3 & MEM_Int)!=0 ){
+ assert( (pOp->p5 & SQLITE_AFF_MASK)!=SQLITE_AFF_TEXT || CORRUPT_DB );
+ /* Common case of comparison of two integers */
+ if( pIn3->u.i > pIn1->u.i ){
+ iCompare = +1;
+ if( sqlite3aGTb[pOp->opcode] ){
+ VdbeBranchTaken(1, (pOp->p5 & SQLITE_NULLEQ)?2:3);
+ goto jump_to_p2;
+ }
+ }else if( pIn3->u.i < pIn1->u.i ){
+ iCompare = -1;
+ if( sqlite3aLTb[pOp->opcode] ){
+ VdbeBranchTaken(1, (pOp->p5 & SQLITE_NULLEQ)?2:3);
+ goto jump_to_p2;
+ }
+ }else{
+ iCompare = 0;
+ if( sqlite3aEQb[pOp->opcode] ){
+ VdbeBranchTaken(1, (pOp->p5 & SQLITE_NULLEQ)?2:3);
+ goto jump_to_p2;
+ }
+ }
+ VdbeBranchTaken(0, (pOp->p5 & SQLITE_NULLEQ)?2:3);
+ break;
+ }
if( (flags1 | flags3)&MEM_Null ){
/* One or both operands are NULL */
if( pOp->p5 & SQLITE_NULLEQ ){
@@ -2051,7 +2099,8 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
break;
}
}else{
- /* Neither operand is NULL. Do a comparison. */
+ /* Neither operand is NULL and we couldn't do the special high-speed
+ ** integer comparison case. So do a general-case comparison. */
affinity = pOp->p5 & SQLITE_AFF_MASK;
if( affinity>=SQLITE_AFF_NUMERIC ){
if( (flags1 | flags3)&MEM_Str ){
@@ -2064,14 +2113,6 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
applyNumericAffinity(pIn3,0);
}
}
- /* Handle the common case of integer comparison here, as an
- ** optimization, to avoid a call to sqlite3MemCompare() */
- if( (pIn1->flags & pIn3->flags & MEM_Int)!=0 ){
- if( pIn3->u.i > pIn1->u.i ){ res = +1; goto compare_op; }
- if( pIn3->u.i < pIn1->u.i ){ res = -1; goto compare_op; }
- res = 0;
- goto compare_op;
- }
}else if( affinity==SQLITE_AFF_TEXT ){
if( (flags1 & MEM_Str)==0 && (flags1&(MEM_Int|MEM_Real|MEM_IntReal))!=0 ){
testcase( pIn1->flags & MEM_Int );
@@ -2094,7 +2135,7 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
assert( pOp->p4type==P4_COLLSEQ || pOp->p4.pColl==0 );
res = sqlite3MemCompare(pIn3, pIn1, pOp->p4.pColl);
}
-compare_op:
+
/* At this point, res is negative, zero, or positive if reg[P1] is
** less than, equal to, or greater than reg[P3], respectively. Compute
** the answer to this operator in res2, depending on what the comparison
@@ -4535,8 +4576,18 @@ case OP_SeekHit: {
assert( pC!=0 );
assert( pOp->p3>=pOp->p2 );
if( pC->seekHit<pOp->p2 ){
+#ifdef SQLITE_DEBUG
+ if( db->flags&SQLITE_VdbeTrace ){
+ printf("seekHit changes from %d to %d\n", pC->seekHit, pOp->p2);
+ }
+#endif
pC->seekHit = pOp->p2;
}else if( pC->seekHit>pOp->p3 ){
+#ifdef SQLITE_DEBUG
+ if( db->flags&SQLITE_VdbeTrace ){
+ printf("seekHit changes from %d to %d\n", pC->seekHit, pOp->p3);
+ }
+#endif
pC->seekHit = pOp->p3;
}
break;
@@ -4651,6 +4702,11 @@ case OP_IfNoHope: { /* jump, in3 */
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
+#ifdef SQLITE_DEBUG
+ if( db->flags&SQLITE_VdbeTrace ){
+ printf("seekHit is %d\n", pC->seekHit);
+ }
+#endif
if( pC->seekHit>=pOp->p4.i ) break;
/* Fall through into OP_NotFound */
/* no break */ deliberate_fall_through
diff --git a/src/vdbemem.c b/src/vdbemem.c
index 384eacc01..fd5212c8a 100644
--- a/src/vdbemem.c
+++ b/src/vdbemem.c
@@ -75,7 +75,9 @@ int sqlite3VdbeCheckMemInvariants(Mem *p){
/* The szMalloc field holds the correct memory allocation size */
assert( p->szMalloc==0
- || p->szMalloc==sqlite3DbMallocSize(p->db,p->zMalloc) );
+ || (p->flags==MEM_Undefined
+ && p->szMalloc<=sqlite3DbMallocSize(p->db,p->zMalloc))
+ || p->szMalloc==sqlite3DbMallocSize(p->db,p->zMalloc));
/* If p holds a string or blob, the Mem.z must point to exactly
** one of the following:
@@ -239,7 +241,9 @@ SQLITE_NOINLINE int sqlite3VdbeMemGrow(Mem *pMem, int n, int bPreserve){
testcase( bPreserve && pMem->z==0 );
assert( pMem->szMalloc==0
- || pMem->szMalloc==sqlite3DbMallocSize(pMem->db, pMem->zMalloc) );
+ || (pMem->flags==MEM_Undefined
+ && pMem->szMalloc<=sqlite3DbMallocSize(pMem->db,pMem->zMalloc))
+ || pMem->szMalloc==sqlite3DbMallocSize(pMem->db,pMem->zMalloc));
if( pMem->szMalloc>0 && bPreserve && pMem->z==pMem->zMalloc ){
if( pMem->db ){
pMem->z = pMem->zMalloc = sqlite3DbReallocOrFree(pMem->db, pMem->z, n);
diff --git a/src/wal.c b/src/wal.c
index ac0a03e93..c3f84dd2e 100644
--- a/src/wal.c
+++ b/src/wal.c
@@ -999,7 +999,6 @@ static void walCleanupHash(Wal *pWal){
int iLimit = 0; /* Zero values greater than this */
int nByte; /* Number of bytes to zero in aPgno[] */
int i; /* Used to iterate through aHash[] */
- int rc; /* Return code form walHashGet() */
assert( pWal->writeLock );
testcase( pWal->hdr.mxFrame==HASHTABLE_NPAGE_ONE-1 );
@@ -1014,8 +1013,8 @@ static void walCleanupHash(Wal *pWal){
*/
assert( pWal->nWiData>walFramePage(pWal->hdr.mxFrame) );
assert( pWal->apWiData[walFramePage(pWal->hdr.mxFrame)] );
- rc = walHashGet(pWal, walFramePage(pWal->hdr.mxFrame), &sLoc);
- if( NEVER(rc) ) return; /* Defense-in-depth, in case (1) above is wrong */
+ i = walHashGet(pWal, walFramePage(pWal->hdr.mxFrame), &sLoc);
+ if( NEVER(i) ) return; /* Defense-in-depth, in case (1) above is wrong */
/* Zero all hash-table entries that correspond to frame numbers greater
** than pWal->hdr.mxFrame.
diff --git a/src/walker.c b/src/walker.c
index e0acd5de2..8c0308473 100644
--- a/src/walker.c
+++ b/src/walker.c
@@ -140,6 +140,9 @@ int sqlite3WalkSelectExpr(Walker *pWalker, Select *p){
Parse *pParse;
if( pWalker->xSelectCallback2==sqlite3WalkWinDefnDummyCallback
|| ((pParse = pWalker->pParse)!=0 && IN_RENAME_OBJECT)
+#ifndef SQLITE_OMIT_CTE
+ || pWalker->xSelectCallback2==sqlite3SelectPopWith
+#endif
){
/* The following may return WRC_Abort if there are unresolvable
** symbols (e.g. a table that does not exist) in a window definition. */
diff --git a/src/where.c b/src/where.c
index 1755a85b5..4062de7ea 100644
--- a/src/where.c
+++ b/src/where.c
@@ -338,6 +338,18 @@ static WhereTerm *whereScanNext(WhereScan *pScan){
}
pScan->pWC = pWC;
pScan->k = k+1;
+#ifdef WHERETRACE_ENABLED
+ if( sqlite3WhereTrace & 0x20000 ){
+ int ii;
+ sqlite3DebugPrintf("SCAN-TERM %p: nEquiv=%d",
+ pTerm, pScan->nEquiv);
+ for(ii=0; ii<pScan->nEquiv; ii++){
+ sqlite3DebugPrintf(" {%d:%d}",
+ pScan->aiCur[ii], pScan->aiColumn[ii]);
+ }
+ sqlite3DebugPrintf("\n");
+ }
+#endif
return pTerm;
}
}
@@ -2501,6 +2513,8 @@ static int whereLoopAddBtreeIndex(
if( pProbe->bUnordered ) opMask &= ~(WO_GT|WO_GE|WO_LT|WO_LE);
assert( pNew->u.btree.nEq<pProbe->nColumn );
+ assert( pNew->u.btree.nEq<pProbe->nKeyCol
+ || pProbe->idxType!=SQLITE_IDXTYPE_PRIMARYKEY );
saved_nEq = pNew->u.btree.nEq;
saved_nBtm = pNew->u.btree.nBtm;
@@ -2634,6 +2648,7 @@ static int whereLoopAddBtreeIndex(
pNew->wsFlags |= WHERE_UNQ_WANTED;
}
}
+ if( scan.iEquiv>1 ) pNew->wsFlags |= WHERE_TRANSCONS;
}else if( eOp & WO_ISNULL ){
pNew->wsFlags |= WHERE_COLUMN_NULL;
}else if( eOp & (WO_GT|WO_GE) ){
@@ -2777,6 +2792,8 @@ static int whereLoopAddBtreeIndex(
if( (pNew->wsFlags & WHERE_TOP_LIMIT)==0
&& pNew->u.btree.nEq<pProbe->nColumn
+ && (pNew->u.btree.nEq<pProbe->nKeyCol ||
+ pProbe->idxType!=SQLITE_IDXTYPE_PRIMARYKEY)
){
whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, nInMul+nIn);
}
@@ -4145,7 +4162,7 @@ static LogEst whereSortingCost(
}else if( (pWInfo->wctrlFlags & WHERE_WANT_DISTINCT) ){
/* TUNING: In the sort for a DISTINCT operator, assume that the DISTINCT
** reduces the number of output rows by a factor of 2 */
- if( nRow>10 ) nRow -= 10; assert( 10==sqlite3LogEst(2) );
+ if( nRow>10 ){ nRow -= 10; assert( 10==sqlite3LogEst(2) ); }
}
rSortCost += estLog(nRow);
return rSortCost;
@@ -5435,6 +5452,8 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
int j;
sqlite3VdbeResolveLabel(v, pLevel->addrNxt);
for(j=pLevel->u.in.nIn, pIn=&pLevel->u.in.aInLoop[j-1]; j>0; j--, pIn--){
+ assert( sqlite3VdbeGetOp(v, pIn->addrInTop+1)->opcode==OP_IsNull
+ || pParse->db->mallocFailed );
sqlite3VdbeJumpHere(v, pIn->addrInTop+1);
if( pIn->eEndLoopOp!=OP_Noop ){
if( pIn->nPrefix ){
@@ -5459,6 +5478,11 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
sqlite3VdbeCurrentAddr(v)+2,
pIn->iBase, pIn->nPrefix);
VdbeCoverage(v);
+ /* Retarget the OP_IsNull against the left operand of IN so
+ ** it jumps past the OP_IfNoHope. This is because the
+ ** OP_IsNull also bypasses the OP_Affinity opcode that is
+ ** required by OP_IfNoHope. */
+ sqlite3VdbeJumpHere(v, pIn->addrInTop+1);
}
}
sqlite3VdbeAddOp2(v, pIn->eEndLoopOp, pIn->iCur, pIn->addrInTop);
diff --git a/src/whereInt.h b/src/whereInt.h
index 8896da027..c5dd83cc8 100644
--- a/src/whereInt.h
+++ b/src/whereInt.h
@@ -293,8 +293,8 @@ struct WhereScan {
const char *zCollName; /* Required collating sequence, if not NULL */
Expr *pIdxExpr; /* Search for this index expression */
char idxaff; /* Must match this affinity, if zCollName!=NULL */
- unsigned char nEquiv; /* Number of entries in aEquiv[] */
- unsigned char iEquiv; /* Next unused slot in aEquiv[] */
+ unsigned char nEquiv; /* Number of entries in aiCur[] and aiColumn[] */
+ unsigned char iEquiv; /* Next unused slot in aiCur[] and aiColumn[] */
u32 opMask; /* Acceptable operators */
int k; /* Resume scanning at this->pWC->a[this->k] */
int aiCur[11]; /* Cursors in the equivalence class */
@@ -603,5 +603,6 @@ void sqlite3WhereTabFuncArgs(Parse*, SrcItem*, WhereClause*);
#define WHERE_IN_EARLYOUT 0x00040000 /* Perhaps quit IN loops early */
#define WHERE_BIGNULL_SORT 0x00080000 /* Column nEq of index is BIGNULL */
#define WHERE_IN_SEEKSCAN 0x00100000 /* Seek-scan optimization for IN */
+#define WHERE_TRANSCONS 0x00200000 /* Uses a transitive constraint */
#endif /* !defined(SQLITE_WHEREINT_H) */
diff --git a/src/wherecode.c b/src/wherecode.c
index 6b4bc8a21..4d0ba880d 100644
--- a/src/wherecode.c
+++ b/src/wherecode.c
@@ -297,6 +297,12 @@ static void disableTerm(WhereLevel *pLevel, WhereTerm *pTerm){
}else{
pTerm->wtFlags |= TERM_CODED;
}
+#ifdef WHERETRACE_ENABLED
+ if( sqlite3WhereTrace & 0x20000 ){
+ sqlite3DebugPrintf("DISABLE-");
+ sqlite3WhereTermPrint(pTerm, (int)(pTerm - (pTerm->pWC->a)));
+ }
+#endif
if( pTerm->iParent<0 ) break;
pTerm = &pTerm->pWC->a[pTerm->iParent];
assert( pTerm!=0 );
@@ -614,7 +620,22 @@ static int codeEqualityTerm(
sqlite3DbFree(pParse->db, aiMap);
#endif
}
- disableTerm(pLevel, pTerm);
+
+ /* As an optimization, try to disable the WHERE clause term that is
+ ** driving the index as it will always be true. The correct answer is
+ ** obtained regardless, but we might get the answer with fewer CPU cycles
+ ** by omitting the term.
+ **
+ ** But do not disable the term unless we are certain that the term is
+ ** not a transitive constraint. For an example of where that does not
+ ** work, see https://sqlite.org/forum/forumpost/eb8613976a (2021-05-04)
+ */
+ if( (pLevel->pWLoop->wsFlags & WHERE_TRANSCONS)==0
+ || (pTerm->eOperator & WO_EQUIV)==0
+ ){
+ disableTerm(pLevel, pTerm);
+ }
+
return iReg;
}
@@ -1728,9 +1749,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
** a forward order scan on a descending index, interchange the
** start and end terms (pRangeStart and pRangeEnd).
*/
- if( (nEq<pIdx->nKeyCol && bRev==(pIdx->aSortOrder[nEq]==SQLITE_SO_ASC))
- || (bRev && pIdx->nKeyCol==nEq)
- ){
+ if( (nEq<pIdx->nColumn && bRev==(pIdx->aSortOrder[nEq]==SQLITE_SO_ASC)) ){
SWAP(WhereTerm *, pRangeEnd, pRangeStart);
SWAP(u8, bSeekPastNull, bStopAtNull);
SWAP(u8, nBtm, nTop);
@@ -2151,7 +2170,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
/* The extra 0x10000 bit on the opcode is masked off and does not
** become part of the new Expr.op. However, it does make the
** op==TK_AND comparison inside of sqlite3PExpr() false, and this
- ** prevents sqlite3PExpr() from implementing AND short-circuit
+ ** prevents sqlite3PExpr() from applying the AND short-circuit
** optimization, which we do not want here. */
pAndExpr = sqlite3PExpr(pParse, TK_AND|0x10000, 0, pAndExpr);
}
@@ -2167,10 +2186,16 @@ Bitmask sqlite3WhereCodeOneLoopStart(
if( pOrTerm->leftCursor==iCur || (pOrTerm->eOperator & WO_AND)!=0 ){
WhereInfo *pSubWInfo; /* Info for single OR-term scan */
Expr *pOrExpr = pOrTerm->pExpr; /* Current OR clause term */
+ Expr *pDelete; /* Local copy of OR clause term */
int jmp1 = 0; /* Address of jump operation */
testcase( (pTabItem[0].fg.jointype & JT_LEFT)!=0
&& !ExprHasProperty(pOrExpr, EP_FromJoin)
); /* See TH3 vtab25.400 and ticket 614b25314c766238 */
+ pDelete = pOrExpr = sqlite3ExprDup(db, pOrExpr, 0);
+ if( db->mallocFailed ){
+ sqlite3ExprDelete(db, pDelete);
+ continue;
+ }
if( pAndExpr ){
pAndExpr->pLeft = pOrExpr;
pOrExpr = pAndExpr;
@@ -2285,6 +2310,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
sqlite3WhereEnd(pSubWInfo);
ExplainQueryPlanPop(pParse);
}
+ sqlite3ExprDelete(db, pDelete);
}
}
ExplainQueryPlanPop(pParse);
diff --git a/src/whereexpr.c b/src/whereexpr.c
index 1807fbb00..31f2ea438 100644
--- a/src/whereexpr.c
+++ b/src/whereexpr.c
@@ -872,7 +872,7 @@ static void exprAnalyzeOrTerm(
idxNew = whereClauseInsert(pWC, pNew, TERM_VIRTUAL|TERM_DYNAMIC);
testcase( idxNew==0 );
exprAnalyze(pSrc, pWC, idxNew);
- /* pTerm = &pWC->a[idxTerm]; // would be needed if pTerm where used again */
+ /* pTerm = &pWC->a[idxTerm]; // would be needed if pTerm where reused */
markTermAsChild(pWC, idxNew, idxTerm);
}else{
sqlite3ExprListDelete(db, pList);
@@ -996,6 +996,7 @@ static int exprMightBeIndexed(
assert( op<=TK_GE );
if( pExpr->op==TK_VECTOR && (op>=TK_GT && ALWAYS(op<=TK_GE)) ){
pExpr = pExpr->x.pList->a[0].pExpr;
+
}
if( pExpr->op==TK_COLUMN ){
@@ -1008,276 +1009,6 @@ static int exprMightBeIndexed(
return exprMightBeIndexed2(pFrom,mPrereq,aiCurCol,pExpr);
}
-/*
-** Expression callback for exprUsesSrclist().
-*/
-static int exprUsesSrclistCb(Walker *p, Expr *pExpr){
- if( pExpr->op==TK_COLUMN ){
- SrcList *pSrc = p->u.pSrcList;
- int iCsr = pExpr->iTable;
- int ii;
- for(ii=0; ii<pSrc->nSrc; ii++){
- if( pSrc->a[ii].iCursor==iCsr ){
- return p->eCode ? WRC_Abort : WRC_Continue;
- }
- }
- return p->eCode ? WRC_Continue : WRC_Abort;
- }
- return WRC_Continue;
-}
-
-/*
-** Select callback for exprUsesSrclist().
-*/
-static int exprUsesSrclistSelectCb(Walker *NotUsed1, Select *NotUsed2){
- UNUSED_PARAMETER(NotUsed1);
- UNUSED_PARAMETER(NotUsed2);
- return WRC_Abort;
-}
-
-/*
-** This function always returns true if expression pExpr contains
-** a sub-select.
-**
-** If there is no sub-select in pExpr, then return true if pExpr
-** contains a TK_COLUMN node for a table that is (bUses==1)
-** or is not (bUses==0) in pSrc.
-**
-** Said another way:
-**
-** bUses Return Meaning
-** -------- ------ ------------------------------------------------
-**
-** bUses==1 true pExpr contains either a sub-select or a
-** TK_COLUMN referencing pSrc.
-**
-** bUses==1 false pExpr contains no sub-selects and all TK_COLUMN
-** nodes reference tables not found in pSrc
-**
-** bUses==0 true pExpr contains either a sub-select or a TK_COLUMN
-** that references a table not in pSrc.
-**
-** bUses==0 false pExpr contains no sub-selects and all TK_COLUMN
-** nodes reference pSrc
-*/
-static int exprUsesSrclist(SrcList *pSrc, Expr *pExpr, int bUses){
- Walker sWalker;
- memset(&sWalker, 0, sizeof(Walker));
- sWalker.eCode = bUses;
- sWalker.u.pSrcList = pSrc;
- sWalker.xExprCallback = exprUsesSrclistCb;
- sWalker.xSelectCallback = exprUsesSrclistSelectCb;
- return (sqlite3WalkExpr(&sWalker, pExpr)==WRC_Abort);
-}
-
-/*
-** Context object used by exprExistsToInIter() as it iterates through an
-** expression tree.
-*/
-struct ExistsToInCtx {
- SrcList *pSrc; /* The tables in an EXISTS(SELECT ... FROM <here> ...) */
- Expr *pInLhs; /* OUT: Use this as the LHS of the IN operator */
- Expr *pEq; /* OUT: The == term that include pInLhs */
- Expr **ppAnd; /* OUT: The AND operator that includes pEq as a child */
- Expr **ppParent; /* The AND operator currently being examined */
-};
-
-/*
-** Iterate through all AND connected nodes in the expression tree
-** headed by (*ppExpr), populating the structure passed as the first
-** argument with the values required by exprAnalyzeExistsFindEq().
-**
-** This function returns non-zero if the expression tree does not meet
-** the two conditions described by the header comment for
-** exprAnalyzeExistsFindEq(), or zero if it does.
-*/
-static int exprExistsToInIter(struct ExistsToInCtx *p, Expr **ppExpr){
- Expr *pExpr = *ppExpr;
- switch( pExpr->op ){
- case TK_AND:
- p->ppParent = ppExpr;
- if( exprExistsToInIter(p, &pExpr->pLeft) ) return 1;
- p->ppParent = ppExpr;
- if( exprExistsToInIter(p, &pExpr->pRight) ) return 1;
- break;
- case TK_EQ: {
- int bLeft = exprUsesSrclist(p->pSrc, pExpr->pLeft, 0);
- int bRight = exprUsesSrclist(p->pSrc, pExpr->pRight, 0);
- if( bLeft || bRight ){
- if( (bLeft && bRight) || p->pInLhs ) return 1;
- p->pInLhs = bLeft ? pExpr->pLeft : pExpr->pRight;
- if( exprUsesSrclist(p->pSrc, p->pInLhs, 1) ) return 1;
- p->pEq = pExpr;
- p->ppAnd = p->ppParent;
- }
- break;
- }
- default:
- if( exprUsesSrclist(p->pSrc, pExpr, 0) ){
- return 1;
- }
- break;
- }
-
- return 0;
-}
-
-/*
-** This function is used by exprAnalyzeExists() when creating virtual IN(...)
-** terms equivalent to user-supplied EXIST(...) clauses. It splits the WHERE
-** clause of the Select object passed as the first argument into one or more
-** expressions joined by AND operators, and then tests if the following are
-** true:
-**
-** 1. Exactly one of the AND separated terms refers to the outer
-** query, and it is an == (TK_EQ) expression.
-**
-** 2. Only one side of the == expression refers to the outer query, and
-** it does not refer to any columns from the inner query.
-**
-** If both these conditions are true, then a pointer to the side of the ==
-** expression that refers to the outer query is returned. The caller will
-** use this expression as the LHS of the IN(...) virtual term. Or, if one
-** or both of the above conditions are not true, NULL is returned.
-**
-** If non-NULL is returned and ppEq is non-NULL, *ppEq is set to point
-** to the == expression node before returning. If pppAnd is non-NULL and
-** the == node is not the root of the WHERE clause, then *pppAnd is set
-** to point to the pointer to the AND node that is the parent of the ==
-** node within the WHERE expression tree.
-*/
-static Expr *exprAnalyzeExistsFindEq(
- Select *pSel, /* The SELECT of the EXISTS */
- Expr **ppEq, /* OUT: == node from WHERE clause */
- Expr ***pppAnd /* OUT: Pointer to parent of ==, if any */
-){
- struct ExistsToInCtx ctx;
- memset(&ctx, 0, sizeof(ctx));
- ctx.pSrc = pSel->pSrc;
- if( exprExistsToInIter(&ctx, &pSel->pWhere) ){
- return 0;
- }
- if( ppEq ) *ppEq = ctx.pEq;
- if( pppAnd ) *pppAnd = ctx.ppAnd;
- return ctx.pInLhs;
-}
-
-/*
-** Term idxTerm of the WHERE clause passed as the second argument is an
-** EXISTS expression with a correlated SELECT statement on the RHS.
-** This function analyzes the SELECT statement, and if possible adds an
-** equivalent "? IN(SELECT...)" virtual term to the WHERE clause.
-**
-** For an EXISTS term such as the following:
-**
-** EXISTS (SELECT ... FROM <srclist> WHERE <e1> = <e2> AND <e3>)
-**
-** The virtual IN() term added is:
-**
-** <e1> IN (SELECT <e2> FROM <srclist> WHERE <e3>)
-**
-** The virtual term is only added if the following conditions are met:
-**
-** 1. The sub-select must not be an aggregate or use window functions,
-**
-** 2. The sub-select must not be a compound SELECT,
-**
-** 3. Expression <e1> must refer to at least one column from the outer
-** query, and must not refer to any column from the inner query
-** (i.e. from <srclist>).
-**
-** 4. <e2> and <e3> must not refer to any values from the outer query.
-** In other words, once <e1> has been removed, the inner query
-** must not be correlated.
-**
-*/
-static void exprAnalyzeExists(
- SrcList *pSrc, /* the FROM clause */
- WhereClause *pWC, /* the WHERE clause */
- int idxTerm /* Index of the term to be analyzed */
-){
- Parse *pParse = pWC->pWInfo->pParse;
- WhereTerm *pTerm = &pWC->a[idxTerm];
- Expr *pExpr = pTerm->pExpr;
- Select *pSel = pExpr->x.pSelect;
- Expr *pDup = 0;
- Expr *pEq = 0;
- Expr *pRet = 0;
- Expr *pInLhs = 0;
- Expr **ppAnd = 0;
- int idxNew;
- sqlite3 *db = pParse->db;
-
- assert( pExpr->op==TK_EXISTS );
- assert( (pExpr->flags & EP_VarSelect) && (pExpr->flags & EP_xIsSelect) );
-
- if( pSel->selFlags & SF_Aggregate ) return;
-#ifndef SQLITE_OMIT_WINDOWFUNC
- if( pSel->pWin ) return;
-#endif
- if( pSel->pPrior ) return;
- if( pSel->pWhere==0 ) return;
- if( pSel->pLimit ) return;
- if( 0==exprAnalyzeExistsFindEq(pSel, 0, 0) ) return;
-
- pDup = sqlite3ExprDup(db, pExpr, 0);
- if( db->mallocFailed ){
- sqlite3ExprDelete(db, pDup);
- return;
- }
- pSel = pDup->x.pSelect;
- sqlite3ExprListDelete(db, pSel->pEList);
- pSel->pEList = 0;
-
- pInLhs = exprAnalyzeExistsFindEq(pSel, &pEq, &ppAnd);
- assert( pInLhs && pEq );
- assert( pEq==pSel->pWhere || ppAnd );
- if( pInLhs==pEq->pLeft ){
- pRet = pEq->pRight;
- }else{
- CollSeq *p = sqlite3ExprCompareCollSeq(pParse, pEq);
- pInLhs = sqlite3ExprAddCollateString(pParse, pInLhs, p?p->zName:"BINARY");
- pRet = pEq->pLeft;
- }
-
- assert( pDup->pLeft==0 );
- pDup->op = TK_IN;
- pDup->pLeft = pInLhs;
- pDup->flags &= ~EP_VarSelect;
- if( pRet->op==TK_VECTOR ){
- pSel->pEList = pRet->x.pList;
- pRet->x.pList = 0;
- sqlite3ExprDelete(db, pRet);
- }else{
- pSel->pEList = sqlite3ExprListAppend(pParse, 0, pRet);
- }
- pEq->pLeft = 0;
- pEq->pRight = 0;
- if( ppAnd ){
- Expr *pAnd = *ppAnd;
- Expr *pOther = (pAnd->pLeft==pEq) ? pAnd->pRight : pAnd->pLeft;
- pAnd->pLeft = pAnd->pRight = 0;
- sqlite3ExprDelete(db, pAnd);
- *ppAnd = pOther;
- }else{
- assert( pSel->pWhere==pEq );
- pSel->pWhere = 0;
- }
- sqlite3ExprDelete(db, pEq);
-
-#ifdef WHERETRACE_ENABLED /* 0x20 */
- if( sqlite3WhereTrace & 0x20 ){
- sqlite3DebugPrintf("Convert EXISTS:\n");
- sqlite3TreeViewExpr(0, pExpr, 0);
- sqlite3DebugPrintf("into IN:\n");
- sqlite3TreeViewExpr(0, pDup, 0);
- }
-#endif
- idxNew = whereClauseInsert(pWC, pDup, TERM_VIRTUAL|TERM_DYNAMIC);
- exprAnalyze(pSrc, pWC, idxNew);
- markTermAsChild(pWC, idxNew, idxTerm);
- pWC->a[idxTerm].wtFlags |= TERM_COPIED;
-}
/*
** The input to this routine is an WhereTerm structure with only the
@@ -1377,6 +1108,7 @@ static void exprAnalyze(
if( op==TK_IS ) pTerm->wtFlags |= TERM_IS;
if( pRight
&& exprMightBeIndexed(pSrc, pTerm->prereqRight, aiCurCol, pRight, op)
+ && !ExprHasProperty(pRight, EP_FixedCol)
){
WhereTerm *pNew;
Expr *pDup;
@@ -1469,16 +1201,6 @@ static void exprAnalyze(
pTerm = &pWC->a[idxTerm];
}
#endif /* SQLITE_OMIT_OR_OPTIMIZATION */
-
- else if( pExpr->op==TK_EXISTS ){
- /* Perhaps treat an EXISTS operator as an IN operator */
- if( (pExpr->flags & EP_VarSelect)!=0
- && OptimizationEnabled(db, SQLITE_ExistsToIN)
- ){
- exprAnalyzeExists(pSrc, pWC, idxTerm);
- }
- }
-
/* The form "x IS NOT NULL" can sometimes be evaluated more efficiently
** as "x>NULL" if x is not an INTEGER PRIMARY KEY. So construct a
** virtual term of that form.
diff --git a/src/window.c b/src/window.c
index 61e57cf37..a997b9c6c 100644
--- a/src/window.c
+++ b/src/window.c
@@ -941,6 +941,14 @@ static int sqlite3WindowExtraAggFuncDepth(Walker *pWalker, Expr *pExpr){
return WRC_Continue;
}
+static int disallowAggregatesInOrderByCb(Walker *pWalker, Expr *pExpr){
+ if( pExpr->op==TK_AGG_FUNCTION && pExpr->pAggInfo==0 ){
+ sqlite3ErrorMsg(pWalker->pParse,
+ "misuse of aggregate: %s()", pExpr->u.zToken);
+ }
+ return WRC_Continue;
+}
+
/*
** If the SELECT statement passed as the second argument does not invoke
** any SQL window functions, this function is a no-op. Otherwise, it
@@ -974,6 +982,11 @@ int sqlite3WindowRewrite(Parse *pParse, Select *p){
}
sqlite3AggInfoPersistWalkerInit(&w, pParse);
sqlite3WalkSelect(&w, p);
+ if( (p->selFlags & SF_Aggregate)==0 ){
+ w.xExprCallback = disallowAggregatesInOrderByCb;
+ w.xSelectCallback = 0;
+ sqlite3WalkExprList(&w, p->pOrderBy);
+ }
p->pSrc = 0;
p->pWhere = 0;
@@ -2263,7 +2276,7 @@ static int windowCodeOp(
}else if( p->regRowid ){
sqlite3VdbeAddOp2(v, OP_Rowid, p->end.csr, regRowid1);
sqlite3VdbeAddOp3(v, OP_Ge, p->regRowid, lblDone, regRowid1);
- VdbeCoverage(v);
+ VdbeCoverageNeverNull(v);
}
sqlite3ReleaseTempReg(pParse, regRowid1);
sqlite3ReleaseTempReg(pParse, regRowid2);
diff --git a/test/alter4.test b/test/alter4.test
index 3aca7df33..c63ba6b07 100644
--- a/test/alter4.test
+++ b/test/alter4.test
@@ -318,16 +318,16 @@ ifcapable trigger&&tempdb {
END;
INSERT INTO t1 VALUES(1, 2);
- SELECT * FROM log;
+ SELECT * FROM log ORDER BY trig, a, b;
}
- } {b 1 2 a 1 2}
+ } {a 1 2 b 1 2}
do_test alter4-6.2 {
execsql {
ALTER TABLE t1 ADD COLUMN c DEFAULT 'c';
INSERT INTO t1(a, b) VALUES(3, 4);
- SELECT * FROM log;
+ SELECT * FROM log ORDER BY trig, a, b;
}
- } {b 1 2 a 1 2 b 3 4 a 3 4}
+ } {a 1 2 a 3 4 b 1 2 b 3 4}
}
# Ticket #1183 - Make sure adding columns to large tables does not cause
diff --git a/test/altertab.test b/test/altertab.test
index 47659935c..576d391ce 100644
--- a/test/altertab.test
+++ b/test/altertab.test
@@ -750,4 +750,53 @@ ifcapable json1&&vtab {
} {1 {table json_each may not be altered}}
}
+# 2021-05-01 dbsqlfuzz bc17a306a09329bba0ecc61547077f6178bcf321
+# Remove a NEVER() inserted on 2019-12-09 that is reachable after all.
+#
+reset_db
+do_execsql_test 26.1 {
+ CREATE TABLE t1(k,v);
+ CREATE TABLE t2_a(k,v);
+ CREATE VIEW t2 AS SELECT * FROM t2_a;
+ CREATE TRIGGER r2 AFTER INSERT ON t1 BEGIN
+ UPDATE t1
+ SET (k,v)=((WITH cte1(a) AS (SELECT 1 FROM t2) SELECT t2.k FROM t2, cte1),1);
+ END;
+ ALTER TABLE t1 RENAME TO t1x;
+ INSERT INTO t2_a VALUES(2,3);
+ INSERT INTO t1x VALUES(98,99);
+ SELECT * FROM t1x;
+} {2 1}
+
+#-------------------------------------------------------------------------
+reset_db
+
+do_execsql_test 27.1 {
+
+ create table t_sa (
+ c_muyat INTEGER NOT NULL,
+ c_d4u TEXT
+ );
+
+ create table t2 ( abc );
+
+ CREATE TRIGGER trig AFTER DELETE ON t_sa
+ BEGIN
+ DELETE FROM t_sa WHERE (
+ SELECT 123 FROM t2
+ WINDOW oamat7fzf AS ( PARTITION BY t_sa.c_d4u )
+ );
+ END;
+}
+
+
+breakpoint
+do_execsql_test 27.2 {
+ alter table t_sa rename column c_muyat to c_dg;
+}
+
+
+
+
+
finish_test
diff --git a/test/corrupt4.test b/test/corrupt4.test
index 0aa42aa6a..5b0965a83 100644
--- a/test/corrupt4.test
+++ b/test/corrupt4.test
@@ -129,19 +129,21 @@ set pgnoChild [get4byte $fd $offChild]
put4byte $fd $offChild 1
close $fd
-sqlite3 db test.db
-do_catchsql_test 2.2 {
- PRAGMA writable_schema = 1;
- SELECT * FROM sqlite_schema;
-} {1 {database disk image is malformed}}
-
-do_test 2.3 {
- list [catch {
- for {set ii $nView} {$ii<$nView*2} {incr ii} {
- execsql "INSERT INTO sqlite_master VALUES(1, 2, 3, 4, 5)"
- }
- } msg] $msg
-} {1 {database disk image is malformed}}
+if {![info exists ::G(perm:presql)]} {
+ sqlite3 db test.db
+ do_catchsql_test 2.2 {
+ PRAGMA writable_schema = 1;
+ SELECT * FROM sqlite_schema;
+ } {1 {database disk image is malformed}}
+
+ do_test 2.3 {
+ list [catch {
+ for {set ii $nView} {$ii<$nView*2} {incr ii} {
+ execsql "INSERT INTO sqlite_master VALUES(1, 2, 3, 4, 5)"
+ }
+ } msg] $msg
+ } {1 {database disk image is malformed}}
+}
finish_test
diff --git a/test/corruptN.test b/test/corruptN.test
index 8eca2fdb8..4349468bb 100644
--- a/test/corruptN.test
+++ b/test/corruptN.test
@@ -149,69 +149,74 @@ INSERT INTO t1(a) SELECT randomblob(null) FROM c;
} {1 {database disk image is malformed}}
reset_db
-do_execsql_test 3.0 {
- CREATE TABLE t1(x INTEGER PRIMARY KEY AUTOINCREMENT, y);
- PRAGMA writable_schema = 1;
- UPDATE sqlite_schema
- SET sql = 'CREATE TABLE sqlite_sequence(name-seq)'
- WHERE name = 'sqlite_sequence';
-}
-db close
-sqlite3 db test.db
-do_catchsql_test 3.1 {
- PRAGMA writable_schema = 1;
- INSERT INTO t1(y) VALUES('abc');
-} {1 {database disk image is malformed}}
+if {![info exists ::G(perm:presql)]} {
+ do_execsql_test 3.0 {
+ CREATE TABLE t1(x INTEGER PRIMARY KEY AUTOINCREMENT, y);
+ PRAGMA writable_schema = 1;
+ UPDATE sqlite_schema
+ SET sql = 'CREATE TABLE sqlite_sequence(name-seq)'
+ WHERE name = 'sqlite_sequence';
+ }
+ db close
+ sqlite3 db test.db
+ do_catchsql_test 3.1 {
+ PRAGMA writable_schema = 1;
+ INSERT INTO t1(y) VALUES('abc');
+ } {1 {database disk image is malformed}}
+ reset_db
+
+ do_execsql_test 4.1 {
+ CREATE TABLE x1(a INTEGER PRIMARY KEY, b UNIQUE, c UNIQUE);
+ INSERT INTO x1 VALUES(1, 1, 2);
+ INSERT INTO x1 VALUES(2, 2, 3);
+ INSERT INTO x1 VALUES(3, 3, 4);
+ INSERT INTO x1 VALUES(4, 5, 6);
+ PRAGMA writable_schema = 1;
+
+ UPDATE sqlite_schema SET rootpage = (
+ SELECT rootpage FROM sqlite_schema WHERE name = 'sqlite_autoindex_x1_2'
+ ) WHERE name = 'sqlite_autoindex_x1_1';
+ }
+
+ db close
+ sqlite3 db test.db
+ breakpoint
+ do_catchsql_test 4.2 {
+ PRAGMA writable_schema = 1;
+ REPLACE INTO x1 VALUES(5, 2, 3);
+ } {1 {database disk image is malformed}}
-reset_db
-do_execsql_test 4.1 {
- CREATE TABLE x1(a INTEGER PRIMARY KEY, b UNIQUE, c UNIQUE);
- INSERT INTO x1 VALUES(1, 1, 2);
- INSERT INTO x1 VALUES(2, 2, 3);
- INSERT INTO x1 VALUES(3, 3, 4);
- INSERT INTO x1 VALUES(4, 5, 6);
- PRAGMA writable_schema = 1;
-
- UPDATE sqlite_schema SET rootpage = (
- SELECT rootpage FROM sqlite_schema WHERE name = 'sqlite_autoindex_x1_2'
- ) WHERE name = 'sqlite_autoindex_x1_1';
}
-db close
-sqlite3 db test.db
-breakpoint
-do_catchsql_test 3.1 {
- PRAGMA writable_schema = 1;
- REPLACE INTO x1 VALUES(5, 2, 3);
-} {1 {database disk image is malformed}}
-
#-------------------------------------------------------------------------
reset_db
-db func strreplace strreplace
-proc strreplace {orig a b} {
- string map [list $a $b] $orig
-}
-
-do_execsql_test 4.0 {
- CREATE TABLE t1(a, b);
- CREATE INDEX t1a ON t1(a);
- CREATE INDEX t1b ON t1(b);
-
- PRAGMA writable_schema = 1;
- UPDATE sqlite_schema
- SET sql = strreplace(sql, 't1', 'json_each')
- WHERE type='index';
-}
-
-db close
-sqlite3 db test.db
-
-do_execsql_test 4.1 {
- PRAGMA writable_schema = 1;
- SELECT * FROM t1
-}
+ifcapable json1&&vtab {
+ db func strreplace strreplace
+ proc strreplace {orig a b} {
+ string map [list $a $b] $orig
+ }
+
+ do_execsql_test 5.0 {
+ CREATE TABLE t1(a, b);
+ CREATE INDEX t1a ON t1(a);
+ CREATE INDEX t1b ON t1(b);
+
+ PRAGMA writable_schema = 1;
+ UPDATE sqlite_schema
+ SET sql = strreplace(sql, 't1', 'json_each')
+ WHERE type='index';
+ }
+
+ db close
+ sqlite3 db test.db
+
+ do_execsql_test 5.1 {
+ PRAGMA writable_schema = 1;
+ SELECT * FROM t1
+ }
+}; # ifcapable json1&&vtab
finish_test
diff --git a/test/dbfuzz2.c b/test/dbfuzz2.c
index 6b30490dd..f0062915d 100644
--- a/test/dbfuzz2.c
+++ b/test/dbfuzz2.c
@@ -31,8 +31,7 @@
**
** mkdir dir
** cp dbfuzz2-seed*.db dir
-** clang-6.0 -I. -g -O1 -fsanitize=fuzzer \
-** -DTHREADSAFE=0 -DSQLITE_ENABLE_DESERIALIZE \
+** clang-6.0 -I. -g -O1 -fsanitize=fuzzer -DTHREADSAFE=0 \
** -DSQLITE_ENABLE_DBSTAT_VTAB dbfuzz2.c sqlite3.c -ldl
** ./a.out dir
*/
diff --git a/test/exists2.test b/test/exists2.test
deleted file mode 100644
index 498b90dd2..000000000
--- a/test/exists2.test
+++ /dev/null
@@ -1,194 +0,0 @@
-# 2021 January 15
-#
-# 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 file is testing cases where EXISTS expressions are
-# transformed to IN() expressions by where.c
-#
-
-set testdir [file dirname $argv0]
-source $testdir/tester.tcl
-set testprefix exists2
-
-do_execsql_test 1.0 {
- CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
- INSERT INTO t1 VALUES(1, 'one');
- INSERT INTO t1 VALUES(2, 'two');
- INSERT INTO t1 VALUES(3, 'three');
- INSERT INTO t1 VALUES(4, 'four');
- INSERT INTO t1 VALUES(5, 'five');
- INSERT INTO t1 VALUES(6, 'six');
- INSERT INTO t1 VALUES(7, 'seven');
-
- CREATE TABLE t2(c INTEGER, d INTEGER);
- INSERT INTO t2 VALUES(1, 1);
- INSERT INTO t2 VALUES(3, 2);
- INSERT INTO t2 VALUES(5, 3);
- INSERT INTO t2 VALUES(7, 4);
-}
-
-proc do_execsql_eqp_test {tn sql eqp res} {
- uplevel [list do_eqp_test $tn.1 $sql [string trim $eqp]]
- uplevel [list do_execsql_test $tn.2 $sql $res]
-}
-
-do_execsql_eqp_test 1.1 {
- SELECT t1.* FROM t1 WHERE EXISTS(SELECT * FROM t2 WHERE t1.a=t2.c);
-} {
- USING INTEGER PRIMARY KEY
-} {
- 1 one 3 three 5 five 7 seven
-}
-
-do_execsql_eqp_test 1.2 {
- SELECT t1.* FROM t1 WHERE EXISTS(SELECT * FROM t2 WHERE t2.c=t1.a);
-} {
- SEARCH t1 USING INTEGER PRIMARY KEY
-} {
- 1 one 3 three 5 five 7 seven
-}
-
-do_execsql_eqp_test 1.3 {
- SELECT t1.* FROM t1 WHERE EXISTS(SELECT * FROM t2 WHERE t2.c+1=t1.a);
-} {
- SEARCH t1 USING INTEGER PRIMARY KEY
-} {
- 2 two 4 four 6 six
-}
-
-do_execsql_eqp_test 1.4 {
- SELECT t1.* FROM t1 WHERE EXISTS(SELECT * FROM t2 WHERE t2.c+1=t1.a+1);
-} {
- SCAN t1
-} {
- 1 one 3 three 5 five 7 seven
-}
-
-do_execsql_eqp_test 1.5 {
- SELECT t1.* FROM t1 WHERE EXISTS(
- SELECT * FROM t2 WHERE t1.a=t2.c AND d IN (1, 2, 3)
- );
-} {
- SEARCH t1 USING INTEGER PRIMARY KEY
-} {
- 1 one 3 three 5 five
-}
-
-do_execsql_eqp_test 1.6 {
- SELECT t1.* FROM t1 WHERE EXISTS(
- SELECT * FROM t2 WHERE d IN (1, 2, 3)AND t1.a=t2.c
- );
-} {
- SEARCH t1 USING INTEGER PRIMARY KEY
-} {
- 1 one 3 three 5 five
-}
-
-do_execsql_eqp_test 1.7 {
- SELECT t1.* FROM t1 WHERE EXISTS(
- SELECT * FROM t2 WHERE d IN (1, 2, 3)AND t1.a=t2.c
- );
-} {
- SEARCH t1 USING INTEGER PRIMARY KEY
-} {
- 1 one 3 three 5 five
-}
-
-#-------------------------------------------------------------------------
-#
-reset_db
-do_execsql_test 2.0 {
- CREATE TABLE t3(a TEXT PRIMARY KEY, b TEXT, x INT) WITHOUT ROWID;
- CREATE TABLE t4(c TEXT COLLATE nocase, y INT);
-
- INSERT INTO t3 VALUES('one', 'i', 1);
- INSERT INTO t3 VALUES('two', 'ii', 2);
- INSERT INTO t3 VALUES('three', 'iii', 3);
- INSERT INTO t3 VALUES('four', 'iv', 4);
- INSERT INTO t3 VALUES('five', 'v', 5);
-
- INSERT INTO t4 VALUES('FIVE',5), ('four',4), ('TWO',2), ('one',1);
-}
-
-do_execsql_test 2.1 { SELECT a FROM t3, t4 WHERE a=c } {four one}
-do_execsql_test 2.2 { SELECT a FROM t3, t4 WHERE c=a } {five four one two}
-
-do_execsql_eqp_test 2.3 {
- SELECT a FROM t3 WHERE EXISTS (SELECT 1 FROM t4 WHERE a=c)
-} {
- SEARCH t3 USING PRIMARY KEY
-} {
- four one
-}
-
-do_execsql_eqp_test 2.4 {
- SELECT a FROM t3 WHERE EXISTS (SELECT 1 FROM t4 WHERE c=a)
-} {
- SCAN t3
-} {
- five four one two
-}
-
-do_execsql_test 2.5 {
- CREATE INDEX t3anc ON t3(a COLLATE nocase, x);
-}
-
-do_execsql_eqp_test 2.6 {
- SELECT a FROM t3 WHERE EXISTS (SELECT 1 FROM t4 WHERE c=a)
-} {
- SEARCH t3 USING COVERING INDEX t3anc
-} {
- five four one two
-}
-do_execsql_test 2.6a {
- SELECT a FROM t3 WHERE EXISTS (SELECT 1 FROM t4 WHERE (c,y)=(a,x))
-} {five four one two}
-
-do_execsql_eqp_test 2.7 {
- SELECT a FROM t3 WHERE EXISTS (SELECT 1 FROM t4 WHERE a=c)
-} {
- SEARCH t3 USING PRIMARY KEY
-} {
- four one
-}
-do_execsql_test 2.7a {
- SELECT a FROM t3 WHERE EXISTS (SELECT 1 FROM t4 WHERE (a,x)=(c,y))
-} {
- four one
-}
-
-do_execsql_test 2.7b {
- SELECT a FROM t3 WHERE EXISTS (SELECT 1 FROM t4 WHERE (a,x)=(c,y) LIMIT 1)
-} {
- four one
-}
-
-# EXISTS clauses using vector expressions in the WHERE clause.
-#
-reset_db
-do_execsql_test 3.0 {
- CREATE TABLE t1(a,b);
- INSERT INTO t1(a,b) VALUES(1,111),(2,222),(8,888);
- CREATE TABLE t2(x INTEGER PRIMARY KEY, y);
- INSERT INTO t2(x,y) VALUES(2,222),(3,333),(7,333);
- SELECT y FROM t2 WHERE EXISTS(SELECT 1 FROM t1 WHERE (x,y)=(a,b));
-} {222}
-do_execsql_test 3.1 {
- SELECT y FROM t2 WHERE EXISTS(SELECT 1 FROM t1 WHERE (a,b)=(x,y));
-} {222}
-do_execsql_test 3.2 {
- SELECT y FROM t2 WHERE EXISTS(SELECT 1 FROM t1 WHERE (x,b)=(a,y));
-} {222}
-
-
-
-
-
-finish_test
diff --git a/test/existsfault.test b/test/existsfault.test
deleted file mode 100644
index 4a33eeb35..000000000
--- a/test/existsfault.test
+++ /dev/null
@@ -1,51 +0,0 @@
-# 2021 January 15
-#
-# 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 file is testing cases where EXISTS expressions are
-# transformed to IN() expressions by where.c
-#
-
-set testdir [file dirname $argv0]
-source $testdir/tester.tcl
-set testprefix existsfault
-
-do_execsql_test 1 {
- CREATE TABLE t1(a PRIMARY KEY, b);
- INSERT INTO t1 VALUES(1, 'one');
- INSERT INTO t1 VALUES(2, 'two');
- INSERT INTO t1 VALUES(3, 'three');
- INSERT INTO t1 VALUES(4, 'four');
- INSERT INTO t1 VALUES(5, 'five');
- INSERT INTO t1 VALUES(6, 'six');
- INSERT INTO t1 VALUES(7, 'seven');
-
- CREATE TABLE t2(c INTEGER, d INTEGER);
- INSERT INTO t2 VALUES(1, 1);
- INSERT INTO t2 VALUES(3, 2);
- INSERT INTO t2 VALUES(5, 3);
- INSERT INTO t2 VALUES(7, 4);
-}
-faultsim_save_and_close
-
-do_faultsim_test 1 -prep {
- faultsim_restore_and_reopen
-} -body {
- execsql {
- SELECT t1.* FROM t1 WHERE EXISTS(
- SELECT * FROM t2 WHERE t2.c=t1.a AND d IN (1, 2, 3)
- )
- }
-} -test {
- faultsim_test_result {0 {1 one 3 three 5 five}}
-}
-
-
-finish_test
diff --git a/test/fuzzcheck.c b/test/fuzzcheck.c
index e7fa5261b..6ec2f8460 100644
--- a/test/fuzzcheck.c
+++ b/test/fuzzcheck.c
@@ -1784,14 +1784,16 @@ int main(int argc, char **argv){
char zLine[2000];
while( rc==0 && fgets(zLine,sizeof(zLine),stdin)!=0 ){
size_t kk = strlen(zLine);
- while( kk>0 && (zLine[kk]=='\n' || zLine[kk]=='\r')) kk--;
+ while( kk>0 && zLine[kk-1]<=' ' ) kk--;
sqlite3_bind_text(pStmt, 1, zLine, kk, SQLITE_STATIC);
+ if( verboseFlag ) printf("loading %.*s\n", (int)kk, zLine);
sqlite3_step(pStmt);
rc = sqlite3_reset(pStmt);
if( rc ) fatalError("insert failed for %s", zLine);
}
}else{
sqlite3_bind_text(pStmt, 1, argv[i], -1, SQLITE_STATIC);
+ if( verboseFlag ) printf("loading %s\n", argv[i]);
sqlite3_step(pStmt);
rc = sqlite3_reset(pStmt);
if( rc ) fatalError("insert failed for %s", argv[i]);
diff --git a/test/fuzzdata8.db b/test/fuzzdata8.db
index 1601b1edb..a55217759 100644
--- a/test/fuzzdata8.db
+++ b/test/fuzzdata8.db
Binary files differ
diff --git a/test/in6.test b/test/in6.test
index 3719a6cbf..f477f60ef 100644
--- a/test/in6.test
+++ b/test/in6.test
@@ -97,4 +97,23 @@ do_execsql_test in6-3.110 {
SELECT quote(v5) FROM v0 LEFT JOIN v3 ON v4 = NULL AND v5 IN(0);
} {NULL}
+# 2021-04-29 forum https://sqlite.org/forum/forumpost/6a3ec138e9
+# An early OP_IsNull bypass might skip over the OP_Affinity and
+# cause the OP_IfNoHope to jump on a false-positive, resulting in
+# incomplete output.
+#
+reset_db
+do_execsql_test in6-3.120 {
+ CREATE TABLE t1(a TEXT, b TEXT);
+ INSERT INTO t1 VALUES(null,10),(0,10),(10,10);
+ CREATE INDEX t1ab ON t1(a,b);
+ SELECT quote(a), quote(b), '|' FROM t1 WHERE b in (SELECT a FROM t1) AND a=0;
+} {'0' '10' |}
+do_execsql_test in6-3.130 {
+ CREATE TABLE t2(x TEXT);
+ INSERT INTO t2(x) VALUES(NULL),(0),(10);
+ SELECT quote(x), quote(a), quote(b), 'x'
+ FROM t2 LEFT JOIN t1 ON a=x AND b in (null,0,10);
+} {NULL NULL NULL x '0' '0' '10' x '10' '10' '10' x}
+
finish_test
diff --git a/test/optfuzz.c b/test/optfuzz.c
index 1992acac3..2acb0ce35 100644
--- a/test/optfuzz.c
+++ b/test/optfuzz.c
@@ -26,7 +26,6 @@
*/
#define SQLITE_THREADSAFE 0
#define SQLITE_OMIT_LOAD_EXTENSION 1
-#define SQLITE_ENABLE_DESERIALIZE 1
#include "sqlite3.c"
/* Content of the read-only test database */
diff --git a/test/releasetest.tcl b/test/releasetest.tcl
index 957be1b6f..da6113a19 100755
--- a/test/releasetest.tcl
+++ b/test/releasetest.tcl
@@ -50,7 +50,6 @@ array set ::Configs [strip_comments {
-O2
--disable-amalgamation --disable-shared
--enable-session
- -DSQLITE_ENABLE_DESERIALIZE
}
"Sanitize" {
CC=clang -fsanitize=undefined
@@ -180,7 +179,6 @@ array set ::Configs [strip_comments {
-DSQLITE_OMIT_TRACE=1
-DSQLITE_TEMP_STORE=3
-DSQLITE_THREADSAFE=2
- -DSQLITE_ENABLE_DESERIALIZE=1
--enable-json1 --enable-fts5 --enable-session
}
"Locking-Style" {
diff --git a/test/releasetest_data.tcl b/test/releasetest_data.tcl
index 62c1e55aa..00be20228 100644
--- a/test/releasetest_data.tcl
+++ b/test/releasetest_data.tcl
@@ -51,7 +51,6 @@ array set ::Configs [strip_comments {
-O2
--disable-amalgamation --disable-shared
--enable-session
- -DSQLITE_ENABLE_DESERIALIZE
}
"Sanitize" {
CC=clang -fsanitize=address,undefined
@@ -188,7 +187,6 @@ array set ::Configs [strip_comments {
-DSQLITE_OMIT_TRACE=1
-DSQLITE_TEMP_STORE=3
-DSQLITE_THREADSAFE=2
- -DSQLITE_ENABLE_DESERIALIZE=1
--enable-json1 --enable-fts5 --enable-session
}
"Locking-Style" {
@@ -629,5 +627,3 @@ if {[string match ${cmd}* configurations] && $n==0} {
} else {
usage
}
-
-
diff --git a/test/returning1.test b/test/returning1.test
index 25aaff43e..dc4655231 100644
--- a/test/returning1.test
+++ b/test/returning1.test
@@ -224,4 +224,98 @@ do_execsql_test 10.4 {
SELECT * FROM log;
} {}
+# 2021-04-27 dbsqlfuzz 78b9400770ef8cc7d9427dfba26f4fcf46ea7dc2
+# Returning clauses on TEMP tables with triggers.
+#
+reset_db
+do_execsql_test 11.1 {
+ CREATE TEMP TABLE t1(a,b);
+ CREATE TEMP TABLE t2(c,d);
+ CREATE TEMP TABLE t3(e,f);
+ CREATE TEMP TABLE log(op,x,y);
+ CREATE TEMP TRIGGER t1r1 AFTER INSERT ON t1 BEGIN
+ INSERT INTO log(op,x,y) VALUES('I1',new.a,new.b);
+ END;
+ CREATE TEMP TRIGGER t1r2 BEFORE DELETE ON t1 BEGIN
+ INSERT INTO log(op,x,y) VALUES('D1',old.a,old.b);
+ END;
+ CREATE TEMP TRIGGER t2r3 AFTER UPDATE ON t1 BEGIN
+ INSERT INTO log(op,x,y) VALUES('U1',new.a,new.b);
+ END;
+ CREATE TEMP TRIGGER t2r1 BEFORE INSERT ON t2 BEGIN
+ INSERT INTO log(op,x,y) VALUES('I2',new.c,new.d);
+ END;
+ CREATE TEMP TRIGGER t3r1 AFTER DELETE ON t3 BEGIN
+ INSERT INTO log(op,x,y) VALUES('D3',old.e,old.f);
+ END;
+ CREATE TEMP TRIGGER t3r2 BEFORE UPDATE ON t3 BEGIN
+ INSERT INTO log(op,x,y) VALUES('U3',new.e,new.f);
+ END;
+ INSERT INTO t1(a,b) VALUES(1,2),('happy','glad') RETURNING a, b, '|';
+} {1 2 | happy glad |}
+do_execsql_test 11.2 {
+ UPDATE t1 SET b=9 WHERE a=1 RETURNING a, b, 'x';
+} {1 9 x}
+do_execsql_test 11.3 {
+ DELETE FROM t1 WHERE a<>'xray' RETURNING a, b, '@';
+} {1 9 @ happy glad @}
+do_execsql_test 11.4 {
+ SELECT * FROM log;
+ DELETE FROM log;
+} {I1 1 2 I1 happy glad U1 1 9 D1 1 9 D1 happy glad}
+do_execsql_test 11.5 {
+ INSERT INTO t2 VALUES('bravo','charlie') RETURNING d, c, 'z';
+} {charlie bravo z}
+do_execsql_test 11.6 {
+ SELECT * FROM log;
+ DELETE FROM log;
+} {I2 bravo charlie}
+do_execsql_test 11.7 {
+ INSERT INTO t3(e) VALUES(1),(2),(3) RETURNING 'I', e;
+ UPDATE t3 SET f=e+100 RETURNING 'U', e, f;
+ DELETE FROM t3 WHERE f>100 RETURNING 'D', e, f;
+} {I 1 I 2 I 3 U 1 101 U 2 102 U 3 103 D 1 101 D 2 102 D 3 103}
+do_execsql_test 11.6 {
+ SELECT * FROM log;
+ DELETE FROM log;
+} {U3 1 101 U3 2 102 U3 3 103 D3 1 101 D3 2 102 D3 3 103}
+
+reset_db
+do_execsql_test 11.11 {
+ CREATE TEMP TABLE t1(a,b);
+ CREATE TRIGGER r1 BEFORE INSERT ON t1 BEGIN SELECT 1; END;
+ DELETE FROM t1 RETURNING *;
+ DROP TRIGGER r1;
+ INSERT INTO t1 VALUES(5,30);
+} {}
+do_execsql_test 11.12 {
+ SELECT * FROM t1;
+} {5 30}
+
+# RETURNING column names are dequoted.
+# https://sqlite.org/forum/forumpost/033daf0b32
+#
+reset_db
+do_test 12.1 {
+ db eval {CREATE TABLE t1(x INT, y INT)}
+ unset -nocomplain cname
+ db eval {INSERT INTO t1(x) VALUES(1) RETURNING "x";} cname {}
+ lsort [array names cname]
+} {* x}
+do_test 12.2 {
+ unset -nocomplain cname
+ db eval {INSERT INTO t1(x) VALUES(2) RETURNING [x];} cname {}
+ lsort [array names cname]
+} {* x}
+do_test 12.3 {
+ unset -nocomplain cname
+ db eval {INSERT INTO t1(x) VALUES(3) RETURNING x AS [xyz];} cname {}
+ lsort [array names cname]
+} {* xyz}
+do_test 12.4 {
+ unset -nocomplain cname
+ db eval {INSERT INTO t1(x,y) VALUES(4,5) RETURNING "x"+"y";} cname {}
+ lsort [array names cname]
+} {{"x"+"y"} *}
+
finish_test
diff --git a/test/threadtest5.c b/test/threadtest5.c
new file mode 100644
index 000000000..6e6610ff6
--- /dev/null
+++ b/test/threadtest5.c
@@ -0,0 +1,339 @@
+/*
+** 2021-05-12
+**
+** 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.
+**
+*************************************************************************
+**
+** Testing threading behavior when multiple database connections in separate
+** threads of the same process are all talking to the same database file.
+**
+** For best results, ensure that SQLite is compiled with HAVE_USLEEP=1
+**
+** Only works on unix platforms.
+**
+** Usage:
+**
+** ./threadtest5 ?DATABASE?
+**
+** If DATABASE is omitted, it defaults to using file:/mem?vfs=memdb.
+*/
+#include "sqlite3.h"
+#include <pthread.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+
+/* Name of the in-memory database */
+static char *zDbName = 0;
+
+/* True for debugging */
+static int eVerbose = 0;
+
+/* If rc is not SQLITE_OK, then print an error message and stop
+** the test.
+*/
+static void error_out(int rc, const char *zCtx, int lineno){
+ if( rc!=SQLITE_OK ){
+ fprintf(stderr, "error %d at %d in \"%s\"\n", rc, lineno, zCtx);
+ exit(-1);
+ }
+}
+
+#if 0
+/* Return the number of milliseconds since the Julian epoch (-4714-11-24).
+*/
+static sqlite3_int64 gettime(void){
+ sqlite3_int64 tm;
+ sqlite3_vfs *pVfs = sqlite3_vfs_find(0);
+ pVfs->xCurrentTimeInt64(pVfs, &tm);
+ return tm;
+}
+#endif
+
+/* Run the SQL in the second argument.
+*/
+static int exec(
+ sqlite3 *db,
+ const char *zId,
+ int lineno,
+ const char *zFormat,
+ ...
+){
+ int rc;
+ va_list ap;
+ char *zSql;
+ va_start(ap, zFormat);
+ zSql = sqlite3_vmprintf(zFormat, ap);
+ va_end(ap);
+ if( eVerbose){
+ printf("%s:%d: [%s]\n", zId, lineno, zSql);
+ fflush(stdout);
+ }
+ rc = sqlite3_exec(db, zSql, 0, 0, 0);
+ if( rc && eVerbose ){
+ printf("%s:%d: return-code %d\n", zId, lineno, rc);
+ fflush(stdout);
+ }
+ sqlite3_free(zSql);
+ return rc;
+}
+
+/* Generate a perpared statement from the input SQL
+*/
+static sqlite3_stmt *prepare(
+ sqlite3 *db,
+ const char *zId,
+ int lineno,
+ const char *zFormat,
+ ...
+){
+ int rc;
+ va_list ap;
+ char *zSql;
+ sqlite3_stmt *pStmt = 0;
+ va_start(ap, zFormat);
+ zSql = sqlite3_vmprintf(zFormat, ap);
+ va_end(ap);
+ if( eVerbose){
+ printf("%s:%d: [%s]\n", zId, lineno, zSql);
+ fflush(stdout);
+ }
+
+ rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
+ if( rc ){
+ printf("%s:%d: ERROR - %s\n", zId, lineno, sqlite3_errmsg(db));
+ exit(-1);
+ }
+ sqlite3_free(zSql);
+ return pStmt;
+}
+
+/*
+** Wait for table zTable to exist in the schema.
+*/
+static void waitOnTable(sqlite3 *db, const char *zWorker, const char *zTable){
+ while(1){
+ int eFound = 0;
+ sqlite3_stmt *q = prepare(db, zWorker, __LINE__,
+ "SELECT 1 FROM sqlite_schema WHERE name=%Q", zTable);
+ if( sqlite3_step(q)==SQLITE_ROW && sqlite3_column_int(q,0)!=0 ){
+ eFound = 1;
+ }
+ sqlite3_finalize(q);
+ if( eFound ) return;
+ sqlite3_sleep(1);
+ }
+}
+
+/*
+** Return true if x is a prime number
+*/
+static int isPrime(int x){
+ int i;
+ if( x<2 ) return 1;
+ for(i=2; i*i<=x; i++){
+ if( (x%i)==0 ) return 0;
+ }
+ return 1;
+}
+
+/* Each worker thread runs an instance of the following */
+static void *worker(void *pArg){
+ int rc;
+ const char *zName = (const char*)pArg;
+ sqlite3 *db = 0;
+
+ if( eVerbose ){
+ printf("%s: startup\n", zName);
+ fflush(stdout);
+ }
+
+ rc = sqlite3_open(zDbName, &db);
+ error_out(rc, "sqlite3_open", __LINE__);
+ sqlite3_busy_timeout(db, 2000);
+
+ while( 1 ){
+ sqlite3_stmt *q1;
+ int tid = -1;
+ q1 = prepare(db, zName, __LINE__,
+ "UPDATE task SET doneby=%Q"
+ " WHERE tid=(SELECT tid FROM task WHERE doneby IS NULL LIMIT 1)"
+ "RETURNING tid", zName
+ );
+ if( sqlite3_step(q1)==SQLITE_ROW ){
+ tid = sqlite3_column_int(q1,0);
+ }
+ sqlite3_finalize(q1);
+ if( tid<0 ) break;
+ if( eVerbose ){
+ printf("%s: starting task %d\n", zName, tid);
+ fflush(stdout);
+ }
+ if( tid==1 ){
+ exec(db, zName, __LINE__,
+ "CREATE TABLE IF NOT EXISTS p1(x INTEGER PRIMARY KEY);"
+ );
+ }else if( tid>=2 && tid<=51 ){
+ int a, b, i;
+ waitOnTable(db, zName, "p1");
+ a = (tid-2)*200 + 1;
+ b = a+200;
+ for(i=a; i<b; i++){
+ if( isPrime(i) ){
+ exec(db, zName, __LINE__,
+ "INSERT INTO p1(x) VALUES(%d)", i);
+ }
+ }
+ }else if( tid==52 ){
+ exec(db, zName, __LINE__,
+ "CREATE TABLE IF NOT EXISTS p2(x INTEGER PRIMARY KEY);"
+ "WITH RECURSIVE"
+ " c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<10000)"
+ "INSERT INTO p2(x) SELECT x FROM c;"
+ );
+ }else if( tid>=53 && tid<=62 ){
+ int a, b, i;
+ waitOnTable(db, zName, "p2");
+ a = (tid-53)*10 + 2;
+ b = a+9;
+ for(i=a; i<=b; i++){
+ exec(db, zName, __LINE__,
+ "DELETE FROM p2 WHERE x>%d AND (x %% %d)==0", i, i);
+ }
+ }
+ if( eVerbose ){
+ printf("%s: completed task %d\n", zName, tid);
+ fflush(stdout);
+ }
+ sqlite3_sleep(1);
+ }
+
+ sqlite3_close(db);
+
+ if( eVerbose ){
+ printf("%s: exit\n", zName);
+ fflush(stdout);
+ }
+ return 0;
+}
+
+/* Print a usage comment and die */
+static void usage(const char *argv0){
+ printf("Usage: %s [options]\n", argv0);
+ printf(
+ " -num-workers N Run N worker threads\n"
+ " -v Debugging output\n"
+ );
+ exit(1);
+}
+
+/* Maximum number of threads */
+#define MX_WORKER 100
+
+/*
+** Main routine
+*/
+int main(int argc, char **argv){
+ int i;
+ int nWorker = 4;
+ int rc;
+ sqlite3 *db = 0;
+ sqlite3_stmt *q;
+ pthread_t aWorker[MX_WORKER];
+ char aWorkerName[MX_WORKER][8];
+
+ for(i=1; i<argc; i++){
+ const char *zArg = argv[i];
+ if( zArg[0]!='-' ){
+ if( zDbName==0 ){
+ zDbName = argv[i];
+ continue;
+ }
+ printf("unknown argument: %s\n", zArg);
+ usage(argv[0]);
+ }
+ if( zArg[1]=='-' ) zArg++;
+ if( strcmp(zArg, "-v")==0 ){
+ eVerbose = 1;
+ continue;
+ }
+ if( strcmp(zArg, "-num-workers")==0 && i+1<argc ){
+ nWorker = atoi(argv[++i]);
+ if( nWorker<1 || nWorker>MX_WORKER ){
+ printf("number of threads must be between 1 and %d\n", MX_WORKER);
+ exit(1);
+ }
+ continue;
+ }
+ printf("unknown option: %s\n", argv[i]);
+ usage(argv[0]);
+ }
+ if( zDbName==0 ) zDbName = "file:/mem?vfs=memdb";
+
+ sqlite3_config(SQLITE_CONFIG_URI, (int)1);
+ rc = sqlite3_open(zDbName, &db);
+ error_out(rc, "sqlite3_open", __LINE__);
+
+ rc = exec(db, "SETUP", __LINE__,
+ "DROP TABLE IF EXISTS task;\n"
+ "DROP TABLE IF EXISTS p1;\n"
+ "DROP TABLE IF EXISTS p2;\n"
+ "DROP TABLE IF EXISTS verify;\n"
+ "CREATE TABLE IF NOT EXISTS task(\n"
+ " tid INTEGER PRIMARY KEY,\n"
+ " doneby TEXT\n"
+ ");\n"
+ "WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<100)"
+ "INSERT INTO task(tid) SELECT x FROM c;\n"
+ );
+ error_out(rc, "sqlite3_exec", __LINE__);
+
+ for(i=0; i<nWorker; i++){
+ sqlite3_snprintf(sizeof(aWorkerName[i]), aWorkerName[i],
+ "W%02d", i);
+ pthread_create(&aWorker[i], 0, worker, aWorkerName[i]);
+ }
+ for(i=0; i<nWorker; i++){
+ pthread_join(aWorker[i], 0);
+ }
+
+ for(i=0; i<nWorker; i++){
+ q = prepare(db, "MAIN", __LINE__,
+ "SELECT group_concat(tid,',') FROM task WHERE doneby=%Q",
+ aWorkerName[i]);
+ if( sqlite3_step(q)==SQLITE_ROW ){
+ printf("%s: %s\n", aWorkerName[i], sqlite3_column_text(q,0));
+ }
+ sqlite3_finalize(q);
+ }
+ q = prepare(db, "MAIN", __LINE__, "SELECT count(*) FROM p2");
+ if( sqlite3_step(q)!=SQLITE_ROW || sqlite3_column_int(q,0)<10 ){
+ printf("incorrect result\n");
+ exit(-1);
+ }
+ sqlite3_finalize(q);
+ q = prepare(db, "MAIN", __LINE__, "SELECT x FROM p1 EXCEPT SELECT x FROM p2");
+ if( sqlite3_step(q)==SQLITE_ROW ){
+ printf("incorrect result\n");
+ exit(-1);
+ }
+ sqlite3_finalize(q);
+ q = prepare(db, "MAIN", __LINE__, "SELECT x FROM p2 EXCEPT SELECT x FROM p1");
+ if( sqlite3_step(q)==SQLITE_ROW ){
+ printf("incorrect result\n");
+ exit(-1);
+ }
+ sqlite3_finalize(q);
+ printf("OK\n");
+
+ sqlite3_close(db);
+ return 0;
+}
diff --git a/test/transitive1.test b/test/transitive1.test
index 951092009..875533849 100644
--- a/test/transitive1.test
+++ b/test/transitive1.test
@@ -353,4 +353,31 @@ do_execsql_test transitive1-570eqp {
SELECT * FROM c1 WHERE x=y AND z=y AND z='abc';
} {/SEARCH c1 USING INDEX c1x/}
+# 2021-05-04 forum https://sqlite.org/forum/forumpost/eb8613976a
+reset_db
+do_execsql_test transitive1-600 {
+ CREATE TABLE t0(a0 INT, b1 INT);
+ CREATE INDEX t0b1 ON t0(b1);
+ CREATE TABLE t1(w,x,y,z3 INT);
+ INSERT INTO t0(a0, b1) VALUES (0,1);
+ INSERT INTO t1(w,x,y,z3) VALUES (7,8,9,1);
+} {}
+do_execsql_test transitive1-610 {
+ SELECT ALL * FROM t0,t1 WHERE b1=z3 AND a0=z3;
+} {}
+do_execsql_test transitive1-620 {
+ SELECT ALL * FROM t0,t1 WHERE likely(b1=z3) AND a0=z3;
+} {}
+do_execsql_test transitive1-630 {
+ DROP TABLE t0;
+ DROP TABLE t1;
+ CREATE TABLE t0(c0 INT, c1 INT UNIQUE);
+ CREATE TABLE t1(c0 INT);
+ INSERT INTO t0(c0, c1) VALUES (0, 1);
+ INSERT INTO t1(c0) VALUES (1);
+ SELECT ALL * FROM t1 NATURAL JOIN t0 WHERE (t1.c0=t0.c1);
+ SELECT ALL * FROM t1 NATURAL JOIN t0 WHERE (likely(t1.c0=t0.c1));
+ SELECT ALL * FROM t1,t0 WHERE (likely(t1.c0=t0.c1) AND t1.c0=t0.c0);
+} {}
+
finish_test
diff --git a/test/vtab1.test b/test/vtab1.test
index e8891a632..3d2e23336 100644
--- a/test/vtab1.test
+++ b/test/vtab1.test
@@ -983,6 +983,7 @@ do_test vtab1.10-5 {
proc match_func {args} {return ""}
do_test vtab1.10-6 {
set echo_module ""
+ sqlite_delete_function db match
db function match match_func
execsql {
SELECT * FROM e WHERE match('pattern', rowid, 'pattern2');
diff --git a/test/where9.test b/test/where9.test
index cb52b2b37..429708f1f 100644
--- a/test/where9.test
+++ b/test/where9.test
@@ -982,6 +982,23 @@ do_test where9-10.2 {
}
} {1 {} 1}
-
+# dbsqlfuzz 9df1d53c24c4c96af0dae15ee764897af415ac76
+# The MULTI-INDEX OR processing evaluates the same WHERE-clause sub-expression
+# twice. But if that sub-expression contains a UNION ALL SELECT statement
+# subject to query flattening, the sub-expression might be transformed in a
+# way that it can only be code-generated once. An assert() will fail on
+# the second attempt to generate code from the same sub-expression.
+# The solution is to make a copy of sub-expressions used by MULTI-INDEX OR
+#
+reset_db
+do_execsql_test where9-11.1 {
+ CREATE TABLE t1(a INTEGER PRIMARY KEY, b TEXT);
+ CREATE TABLE t2_a(k INTEGER PRIMARY KEY, v TEXT);
+ CREATE TABLE t2_b(k INTEGER PRIMARY KEY, v TEXT);
+ CREATE VIEW t2 AS SELECT * FROM t2_a UNION ALL SELECT * FROM t2_b;
+ SELECT 1 FROM t1 JOIN t1 USING(a)
+ WHERE (a=1)
+ OR (a=2 AND (SELECT 4 FROM t2,(SELECT 5 FROM t1 ORDER BY a) WHERE a));
+} {}
finish_test
diff --git a/test/whereL.test b/test/whereL.test
index 5422ac531..b6f86fc2d 100644
--- a/test/whereL.test
+++ b/test/whereL.test
@@ -28,11 +28,11 @@ do_eqp_test 110 {
QUERY PLAN
`--COMPOUND QUERY
|--LEFT-MOST SUBQUERY
- | |--SEARCH t2 USING INDEX sqlite_autoindex_t2_1 (a=?)
- | `--SEARCH t1 USING INDEX sqlite_autoindex_t1_1 (a=?)
+ | |--SEARCH t1 USING INDEX sqlite_autoindex_t1_1 (a=?)
+ | `--SEARCH t2 USING INDEX sqlite_autoindex_t2_1 (a=?)
`--UNION ALL
- |--SEARCH t3 USING INDEX sqlite_autoindex_t3_1 (a=?)
- `--SEARCH t1 USING INDEX sqlite_autoindex_t1_1 (a=?)
+ |--SEARCH t1 USING INDEX sqlite_autoindex_t1_1 (a=?)
+ `--SEARCH t3 USING INDEX sqlite_autoindex_t3_1 (a=?)
}
# The scan of the t1 table goes first since that enables the ORDER BY
diff --git a/test/window1.test b/test/window1.test
index 604007e51..f4b573d29 100644
--- a/test/window1.test
+++ b/test/window1.test
@@ -1915,11 +1915,59 @@ do_execsql_test 60.1 {
# the Parse object is destroyed.
#
reset_db
-do_execsql_test 61.1 {
+do_catchsql_test 61.1 {
CREATE TABLE t1(a);
INSERT INTO t1 VALUES(5),(NULL),('seventeen');
SELECT (SELECT max(x)OVER(ORDER BY x) % min(x)OVER(ORDER BY CASE x WHEN 889 THEN x WHEN x THEN x END)) FROM (SELECT (SELECT sum(CAST(a IN(SELECT (SELECT max(x)OVER(ORDER BY CASE x WHEN 889 THEN 299 WHEN 863 THEN 863 END)) FROM (SELECT (SELECT sum(CAST((SELECT (SELECT max(x)OVER(ORDER BY x) / min(x)OVER(ORDER BY CASE x WHEN 889 THEN 299 WHEN -true THEN 863 END)) FROM (SELECT (SELECT sum(CAST(a IN(SELECT (SELECT max(x) & sum ( a )OVER(ORDER BY CASE x WHEN -8 THEN 299 WHEN 863 THEN 863 END)) FROM (SELECT (SELECT sum(CAST(a AS )) FROM t1) AS x FROM t1)) AS t1 )) FROM t1) AS x FROM t1)) AS x )) FROM t1) AS x FROM t1)) AS real)) FROM t1) AS x FROM t1);
-} {{} {} {}}
+} {0 {{} {} {}}}
+
+foreach tn {1 2} {
+ if {$tn==2} { optimization_control db query-flattener 0 }
+ do_catchsql_test 61.2.$tn {
+ SELECT
+ (SELECT max(x)OVER(ORDER BY x) / min(x) OVER() )
+ FROM (
+ SELECT (SELECT sum(a) FROM t1 ) AS x FROM t1
+ )
+
+ } {0 {1.0 1.0 1.0}}
+}
+
+reset_db
+optimization_control db all 0
+do_execsql_test 61.3.0 {
+ CREATE TABLE t1(a);
+ CREATE TABLE t2(y);
+}
+
+do_execsql_test 61.3.1 {
+ SELECT (
+ SELECT count(a) OVER ( ORDER BY (SELECT sum(y) FROM t2) )
+ + total(a) OVER()
+ )
+ FROM t1
+} {}
+do_execsql_test 61.4.2 {
+ SELECT (
+ SELECT count(a) OVER ( ORDER BY sum(a) )
+ + total(a) OVER()
+ )
+ FROM t1
+} {0.0}
+
+do_catchsql_test 61.4.3 {
+ SELECT
+ sum(a) OVER ( ORDER BY a )
+ FROM t1
+ ORDER BY (SELECT sum(a) FROM t2)
+} {1 {misuse of aggregate: sum()}}
+do_execsql_test 61.4.4 {
+ SELECT
+ sum(a) OVER ( ORDER BY a )
+ FROM t1
+ ORDER BY (SELECT sum(y) FROM t2)
+}
+
#-------------------------------------------------------------------------
reset_db
@@ -2090,6 +2138,25 @@ do_catchsql_test 67.1 {
SELECT nth_value(a,2) OVER w1
WINDOW w1 AS ( ORDER BY ((SELECT 1 FROM v1)) )
)
+} {1 {no such table: v1}}
+
+do_catchsql_test 67.2 {
+ SELECT a,c,b FROM t1 INTERSECT SELECT a,b,c FROM t1 ORDER BY (
+ SELECT nth_value(a,2) OVER w1
+ WINDOW w1 AS ( ORDER BY ((SELECT 1 FROM t2)) )
+ )
} {1 {1st ORDER BY term does not match any column in the result set}}
+# 2021-05-07
+# Do not allow aggregate functions in the ORDER BY clause even if
+# there are window functions in the result set.
+# Forum: /forumpost/540fdfef77
+#
+reset_db
+do_catchsql_test 68.0 {
+ CREATE TABLE t1(a,b);
+ INSERT INTO t1(a,b) VALUES(0,0),(1,1),(2,4),(3,9),(4,99);
+ SELECT rowid, a, b, sum(a)OVER() FROM t1 ORDER BY count(b);
+} {1 {misuse of aggregate: count()}}
+
finish_test
diff --git a/test/window8.tcl b/test/window8.tcl
index a8333f190..69ad0ad26 100644
--- a/test/window8.tcl
+++ b/test/window8.tcl
@@ -418,6 +418,76 @@ execsql_test 7.$tn.9 "
"
}
+==========
+
+execsql_test 8.0 {
+ DROP TABLE IF EXISTS tx;
+ CREATE TABLE tx(a INTEGER PRIMARY KEY);
+ INSERT INTO tx VALUES(1), (2), (3), (4), (5), (6);
+
+ DROP TABLE IF EXISTS map;
+ CREATE TABLE map(v INTEGER PRIMARY KEY, t TEXT);
+ INSERT INTO map VALUES
+ (1, 'odd'), (2, 'even'), (3, 'odd'),
+ (4, 'even'), (5, 'odd'), (6, 'even');
+}
+
+execsql_test 8.1 {
+ SELECT sum(a) OVER (
+ PARTITION BY (
+ SELECT t FROM map WHERE v=a
+ ) ORDER BY a
+ ) FROM tx;
+}
+
+execsql_test 8.2 {
+ SELECT sum(a) OVER win FROM tx
+ WINDOW win AS (
+ PARTITION BY (
+ SELECT t FROM map WHERE v=a
+ ) ORDER BY a
+ );
+}
+
+execsql_test 8.3 {
+ WITH map2 AS (
+ SELECT * FROM map
+ )
+ SELECT sum(a) OVER (
+ PARTITION BY (
+ SELECT t FROM map2 WHERE v=a
+ ) ORDER BY a
+ ) FROM tx;
+}
+
+execsql_test 8.4 {
+ WITH map2 AS (
+ SELECT * FROM map
+ )
+ SELECT sum(a) OVER win FROM tx
+ WINDOW win AS (
+ PARTITION BY (
+ SELECT t FROM map2 WHERE v=a
+ ) ORDER BY a
+ );
+}
+
+==========
+
+execsql_test 9.1 {
+ DROP TABLE IF EXISTS t1;
+ DROP TABLE IF EXISTS t2;
+ CREATE TABLE t1(a INTEGER);
+ CREATE TABLE t2(y INTEGER);
+}
+
+execsql_test 9.2 {
+ SELECT (
+ SELECT max(a) OVER ( ORDER BY (SELECT sum(a) FROM t1) )
+ + min(a) OVER()
+ )
+ FROM t1
+}
finish_test
diff --git a/test/window8.test b/test/window8.test
index ed720ebd4..0c5d39bad 100644
--- a/test/window8.test
+++ b/test/window8.test
@@ -6469,4 +6469,75 @@ do_execsql_test 7.4.9 {
);
} {4 4 4 {} {} {}}
+#==========================================================================
+
+do_execsql_test 8.0 {
+ DROP TABLE IF EXISTS tx;
+ CREATE TABLE tx(a INTEGER PRIMARY KEY);
+ INSERT INTO tx VALUES(1), (2), (3), (4), (5), (6);
+
+ DROP TABLE IF EXISTS map;
+ CREATE TABLE map(v INTEGER PRIMARY KEY, t TEXT);
+ INSERT INTO map VALUES
+ (1, 'odd'), (2, 'even'), (3, 'odd'),
+ (4, 'even'), (5, 'odd'), (6, 'even');
+} {}
+
+do_execsql_test 8.1 {
+ SELECT sum(a) OVER (
+ PARTITION BY (
+ SELECT t FROM map WHERE v=a
+ ) ORDER BY a
+ ) FROM tx;
+} {2 6 12 1 4 9}
+
+do_execsql_test 8.2 {
+ SELECT sum(a) OVER win FROM tx
+ WINDOW win AS (
+ PARTITION BY (
+ SELECT t FROM map WHERE v=a
+ ) ORDER BY a
+ );
+} {2 6 12 1 4 9}
+
+do_execsql_test 8.3 {
+ WITH map2 AS (
+ SELECT * FROM map
+ )
+ SELECT sum(a) OVER (
+ PARTITION BY (
+ SELECT t FROM map2 WHERE v=a
+ ) ORDER BY a
+ ) FROM tx;
+} {2 6 12 1 4 9}
+
+do_execsql_test 8.4 {
+ WITH map2 AS (
+ SELECT * FROM map
+ )
+ SELECT sum(a) OVER win FROM tx
+ WINDOW win AS (
+ PARTITION BY (
+ SELECT t FROM map2 WHERE v=a
+ ) ORDER BY a
+ );
+} {2 6 12 1 4 9}
+
+#==========================================================================
+
+do_execsql_test 9.1 {
+ DROP TABLE IF EXISTS t1;
+ DROP TABLE IF EXISTS t2;
+ CREATE TABLE t1(a INTEGER);
+ CREATE TABLE t2(y INTEGER);
+} {}
+
+do_execsql_test 9.2 {
+ SELECT (
+ SELECT max(a) OVER ( ORDER BY (SELECT sum(a) FROM t1) )
+ + min(a) OVER()
+ )
+ FROM t1
+} {}
+
finish_test
diff --git a/test/without_rowid1.test b/test/without_rowid1.test
index 02a089610..e4e69eb72 100644
--- a/test/without_rowid1.test
+++ b/test/without_rowid1.test
@@ -452,5 +452,18 @@ do_execsql_test 13.10 {
PRAGMA integrity_check;
SELECT * FROM t0, t1;
} {ok abc xyz abc xyz}
+
+# 2021-05-13 https://sqlite.org/forum/forumpost/6c8960f545
+reset_db
+do_execsql_test 14.1 {
+ CREATE TABLE t1(a INT PRIMARY KEY) WITHOUT ROWID;
+ INSERT INTO t1(a) VALUES(10);
+ ALTER TABLE t1 ADD COLUMN b INT;
+ SELECT * FROM t1 WHERE a=20 OR (a=10 AND b=10);
+} {}
+do_execsql_test 14.2 {
+ CREATE TABLE dual AS SELECT 'X' AS dummy;
+ EXPLAIN QUERY PLAN SELECT * FROM dual, t1 WHERE a=10 AND b=10;
+} {~/b=/}
finish_test
diff --git a/tool/mkopcodeh.tcl b/tool/mkopcodeh.tcl
index 57017364a..cc372e404 100644
--- a/tool/mkopcodeh.tcl
+++ b/tool/mkopcodeh.tcl
@@ -145,7 +145,9 @@ foreach name {OP_Noop OP_Explain OP_Abortable} {
incr nOp
}
-# The following are the opcodes that are processed by resolveP2Values()
+# The following are the opcodes that receive special processing in the
+# resolveP2Values() routine. Update this list whenever new cases are
+# added to the pOp->opcode switch within resolveP2Values().
#
set rp2v_ops {
OP_Transaction
@@ -157,13 +159,11 @@ set rp2v_ops {
OP_VUpdate
OP_VFilter
OP_Next
- OP_NextIfOpen
OP_SorterNext
OP_Prev
- OP_PrevIfOpen
}
-# Assign small values to opcodes that are processed by resolveP2Values()
+# Assign the smallest values to opcodes that are processed by resolveP2Values()
# to make code generation for the switch() statement smaller and faster.
#
set cnt -1
@@ -177,6 +177,7 @@ for {set i 0} {$i<$nOp} {incr i} {
set def($cnt) $name
}
}
+set mxCase1 $cnt
# Assign the next group of values to JUMP opcodes
#
@@ -311,7 +312,7 @@ for {set i 0} {$i<=$max} {incr i} {
}
puts "\175"
puts ""
-puts "/* The sqlite3P2Values() routine is able to run faster if it knows"
+puts "/* The resolve3P2Values() routine is able to run faster if it knows"
puts "** the value of the largest JUMP opcode. The smaller the maximum"
puts "** JUMP opcode the better, so the mkopcodeh.tcl script that"
puts "** generated this include file strives to group all JUMP opcodes"
diff --git a/tool/omittest.tcl b/tool/omittest.tcl
index ba16abbbd..9f24d6d3d 100644
--- a/tool/omittest.tcl
+++ b/tool/omittest.tcl
@@ -206,6 +206,7 @@ proc main {argv} {
SQLITE_OMIT_DATETIME_FUNCS \
SQLITE_OMIT_DECLTYPE \
SQLITE_OMIT_DEPRECATED \
+ SQLITE_OMIT_DESERIALIZE \
SQLITE_OMIT_DISKIO \
SQLITE_OMIT_EXPLAIN \
SQLITE_OMIT_FLAG_PRAGMAS \