diff options
author | larrybr <larrybr@noemail.net> | 2021-05-19 19:55:10 +0000 |
---|---|---|
committer | larrybr <larrybr@noemail.net> | 2021-05-19 19:55:10 +0000 |
commit | 4f878f33a981786a5bf3db3372a11cf690260de7 (patch) | |
tree | b8c05ad24cf1596c5b8db1c3b4ae28cfa40ed3d8 | |
parent | 3ec4861c000cc5b26520c248043c18299a749d99 (diff) | |
parent | 1f4f7c7a416801a4e195634b03650191a4a43c7a (diff) | |
download | sqlite-4f878f33a981786a5bf3db3372a11cf690260de7.tar.gz sqlite-4f878f33a981786a5bf3db3372a11cf690260de7.zip |
merge from trunk
FossilOrigin-Name: 19ffe3cfe278a4046f32df56f75080c2377e4c44ad40a02d39db8e7701526204
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 @@ -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 @@ -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); @@ -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 Binary files differindex 1601b1edb..a55217759 100644 --- a/test/fuzzdata8.db +++ b/test/fuzzdata8.db 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 \ |