aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorstephan <stephan@noemail.net>2023-02-06 22:25:18 +0000
committerstephan <stephan@noemail.net>2023-02-06 22:25:18 +0000
commitf8c73aed6716f911d8a19511586751e5b9aa1e9f (patch)
tree8d35e728901da3454cbff9c600fd0bc1602b2ce8
parent87ce1ff7f72621cb8a8a99dc93141d253899eba0 (diff)
parent9f29998d2a8890d58b52d13605324193703525c3 (diff)
downloadsqlite-f8c73aed6716f911d8a19511586751e5b9aa1e9f.tar.gz
sqlite-f8c73aed6716f911d8a19511586751e5b9aa1e9f.zip
Merge trunk into wasi-patches branch.
FossilOrigin-Name: 656d36f50f630da68262469087bad1ac71b10325e233a7963103c8cbc232f61a
-rw-r--r--Makefile.in14
-rw-r--r--Makefile.msc12
-rw-r--r--ext/fts5/fts5_index.c4
-rw-r--r--ext/fts5/test/fts5optimize2.test62
-rw-r--r--ext/misc/base85.c3
-rw-r--r--ext/rbu/rbu1.test3
-rw-r--r--ext/rbu/rbu10.test7
-rw-r--r--ext/rbu/rbu11.test6
-rw-r--r--ext/rbu/rbu12.test6
-rw-r--r--ext/rbu/rbu13.test6
-rw-r--r--ext/rbu/rbu14.test6
-rw-r--r--ext/rbu/rbu3.test9
-rw-r--r--ext/rbu/rbu5.test1
-rw-r--r--ext/rbu/rbu6.test6
-rw-r--r--ext/rbu/rbu7.test6
-rw-r--r--ext/rbu/rbu8.test6
-rw-r--r--ext/rbu/rbu9.test6
-rw-r--r--ext/rbu/rbuA.test6
-rw-r--r--ext/rbu/rbuB.test1
-rw-r--r--ext/rbu/rbuC.test1
-rw-r--r--ext/rbu/rbu_common.tcl9
-rw-r--r--ext/rbu/rbubusy.test2
-rw-r--r--ext/rbu/rbucollate.test6
-rw-r--r--ext/rbu/rbucrash.test12
-rw-r--r--ext/rbu/rbucrash2.test12
-rw-r--r--ext/rbu/rbudiff.test7
-rw-r--r--ext/rbu/rbudor.test6
-rw-r--r--ext/rbu/rbuexlock.test20
-rw-r--r--ext/rbu/rbuexpr.test7
-rw-r--r--ext/rbu/rbufault.test6
-rw-r--r--ext/rbu/rbufault2.test6
-rw-r--r--ext/rbu/rbufault3.test1
-rw-r--r--ext/rbu/rbufault4.test9
-rw-r--r--ext/rbu/rbufts.test6
-rw-r--r--ext/rbu/rbumisc.test6
-rw-r--r--ext/rbu/rbumulti.test3
-rw-r--r--ext/rbu/rbupartial.test3
-rw-r--r--ext/rbu/rbupass.test13
-rw-r--r--ext/rbu/rbuprogress.test1
-rw-r--r--ext/rbu/rburename.test1
-rw-r--r--ext/rbu/rburesume.test7
-rw-r--r--ext/rbu/rbusave.test6
-rw-r--r--ext/rbu/rbusplit.test3
-rw-r--r--ext/rbu/rbutemplimit.test3
-rw-r--r--ext/rbu/rbuvacuum.test1
-rw-r--r--ext/rbu/rbuvacuum2.test1
-rw-r--r--ext/rbu/rbuvacuum3.test1
-rw-r--r--ext/rbu/rbuvacuum4.test2
-rw-r--r--ext/recover/recover1.test12
-rw-r--r--ext/rtree/rtreecheck.test15
-rw-r--r--ext/session/test_session.c3
-rw-r--r--ext/wasm/GNUmakefile447
-rw-r--r--ext/wasm/README-dist.txt37
-rw-r--r--ext/wasm/api/extern-post-js.c-pp.js13
-rw-r--r--ext/wasm/api/pre-js.c-pp.js11
-rw-r--r--ext/wasm/api/sqlite3-api-cleanup.js5
-rw-r--r--ext/wasm/api/sqlite3-api-oo1.js25
-rw-r--r--ext/wasm/api/sqlite3-api-prologue.js10
-rw-r--r--ext/wasm/api/sqlite3-api-worker1.js4
-rw-r--r--ext/wasm/api/sqlite3-vfs-opfs.c-pp.js24
-rw-r--r--ext/wasm/api/sqlite3-worker1-promiser.c-pp.js (renamed from ext/wasm/api/sqlite3-worker1-promiser.js)8
-rw-r--r--ext/wasm/api/sqlite3-worker1.c-pp.js (renamed from ext/wasm/api/sqlite3-worker1.js)4
-rw-r--r--ext/wasm/c-pp.c39
-rw-r--r--ext/wasm/dist.make23
-rw-r--r--ext/wasm/index.html2
-rw-r--r--ext/wasm/tester1-worker.html8
-rw-r--r--ext/wasm/tester1.c-pp.html8
-rw-r--r--ext/wasm/tester1.c-pp.js36
-rw-r--r--ext/wasm/tests/opfs/concurrency/index.html5
-rw-r--r--main.mk6
-rw-r--r--manifest243
-rw-r--r--manifest.uuid2
-rw-r--r--src/analyze.c4
-rw-r--r--src/btree.c4
-rw-r--r--src/dbpage.c19
-rw-r--r--src/os_unix.c36
-rw-r--r--src/pager.c4
-rw-r--r--src/pragma.c19
-rw-r--r--src/resolve.c38
-rw-r--r--src/select.c19
-rw-r--r--src/shell.c.in7
-rw-r--r--src/test7.c718
-rw-r--r--src/test_server.c516
-rw-r--r--src/test_tclsh.c2
-rw-r--r--src/test_thread.c46
-rw-r--r--src/test_vfs.c5
-rw-r--r--src/treeview.c7
-rw-r--r--src/vdbemem.c5
-rw-r--r--src/where.c22
-rw-r--r--src/window.c1
-rw-r--r--test/auth.test18
-rw-r--r--test/bloom1.test36
-rw-r--r--test/cast.test32
-rw-r--r--test/dbpagefault.test4
-rw-r--r--test/distinctagg.test1
-rw-r--r--test/fuzzcheck.c30
-rw-r--r--test/join5.test4
-rw-r--r--test/join8.test2
-rw-r--r--test/memsubsys2.test29
-rw-r--r--test/mutex1.test1
-rw-r--r--test/pager2.test2
-rw-r--r--test/pendingrace.test126
-rw-r--r--test/permutations.test6
-rw-r--r--test/pragma.test24
-rw-r--r--test/quickcheck.test34
-rw-r--r--test/releasetest_data.tcl170
-rw-r--r--test/scanstatus.test44
-rw-r--r--test/scanstatus2.test24
-rw-r--r--test/server1.test180
-rw-r--r--test/shrink.test7
-rw-r--r--test/sort4.test2
-rw-r--r--test/speed1.test2
-rw-r--r--test/speed1p.test2
-rw-r--r--test/sqllimits1.test54
-rw-r--r--test/tester.tcl15
-rw-r--r--test/testrunner.tcl1221
-rw-r--r--test/testrunner_data.tcl143
-rw-r--r--test/vt02.c6
-rw-r--r--test/where.test81
-rw-r--r--test/windowB.test5
-rw-r--r--test/with6.test51
-rw-r--r--tool/showdb.c14
-rw-r--r--tool/showwal.c14
123 files changed, 2497 insertions, 2680 deletions
diff --git a/Makefile.in b/Makefile.in
index 6a6b5a8e1..e5b0e9976 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -373,7 +373,6 @@ TESTSRC = \
$(TOP)/src/test4.c \
$(TOP)/src/test5.c \
$(TOP)/src/test6.c \
- $(TOP)/src/test7.c \
$(TOP)/src/test8.c \
$(TOP)/src/test9.c \
$(TOP)/src/test_autoext.c \
@@ -402,7 +401,6 @@ TESTSRC = \
$(TOP)/src/test_quota.c \
$(TOP)/src/test_rtree.c \
$(TOP)/src/test_schema.c \
- $(TOP)/src/test_server.c \
$(TOP)/src/test_superlock.c \
$(TOP)/src/test_syscall.c \
$(TOP)/src/test_tclsh.c \
@@ -1283,6 +1281,15 @@ tcltest: ./testfixture$(TEXE)
testrunner: testfixture$(TEXE)
./testfixture$(TEXE) $(TOP)/test/testrunner.tcl
+# Runs both fuzztest and testrunner, consecutively.
+#
+devtest: testfixture$(TEXE) fuzztest testrunner
+
+# Testing for a release
+#
+releasetest: testfixture$(TEXE)
+ ./testfixture$(TEXE) $(TOP)/test/testrunner.tcl release
+
# Minimal testing that runs in less than 3 minutes
#
quicktest: ./testfixture$(TEXE)
@@ -1440,9 +1447,6 @@ threadtest: 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
-
# Standard install and cleanup targets
#
lib_install: libsqlite3.la
diff --git a/Makefile.msc b/Makefile.msc
index 98a5a5e1f..884bb1065 100644
--- a/Makefile.msc
+++ b/Makefile.msc
@@ -1485,7 +1485,6 @@ TESTSRC = \
$(TOP)\src\test4.c \
$(TOP)\src\test5.c \
$(TOP)\src\test6.c \
- $(TOP)\src\test7.c \
$(TOP)\src\test8.c \
$(TOP)\src\test9.c \
$(TOP)\src\test_autoext.c \
@@ -1514,7 +1513,6 @@ TESTSRC = \
$(TOP)\src\test_quota.c \
$(TOP)\src\test_rtree.c \
$(TOP)\src\test_schema.c \
- $(TOP)\src\test_server.c \
$(TOP)\src\test_superlock.c \
$(TOP)\src\test_syscall.c \
$(TOP)\src\test_tclsh.c \
@@ -2451,6 +2449,16 @@ tcltest: testfixture.exe
testrunner: testfixture.exe
.\testfixture.exe $(TOP)\test\testrunner.tcl
+# Runs both fuzztest and testrunner, consecutively.
+#
+devtest: testfixture.exe fuzztest testrunner
+
+# Testing for a release
+#
+releasetest: testfixture.exe fuzztest
+ testfixture.exe $(TOP)/test/testrunner.tcl release
+
+
smoketest: $(TESTPROGS)
@set PATH=$(LIBTCLPATH);$(PATH)
.\testfixture.exe $(TOP)\test\main.test $(TESTOPTS)
diff --git a/ext/fts5/fts5_index.c b/ext/fts5/fts5_index.c
index 0c883f020..2ce75c196 100644
--- a/ext/fts5/fts5_index.c
+++ b/ext/fts5/fts5_index.c
@@ -54,6 +54,8 @@
# error "FTS5_MAX_PREFIX_INDEXES is too large"
#endif
+#define FTS5_MAX_LEVEL 64
+
/*
** Details:
**
@@ -4771,7 +4773,7 @@ static Fts5Structure *fts5IndexOptimizeStruct(
pNew->nLevel = pStruct->nLevel+1;
pNew->nRef = 1;
pNew->nWriteCounter = pStruct->nWriteCounter;
- pLvl = &pNew->aLevel[pStruct->nLevel];
+ pLvl = &pNew->aLevel[MIN(pStruct->nLevel, FTS5_MAX_LEVEL-1)];
pLvl->aSeg = (Fts5StructureSegment*)sqlite3Fts5MallocZero(&p->rc, nByte);
if( pLvl->aSeg ){
int iLvl, iSeg;
diff --git a/ext/fts5/test/fts5optimize2.test b/ext/fts5/test/fts5optimize2.test
new file mode 100644
index 000000000..78373e5e4
--- /dev/null
+++ b/ext/fts5/test/fts5optimize2.test
@@ -0,0 +1,62 @@
+# 2014 Dec 20
+#
+# 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.
+#
+#***********************************************************************
+#
+# TESTRUNNER: slow
+#
+
+source [file join [file dirname [info script]] fts5_common.tcl]
+set testprefix fts5optimize2
+
+# If SQLITE_ENABLE_FTS5 is defined, omit this file.
+ifcapable !fts5 {
+ finish_test
+ return
+}
+
+do_execsql_test 1.0 {
+ CREATE VIRTUAL TABLE t1 USING fts5(x);
+ INSERT INTO t1(t1, rank) VALUES('pgsz', 32);
+}
+
+do_test 1.1 {
+ for {set ii 0} {$ii < 1500} {incr ii} {
+ execsql {
+ INSERT INTO t1 VALUES('abc def ghi');
+ INSERT INTO t1 VALUES('jkl mno pqr');
+ INSERT INTO t1(t1) VALUES('optimize');
+ }
+ }
+} {}
+
+do_execsql_test 1.2 {
+ SELECT count(*) FROM t1('mno')
+} {1500}
+
+do_execsql_test 2.0 {
+ CREATE VIRTUAL TABLE t2 USING fts5(x);
+ INSERT INTO t2(t2, rank) VALUES('pgsz', 32);
+}
+
+do_test 2.1 {
+ for {set ii 0} {$ii < 1500} {incr ii} {
+ execsql {
+ INSERT INTO t2 VALUES('abc def ghi');
+ INSERT INTO t2 VALUES('jkl mno pqr');
+ INSERT INTO t2(t2, rank) VALUES('merge', -1);
+ }
+ }
+} {}
+
+do_execsql_test 2.2 {
+ SELECT count(*) FROM t2('mno')
+} {1500}
+
+finish_test
diff --git a/ext/misc/base85.c b/ext/misc/base85.c
index 019136874..5ec136dbc 100644
--- a/ext/misc/base85.c
+++ b/ext/misc/base85.c
@@ -171,7 +171,8 @@ static char* toBase85( u8 *pIn, int nbIn, char *pOut, char *pSep ){
int nCol = 0;
while( nbIn >= 4 ){
int nco = 5;
- unsigned long qbv = (pIn[0]<<24)|(pIn[1]<<16)|(pIn[2]<<8)|pIn[3];
+ unsigned long qbv = (((unsigned long)pIn[0])<<24) |
+ (pIn[1]<<16) | (pIn[2]<<8) | pIn[3];
while( nco > 0 ){
unsigned nqv = (unsigned)(qbv/85UL);
unsigned char dv = qbv - 85UL*nqv;
diff --git a/ext/rbu/rbu1.test b/ext/rbu/rbu1.test
index 9237dbcea..418857d8b 100644
--- a/ext/rbu/rbu1.test
+++ b/ext/rbu/rbu1.test
@@ -11,11 +11,10 @@
#
source [file join [file dirname [info script]] rbu_common.tcl]
+if_no_rbu_support { finish_test ; return }
set ::testprefix rbu1
db close
-sqlite3_shutdown
-sqlite3_config_uri 1
# Create a simple RBU database. That expects to write to a table:
#
diff --git a/ext/rbu/rbu10.test b/ext/rbu/rbu10.test
index aa4db8a29..8705c7b2e 100644
--- a/ext/rbu/rbu10.test
+++ b/ext/rbu/rbu10.test
@@ -10,13 +10,10 @@
#***********************************************************************
#
-if {![info exists testdir]} {
- set testdir [file join [file dirname [info script]] .. .. test]
-}
-source $testdir/tester.tcl
+source [file join [file dirname [info script]] rbu_common.tcl]
+if_no_rbu_support { finish_test ; return }
set ::testprefix rbu10
-
#--------------------------------------------------------------------
# Test that UPDATE commands work even if the input columns are in a
# different order to the output columns.
diff --git a/ext/rbu/rbu11.test b/ext/rbu/rbu11.test
index 5a4219b00..a42163cce 100644
--- a/ext/rbu/rbu11.test
+++ b/ext/rbu/rbu11.test
@@ -10,10 +10,8 @@
#***********************************************************************
#
-if {![info exists testdir]} {
- set testdir [file join [file dirname [info script]] .. .. test]
-}
-source $testdir/tester.tcl
+source [file join [file dirname [info script]] rbu_common.tcl]
+if_no_rbu_support { finish_test ; return }
set ::testprefix rbu11
diff --git a/ext/rbu/rbu12.test b/ext/rbu/rbu12.test
index 7816bfe89..a753ef249 100644
--- a/ext/rbu/rbu12.test
+++ b/ext/rbu/rbu12.test
@@ -10,10 +10,8 @@
#***********************************************************************
#
-if {![info exists testdir]} {
- set testdir [file join [file dirname [info script]] .. .. test]
-}
-source $testdir/tester.tcl
+source [file join [file dirname [info script]] rbu_common.tcl]
+if_no_rbu_support { finish_test ; return }
source $testdir/lock_common.tcl
set ::testprefix rbu12
diff --git a/ext/rbu/rbu13.test b/ext/rbu/rbu13.test
index 624c587cc..9bf2adc6f 100644
--- a/ext/rbu/rbu13.test
+++ b/ext/rbu/rbu13.test
@@ -13,10 +13,8 @@
# for UPDATE statements. This tests RBU's internal UPDATE statement cache.
#
-if {![info exists testdir]} {
- set testdir [file join [file dirname [info script]] .. .. test]
-}
-source $testdir/tester.tcl
+source [file join [file dirname [info script]] rbu_common.tcl]
+if_no_rbu_support { finish_test ; return }
source $testdir/lock_common.tcl
set ::testprefix rbu13
diff --git a/ext/rbu/rbu14.test b/ext/rbu/rbu14.test
index 07f678409..ac5b92c6c 100644
--- a/ext/rbu/rbu14.test
+++ b/ext/rbu/rbu14.test
@@ -13,10 +13,8 @@
# table.
#
-if {![info exists testdir]} {
- set testdir [file join [file dirname [info script]] .. .. test]
-}
-source $testdir/tester.tcl
+source [file join [file dirname [info script]] rbu_common.tcl]
+if_no_rbu_support { finish_test ; return }
source $testdir/lock_common.tcl
set ::testprefix rbu14
diff --git a/ext/rbu/rbu3.test b/ext/rbu/rbu3.test
index da87561fb..4ea6adbcd 100644
--- a/ext/rbu/rbu3.test
+++ b/ext/rbu/rbu3.test
@@ -10,10 +10,8 @@
#***********************************************************************
#
-if {![info exists testdir]} {
- set testdir [file join [file dirname [info script]] .. .. test]
-}
-source $testdir/tester.tcl
+source [file join [file dirname [info script]] rbu_common.tcl]
+if_no_rbu_support { finish_test ; return }
set ::testprefix rbu3
@@ -26,9 +24,6 @@ proc run_rbu {target rbu} {
}
forcedelete test.db-oal rbu.db
-db close
-sqlite3_shutdown
-sqlite3_config_uri 1
reset_db
#--------------------------------------------------------------------
diff --git a/ext/rbu/rbu5.test b/ext/rbu/rbu5.test
index 3696dfb87..2ae69e965 100644
--- a/ext/rbu/rbu5.test
+++ b/ext/rbu/rbu5.test
@@ -13,6 +13,7 @@
#
source [file join [file dirname [info script]] rbu_common.tcl]
+if_no_rbu_support { finish_test ; return }
set ::testprefix rbu5
diff --git a/ext/rbu/rbu6.test b/ext/rbu/rbu6.test
index bb5b17f42..29d4c5e1a 100644
--- a/ext/rbu/rbu6.test
+++ b/ext/rbu/rbu6.test
@@ -13,10 +13,8 @@
# outcome of some other client writing to the database while an RBU update
# is being applied.
-if {![info exists testdir]} {
- set testdir [file join [file dirname [info script]] .. .. test]
-}
-source $testdir/tester.tcl
+source [file join [file dirname [info script]] rbu_common.tcl]
+if_no_rbu_support { finish_test ; return }
set ::testprefix rbu6
proc setup_test {} {
diff --git a/ext/rbu/rbu7.test b/ext/rbu/rbu7.test
index 1e3bc174d..ffe6ebe1b 100644
--- a/ext/rbu/rbu7.test
+++ b/ext/rbu/rbu7.test
@@ -13,10 +13,8 @@
#
-if {![info exists testdir]} {
- set testdir [file join [file dirname [info script]] .. .. test]
-}
-source $testdir/tester.tcl
+source [file join [file dirname [info script]] rbu_common.tcl]
+if_no_rbu_support { finish_test ; return }
set ::testprefix rbu7
# Test index:
diff --git a/ext/rbu/rbu8.test b/ext/rbu/rbu8.test
index c0ccd8c5e..b73bde274 100644
--- a/ext/rbu/rbu8.test
+++ b/ext/rbu/rbu8.test
@@ -12,10 +12,8 @@
# Test the rbu_delta() feature.
#
-if {![info exists testdir]} {
- set testdir [file join [file dirname [info script]] .. .. test]
-}
-source $testdir/tester.tcl
+source [file join [file dirname [info script]] rbu_common.tcl]
+if_no_rbu_support { finish_test ; return }
set ::testprefix rbu8
do_execsql_test 1.0 {
diff --git a/ext/rbu/rbu9.test b/ext/rbu/rbu9.test
index 0efdc1dde..499ff0945 100644
--- a/ext/rbu/rbu9.test
+++ b/ext/rbu/rbu9.test
@@ -12,10 +12,8 @@
# Test RBU with virtual tables. And tables with no PRIMARY KEY declarations.
#
-if {![info exists testdir]} {
- set testdir [file join [file dirname [info script]] .. .. test]
-}
-source $testdir/tester.tcl
+source [file join [file dirname [info script]] rbu_common.tcl]
+if_no_rbu_support { finish_test ; return }
set ::testprefix rbu9
ifcapable !fts3 {
diff --git a/ext/rbu/rbuA.test b/ext/rbu/rbuA.test
index 642caca19..b43d30d4f 100644
--- a/ext/rbu/rbuA.test
+++ b/ext/rbu/rbuA.test
@@ -14,10 +14,8 @@
# a wal mode database via RBU.
#
-if {![info exists testdir]} {
- set testdir [file join [file dirname [info script]] .. .. test]
-}
-source $testdir/tester.tcl
+source [file join [file dirname [info script]] rbu_common.tcl]
+if_no_rbu_support { finish_test ; return }
set ::testprefix rbuA
set db_sql {
diff --git a/ext/rbu/rbuB.test b/ext/rbu/rbuB.test
index 6eb917e57..3e777631d 100644
--- a/ext/rbu/rbuB.test
+++ b/ext/rbu/rbuB.test
@@ -12,6 +12,7 @@
#
source [file join [file dirname [info script]] rbu_common.tcl]
+if_no_rbu_support { finish_test ; return }
set ::testprefix rbuB
db close
diff --git a/ext/rbu/rbuC.test b/ext/rbu/rbuC.test
index ff3d4d507..a38a6918a 100644
--- a/ext/rbu/rbuC.test
+++ b/ext/rbu/rbuC.test
@@ -13,6 +13,7 @@
#
source [file join [file dirname [info script]] rbu_common.tcl]
+if_no_rbu_support { finish_test ; return }
set ::testprefix rbuC
#-------------------------------------------------------------------------
diff --git a/ext/rbu/rbu_common.tcl b/ext/rbu/rbu_common.tcl
index c4e98784a..cb4f63820 100644
--- a/ext/rbu/rbu_common.tcl
+++ b/ext/rbu/rbu_common.tcl
@@ -15,6 +15,15 @@ if {![info exists testdir]} {
}
source $testdir/tester.tcl
+proc if_no_rbu_support {tcl} {
+ set bOk 1
+ ifcapable !rbu { set bOk 0 }
+ if {[permutation]=="journaltest"} { set bOk 0 }
+ if {$bOk==0} {
+ uplevel $tcl
+ }
+}
+
proc check_prestep_state {target state} {
set oal_exists [file exists $target-oal]
set wal_exists [file exists $target-wal]
diff --git a/ext/rbu/rbubusy.test b/ext/rbu/rbubusy.test
index 8cc47db8f..b4b43219b 100644
--- a/ext/rbu/rbubusy.test
+++ b/ext/rbu/rbubusy.test
@@ -12,6 +12,8 @@
#
source [file join [file dirname [info script]] rbu_common.tcl]
+ifcapable !rbu { finish_test ; return }
+if_no_rbu_support { finish_test ; return }
set ::testprefix rbubusy
db close
diff --git a/ext/rbu/rbucollate.test b/ext/rbu/rbucollate.test
index ccc097624..beb54aa54 100644
--- a/ext/rbu/rbucollate.test
+++ b/ext/rbu/rbucollate.test
@@ -11,6 +11,7 @@
#
source [file join [file dirname [info script]] rbu_common.tcl]
+if_no_rbu_support { finish_test ; return }
set ::testprefix rbucollate
ifcapable !icu_collations {
@@ -18,11 +19,6 @@ ifcapable !icu_collations {
return
}
-db close
-sqlite3_shutdown
-sqlite3_config_uri 1
-reset_db
-
# Create a simple RBU database. That expects to write to a table:
#
# CREATE TABLE t1(a PRIMARY KEY, b, c);
diff --git a/ext/rbu/rbucrash.test b/ext/rbu/rbucrash.test
index 34ac2c86f..e187e8db3 100644
--- a/ext/rbu/rbucrash.test
+++ b/ext/rbu/rbucrash.test
@@ -10,18 +10,10 @@
#***********************************************************************
#
-if {![info exists testdir]} {
- set testdir [file join [file dirname [info script]] .. .. test]
-}
-source $testdir/tester.tcl
+source [file join [file dirname [info script]] rbu_common.tcl]
+if_no_rbu_support { finish_test ; return }
set ::testprefix rbucrash
-db close
-forcedelete test.db-oal rbu.db
-sqlite3_shutdown
-sqlite3_config_uri 1
-reset_db
-
# Set up a target database and an rbu update database. The target
# db is the usual "test.db", the rbu db is "test.db2".
#
diff --git a/ext/rbu/rbucrash2.test b/ext/rbu/rbucrash2.test
index 9ff6eba4f..10721df70 100644
--- a/ext/rbu/rbucrash2.test
+++ b/ext/rbu/rbucrash2.test
@@ -10,18 +10,10 @@
#***********************************************************************
#
-if {![info exists testdir]} {
- set testdir [file join [file dirname [info script]] .. .. test]
-}
-source $testdir/tester.tcl
+source [file join [file dirname [info script]] rbu_common.tcl]
+if_no_rbu_support { finish_test ; return }
set ::testprefix rbucrash2
-db close
-forcedelete test.db-oal rbu.db
-sqlite3_shutdown
-sqlite3_config_uri 1
-reset_db
-
# Set up a target database and an rbu update database. The target
# db is the usual "test.db", the rbu db is "test.db2".
#
diff --git a/ext/rbu/rbudiff.test b/ext/rbu/rbudiff.test
index 5c2bf9bee..e5e3df12f 100644
--- a/ext/rbu/rbudiff.test
+++ b/ext/rbu/rbudiff.test
@@ -12,10 +12,9 @@
# Tests for the [sqldiff --rbu] command.
#
#
-if {![info exists testdir]} {
- set testdir [file join [file dirname [info script]] .. .. test]
-}
-source $testdir/tester.tcl
+
+source [file join [file dirname [info script]] rbu_common.tcl]
+if_no_rbu_support { finish_test ; return }
set testprefix rbudiff
set PROG [test_find_sqldiff]
diff --git a/ext/rbu/rbudor.test b/ext/rbu/rbudor.test
index df4d934de..c456d6ab7 100644
--- a/ext/rbu/rbudor.test
+++ b/ext/rbu/rbudor.test
@@ -13,10 +13,8 @@
# enabled by SQLITE_DIRECT_OVERFLOW_READ - Direct Overflow Read.
#
-if {![info exists testdir]} {
- set testdir [file join [file dirname [info script]] .. .. test]
-}
-source $testdir/tester.tcl
+source [file join [file dirname [info script]] rbu_common.tcl]
+if_no_rbu_support { finish_test ; return }
set ::testprefix rbudor
set bigA [string repeat a 5000]
diff --git a/ext/rbu/rbuexlock.test b/ext/rbu/rbuexlock.test
index eddcdc115..27fd6c4ba 100644
--- a/ext/rbu/rbuexlock.test
+++ b/ext/rbu/rbuexlock.test
@@ -11,11 +11,15 @@
#
source [file join [file dirname [info script]] rbu_common.tcl]
+if_no_rbu_support { finish_test ; return }
set ::testprefix rbuexlock
db close
-sqlite3_shutdown
-sqlite3_config_uri 1
+
+set journalmode delete
+if {[permutation]=="inmemory_journal"} {
+ set journalmode memory
+}
# Create a simple RBU database. That expects to write to a table:
#
@@ -64,7 +68,7 @@ do_test 1.2.0 {
do_catchsql_test 1.2.1 { SELECT * FROM t1 } {0 {1 2 3}}
do_test 1.2.2 {
db eval {PRAGMA journal_mode}
-} {delete}
+} $journalmode
do_test 1.3.0 {
while {[file exists test.db-wal]==0} {
@@ -74,7 +78,7 @@ do_test 1.3.0 {
do_catchsql_test 1.3.1 { SELECT * FROM t1 } {1 {database is locked}}
do_test 1.3.2 {
db eval {PRAGMA journal_mode}
-} {delete}
+} $journalmode
do_test 1.4.0 {
@@ -83,7 +87,7 @@ do_test 1.4.0 {
do_catchsql_test 1.4.1 { SELECT * FROM t1 } {1 {database is locked}}
do_test 1.4.2 {
db eval {PRAGMA journal_mode}
-} {delete}
+} $journalmode
rbu close
@@ -98,7 +102,7 @@ do_test 1.5.1 {
do_catchsql_test 1.5.2 { SELECT * FROM t1 } {1 {database is locked}}
do_test 1.5.2 {
db eval {PRAGMA journal_mode}
-} {delete}
+} $journalmode
do_test 1.6.0 {
@@ -107,7 +111,7 @@ do_test 1.6.0 {
do_catchsql_test 1.6.1 { SELECT * FROM t1 } {1 {database is locked}}
do_test 1.6.2 {
db eval {PRAGMA journal_mode}
-} {delete}
+} $journalmode
do_test 1.7.0 {
while {[rbu step]=="SQLITE_OK"} {}
@@ -116,7 +120,7 @@ do_test 1.7.0 {
do_catchsql_test 1.7.2 { SELECT count(*) FROM t1 } {0 9}
do_test 1.7.2 {
db eval {PRAGMA journal_mode}
-} {delete}
+} $journalmode
reset_db
do_execsql_test 2.0 {
diff --git a/ext/rbu/rbuexpr.test b/ext/rbu/rbuexpr.test
index a392c4ed8..4635d9fef 100644
--- a/ext/rbu/rbuexpr.test
+++ b/ext/rbu/rbuexpr.test
@@ -11,14 +11,9 @@
#
source [file join [file dirname [info script]] rbu_common.tcl]
+if_no_rbu_support { finish_test ; return }
set ::testprefix rbuexpr
-db close
-sqlite3_shutdown
-sqlite3_config_uri 1
-
-sqlite3 db test.db
-
do_execsql_test 1.0 {
CREATE TABLE t1(a, b, c PRIMARY KEY);
CREATE INDEX i1 ON t1(a, null, b+1);
diff --git a/ext/rbu/rbufault.test b/ext/rbu/rbufault.test
index 247a99189..d35c389d7 100644
--- a/ext/rbu/rbufault.test
+++ b/ext/rbu/rbufault.test
@@ -10,10 +10,8 @@
#***********************************************************************
#
-if {![info exists testdir]} {
- set testdir [file join [file dirname [info script]] .. .. test]
-}
-source $testdir/tester.tcl
+source [file join [file dirname [info script]] rbu_common.tcl]
+if_no_rbu_support { finish_test ; return }
source $testdir/malloc_common.tcl
set ::testprefix rbufault
diff --git a/ext/rbu/rbufault2.test b/ext/rbu/rbufault2.test
index 36f2b6b6f..fafe0ede7 100644
--- a/ext/rbu/rbufault2.test
+++ b/ext/rbu/rbufault2.test
@@ -10,10 +10,8 @@
#***********************************************************************
#
-if {![info exists testdir]} {
- set testdir [file join [file dirname [info script]] .. .. test]
-}
-source $testdir/tester.tcl
+source [file join [file dirname [info script]] rbu_common.tcl]
+if_no_rbu_support { finish_test ; return }
source $testdir/malloc_common.tcl
set ::testprefix rbufault2
diff --git a/ext/rbu/rbufault3.test b/ext/rbu/rbufault3.test
index 4f690284a..543e23762 100644
--- a/ext/rbu/rbufault3.test
+++ b/ext/rbu/rbufault3.test
@@ -13,6 +13,7 @@
#
source [file join [file dirname [info script]] rbu_common.tcl]
+if_no_rbu_support { finish_test ; return }
source $testdir/malloc_common.tcl
set ::testprefix rbufault3
diff --git a/ext/rbu/rbufault4.test b/ext/rbu/rbufault4.test
index 551b8b2b6..b95612449 100644
--- a/ext/rbu/rbufault4.test
+++ b/ext/rbu/rbufault4.test
@@ -10,10 +10,8 @@
#***********************************************************************
#
-if {![info exists testdir]} {
- set testdir [file join [file dirname [info script]] .. .. test]
-}
-source $testdir/tester.tcl
+source [file join [file dirname [info script]] rbu_common.tcl]
+if_no_rbu_support { finish_test ; return }
source $testdir/malloc_common.tcl
set ::testprefix rbufault4
@@ -26,6 +24,7 @@ for {set tn 1} {1} {incr tn} {
INSERT INTO t1 VALUES(1, 2, 3);
INSERT INTO t1 VALUES(4, 5, 6);
}
+ db close
forcedelete test.db2
sqlite3rbu_vacuum rbu test.db test.db2
@@ -55,8 +54,10 @@ for {set tn 1} {1} {incr tn} {
set trc [rbu close]
if {$trc!="SQLITE_DONE"} { error "Got $trc instead of SQLITE_DONE!" }
+ sqlite3 db test.db
set rc [db one {PRAGMA integrity_check}]
if {$rc!="ok"} { error "Got $rc instead of ok!" }
+ db close
}
}
diff --git a/ext/rbu/rbufts.test b/ext/rbu/rbufts.test
index 95d4e75c5..b46c32fdc 100644
--- a/ext/rbu/rbufts.test
+++ b/ext/rbu/rbufts.test
@@ -13,10 +13,8 @@
# contains tests to ensure that RBU works with FTS tables.
#
-if {![info exists testdir]} {
- set testdir [file join [file dirname [info script]] .. .. test]
-}
-source $testdir/tester.tcl
+source [file join [file dirname [info script]] rbu_common.tcl]
+if_no_rbu_support { finish_test ; return }
set ::testprefix rbufts
ifcapable !fts3 {
diff --git a/ext/rbu/rbumisc.test b/ext/rbu/rbumisc.test
index c2a3906c0..16293141b 100644
--- a/ext/rbu/rbumisc.test
+++ b/ext/rbu/rbumisc.test
@@ -11,13 +11,9 @@
#
source [file join [file dirname [info script]] rbu_common.tcl]
+if_no_rbu_support { finish_test ; return }
set ::testprefix rbumisc
-db close
-sqlite3_shutdown
-sqlite3_config_uri 1
-reset_db
-
proc populate_rbu_db {} {
forcedelete rbu.db
sqlite3 rbu rbu.db
diff --git a/ext/rbu/rbumulti.test b/ext/rbu/rbumulti.test
index 727d5e992..c24da3518 100644
--- a/ext/rbu/rbumulti.test
+++ b/ext/rbu/rbumulti.test
@@ -16,11 +16,10 @@
#
source [file join [file dirname [info script]] rbu_common.tcl]
+if_no_rbu_support { finish_test ; return }
set ::testprefix rbumulti
db close
-sqlite3_shutdown
-sqlite3_config_uri 1
autoinstall_test_functions
diff --git a/ext/rbu/rbupartial.test b/ext/rbu/rbupartial.test
index d6cd7330f..0c8191d2b 100644
--- a/ext/rbu/rbupartial.test
+++ b/ext/rbu/rbupartial.test
@@ -11,11 +11,10 @@
#
source [file join [file dirname [info script]] rbu_common.tcl]
+if_no_rbu_support { finish_test ; return }
set ::testprefix rbupartial
db close
-sqlite3_shutdown
-sqlite3_config_uri 1
foreach {tn without_rowid a b c d} {
1 "" a b c d
diff --git a/ext/rbu/rbupass.test b/ext/rbu/rbupass.test
index 044a3f2eb..8b921cba4 100644
--- a/ext/rbu/rbupass.test
+++ b/ext/rbu/rbupass.test
@@ -11,6 +11,7 @@
#
source [file join [file dirname [info script]] rbu_common.tcl]
+if_no_rbu_support { finish_test ; return }
set ::testprefix rbupass
if {[info commands register_demovfs]==""} {
@@ -19,22 +20,22 @@ if {[info commands register_demovfs]==""} {
}
db close
-sqlite3_shutdown
-sqlite3_config_uri 1
register_demovfs
sqlite3rbu_create_vfs myvfs demo
-sqlite3 db file:test.db?vfs=myvfs
+sqlite3 db file:test.db?vfs=myvfs -uri 1
do_execsql_test 1.0 {
CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
INSERT INTO t1 VALUES(1, 2);
SELECT * FROM t1;
} {1 2}
-do_execsql_test 1.1 {
- PRAGMA journal_mode = wal;
-} {delete}
+if {[permutation]!="inmemory_journal"} {
+ do_execsql_test 1.1 {
+ PRAGMA journal_mode = wal;
+ } {delete}
+}
do_execsql_test 1.2 {
SELECT * FROM t1;
diff --git a/ext/rbu/rbuprogress.test b/ext/rbu/rbuprogress.test
index bf37b4e50..072683742 100644
--- a/ext/rbu/rbuprogress.test
+++ b/ext/rbu/rbuprogress.test
@@ -11,6 +11,7 @@
#
source [file join [file dirname [info script]] rbu_common.tcl]
+if_no_rbu_support { finish_test ; return }
set ::testprefix rbuprogress
diff --git a/ext/rbu/rburename.test b/ext/rbu/rburename.test
index 2275396bc..e2bacaea5 100644
--- a/ext/rbu/rburename.test
+++ b/ext/rbu/rburename.test
@@ -12,6 +12,7 @@
#
source [file join [file dirname [info script]] rbu_common.tcl]
+if_no_rbu_support { finish_test ; return }
set ::testprefix rburename
diff --git a/ext/rbu/rburesume.test b/ext/rbu/rburesume.test
index 82c8c66b9..cdd890843 100644
--- a/ext/rbu/rburesume.test
+++ b/ext/rbu/rburesume.test
@@ -16,6 +16,7 @@
#
source [file join [file dirname [info script]] rbu_common.tcl]
+if_no_rbu_support { finish_test ; return }
set ::testprefix rburesume
forcedelete test.db-shm test.db-oal
@@ -99,7 +100,7 @@ for {set n 1} {$n < 5000} {incr n} {
break
}
- foreach f {test.db test.db-oal test.db-wal test.db-shm test.db-vacuum} {
+ foreach f {test.db test.db-oal test.db-wal test.db-vacuum} {
set f2 [string map [list test.db test.db2] $f]
if {[file exists $f]} {
forcecopy $f $f2
@@ -158,7 +159,7 @@ for {set n 1} {$n < 5000} {incr n} {
break
}
- foreach f {test.db test.db-oal test.db-wal test.db-shm test.db-vacuum} {
+ foreach f {test.db test.db-oal test.db-wal test.db-vacuum} {
set f2 [string map [list test.db test.db2] $f]
if {[file exists $f]} {
forcecopy $f $f2
@@ -225,7 +226,7 @@ for {set n 1} {$n < 5000} {incr n} {
break
}
- foreach f {test.db test.db-oal test.db-wal test.db-shm test.db-vacuum} {
+ foreach f {test.db test.db-oal test.db-wal test.db-vacuum} {
set f2 [string map [list test.db test.db2] $f]
if {[file exists $f]} {
forcecopy $f $f2
diff --git a/ext/rbu/rbusave.test b/ext/rbu/rbusave.test
index 210d7b545..8e9708980 100644
--- a/ext/rbu/rbusave.test
+++ b/ext/rbu/rbusave.test
@@ -10,10 +10,8 @@
#***********************************************************************
#
-if {![info exists testdir]} {
- set testdir [file join [file dirname [info script]] .. .. test]
-}
-source $testdir/tester.tcl
+source [file join [file dirname [info script]] rbu_common.tcl]
+if_no_rbu_support { finish_test ; return }
set ::testprefix rbusave
do_execsql_test 1.0 {
diff --git a/ext/rbu/rbusplit.test b/ext/rbu/rbusplit.test
index 34fef3867..fb1d7238d 100644
--- a/ext/rbu/rbusplit.test
+++ b/ext/rbu/rbusplit.test
@@ -12,11 +12,10 @@
#
source [file join [file dirname [info script]] rbu_common.tcl]
+if_no_rbu_support { finish_test ; return }
set ::testprefix rbusplit
db close
-sqlite3_shutdown
-sqlite3_config_uri 1
autoinstall_test_functions
diff --git a/ext/rbu/rbutemplimit.test b/ext/rbu/rbutemplimit.test
index 2acba3624..88b5f4152 100644
--- a/ext/rbu/rbutemplimit.test
+++ b/ext/rbu/rbutemplimit.test
@@ -12,11 +12,10 @@
# TESTRUNNER: slow
source [file join [file dirname [info script]] rbu_common.tcl]
+if_no_rbu_support { finish_test ; return }
set ::testprefix rbutemplimit
db close
-sqlite3_shutdown
-sqlite3_config_uri 1
proc setup_databases {} {
forcedelete test.db2
diff --git a/ext/rbu/rbuvacuum.test b/ext/rbu/rbuvacuum.test
index 1785f529b..ad377a4be 100644
--- a/ext/rbu/rbuvacuum.test
+++ b/ext/rbu/rbuvacuum.test
@@ -15,6 +15,7 @@
#
source [file join [file dirname [info script]] rbu_common.tcl]
+if_no_rbu_support { finish_test ; return }
set ::testprefix rbuvacuum
foreach step {0 1} {
diff --git a/ext/rbu/rbuvacuum2.test b/ext/rbu/rbuvacuum2.test
index d4f7c5232..34ec26188 100644
--- a/ext/rbu/rbuvacuum2.test
+++ b/ext/rbu/rbuvacuum2.test
@@ -15,6 +15,7 @@
#
source [file join [file dirname [info script]] rbu_common.tcl]
+if_no_rbu_support { finish_test ; return }
foreach {step} {0 1} {
foreach {ttt state} {
diff --git a/ext/rbu/rbuvacuum3.test b/ext/rbu/rbuvacuum3.test
index 7e1e337f3..d70c094f2 100644
--- a/ext/rbu/rbuvacuum3.test
+++ b/ext/rbu/rbuvacuum3.test
@@ -15,6 +15,7 @@
#
source [file join [file dirname [info script]] rbu_common.tcl]
+if_no_rbu_support { finish_test ; return }
set testprefix rbuvacuum3
do_execsql_test 1.0 {
diff --git a/ext/rbu/rbuvacuum4.test b/ext/rbu/rbuvacuum4.test
index 5cf33d676..7b0db974d 100644
--- a/ext/rbu/rbuvacuum4.test
+++ b/ext/rbu/rbuvacuum4.test
@@ -15,6 +15,7 @@
#
source [file join [file dirname [info script]] rbu_common.tcl]
+if_no_rbu_support { finish_test ; return }
set testprefix rbuvacuum4
set step 1
@@ -87,6 +88,7 @@ do_execsql_test 4.2 {
SELECT count(*) fROM x1
} 6
+db cache flush
do_rbu_vacuum_test 4.1.2 0
#-------------------------------------------------------------------------
diff --git a/ext/recover/recover1.test b/ext/recover/recover1.test
index 3e8a69149..fef1bf90f 100644
--- a/ext/recover/recover1.test
+++ b/ext/recover/recover1.test
@@ -275,11 +275,13 @@ do_recover_test 15
#-------------------------------------------------------------------------
reset_db
-do_execsql_test 16.1 {
- PRAGMA journal_mode = wal;
- CREATE TABLE t1(x);
- INSERT INTO t1 VALUES(1), (2), (3);
-} {wal}
+do_test 16.1 {
+ execsql { PRAGMA journal_mode = wal }
+ execsql {
+ CREATE TABLE t1(x);
+ INSERT INTO t1 VALUES(1), (2), (3);
+ }
+} {}
do_test 16.2 {
set R [sqlite3_recover_init db main test.db2]
$R run
diff --git a/ext/rtree/rtreecheck.test b/ext/rtree/rtreecheck.test
index 1754ff5c3..ff5397e1e 100644
--- a/ext/rtree/rtreecheck.test
+++ b/ext/rtree/rtreecheck.test
@@ -167,9 +167,18 @@ do_execsql_test 6.0 {
}
db close
sqlite3 db test.db
-do_catchsql_test 6.1 {
- SELECT ( 'elvis' IN(SELECT rtreecheck('t1')) ) FROM (SELECT 1) GROUP BY 1;
-} {1 {database table is locked}}
+
+if {[permutation]=="inmemory_journal"} {
+ # This doesn't hit an SQLITE_LOCKED in this permutation as the schema
+ # has already been loaded.
+ do_catchsql_test 6.1.inmemory_journal {
+ SELECT ( 'elvis' IN(SELECT rtreecheck('t1')) ) FROM (SELECT 1) GROUP BY 1;
+ } {0 0}
+} else {
+ do_catchsql_test 6.1 {
+ SELECT ( 'elvis' IN(SELECT rtreecheck('t1')) ) FROM (SELECT 1) GROUP BY 1;
+ } {1 {database table is locked}}
+}
finish_test
diff --git a/ext/session/test_session.c b/ext/session/test_session.c
index bf8babcdf..242e0fb0f 100644
--- a/ext/session/test_session.c
+++ b/ext/session/test_session.c
@@ -102,9 +102,8 @@ int sql_exec_changeset(
#ifdef SQLITE_DEBUG
static int sqlite3_test_changeset(int, void *, char **);
static void assert_changeset_is_ok(int n, void *p){
- int rc = 0;
char *z = 0;
- rc = sqlite3_test_changeset(n, p, &z);
+ (void)sqlite3_test_changeset(n, p, &z);
assert( z==0 );
}
#else
diff --git a/ext/wasm/GNUmakefile b/ext/wasm/GNUmakefile
index f391868d4..7ffd866f2 100644
--- a/ext/wasm/GNUmakefile
+++ b/ext/wasm/GNUmakefile
@@ -37,6 +37,15 @@
# - wasm-strip for release builds: https://github.com/WebAssembly/wabt
# - InfoZip for 'dist' zip file
########################################################################
+#
+# Significant TODOs for this build include, but are not necessarily
+# limited to:
+#
+# 1) Consolidate the code generation for sqlite3*.*js into a script
+# which generates the makefile code, rather than using $(call) and
+# $(eval), or at least centralize the setup of the numerous vars
+# related to each build variant (vanilla, esm, bundler-friendly).
+#
SHELL := $(shell which bash 2>/dev/null)
MAKEFILE := $(lastword $(MAKEFILE_LIST))
CLEAN_FILES :=
@@ -50,6 +59,20 @@ emcc.bin ?= $(word 1,$(wildcard $(EMSDK_HOME)/upstream/emscripten/emcc) $(shell
ifeq (,$(emcc.bin))
$(error Cannot find emcc.)
endif
+emcc.version := $(shell "$(emcc.bin)" --version | sed -n 1p \
+ | sed -e 's/^.* \([3-9][^ ]*\) .*$$/\1/;')
+ifeq (,$(emcc.version))
+ $(warning Cannot determine emcc version. This might unduly impact build flags.)
+else
+ $(info using emcc version [$(emcc.version)])
+endif
+emcc.version := $(shell "$(emcc.bin)" --version | sed -n 1p \
+ | sed -e 's/^.* \([3-9][^ ]*\) .*$$/\1/;')
+ifeq (,$(emcc.version))
+ $(warning Cannot determine emcc version. This might unduly impact build flags.)
+else
+ $(info using emcc version [$(emcc.version)])
+endif
wasm-strip ?= $(shell which wasm-strip 2>/dev/null)
ifeq (,$(filter clean,$(MAKECMDGOALS)))
@@ -226,12 +249,9 @@ $(2): $(1) $$(MAKEFILE) $$(bin.c-pp)
$$(bin.c-pp) -f $(1) -o $$@ $(3)
CLEAN_FILES += $(2)
endef
-c-pp.D.vanilla ?=
-c-pp.D.esm ?= -Dtarget=es6-module
# /end C-PP.FILTER
########################################################################
-
# cflags.common = C compiler flags for all builds
cflags.common := -I. -I.. -I$(dir.top)
# emcc.WASM_BIGINT = 1 for BigInt (C int64) support, else 0. The API
@@ -307,8 +327,6 @@ sqlite3-api.jses += $(dir.api)/sqlite3-api-cleanup.js
# "External" API files which are part of our distribution
# but not part of the sqlite3-api.js amalgamation.
SOAP.js := $(dir.api)/sqlite3-opfs-async-proxy.js
-sqlite3-worker1.js := $(dir.api)/sqlite3-worker1.js
-sqlite3-worker1-promiser.js := $(dir.api)/sqlite3-worker1-promiser.js
# COPY_XAPI = a $(call)able function to copy $1 to $(dir.dout), where
# $1 must be one of the "external" JS API files.
define COPY_XAPI
@@ -316,11 +334,32 @@ sqlite3-api.ext.jses += $$(dir.dout)/$$(notdir $(1))
$$(dir.dout)/$$(notdir $(1)): $(1) $$(MAKEFILE)
cp $$< $$@
endef
-$(foreach X,$(SOAP.js) $(sqlite3-worker1.js) $(sqlite3-worker1-promiser.js),\
+$(foreach X,$(SOAP.js),\
$(eval $(call COPY_XAPI,$(X))))
all quick: $(sqlite3-api.ext.jses)
q: quick
+########################################################################
+# $(sqlite3-api*.*js) contain the core library code but not the
+# Emscripten-related glue which deals with loading sqlite3.wasm. In
+# theory they can be used by arbitrary build environments and WASM
+# loaders, but in practice that breaks down because the WASM loader
+# has to be able to provide all of the necessary "imports" to
+# sqlite3.wasm, and that list of imports is unknown until sqlite3.wasm
+# is compiled, at which point Emscripten sets up the imports
+# appropriately. Abstractly speaking, it's impossible for other build
+# environments to know exactly which imports are needed and provide
+# them. Tools like wasm-objdump can be used to find the list of
+# imports but it's questionable whether a non-Emscripten tool could
+# realistically use that info to provide proper implementations.
+# Sidebar: some of the imports are used soley by the Emscripten glue,
+# which the sqlite3 JS code does not rely on.
+#
+# We build $(sqlite3-api*.*) "because we can" and because it might be
+# a useful point of experimentation for some clients, but the
+# above-described caveat may well make them unusable for real-life
+# clients.
+#
# sqlite3-api.js.in = the generated sqlite3-api.js before it gets
# preprocessed. It contains all of $(sqlite3-api.jses) but none of the
# Emscripten-specific headers and footers.
@@ -334,136 +373,6 @@ $(sqlite3-api.js.in): $(sqlite3-api.jses) $(MAKEFILE)
done > $@
########################################################################
-# $(sqlite3-api.js) and $(sqlite3-api.mjs) (ES6 module) contain the
-# core library code but not the Emscripten-related glue which deals
-# with loading sqlite3.wasm. In theory they can be used by arbitrary
-# build environments and WASM loaders, but in practice that breaks
-# down because the WASM loader has to be able to provide all of the
-# necessary "imports" to sqlite3.wasm, and that list of imports is
-# unknown until sqlite3.wasm is compiled, at which point Emscripten
-# sets up the imports appropriately. Abstractly speaking, it's
-# impossible for other build environments to know exactly which
-# imports are needed and provide them. Tools like wasm-objdump can be
-# used to find the list of imports but it's questionable whether a
-# non-Emscripten tool could realistically use that info to provide
-# proper implementations. Sidebar: some of the imports are used soley
-# by the Emscripten glue, which the sqlite3 JS code does not rely on.
-#
-# We build $(sqlite3-api.js) and $(sqlite3-api.mjs) "because we can"
-# and because it might be a useful point of experimentation for some
-# clients, but the above-described caveat may well make them unusable
-# for real-life clients.
-sqlite3-api.js := $(dir.dout)/sqlite3-api.js
-sqlite3-api.mjs := $(dir.dout)/sqlite3-api.mjs
-$(eval $(call C-PP.FILTER, $(sqlite3-api.js.in), $(sqlite3-api.js)))
-$(eval $(call C-PP.FILTER, $(sqlite3-api.js.in), $(sqlite3-api.mjs), $(c-pp.D.esm)))
-all: $(sqlite3-api.js) $(sqlite3-api.mjs)
-
-$(sqlite3-api-build-version.js): $(bin.version-info) $(MAKEFILE)
- @echo "Making $@..."
- @{ \
- echo 'self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){'; \
- echo -n ' sqlite3.version = '; \
- $(bin.version-info) --json; \
- echo ';'; \
- echo '});'; \
- } > $@
-$(sqlite3-license-version.js): $(sqlite3.h) $(sqlite3-license-version-header.js) \
- $(MAKEFILE)
- @echo "Making $@..."; { \
- cat $(sqlite3-license-version-header.js); \
- echo '/*'; \
- echo '** This code was built from sqlite3 version...'; \
- echo "** "; \
- awk -e '/define SQLITE_VERSION/{$$1=""; print "**" $$0}' \
- -e '/define SQLITE_SOURCE_ID/{$$1=""; print "**" $$0}' $(sqlite3.h); \
- echo '*/'; \
- } > $@
-
-########################################################################
-# --post-js and --pre-js are emcc flags we use to append/prepend JS to
-# the generated emscripten module file. The following rules generate
-# various versions of those files for the vanilla and ESM builds.
-pre-js.js.in := $(dir.api)/pre-js.c-pp.js
-pre-js.js.esm := $(dir.tmp)/pre-js.esm.js
-pre-js.js.vanilla := $(dir.tmp)/pre-js.vanilla.js
-$(eval $(call C-PP.FILTER,$(pre-js.js.in),$(pre-js.js.vanilla),$(c-pp.D.vanilla)))
-$(eval $(call C-PP.FILTER,$(pre-js.js.in),$(pre-js.js.esm),$(c-pp.D.esm)))
-post-js.js.in := $(dir.tmp)/post-js.c-pp.js
-post-js.js.vanilla := $(dir.tmp)/post-js.vanilla.js
-post-js.js.esm := $(dir.tmp)/post-js.esm.js
-post-jses.js := \
- $(dir.api)/post-js-header.js \
- $(sqlite3-api.js.in) \
- $(dir.api)/post-js-footer.js
-$(post-js.js.in): $(post-jses.js) $(MAKEFILE)
- @echo "Making $@..."
- @for i in $(post-jses.js); do \
- echo "/* BEGIN FILE: $$i */"; \
- cat $$i; \
- echo "/* END FILE: $$i */"; \
- done > $@
-$(eval $(call C-PP.FILTER,$(post-js.js.in),$(post-js.js.vanilla),$(c-pp.D.vanilla)))
-$(eval $(call C-PP.FILTER,$(post-js.js.in),$(post-js.js.esm),$(c-pp.D.esm)))
-
-# extern-post-js* and extern-pre-js* are files for use with
-# Emscripten's --extern-pre-js and --extern-post-js flags. These
-# rules make different copies for the vanilla and ESM builds.
-extern-post-js.js.in := $(dir.api)/extern-post-js.c-pp.js
-extern-post-js.js.vanilla := $(dir.tmp)/extern-post-js.vanilla.js
-extern-post-js.js.esm := $(dir.tmp)/extern-post-js.esm.js
-$(eval $(call C-PP.FILTER,$(extern-post-js.js.in),$(extern-post-js.js.vanilla),$(c-pp.D.vanilla)))
-$(eval $(call C-PP.FILTER,$(extern-post-js.js.in),$(extern-post-js.js.esm),$(c-pp.D.esm)))
-extern-pre-js.js := $(dir.api)/extern-pre-js.js
-
-# Emscripten flags for --[extern-][pre|post]-js=... for the
-# various builds.
-pre-post-common.flags := \
- --extern-pre-js=$(sqlite3-license-version.js)
-pre-post-common.flags.vanilla := \
- $(pre-post-common.flags) \
- --post-js=$(post-js.js.vanilla) \
- --extern-post-js=$(extern-post-js.js.vanilla)
-pre-post-common.flags.esm := \
- $(pre-post-common.flags) \
- --post-js=$(post-js.js.esm) \
- --extern-post-js=$(extern-post-js.js.esm)
-
-# pre-post-jses.deps.* = a list of dependencies for the
-# --[extern-][pre/post]-js files.
-pre-post-jses.deps.common := $(extern-pre-js.js) $(sqlite3-license-version.js)
-pre-post-jses.deps.vanilla := $(pre-post-jses.deps.common) \
- $(post-js.js.vanilla) $(extern-post-js.js.vanilla)
-pre-post-jses.deps.esm := $(pre-post-jses.deps.common) \
- $(post-js.js.esm) $(extern-post-js.js.esm)
-
-########################################################################
-# call-make-pre-js is a $(call)able which creates rules for
-# pre-js-$(1).js. $1 = the base name of the JS file on whose behalf
-# this pre-js is for. $2 is the build mode: one of (vanilla, esm).
-# This sets up --[extern-][pre/post]-js flags in
-# $(pre-post-$(1).flags.$(2)) and dependencies in
-# $(pre-post-$(1).deps.$(2)).
-define call-make-pre-js
-pre-post-$(1).flags.$(2) ?=
-$$(dir.tmp)/pre-js-$(1)-$(2).js: $$(pre-js.js.$(2)) $$(MAKEFILE)
- cp $$(pre-js.js.$(2)) $$@
- @if [ sqlite3-wasmfs = $(1) ]; then \
- echo "delete Module[xNameOfInstantiateWasm] /*for WASMFS build*/;"; \
- elif [ sqlite3 != $(1) ]; then \
- echo "Module[xNameOfInstantiateWasm].uri = '$(1).wasm';"; \
- fi >> $$@
-pre-post-$(1).deps.$(2) := \
- $$(pre-post-jses.deps.$(2)) \
- $$(dir.tmp)/pre-js-$(1)-$(2).js
-pre-post-$(1).flags.$(2) += \
- $$(pre-post-common.flags.$(2)) \
- --pre-js=$$(dir.tmp)/pre-js-$(1)-$(2).js
-endef
-# /post-js and pre-js
-########################################################################
-
-########################################################################
# emcc flags for .c/.o/.wasm/.js.
emcc.flags :=
ifeq (1,$(emcc.verbose))
@@ -477,7 +386,6 @@ emcc.cflags :=
emcc.cflags += -std=c99 -fPIC
# -------------^^^^^^^^ we need c99 for $(sqlite3-wasm.c).
emcc.cflags += -I. -I$(dir.top)
-
########################################################################
# emcc flags specific to building .js/.wasm files...
emcc.jsflags := -fPIC
@@ -485,7 +393,6 @@ emcc.jsflags += --minify 0
emcc.jsflags += --no-entry
emcc.jsflags += -sWASM_BIGINT=$(emcc.WASM_BIGINT)
emcc.jsflags += -sMODULARIZE
-emcc.jsflags += -sSTRICT_JS
emcc.jsflags += -sDYNAMIC_EXECUTION=0
emcc.jsflags += -sNO_POLYFILL
emcc.jsflags += -sEXPORTED_FUNCTIONS=@$(EXPORTED_FUNCTIONS.api)
@@ -495,6 +402,13 @@ emcc.exportedRuntimeMethods := \
emcc.jsflags += $(emcc.exportedRuntimeMethods)
emcc.jsflags += -sUSE_CLOSURE_COMPILER=0
emcc.jsflags += -sIMPORTED_MEMORY
+ifeq (3.1.31,$(emcc.version))
+ emcc.jsflags += -sSTRICT_JS=0
+ $(warning Disabling -sSTRICT_JS for emcc $(emcc.version): \
+ https://github.com/emscripten-core/emscripten/issues/18610)
+else
+ emcc.jsflags += -sSTRICT_JS=1
+endif
emcc.environment := -sENVIRONMENT=web,worker
########################################################################
# -sINITIAL_MEMORY: How much memory we need to start with is governed
@@ -581,7 +495,6 @@ emcc.jsflags += -sLLD_REPORT_UNDEFINED
# such constructs are found all over the place in the source code.
########################################################################
-
########################################################################
# -sSINGLE_FILE:
# https://github.com/emscripten-core/emscripten/blob/main/src/settings.js
@@ -593,27 +506,89 @@ emcc.jsflags += -sLLD_REPORT_UNDEFINED
# -g3 debugging info, _huge_.
########################################################################
-sqlite3.js := $(dir.dout)/sqlite3.js
-sqlite3.mjs := $(dir.dout)/sqlite3.mjs
+$(sqlite3-api-build-version.js): $(bin.version-info) $(MAKEFILE)
+ @echo "Making $@..."
+ @{ \
+ echo 'self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){'; \
+ echo -n ' sqlite3.version = '; \
+ $(bin.version-info) --json; \
+ echo ';'; \
+ echo '});'; \
+ } > $@
+$(sqlite3-license-version.js): $(sqlite3.h) $(sqlite3-license-version-header.js) \
+ $(MAKEFILE)
+ @echo "Making $@..."; { \
+ cat $(sqlite3-license-version-header.js); \
+ echo '/*'; \
+ echo '** This code was built from sqlite3 version...'; \
+ echo "**"; \
+ awk -e '/define SQLITE_VERSION/{$$1=""; print "**" $$0}' \
+ -e '/define SQLITE_SOURCE_ID/{$$1=""; print "**" $$0}' $(sqlite3.h); \
+ echo "**"; \
+ echo "** Using the Emscripten SDK version $(emcc.version)."; \
+ echo '*/'; \
+ } > $@
+
+########################################################################
+# --post-js and --pre-js are emcc flags we use to append/prepend JS to
+# the generated emscripten module file. These rules set up the core
+# pre/post files for use by the various builds.
+pre-js.js.in := $(dir.api)/pre-js.c-pp.js
+post-js.js.in := $(dir.tmp)/post-js.c-pp.js
+post-jses.js := \
+ $(dir.api)/post-js-header.js \
+ $(sqlite3-api.js.in) \
+ $(dir.api)/post-js-footer.js
+$(post-js.js.in): $(post-jses.js) $(MAKEFILE)
+ @echo "Making $@..."
+ @for i in $(post-jses.js); do \
+ echo "/* BEGIN FILE: $$i */"; \
+ cat $$i; \
+ echo "/* END FILE: $$i */"; \
+ done > $@
+
+
+########################################################################
+# call-make-pre-post is a $(call)able which creates rules for
+# pre-js-$(1).js. $1 = the base name of the JS file on whose behalf
+# this pre-js is for (one of: sqlite3, sqlite3-wasmfs). $2 is the build
+# mode: one of (vanilla, esm, bundler-friendly). This sets up
+# --[extern-][pre/post]-js flags in $(pre-post-$(1).flags.$(2)) and
+# dependencies in $(pre-post-$(1).deps.$(2)).
+define call-make-pre-post
+pre-post-$(1).flags.$(2) ?=
+$$(dir.tmp)/pre-js-$(1)-$(2).js: $$(pre-js.js.$(2)) $$(MAKEFILE)
+ cp $$(pre-js.js.$(2)) $$@
+ @if [ sqlite3-wasmfs = $(1) ]; then \
+ echo "delete Module[xNameOfInstantiateWasm] /*for WASMFS build*/;"; \
+ elif [ sqlite3 != $(1) ]; then \
+ echo "Module[xNameOfInstantiateWasm].uri = '$(1).wasm';"; \
+ fi >> $$@
+pre-post-$(1).deps.$(2) := \
+ $$(pre-post-jses.deps.$(2)) \
+ $$(dir.tmp)/pre-js-$(1)-$(2).js
+pre-post-$(1).flags.$(2) += \
+ $$(pre-post-common.flags.$(2)) \
+ --pre-js=$$(dir.tmp)/pre-js-$(1)-$(2).js
+endef
+# /post-js and pre-js
+########################################################################
+
# Undocumented Emscripten feature: if the target file extension is
# "mjs", it defaults to ES6 module builds:
# https://github.com/emscripten-core/emscripten/issues/14383
sqlite3.wasm := $(dir.dout)/sqlite3.wasm
sqlite3-wasm.c := $(dir.api)/sqlite3-wasm.c
# sqlite3-wasm.o vs sqlite3-wasm.c: building against the latter
-# (predictably) results in a slightly faster binary, but we're close
+# (predictably) results in a slightly faster binary. We're close
# enough to the target speed requirements that the 500ms makes a
-# difference. Thus we build all binaries against sqlite3-wasm.c
-# instead of building a shared copy of sqlite3-wasm.o.
-$(eval $(call call-make-pre-js,sqlite3,vanilla))
-$(eval $(call call-make-pre-js,sqlite3,esm))
-$(sqlite3.js) $(sqlite3.mjs): $(MAKEFILE) $(sqlite3-wasm.c) \
- $(EXPORTED_FUNCTIONS.api)
-$(sqlite3.js): $(pre-post-sqlite3.deps.vanilla)
-$(sqlite3.mjs): $(pre-post-sqlite3.deps.esm)
-########################################################################
-# SQLITE3.xJS.RECIPE = the $(call)able recipe body for $(sqlite3.js)
-# and $(sqlite3.mjs). $1 = one of (vanilla, esm).
+# difference, so we build all binaries against sqlite3-wasm.c instead
+# of building a shared copy of sqlite3-wasm.o to link against.
+########################################################################
+# SQLITE3.xJS.EXPORT-DEFAULT is part of SQLITE3-WASMFS.xJS.RECIPE and
+# SETUP_LIB_BUILD_MODE, factored into a separate piece to avoid code
+# duplication. $1 is 1 if the build mode needs this workaround (esm,
+# bundler-friendly) and 0 if not (vanilla).
#
# Reminder for ESM builds: even if we use -sEXPORT_ES6=0, emcc _still_
# adds:
@@ -622,17 +597,13 @@ $(sqlite3.mjs): $(pre-post-sqlite3.deps.esm)
#
# when building *.mjs, which is bad because we need to export an
# overwritten version of that function and cannot "export default"
-# twice. Because of this, we have to sed $(sqlite3.mjs) to remove the
-# _first_ instance (only) of /^export default/.
+# twice. Because of this, we have to sed *.mjs to remove the _first_
+# instance (only) of /^export default/.
#
# Upstream RFE:
# https://github.com/emscripten-core/emscripten/issues/18237
-########################################################################
-# SQLITE3.xJS.EXPORT-DEFAULT is part of SQLITE3[-WASMFS].xJS.RECIPE,
-# factored into a separate piece to avoid code duplication. $1 is
-# the build mode: one of (vanilla, esm).
define SQLITE3.xJS.ESM-EXPORT-DEFAULT
-if [ esm = $(1) ]; then \
+if [ x1 = x$(1) ]; then \
echo "Fragile workaround for an Emscripten annoyance. See SQLITE3.xJS.RECIPE."; \
sed -i -e '0,/^export default/{/^export default/d;}' $@ || exit $$?; \
if ! grep -q '^export default' $@; then \
@@ -641,38 +612,129 @@ if [ esm = $(1) ]; then \
fi; \
fi
endef
-define SQLITE3.xJS.RECIPE
- @echo "Building $@ ..."
- $(emcc.bin) -o $@ $(emcc_opt_full) $(emcc.flags) \
- $(emcc.jsflags) \
- $(pre-post-sqlite3.flags.$(1)) $(emcc.flags.sqlite3.$(1)) \
- $(cflags.common) $(SQLITE_OPT) $(sqlite3-wasm.c)
- @$(call SQLITE3.xJS.ESM-EXPORT-DEFAULT,$(1))
- chmod -x $(sqlite3.wasm)
- $(maybe-wasm-strip) $(sqlite3.wasm)
- @ls -la $@ $(sqlite3.wasm)
+
+# extern-post-js* and extern-pre-js* are files for use with
+# Emscripten's --extern-pre-js and --extern-post-js flags.
+extern-pre-js.js := $(dir.api)/extern-pre-js.js
+extern-post-js.js.in := $(dir.api)/extern-post-js.c-pp.js
+# Emscripten flags for --[extern-][pre|post]-js=... for the
+# various builds.
+pre-post-common.flags := \
+ --extern-pre-js=$(sqlite3-license-version.js)
+# pre-post-jses.deps.* = a list of dependencies for the
+# --[extern-][pre/post]-js files.
+pre-post-jses.deps.common := $(extern-pre-js.js) $(sqlite3-license-version.js)
+########################################################################
+# SETUP_LIB_BUILD_MODE is a $(call)'able which sets up numerous pieces
+# for one of the build modes (vanilla, esm, bundler-friendly).
+#
+# $1 = build mode name
+# $2 = 1 for ESM build mode, else 0
+# $3 = resulting sqlite-api JS/MJS file
+# $4 = resulting JS/MJS file
+# $5 = -D... flags for $(bin.c-pp)
+# $6 = emcc -sXYZ flags
+define SETUP_LIB_BUILD_MODE
+$(info Setting up build [$(1)]: $(4))
+c-pp.D.$(1) := $(5)
+pre-js.js.$(1) := $$(dir.api)/pre-js.$(1).js
+$$(eval $$(call C-PP.FILTER,$$(pre-js.js.in),$$(pre-js.js.$(1)),$$(c-pp.D.$(1))))
+post-js.js.$(1) := $$(dir.tmp)/post-js.$(1).js
+$$(eval $$(call C-PP.FILTER,$$(post-js.js.in),$$(post-js.js.$(1)),$$(c-pp.D.$(1))))
+extern-post-js.js.$(1) := $$(dir.tmp)/extern-post-js.$(1).js
+$$(eval $$(call C-PP.FILTER,$$(extern-post-js.js.in),$$(extern-post-js.js.$(1)),$$(c-pp.D.$(1))))
+pre-post-common.flags.$(1) := \
+ $$(pre-post-common.flags) \
+ --post-js=$$(post-js.js.$(1)) \
+ --extern-post-js=$$(extern-post-js.js.$(1))
+pre-post-jses.deps.$(1) := $$(pre-post-jses.deps.common) \
+ $$(post-js.js.$(1)) $$(extern-post-js.js.$(1))
+$$(eval $$(call call-make-pre-post,sqlite3,$(1)))
+emcc.flags.sqlite3.$(1) := $(6)
+$$(eval $$(call C-PP.FILTER, $$(sqlite3-api.js.in), $(3), $(5)))
+$(4): $(3)
+$(4): $(3) $$(MAKEFILE) $$(sqlite3-wasm.c) $$(EXPORTED_FUNCTIONS.api) $$(pre-post-sqlite3.deps.$(1))
+ @echo "Building $$@ ..."
+ $$(emcc.bin) -o $$@ $$(emcc_opt_full) $$(emcc.flags) \
+ $$(emcc.jsflags) \
+ $$(pre-post-sqlite3.flags.$(1)) $$(emcc.flags.sqlite3.$(1)) \
+ $$(cflags.common) $$(SQLITE_OPT) $$(sqlite3-wasm.c)
+ @$$(call SQLITE3.xJS.ESM-EXPORT-DEFAULT,$(2))
+ @if [ bundler-friendly = $(1) ]; then \
+ echo "Patching $(3) for sqlite3.wasm..."; \
+ rm -f $$(dir.dout)/sqlite3-bundler-friendly.wasm; \
+ sed -i -e 's/sqlite3-bundler-friendly.wasm/sqlite3.wasm/g' $$@ || exit $$$$?; \
+ fi
+ chmod -x $$(sqlite3.wasm)
+ $$(maybe-wasm-strip) $$(sqlite3.wasm)
+ @ls -la $@ $$(sqlite3.wasm)
+all: $(4)
+quick: $(4)
+CLEAN_FILES += $(3) $(4)
endef
-emcc.flags.sqlite3.vanilla :=
-emcc.flags.sqlite3.esm := -sEXPORT_ES6 -sUSE_ES6_IMPORT_META
-$(sqlite3.js):
- $(call SQLITE3.xJS.RECIPE,vanilla)
-$(sqlite3.mjs):
- $(call SQLITE3.xJS.RECIPE,esm)
-########################################################################
-# We have to ensure that we do not build both $(sqlite3.js) and
-# $(sqlite3.mjs) in parallel because both result in the creation of
-# $(sqlite3.wasm). We have no(?) way to build just the .mjs file
-# without also building the .wasm file. i.e. we're building
-# $(sqlite3.wasm) twice, but that's apparently unavoidable (and
-# harmless, just a waste of build time).
+# ^^^ /SETUP_LIB_BUILD_MODE
+########################################################################
+sqlite3-api.js := $(dir.dout)/sqlite3-api.js
+sqlite3.js := $(dir.dout)/sqlite3.js
+sqlite3-api.mjs := $(dir.dout)/sqlite3-api.mjs
+sqlite3.mjs := $(dir.dout)/sqlite3.mjs
+sqlite3-api-bundler-friendly.mjs := $(dir.dout)/sqlite3-api-bundler-friendly.mjs
+sqlite3-bundler-friendly.mjs := $(dir.dout)/sqlite3-bundler-friendly.mjs
+# Maintenance reminder: careful not to introduce spaces around args $1, $2
+#$(info $(call SETUP_LIB_BUILD_MODE,vanilla,0, $(sqlite3-api.js), $(sqlite3.js)))
+$(eval $(call SETUP_LIB_BUILD_MODE,vanilla,0, $(sqlite3-api.js), $(sqlite3.js)))
+$(eval $(call SETUP_LIB_BUILD_MODE,esm,1, $(sqlite3-api.mjs), $(sqlite3.mjs), \
+ -Dtarget=es6-module, -sEXPORT_ES6 -sUSE_ES6_IMPORT_META))
+$(eval $(call SETUP_LIB_BUILD_MODE,bundler-friendly,1,\
+ $(sqlite3-api-bundler-friendly.mjs),$(sqlite3-bundler-friendly.mjs),\
+ $(c-pp.D.esm) -Dtarget=es6-bundler-friendly, $(emcc.flags.sqlite3.esm)))
+# The various -D... values used by *.c-pp.js include:
+#
+# -Dtarget=es6-module: for all ESM module builds
+#
+# -Dtarget=es6-module -Dtarget=es6-bundler-friendly: intended for
+# "bundler-friendly" ESM module build. These have some restrictions
+# on how URL() objects are constructed in some contexts: URLs which
+# refer to files which are part of this project must be references
+# as string literals so that bundlers' static-analysis tools can
+# find those files and include them in their bundles.
+#
+########################################################################
+########################################################################
+# We have to ensure that we do not build both $(sqlite3*.*js) in
+# parallel because both result in the creation of $(sqlite3.wasm). We
+# have no way to build just the .mjs file without also building the
+# .wasm file because the generated .mjs file has to include info about
+# the imports needed by the wasm file, so they have to be built
+# together. i.e. we're building $(sqlite3.wasm) multiple times, but
+# that's unavoidable (and harmless, just a waste of build time).
$(sqlite3.wasm): $(sqlite3.js)
$(sqlite3.mjs): $(sqlite3.js)
-CLEAN_FILES += $(sqlite3.js) $(sqlite3.mjs) $(sqlite3.wasm)
-all: $(sqlite3.js) $(sqlite3.mjs)
-quick: $(sqlite3.js)
-quick: $(sqlite3.mjs) # for the sake of the snapshot build
-# End main $(sqlite3.js) build
-########################################################################
+$(sqlite3-bundler-friendly.mjs): $(sqlite3.mjs)
+CLEAN_FILES += $(sqlite3.wasm)
+
+########################################################################
+# We need separate copies of certain supplementary JS files for the
+# bundler-friendly build. Concretely, any supplemental JS files which
+# themselves use importScripts() or Workers or URL() constructors
+# which refer to other in-tree (m)JS files quire a bundler-friendly
+# copy.
+sqlite3-worker1.js.in := $(dir.api)/sqlite3-worker1.c-pp.js
+sqlite3-worker1-promiser.js.in := $(dir.api)/sqlite3-worker1-promiser.c-pp.js
+sqlite3-worker1.js := $(dir.dout)/sqlite3-worker1.js
+sqlite3-worker1-promiser.js := $(dir.dout)/sqlite3-worker1-promiser.js
+sqlite3-worker1-bundler-friendly.js := $(dir.dout)/sqlite3-worker1-bundler-friendly.js
+sqlite3-worker1-promiser-bundler-friendly.js := $(dir.dout)/sqlite3-worker1-promiser-bundler-friendly.js
+$(eval $(call C-PP.FILTER,$(sqlite3-worker1.js.in),$(sqlite3-worker1.js)))
+$(eval $(call C-PP.FILTER,$(sqlite3-worker1.js.in),$(sqlite3-worker1-bundler-friendly.js),\
+ $(c-pp.D.bundler-friendly)))
+$(eval $(call C-PP.FILTER,$(sqlite3-worker1-promiser.js.in),$(sqlite3-worker1-promiser.js)))
+$(eval $(call C-PP.FILTER,$(sqlite3-worker1-promiser.js.in),\
+ $(sqlite3-worker1-promiser-bundler-friendly.js),\
+ $(c-pp.D.bundler-friendly)))
+$(sqlite3-bundler-friendly.mjs): $(sqlite3-worker1-bundler-friendly.js) \
+ $(sqlite3-worker1-promiser-bundler-friendly.js)
+$(sqlite3.js) $(sqlite3.mjs): $(sqlite3-worker1.js) $(sqlite3-worker1-promiser.js)
########################################################################
# batch-runner.js is part of one of the test apps which reads in SQL
@@ -709,7 +771,6 @@ emcc.speedtest1 += -sALLOW_MEMORY_GROWTH
emcc.speedtest1 += -sINITIAL_MEMORY=$(emcc.INITIAL_MEMORY.$(emcc.INITIAL_MEMORY))
emcc.speedtest1.common += -sINVOKE_RUN=0
emcc.speedtest1.common += --no-entry
-#emcc.speedtest1.common += -flto
emcc.speedtest1.common += -sABORTING_MALLOC
emcc.speedtest1.common += -sSTRICT_JS
emcc.speedtest1.common += -sMODULARIZE
@@ -749,7 +810,7 @@ speedtest1.js := $(dir.dout)/speedtest1.js
speedtest1.wasm := $(dir.dout)/speedtest1.wasm
cflags.speedtest1 := $(cflags.common) -DSQLITE_SPEEDTEST1_WASM
speedtest1.cses := $(speedtest1.c) $(sqlite3-wasm.c)
-$(eval $(call call-make-pre-js,speedtest1,vanilla))
+$(eval $(call call-make-pre-post,speedtest1,vanilla))
$(speedtest1.js): $(MAKEFILE) $(speedtest1.cses) \
$(pre-post-speedtest1.deps.vanilla) \
$(EXPORTED_FUNCTIONS.speedtest1)
@@ -780,7 +841,7 @@ CLEAN_FILES += $(speedtest1.js) $(speedtest1.wasm)
# 4) Load sqlite3 as an ESM worker. (Not all browsers support this.)
#
# To that end, we require two separate builds of tester1.js:
-#
+#
# tester1.js: cases 1 and 2
# tester1.mjs: cases 3 and 4
#
@@ -790,6 +851,8 @@ $(eval $(call C-PP.FILTER,tester1.c-pp.js,tester1.mjs,$(c-pp.D.esm)))
$(eval $(call C-PP.FILTER,tester1.c-pp.html,tester1.html))
$(eval $(call C-PP.FILTER,tester1.c-pp.html,tester1-esm.html,$(c-pp.D.esm)))
tester1: tester1.js tester1.mjs tester1.html tester1-esm.html
+# Note that we do not include $(sqlite3-bundler-friendly.mjs) in this
+# because bundlers are client-specific.
all quick: tester1
########################################################################
diff --git a/ext/wasm/README-dist.txt b/ext/wasm/README-dist.txt
index 909a5ebbe..6656a2072 100644
--- a/ext/wasm/README-dist.txt
+++ b/ext/wasm/README-dist.txt
@@ -4,19 +4,42 @@ Main project page: https://sqlite.org
Documentation: https://sqlite.org/wasm
-This archive contains the sqlite3.js, sqlite3.mjs, and sqlite3.wasm
-files which make up the sqlite3 WASM/JS build.
+This archive contains the following deliverables for the WASM/JS
+build:
-The jswasm directory contains the core sqlite3 deliverables and the
-top-level directory contains demonstration and test applications.
+- jswasm/sqlite3.js is the canonical "vanilla JS" version.
-Browsers will not serve WASM files from file:// URLs, so the demo/test
-apps require a web server and that server must include the following
-headers in its response when serving the files:
+- jswasm/sqlite3.mjs is the same but in ES6 module form
+
+- jswasm/*-bundler-friendly.js and .mjs are variants which are
+ intended to be compatible with "bundler" tools commonly seen in
+ node.js-based projects. Projects using such tools should use those
+ variants, where available, instead of files without the
+ "-bundler-friendly" suffix. Some files do not have separate
+ variants.
+
+- jswasm/sqlite3.wasm is the binary WASM file imported by all of the
+ above-listed JS files.
+
+- The jswasm directory additionally contains a number of supplemental
+ JS files which cannot be bundled directly with the main JS files
+ but are necessary for certain usages.
+
+- The top-level directory contains various demonstration and test
+ applications for sqlite3.js and sqlite3.mjs.
+ sqlite3-bundler-friendly.mjs requires client-side build tools to make
+ use of and is not demonstrated here.
+
+Browsers will not serve WASM files from file:// URLs, so the test and
+demonstration apps require a web server and that server must include
+the following headers in its response when serving the files:
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp
+The core library will function without those headers but certain
+features, most notably OPFS storage, will not be available.
+
One simple way to get the demo apps up and running on Unix-style
systems is to install althttpd (https://sqlite.org/althttpd) and run:
diff --git a/ext/wasm/api/extern-post-js.c-pp.js b/ext/wasm/api/extern-post-js.c-pp.js
index 225869794..a577a63e1 100644
--- a/ext/wasm/api/extern-post-js.c-pp.js
+++ b/ext/wasm/api/extern-post-js.c-pp.js
@@ -9,7 +9,7 @@
Emscripten-generated module init scope, in the current
global scope. */
//#if target=es6-module
-const toExportForES6 =
+const toExportForESM =
//#endif
(function(){
/**
@@ -45,10 +45,10 @@ const toExportForES6 =
moduleScript: self?.document?.currentScript,
isWorker: ('undefined' !== typeof WorkerGlobalScope),
location: self.location,
- urlParams: new URL(self.location.href).searchParams
+ urlParams: new URL(self.location.href).searchParams
});
initModuleState.debugModule =
- (new URL(self.location.href).searchParams).has('sqlite3.debugModule')
+ initModuleState.urlParams.has('sqlite3.debugModule')
? (...args)=>console.warn('sqlite3.debugModule:',...args)
: ()=>{};
@@ -105,6 +105,10 @@ const toExportForES6 =
document?.currentScript?.src);
}
}
+//#ifnot target=es6-module
+// Emscripten does not inject these module-loader bits in ES6 module
+// builds and including them here breaks JS bundlers, so elide them
+// from ESM builds.
/* Replace the various module exports performed by the Emscripten
glue... */
if (typeof exports === 'object' && typeof module === 'object'){
@@ -114,8 +118,9 @@ const toExportForES6 =
}
/* AMD modules get injected in a way we cannot override,
so we can't handle those here. */
+//#endif // !target=es6-module
return self.sqlite3InitModule /* required for ESM */;
})();
//#if target=es6-module
-export default toExportForES6;
+export default toExportForESM;
//#endif
diff --git a/ext/wasm/api/pre-js.c-pp.js b/ext/wasm/api/pre-js.c-pp.js
index 2e2fe66bc..a25c7ce77 100644
--- a/ext/wasm/api/pre-js.c-pp.js
+++ b/ext/wasm/api/pre-js.c-pp.js
@@ -6,10 +6,14 @@
*/
// See notes in extern-post-js.js
-const sqlite3InitModuleState = self.sqlite3InitModuleState || Object.create(null);
+const sqlite3InitModuleState = self.sqlite3InitModuleState
+ || Object.assign(Object.create(null),{
+ debugModule: ()=>{}
+ });
delete self.sqlite3InitModuleState;
sqlite3InitModuleState.debugModule('self.location =',self.location);
+//#ifnot target=es6-bundler-friendly
/**
This custom locateFile() tries to figure out where to load `path`
from. The intent is to provide a way for foo/bar/X.js loaded from a
@@ -51,8 +55,9 @@ Module['locateFile'] = function(path, prefix) {
"result =", theFile
);
return theFile;
-//#endif /* SQLITE_JS_EMS */
+//#endif target=es6-module
}.bind(sqlite3InitModuleState);
+//#endif ifnot target=es6-bundler-friendly
/**
Bug warning: a custom Module.instantiateWasm() does not work
@@ -62,7 +67,7 @@ Module['locateFile'] = function(path, prefix) {
In such builds we must disable this.
*/
-const xNameOfInstantiateWasm = true
+const xNameOfInstantiateWasm = false
? 'instantiateWasm'
: 'emscripten-bug-17951';
Module[xNameOfInstantiateWasm] = function callee(imports,onSuccess){
diff --git a/ext/wasm/api/sqlite3-api-cleanup.js b/ext/wasm/api/sqlite3-api-cleanup.js
index 30cd64b05..7c23f8f89 100644
--- a/ext/wasm/api/sqlite3-api-cleanup.js
+++ b/ext/wasm/api/sqlite3-api-cleanup.js
@@ -51,11 +51,6 @@ if('undefined' !== typeof Module){ // presumably an Emscripten build
delete self.sqlite3ApiConfig;
}
- if(self.location && +self.location.port > 1024){
- console.warn("Installing sqlite3 bits as global S for local dev/test purposes.");
- self.S = sqlite3;
- }
-
Module.sqlite3 = sqlite3 /* Needed for customized sqlite3InitModule() to be able to
pass the sqlite3 object off to the client. */;
}else{
diff --git a/ext/wasm/api/sqlite3-api-oo1.js b/ext/wasm/api/sqlite3-api-oo1.js
index ba210e7f9..914497602 100644
--- a/ext/wasm/api/sqlite3-api-oo1.js
+++ b/ext/wasm/api/sqlite3-api-oo1.js
@@ -136,7 +136,7 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
if(('string'!==typeof fn && 'number'!==typeof fn)
|| 'string'!==typeof flagsStr
|| (vfsName && ('string'!==typeof vfsName && 'number'!==typeof vfsName))){
- console.error("Invalid DB ctor args",opt,arguments);
+ sqlite3.config.error("Invalid DB ctor args",opt,arguments);
toss3("Invalid arguments for DB constructor.");
}
let fnJs = ('number'===typeof fn) ? wasm.cstrToJs(fn) : fn;
@@ -183,7 +183,7 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
checkSqlite3Rc(
pDb, capi.sqlite3_exec(pDb, postInitSql, 0, 0, 0)
);
- }
+ }
}catch(e){
this.close();
throw e;
@@ -422,6 +422,10 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
default:
toss3("Invalid returnValue value:",opt.returnValue);
}
+ if(!opt.callback && !opt.returnValue && undefined!==opt.rowMode){
+ if(!opt.resultRows) opt.resultRows = [];
+ out.returnVal = ()=>opt.resultRows;
+ }
if(opt.callback || opt.resultRows){
switch((undefined===opt.rowMode)
? 'array' : opt.rowMode) {
@@ -770,8 +774,11 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
- `returnValue`: is a string specifying what this function
should return:
- A) The default value is `"this"`, meaning that the
- DB object itself should be returned.
+ A) The default value is (usually) `"this"`, meaning that the
+ DB object itself should be returned. The exceptions is if
+ the caller passes neither of `callback` nor `returnValue`
+ but does pass an explicit `rowMode` then the default
+ `returnValue` is `"resultRows"`, described below.
B) `"resultRows"` means to return the value of the
`resultRows` option. If `resultRows` is not set, this
@@ -874,7 +881,7 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
stmt = null;
}
}/*catch(e){
- console.warn("DB.exec() is propagating exception",opt,e);
+ sqlite3.config.warn("DB.exec() is propagating exception",opt,e);
throw e;
}*/finally{
if(stmt){
@@ -1271,7 +1278,7 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
function returns that value, else it throws.
*/
const affirmSupportedBindType = function(v){
- //console.log('affirmSupportedBindType',v);
+ //sqlite3.config.log('affirmSupportedBindType',v);
return isSupportedBindType(v) || toss3("Unsupported bind() argument type:",typeof v);
};
@@ -1387,7 +1394,7 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
break;
}
default:
- console.warn("Unsupported bind() argument type:",val);
+ sqlite3.config.warn("Unsupported bind() argument type:",val);
toss3("Unsupported bind() argument type: "+(typeof val));
}
if(rc) DB.checkRc(stmt.db.pointer, rc);
@@ -1592,7 +1599,7 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
case capi.SQLITE_ROW: return this._mayGet = true;
default:
this._mayGet = false;
- console.warn("sqlite3_step() rc=",rc,
+ sqlite3.config.warn("sqlite3_step() rc=",rc,
capi.sqlite3_js_rc_str(rc),
"SQL =", capi.sqlite3_sql(this.pointer));
DB.checkRc(this.db.pointer, rc);
@@ -1715,7 +1722,7 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
hope for the best, as the C API would do. */
toss3("Integer is out of range for JS integer range: "+rc);
}
- //console.log("get integer rc=",rc,isInt32(rc));
+ //sqlite3.config.log("get integer rc=",rc,isInt32(rc));
return util.isInt32(rc) ? (rc | 0) : rc;
}
}
diff --git a/ext/wasm/api/sqlite3-api-prologue.js b/ext/wasm/api/sqlite3-api-prologue.js
index 137ab1ee7..b08ad7a7c 100644
--- a/ext/wasm/api/sqlite3-api-prologue.js
+++ b/ext/wasm/api/sqlite3-api-prologue.js
@@ -82,6 +82,12 @@
the `realloc(3)`-compatible routine for the WASM
environment. Defaults to `"sqlite3_realloc"`.
+ - `debug`, `log`, `warn`, and `error` may be functions equivalent
+ to the like-named methods of the global `console` object. By
+ default, these map directly to their `console` counterparts, but
+ can be replaced with (e.g.) empty functions to squelch all such
+ output.
+
- `wasmfsOpfsDir`[^1]: As of 2022-12-17, this feature does not
currently work due to incompatible Emscripten-side changes made
in the WASMFS+OPFS combination. This option is currently ignored.
@@ -113,6 +119,10 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
}
return !!self.BigInt64Array;
})(),
+ debug: console.debug.bind(console),
+ warn: console.warn.bind(console),
+ error: console.error.bind(console),
+ log: console.log.bind(console),
wasmfsOpfsDir: '/opfs',
/**
useStdAlloc is just for testing an allocator discrepancy. The
diff --git a/ext/wasm/api/sqlite3-api-worker1.js b/ext/wasm/api/sqlite3-api-worker1.js
index 58b9b0091..f82be6cd0 100644
--- a/ext/wasm/api/sqlite3-api-worker1.js
+++ b/ext/wasm/api/sqlite3-api-worker1.js
@@ -612,8 +612,8 @@ sqlite3.initWorker1API = function(){
result.stack = ('string'===typeof err.stack)
? err.stack.split(/\n\s*/) : err.stack;
}
- if(0) console.warn("Worker is propagating an exception to main thread.",
- "Reporting it _here_ for the stack trace:",err,result);
+ if(0) sqlite3.config.warn("Worker is propagating an exception to main thread.",
+ "Reporting it _here_ for the stack trace:",err,result);
}
if(!dbId){
dbId = result.dbId/*from 'open' cmd*/
diff --git a/ext/wasm/api/sqlite3-vfs-opfs.c-pp.js b/ext/wasm/api/sqlite3-vfs-opfs.c-pp.js
index 2ded905ad..3e3255b0c 100644
--- a/ext/wasm/api/sqlite3-vfs-opfs.c-pp.js
+++ b/ext/wasm/api/sqlite3-vfs-opfs.c-pp.js
@@ -112,16 +112,16 @@ const installOpfsVfs = function callee(options){
options.proxyUri = callee.defaultProxyUri;
}
- //console.warn("OPFS options =",options,self.location);
+ //sqlite3.config.warn("OPFS options =",options,self.location);
if('function' === typeof options.proxyUri){
options.proxyUri = options.proxyUri();
}
const thePromise = new Promise(function(promiseResolve, promiseReject_){
const loggers = {
- 0:console.error.bind(console),
- 1:console.warn.bind(console),
- 2:console.log.bind(console)
+ 0:sqlite3.config.error.bind(console),
+ 1:sqlite3.config.warn.bind(console),
+ 2:sqlite3.config.log.bind(console)
};
const logImpl = (level,...args)=>{
if(options.verbose>level) loggers[level]("OPFS syncer:",...args);
@@ -171,11 +171,11 @@ const installOpfsVfs = function callee(options){
m.avgTime = (m.count && m.time) ? (m.time / m.count) : 0;
m.avgWait = (m.count && m.wait) ? (m.wait / m.count) : 0;
}
- console.log(self.location.href,
+ sqlite3.config.log(self.location.href,
"metrics for",self.location.href,":",metrics,
"\nTotal of",n,"op(s) for",t,
"ms (incl. "+w+" ms of waiting on the async side)");
- console.log("Serialization metrics:",metrics.s11n);
+ sqlite3.config.log("Serialization metrics:",metrics.s11n);
W.postMessage({type:'opfs-async-metrics'});
},
reset: function(){
@@ -198,7 +198,9 @@ const installOpfsVfs = function callee(options){
return promiseReject_(err);
};
const W =
-//#if target=es6-module
+//#if target=es6-bundler-friendly
+ new Worker(new URL("sqlite3-opfs-async-proxy.js", import.meta.url));
+//#elif target=es6-module
new Worker(new URL(options.proxyUri, import.meta.url));
//#else
new Worker(options.proxyUri);
@@ -943,7 +945,7 @@ const installOpfsVfs = function callee(options){
await opfsUtil.getDirForFilename(absDirName+"/filepart", true);
return true;
}catch(e){
- //console.warn("mkdir(",absDirName,") failed:",e);
+ //sqlite3.config.warn("mkdir(",absDirName,") failed:",e);
return false;
}
};
@@ -1315,13 +1317,13 @@ self.sqlite3ApiBootstrap.initializersAsync.push(async (sqlite3)=>{
if(sqlite3.scriptInfo.sqlite3Dir){
installOpfsVfs.defaultProxyUri =
sqlite3.scriptInfo.sqlite3Dir + proxyJs;
- //console.warn("installOpfsVfs.defaultProxyUri =",installOpfsVfs.defaultProxyUri);
+ //sqlite3.config.warn("installOpfsVfs.defaultProxyUri =",installOpfsVfs.defaultProxyUri);
}
return installOpfsVfs().catch((e)=>{
- console.warn("Ignoring inability to install OPFS sqlite3_vfs:",e.message);
+ sqlite3.config.warn("Ignoring inability to install OPFS sqlite3_vfs:",e.message);
});
}catch(e){
- console.error("installOpfsVfs() exception:",e);
+ sqlite3.config.error("installOpfsVfs() exception:",e);
throw e;
}
});
diff --git a/ext/wasm/api/sqlite3-worker1-promiser.js b/ext/wasm/api/sqlite3-worker1-promiser.c-pp.js
index 7360512d4..0f1ae39ea 100644
--- a/ext/wasm/api/sqlite3-worker1-promiser.js
+++ b/ext/wasm/api/sqlite3-worker1-promiser.c-pp.js
@@ -238,20 +238,24 @@ self.sqlite3Worker1Promiser = function callee(config = callee.defaultConfig){
}/*sqlite3Worker1Promiser()*/;
self.sqlite3Worker1Promiser.defaultConfig = {
worker: function(){
+//#if target=es6-bundler-friendly
+ return new Worker("sqlite3-worker1.js");
+//#else
let theJs = "sqlite3-worker1.js";
if(this.currentScript){
const src = this.currentScript.src.split('/');
src.pop();
theJs = src.join('/')+'/' + theJs;
- //console.warn("promiser currentScript, theJs =",this.currentScript,theJs);
+ //sqlite3.config.warn("promiser currentScript, theJs =",this.currentScript,theJs);
}else{
- //console.warn("promiser self.location =",self.location);
+ //sqlite3.config.warn("promiser self.location =",self.location);
const urlParams = new URL(self.location.href).searchParams;
if(urlParams.has('sqlite3.dir')){
theJs = urlParams.get('sqlite3.dir') + '/' + theJs;
}
}
return new Worker(theJs + self.location.search);
+//#endif
}.bind({
currentScript: self?.document?.currentScript
}),
diff --git a/ext/wasm/api/sqlite3-worker1.js b/ext/wasm/api/sqlite3-worker1.c-pp.js
index 4ff19b888..9e9c3ac42 100644
--- a/ext/wasm/api/sqlite3-worker1.js
+++ b/ext/wasm/api/sqlite3-worker1.c-pp.js
@@ -33,6 +33,9 @@
*/
"use strict";
(()=>{
+//#if target=es6-bundler-friendly
+ importScripts('sqlite3.js');
+//#else
const urlParams = new URL(self.location.href).searchParams;
let theJs = 'sqlite3.js';
if(urlParams.has('sqlite3.dir')){
@@ -40,6 +43,7 @@
}
//console.warn("worker1 theJs =",theJs);
importScripts(theJs);
+//#endif
sqlite3InitModule().then((sqlite3)=>{
sqlite3.initWorker1API();
});
diff --git a/ext/wasm/c-pp.c b/ext/wasm/c-pp.c
index 881c009ac..c439a0d09 100644
--- a/ext/wasm/c-pp.c
+++ b/ext/wasm/c-pp.c
@@ -51,10 +51,10 @@
**
** Design note: this code makes use of sqlite3. Though not _strictly_
** needed in order to implement it, this tool was specifically created
-** for potential use with the sqlite3 project's own JavaScript code,
-** so there's no reason not to make use of it to do some of the heavy
-** lifting. It does not require any cutting-edge sqlite3 features and
-** should be usable with any version which supports `WITHOUT ROWID`.
+** for use with the sqlite3 project's own JavaScript code, so there's
+** no reason not to make use of it to do some of the heavy lifting. It
+** does not require any cutting-edge sqlite3 features and should be
+** usable with any version which supports `WITHOUT ROWID`.
**
** Author(s):
**
@@ -603,18 +603,9 @@ void g_stderr(char const *zFmt, ...){
va_end(va);
}
-#if 0
-void cmpp_t_outf(CmppTokenizer * t, char const *zFmt, ...){
- if(!CT_skip(t)){
- va_list va;
- va_start(va, zFmt);
- vfprintf(g.out.pFile, zFmt, va);
- va_end(va);
- }
-}
-#endif
-
void cmpp_t_out(CmppTokenizer * t, void const *z, unsigned int n){
+ g_debug(3,("CT_skipLevel() ?= %d\n",CT_skipLevel(t)));
+ g_debug(3,("CT_skip() ?= %d\n",CT_skip(t)));
if(!CT_skip(t)){
if(1!=fwrite(z, n, 1, g.out.pFile)){
int const err = errno;
@@ -631,18 +622,28 @@ void CmppLevel_push(CmppTokenizer * const t){
g.zDelim, CmppLevel_Max);
}
pPrev = &CT_level(t);
+ g_debug(3,("push from tokenizer level=%u flags=%04x\n", t->level.ndx, pPrev->flags));
p = &t->level.stack[++t->level.ndx];
*p = CmppLevel_empty;
p->token = t->token;
p->flags = (CmppLevel_F_INHERIT_MASK & pPrev->flags);
if(CLvl_skip(pPrev)) p->flags |= CmppLevel_F_ELIDE;
+ g_debug(3,("push to tokenizer level=%u flags=%04x\n", t->level.ndx, p->flags));
}
void CmppLevel_pop(CmppTokenizer * const t){
if(!t->level.ndx){
fatal("Internal error: CmppLevel_pop() at the top of the stack");
}
+ g_debug(3,("pop from tokenizer level=%u, flags=%04x skipLevel?=%d\n", t->level.ndx,
+ t->level.stack[t->level.ndx].flags, CT_skipLevel(t)));
+ g_debug(3,("CT_skipLevel() ?= %d\n",CT_skipLevel(t)));
+ g_debug(3,("CT_skip() ?= %d\n",CT_skip(t)));
t->level.stack[t->level.ndx--] = CmppLevel_empty;
+ g_debug(3,("pop to tokenizer level=%u, flags=%04x\n", t->level.ndx,
+ t->level.stack[t->level.ndx].flags));
+ g_debug(3,("CT_skipLevel() ?= %d\n",CT_skipLevel(t)));
+ g_debug(3,("CT_skip() ?= %d\n",CT_skip(t)));
}
CmppLevel * CmppLevel_get(CmppTokenizer * const t){
@@ -776,7 +777,7 @@ int db_define_has(const char * zName){
assert(SQLITE_DONE==rc);
rc = 0;
}
- g_debug(1,("define has [%s] = %d\n",zName, rc));
+ g_debug(1,("defined [%s] ?= %d\n",zName, rc));
sqlite3_clear_bindings(g.stmt.defHas);
sqlite3_reset(g.stmt.defHas);
return rc;
@@ -1220,10 +1221,11 @@ static void cmpp_kwd_if(CmppKeyword const * pKw, CmppTokenizer *t){
if(TT_IfNot==pKw->ttype || TT_ElifNot==pKw->ttype) buul = !buul;
if(buul){
CT_pstate(t) = tmpState = TS_IfPassed;
- CT_skipLevel(t) = 0;
+ CT_skipLevel(t) = 0;
}else{
CT_pstate(t) = TS_If /* also for TT_IfNot, TT_Elif, TT_ElifNot */;
CT_skipLevel(t) = 1;
+ g_debug(3,("setting CT_skipLevel = 1 @ level %d\n", t->level.ndx));
}
if(TT_If==pKw->ttype || TT_IfNot==pKw->ttype){
unsigned const lvlIf = t->level.ndx;
@@ -1234,10 +1236,13 @@ static void cmpp_kwd_if(CmppKeyword const * pKw, CmppTokenizer *t){
assert(TT_EndIf == t->token.ttype);
break;
}
+#if 0
if(TS_IfPassed==tmpState){
tmpState = TS_Start;
t->level.stack[lvlIf].flags |= CmppLevel_F_ELIDE;
+ g_debug(1,("Setting ELIDE for TS_IfPassed @ lv %d (lvlIf=%d)\n", t->level.ndx, lvlIf));
}
+#endif
}
if(lvlIf <= t->level.ndx){
cmpp_kwd__err_prefix(pKw, t, NULL);
diff --git a/ext/wasm/dist.make b/ext/wasm/dist.make
index 8b1a2d4f1..7073c24b7 100644
--- a/ext/wasm/dist.make
+++ b/ext/wasm/dist.make
@@ -56,6 +56,21 @@ dist.common.extras := \
$(dir.common)/SqliteTestUtil.js
.PHONY: dist snapshot
+# DIST_STRIP_COMMENTS $(call)able to be used in stripping C-style
+# from the dist copies of certain files.
+#
+# $1 = source js file
+# $2 = flags for $(bin.stripcomments)
+define DIST_STRIP_COMMENTS
+$(bin.stripccomments) $(2) < $(1) > $(dist-dir.jswasm)/$(notdir $(1)) || exit;
+endef
+# STRIP_K1.js = list of JS files which need to be passed through
+# $(bin.stripcomments) with a single -k flag.
+STRIP_K1.js := $(sqlite3-worker1.js) $(sqlite3-worker1-promiser.js) \
+ $(sqlite3-worker1-bundler-friendly.js) $(sqlite3-worker1-promiser-bundler-friendly.js)
+# STRIP_K2.js = list of JS files which need to be passed through
+# $(bin.stripcomments) with two -k flags.
+STRIP_K2.js := $(sqlite3.js) $(sqlite3.mjs) $(sqlite3-bundler-friendly.mjs)
########################################################################
# dist: create the end-user deliverable archive.
#
@@ -71,7 +86,7 @@ dist.common.extras := \
# target name equal to the archive name.
dist: \
$(bin.stripccomments) $(bin.version-info) \
- $(dist.build) \
+ $(dist.build) $(STRIP_K1.js) $(STRIP_K2.js) \
$(MAKEFILE) $(MAKEFILE.dist)
@echo "Making end-user deliverables..."
@rm -fr $(dist-dir.top)
@@ -80,10 +95,8 @@ dist: \
@cp -p README-dist.txt $(dist-dir.top)/README.txt
@cp -p index-dist.html $(dist-dir.top)/index.html
@cp -p $(dist.jswasm.extras) $(dist-dir.jswasm)
- @$(bin.stripccomments) -k -k < $(sqlite3.js) \
- > $(dist-dir.jswasm)/$(notdir $(sqlite3.js))
- @$(bin.stripccomments) -k -k < $(sqlite3.mjs) \
- > $(dist-dir.jswasm)/$(notdir $(sqlite3.mjs))
+ @$(foreach JS,$(STRIP_K1.js),$(call DIST_STRIP_COMMENTS,$(JS),-k))
+ @$(foreach JS,$(STRIP_K2.js),$(call DIST_STRIP_COMMENTS,$(JS),-k -k))
@cp -p $(dist.common.extras) $(dist-dir.common)
@set -e; \
vnum=$$($(bin.version-info) --download-version); \
diff --git a/ext/wasm/index.html b/ext/wasm/index.html
index 767cc5e74..969d9553e 100644
--- a/ext/wasm/index.html
+++ b/ext/wasm/index.html
@@ -131,7 +131,7 @@
</style>
<script>//Assign a distinct target tab name for each test page...
document.querySelectorAll('a').forEach(function(e){
- e.target = e.href;
+ e.target = e.href.replace(/^http*:\/\/[^/]+\//, '');
});
</script>
</body>
diff --git a/ext/wasm/tester1-worker.html b/ext/wasm/tester1-worker.html
index a9c12d72c..03e1f02b0 100644
--- a/ext/wasm/tester1-worker.html
+++ b/ext/wasm/tester1-worker.html
@@ -11,8 +11,12 @@
</head>
<body>
<h1 id='color-target'>sqlite3 tester #1: Worker thread</h1>
- <div>See <a href='tester1.html' target='tester1.html'>tester1.html</a>
- for the UI-thread variant.</div>
+ <div>Variants:
+ <a href='tester1.html' target='tester1.html'>conventional UI thread</a>,
+ <a href='tester1-worker.html' target='tester1-worker.html'>conventional worker</a>,
+ <a href='tester1-esm.html' target='tester1-esm.html'>ESM in UI thread</a>,
+ <a href='tester1-worker.html?esm' target='tester1-worker.html?esm'>ESM worker</a>
+ </div>
<div class='input-wrapper'>
<input type='checkbox' id='cb-log-reverse'>
<label for='cb-log-reverse'>Reverse log order?</label>
diff --git a/ext/wasm/tester1.c-pp.html b/ext/wasm/tester1.c-pp.html
index 535e58962..bbdd8b223 100644
--- a/ext/wasm/tester1.c-pp.html
+++ b/ext/wasm/tester1.c-pp.html
@@ -16,8 +16,12 @@ UI thread
<style></style>
</head>
<body><h1 id='color-target'></h1>
- <div>See <a href='tester1-worker.html' target='tester1-worker.html'>tester1-worker.html</a>
- for the Worker-thread variant.</div>
+ <div>Variants:
+ <a href='tester1.html' target='tester1.html'>conventional UI thread</a>,
+ <a href='tester1-worker.html' target='tester1-worker.html'>conventional worker</a>,
+ <a href='tester1-esm.html' target='tester1-esm.html'>ESM in UI thread</a>,
+ <a href='tester1-worker.html?esm' target='tester1-worker.html?esm'>ESM worker</a>
+ </div>
<div class='input-wrapper'>
<input type='checkbox' id='cb-log-reverse'>
<label for='cb-log-reverse'>Reverse log order?</label>
diff --git a/ext/wasm/tester1.c-pp.js b/ext/wasm/tester1.c-pp.js
index 7f5de5166..42d1167b6 100644
--- a/ext/wasm/tester1.c-pp.js
+++ b/ext/wasm/tester1.c-pp.js
@@ -1192,13 +1192,13 @@ self.sqlite3InitModule = sqlite3InitModule;
rc = capi.sqlite3_db_status(this.db, capi.SQLITE_DBSTATUS_LOOKASIDE_USED,
pCur, pHi, 0);
T.assert(0===rc);
- if(wasm.peek32(pCur)){
- warn("Cannot test db_config(SQLITE_DBCONFIG_LOOKASIDE)",
- "while lookaside memory is in use.");
- }else{
+ if(!wasm.peek32(pCur)){
rc = capi.sqlite3_db_config(this.db, capi.SQLITE_DBCONFIG_LOOKASIDE,
0, 4096, 12);
T.assert(0 === rc);
+ }else{
+ console.debug("Cannot test db_config(SQLITE_DBCONFIG_LOOKASIDE)",
+ "while lookaside memory is in use.");
}
wasm.poke32([pCur, pHi], 0);
let [vCur, vHi] = wasm.peek32(pCur, pHi);
@@ -1412,14 +1412,26 @@ self.sqlite3InitModule = sqlite3InitModule;
db.selectValue("SELECT "+Number.MIN_SAFE_INTEGER)).
assert(Number.MAX_SAFE_INTEGER ===
db.selectValue("SELECT "+Number.MAX_SAFE_INTEGER));
-
counter = 0;
- db.exec({
+ let rv = db.exec({
sql: "SELECT a FROM t",
callback: ()=>(1===++counter),
});
- T.assert(2===counter,
+ T.assert(db === rv)
+ .assert(2===counter,
"Expecting exec step() loop to stop if callback returns false.");
+ /** If exec() is passed neither callback nor returnValue but
+ is passed an explicit rowMode then the default returnValue
+ is the whole result set, as if an empty resultRows option
+ had been passed. */
+ rv = db.exec({
+ sql: "SELECT -1 UNION ALL SELECT -2 UNION ALL SELECT -3 ORDER BY 1 DESC",
+ rowMode: 0
+ });
+ T.assert(Array.isArray(rv)).assert(3===rv.length)
+ .assert(-1===rv[0]).assert(-3===rv[2]);
+ rv = db.exec("SELECT 1 WHERE 0",{rowMode: 0});
+ T.assert(Array.isArray(rv)).assert(0===rv.length);
if(wasm.bigIntEnabled && haveWasmCTests()){
const mI = wasm.xCall('sqlite3_wasm_test_int64_max');
const b = BigInt(Number.MAX_SAFE_INTEGER * 2);
@@ -2960,6 +2972,14 @@ self.sqlite3InitModule = sqlite3InitModule;
////////////////////////////////////////////////////////////////////////
log("Loading and initializing sqlite3 WASM module...");
+ if(0){
+ self.sqlite3ApiConfig = {
+ debug: ()=>{},
+ log: ()=>{},
+ warn: ()=>{},
+ error: ()=>{}
+ }
+ }
if(!self.sqlite3InitModule && !isUIThread()){
/* Vanilla worker, as opposed to an ES6 module worker */
/*
@@ -2992,6 +3012,8 @@ self.sqlite3InitModule = sqlite3InitModule;
}).then(function(sqlite3){
//console.log('sqlite3 =',sqlite3);
log("Done initializing WASM/JS bits. Running tests...");
+ sqlite3.config.warn("Installing sqlite3 bits as global S for local dev/test purposes.");
+ self.S = sqlite3;
capi = sqlite3.capi;
wasm = sqlite3.wasm;
log("sqlite3 version:",capi.sqlite3_libversion(),
diff --git a/ext/wasm/tests/opfs/concurrency/index.html b/ext/wasm/tests/opfs/concurrency/index.html
index 9a826c6e1..595ab2452 100644
--- a/ext/wasm/tests/opfs/concurrency/index.html
+++ b/ext/wasm/tests/opfs/concurrency/index.html
@@ -26,9 +26,8 @@
workload with <code>interval=N</code> (milliseconds). Set the
number of worker iterations with <code>iterations=N</code>.
Enable OPFS VFS verbosity with <code>verbose=1-3</code> (output
- goes to the dev console). Enable/disable "unlock ASAP" mode
- (higher concurrency, lower speed)
- with <code>unlock-asap=0-1</code>.
+ goes to the dev console). Disable/enable "unlock ASAP" mode
+ (higher concurrency, lower speed) with <code>unlock-asap=0-1</code>.
</p>
<p>Achtung: if it does not start to do anything within a couple of
seconds, check the dev console: Chrome sometimes fails to load
diff --git a/main.mk b/main.mk
index c2cde0756..628f3d162 100644
--- a/main.mk
+++ b/main.mk
@@ -298,7 +298,6 @@ TESTSRC = \
$(TOP)/src/test4.c \
$(TOP)/src/test5.c \
$(TOP)/src/test6.c \
- $(TOP)/src/test7.c \
$(TOP)/src/test8.c \
$(TOP)/src/test9.c \
$(TOP)/src/test_autoext.c \
@@ -327,7 +326,6 @@ TESTSRC = \
$(TOP)/src/test_quota.c \
$(TOP)/src/test_rtree.c \
$(TOP)/src/test_schema.c \
- $(TOP)/src/test_server.c \
$(TOP)/src/test_sqllog.c \
$(TOP)/src/test_superlock.c \
$(TOP)/src/test_syscall.c \
@@ -931,6 +929,10 @@ tcltest: ./testfixture$(EXE)
testrunner: testfixture$(EXE)
./testfixture$(EXE) $(TOP)/test/testrunner.tcl
+# Runs both fuzztest and testrunner, consecutively.
+#
+devtest: testfixture$(EXE) fuzztest testrunner
+
# A very quick test using only testfixture and omitting all the slower
# tests. Designed to run in under 3 minutes on a workstation.
#
diff --git a/manifest b/manifest
index 7f9f23a96..34aa88c15 100644
--- a/manifest
+++ b/manifest
@@ -1,11 +1,11 @@
C Merge\strunk\sinto\swasi-patches\sbranch.
-D 2023-01-27T05:37:24.147
+D 2023-02-06T22:25:18.370
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
-F Makefile.in 7608208f680a288a7e84717a74d05db789dbf4deba2c905ef7c17482f2bc4ef6
+F Makefile.in 8cf9ca38d9a62173d36fe68370b0a95a1e83b93723d05dd76de7d4d7d6115873
F Makefile.linux-gcc f609543700659711fbd230eced1f01353117621dccae7b9fb70daa64236c5241
-F Makefile.msc 6de67bb5a8e849f9a7a11085366cc8daf99845fa21368e89b3cd195abd62cd2a
+F Makefile.msc 26e2fa6144907df27487b7c25767a87dbc5c4a312ccc382dbf44648f40073623
F README.md 8b8df9ca852aeac4864eb1e400002633ee6db84065bd01b78c33817f97d31f5e
F VERSION 413ec94920a487ae32c9a2a8819544d690662d6f7c7ce025c0d0b8a1e74fa9db
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
@@ -92,7 +92,7 @@ F ext/fts5/fts5_buffer.c 3001fbabb585d6de52947b44b455235072b741038391f830d6b7292
F ext/fts5/fts5_config.c 501e7d3566bc92766b0e11c0109a7c5a6146bc41144195459af5422f6c2078aa
F ext/fts5/fts5_expr.c 40174a64829d30cc86e8266306ad24980f6911edd5ca0b8c1ce7821ea1341b88
F ext/fts5/fts5_hash.c d4fb70940359f2120ccd1de7ffe64cc3efe65de9e8995b822cd536ff64c96982
-F ext/fts5/fts5_index.c e879315306f368b5681d32cffc90770b124649814214615b88d79ddd957f6747
+F ext/fts5/fts5_index.c 8a78d6c57a1ac1b4652e88ca994ac024a8652335431e12443f241fa61c6c6049
F ext/fts5/fts5_main.c fe67b6fb2ef134d9dbfa3941c63f777d755b075449be1863cb913a7f8754cb69
F ext/fts5/fts5_storage.c 76c6085239eb44424004c022e9da17a5ecd5aaec859fba90ad47d3b08f4c8082
F ext/fts5/fts5_tcl.c b1445cbe69908c411df8084a10b2485500ac70a9c747cdc8cda175a3da59d8ae
@@ -174,6 +174,7 @@ F ext/fts5/test/fts5multiclient.test 5ff811c028d6108045ffef737f1e9f05028af2458e4
F ext/fts5/test/fts5near.test 211477940142d733ac04fad97cb24095513ab2507073a99c2765c3ddd2ef58bd
F ext/fts5/test/fts5onepass.test f9b7d9b2c334900c6542a869760290e2ab5382af8fbd618834bf1fcc3e7b84da
F ext/fts5/test/fts5optimize.test 36a752d24c818792032e4ff502936fc9cc5ef938721696396fdc79214b2717f1
+F ext/fts5/test/fts5optimize2.test 8ec4fccee2b33f3a7dbd431064b2e79f11e636345e3c997683eb158d6975999c
F ext/fts5/test/fts5phrase.test 13e5d8e9083077b3d9c74315b3c92ec723cc6eb37c8155e0bfe1bba00559f07b
F ext/fts5/test/fts5plan.test b65cfcca9ddd6fdaa118c61e17aeec8e8433bc5b6bb307abd116514f79c49c5a
F ext/fts5/test/fts5porter.test 8d08010c28527db66bc3feebd2b8767504aaeb9b101a986342fa7833d49d0d15
@@ -264,7 +265,7 @@ F ext/misc/amatch.c e3ad5532799cee9a97647f483f67f43b38796b84b5a8c60594fe782a4338
F ext/misc/anycollseq.c 5ffdfde9829eeac52219136ad6aa7cd9a4edb3b15f4f2532de52f4a22525eddb
F ext/misc/appendvfs.c 9642c7a194a2a25dca7ad3e36af24a0a46d7702168c4ad7e59c9f9b0e16a3824
F ext/misc/base64.c d43d2b209c8ab70ca3f860104bb353b0f52a1c5462a2466140025c954e4f3ea7 x
-F ext/misc/base85.c 4b53d66c50e120e8697dd2a8ea6ddbc8750a4a1f6bcc6e0b7202a3998b0852bc
+F ext/misc/base85.c 77dfd5813d23ea561d0348f922583888e78f8eaeb2b9a4a28226d092389890b8
F ext/misc/basexx.c 5e859e1820620aa8080fb9145eb47089de426ae808f6abb01a8e12921c3a8e67
F ext/misc/blobio.c a867c4c4617f6ec223a307ebfe0eabb45e0992f74dd47722b96f3e631c0edb2a
F ext/misc/btreeinfo.c d28ce349b40054eaa9473e835837bad7a71deec33ba13e39f963d50933bfa0f9
@@ -318,54 +319,54 @@ F ext/misc/wholenumber.c a838d1bea913c514ff316c69695efbb49ea3b8cb37d22afc57f73b6
F ext/misc/zipfile.c f98239261488397618ce4754c500626d1de20cd2d44bf2f2d571d7ddaab668a7
F ext/misc/zorder.c b0ff58fa643afa1d846786d51ea8d5c4b6b35aa0254ab5a82617db92f3adda64
F ext/rbu/rbu.c 801450b24eaf14440d8fd20385aacc751d5c9d6123398df41b1b5aa804bf4ce8
-F ext/rbu/rbu1.test c62904bd9526dcdc3496a21199aaf14ae191bbadbf67f076bf16be6b3f2115c2
-F ext/rbu/rbu10.test 06d2bc934a03a0978e750cc9c95b419d9b0bcbec1fc77128e33e377c3a73240b
-F ext/rbu/rbu11.test 5c834cf491086b45e071eabf71f708febc143e86a384a92de69e0b1a4cace144
-F ext/rbu/rbu12.test 29f8b2118f6c96fac3755bd6d2b55c2db24f878b1f11fbfbe294f3a230a3dcdc
-F ext/rbu/rbu13.test 1285298e3360ec74511764841b3c174dcfe21da2f618c22febf1a20abd0365c2
-F ext/rbu/rbu14.test 4a7bf0b3a4516d3ab0bc0ba4ceb53eb7e3324147ccda152e561060f659dbba31
-F ext/rbu/rbu3.test d6c6cc7a1326e8e23b9820f30bd3054f22092e503fadfd2a660ae006653f6d80
-F ext/rbu/rbu5.test 724b38ea5f722e3d22dc76343860bd998bb676c3f78c4bc8175df5c5d7720e23
-F ext/rbu/rbu6.test 401064236d3cf86b7edc01c586d7c5554f48553946fbfa1a3af35d7e47dce9e3
-F ext/rbu/rbu7.test ae25f47b56f178197fc1098537a35a39176cc73d1629b03dc9d795929fc36ec2
-F ext/rbu/rbu8.test b98a6fc58ead84a0e6ddee775b9702cd981f318d5d4fd1d4df0fa0c40db7251b
-F ext/rbu/rbu9.test 0e4d985e25620d61920597e8ea69c871c9e8c1f5a0be2ae9fa70bb641d74378c
-F ext/rbu/rbuA.test b34a90cb495682c25b5fc03a9d5e7a4fc99541c29256f25e2e2a4f6542b4f5b3
-F ext/rbu/rbuB.test 8d1f141711be8122739853d876af4306bc756d925499577f9b917ec1f1c5ae65
-F ext/rbu/rbuC.test 80f1cc2fb74f44b1128fd0ed8eedab3a76fefeb72a947860e2869ef76fc8dc6b
-F ext/rbu/rbu_common.tcl 60d904133ff843fe72cc0514e9dd2486707181e6e0fbab20979da28c48d21de9
-F ext/rbu/rbubusy.test f38ef557358564491b8a2ee70e4cad31e40fcea57a16f27bc56ba40a59bbde50
-F ext/rbu/rbucollate.test cac528a9a46318cba42e61258bb42660bbbf4fdb9a8c863de5a54ad0c658d197
-F ext/rbu/rbucrash.test 000981a1fe8a6e4d9a684232f6a129e66a3ef595f5ed74655e2f9c68ffa613b4
-F ext/rbu/rbucrash2.test efa143cc94228eb0266d3f1abfbee60a5838a84cef7cc3fcb8c145b74d96fd41
-F ext/rbu/rbudiff.test abe895a8d479e4d33acb40e244e3d8e2cd25f55a18dfa8b9f83e13d00073f600
-F ext/rbu/rbudor.test e3e8623926012f43eebe51fedf06a102df2640750d971596b052495f2536db20
-F ext/rbu/rbuexlock.test 4634a5526d02bf80b0c563f95774bd5af5783e3219ddeb30e413753c9a65510c
-F ext/rbu/rbuexpr.test 10d0420537c3bc7666e576d72adeffe7e86cfbb00dcc30aa9ce096c042415190
-F ext/rbu/rbufault.test 2d7f567b79d558f6e093c58808cab4354f8a174e3802f69e7790a9689b3c09f8
-F ext/rbu/rbufault2.test c81327a3ac2c385b9b954db3644d4e0df93eeebfc3de9f1f29975a1e73fd3d0c
-F ext/rbu/rbufault3.test b2fcc9db5c982b869f67d1d4688d8cb515d5b92f58011fff95665f2e62cec179
-F ext/rbu/rbufault4.test 03d2849c3df7d7bd14a622e789ff049e5080edd34a79cd432e01204db2a5930a
-F ext/rbu/rbufts.test 0ae8d1da191c75bd776b86e24456db0fb6e97b7c944259fae5407ea55d23c31d
-F ext/rbu/rbumisc.test 329986cf5dd51890c4eb906c2f960ebb773a79a64bed90f506b7c417825b37eb
-F ext/rbu/rbumulti.test bf28c1486b45215f5bf877cc560a4ddf50d22c4ed2ae267482bcf4af285bb115
-F ext/rbu/rbupartial.test f25df014b8dbe3c5345851fba6e66f79ab237f57dc201b2d5f0dbae658ae5a4c
-F ext/rbu/rbupass.test 1a8f635a9f6026f905a952e70a081811d8042de28165099d874832c1bf49d4b9
-F ext/rbu/rbuprogress.test 857cf1f8166c83ef977edb9ef4fc42d80f71fbd798652b46ae2f3a7031870f8d
-F ext/rbu/rburename.test a9b4aea612352b74c45de1757edd2ecb2079348b1d4cc734572dc29e55b1b376
-F ext/rbu/rburesume.test c46a77f031cbaec58abf0edbafbf75190cbafd3b941ed081cb6626ebb3e8230c
-F ext/rbu/rbusave.test f4190a1a86fccf84f723af5c93813365ae33feda35845ba107b59683d1cdd926
-F ext/rbu/rbusplit.test b37e7b40b38760881dc9c854bd40b4744c6b6cd74990754eca3bda0f407051e8
-F ext/rbu/rbutemplimit.test 8d18f1c7e8a04814d9dbe36f75f0d8921bcca00c18901d518bce5fc6bc98b877
-F ext/rbu/rbuvacuum.test 55e101e90168c2b31df6c9638fe73dc7f7cc666b6142266d1563697d79f73534
-F ext/rbu/rbuvacuum2.test 2643b58f4d8d3573db0f93faae18805a35ab162b4c55ff6b656062ff432ed55b
-F ext/rbu/rbuvacuum3.test 8addd82e4b83b4c93fa47428eae4fd0dbf410f8512c186f38e348feb49ba03dc
-F ext/rbu/rbuvacuum4.test a78898e438a44803eb2bc897ba3323373c9f277418e2d6d76e90f2f1dbccfd10
+F ext/rbu/rbu1.test 25870dd7db7eb5597e2b4d6e29e7a7e095abf332660f67d89959552ce8f8f255
+F ext/rbu/rbu10.test 7c22caa32c2ff26983ca8320779a31495a6555737684af7aba3daaf762ef3363
+F ext/rbu/rbu11.test 8584f80ef4be00e6beec4154f638847ffc40b5f2832ffadfbaf558ae40e50cb5
+F ext/rbu/rbu12.test ec63aa7bfc3c65c1d774bf4357ed731723827d211d9d7cb0efa171bbaeeebaf4
+F ext/rbu/rbu13.test 658edbc3325d79252a98b761fde95460e439f80e820ff29e10261e25f870b3b6
+F ext/rbu/rbu14.test 05dac607a62f62102f4db92135979a8a4501143638060019aca08c753822cf39
+F ext/rbu/rbu3.test 4a81517af618c3bf8c72e2d0b81c7c06acb8d176036d63d8e6669b73342306ae
+F ext/rbu/rbu5.test e21820b83822ae4c12afc2078a7b6c0523fb0cefe69c8b23c044cea91359e81c
+F ext/rbu/rbu6.test db2ff1f832dfc9e34c7910b17e157c2fe0e36024a3fe1119dd6437640dc07c82
+F ext/rbu/rbu7.test 5fa41734613a3ae1bb93d280eb3c341cff5dcc72652ff9ec7fbaa12425eda9c2
+F ext/rbu/rbu8.test 93d45824dab8f68872b6d22acc787ab18ba92ef0fa0d430be37653d0246c7a0d
+F ext/rbu/rbu9.test 4b66f0705442711a44b54ef2cc3c59952f1ea15f12e34442681bdb1a6eb33065
+F ext/rbu/rbuA.test 3f8fdd4ae7b9a0571af7361cd88359254f63e445ac4acfe395173e31d7e3fc31
+F ext/rbu/rbuB.test c639803bbc1dc9358afe6abe046dc4d3e9965238b75239b04e3a8e33e3e90f85
+F ext/rbu/rbuC.test 5326ea3954754c68fd518beb70d3e6b6690af53e1a5fa102d650e4110b26b4c5
+F ext/rbu/rbu_common.tcl 815cc97be0e67e96f3ccaff74d951eef89cefc34cec7d93d64f01d9402121545
+F ext/rbu/rbubusy.test 88298187ad35aac9084436d85ca66b3722f96eaa704a09cfe5f931d452ab7237
+F ext/rbu/rbucollate.test 9852ec5e5ba7f3b04ce849a24ef7298e03ae0f16e58e6031d0f845234559feec
+F ext/rbu/rbucrash.test d2b5d619d9281c89cad74401b73b46172daa89906940b1d739c813ddc0cd2cf5
+F ext/rbu/rbucrash2.test 0a1a72223d880215ce2893a3260320c31a9358d23cb124c610e4f0d984a93285
+F ext/rbu/rbudiff.test 8b8b8b569c68fc880134e0fac4bf6b4b7a907aea4cc6eacf7e1d45e1d47b6aac
+F ext/rbu/rbudor.test 293a192e668bb8e9c7c9704b080c1086ee17496f768e0f1823049e7d02651d1b
+F ext/rbu/rbuexlock.test e3ece733cc8e0a6cb08533a41ed6f562438539ed309028c63375a5adee4a263b
+F ext/rbu/rbuexpr.test 2c91617509c88b6e9030f7bf6ff720df26032fcd801adc25533feae726a57382
+F ext/rbu/rbufault.test c51de14067cfe867849530d3d1718ffeb28522f28d52937f95dd7bc2116eb42e
+F ext/rbu/rbufault2.test 8cc8f6298d2d7d20080b2c77e65b607af8b89839f9d87c0972b27e6442edc258
+F ext/rbu/rbufault3.test d14ff46e050816ce43c4ed320a0927712636ac11bf48bfc5f74601f183af5445
+F ext/rbu/rbufault4.test 39fbf093b7e16aae85dc309262ec570d217a1578538c1c74dd621e5451c083d6
+F ext/rbu/rbufts.test df754d2f96c22d1da8b5d685b4a4a49863971920856d17620cef724e3a9b6edd
+F ext/rbu/rbumisc.test 6641749e42c83062824c86b3d03a47f8ec35760f341bc023f53e612655b0a8af
+F ext/rbu/rbumulti.test 6f6cdd9b3775108aada5216762cbbd7b5d5caa7cb620b3e6e1b8ace81286a2e0
+F ext/rbu/rbupartial.test 4ed7789f47128c8aa7ff58445face8a070cef852993afe03c863913f3cea8729
+F ext/rbu/rbupass.test 2ee86581a441f3b4b449b99a2dc203d5d6a08750dd2ee9ab6a02743e238d3c8a
+F ext/rbu/rbuprogress.test db8bb26a8123d35f52acfc3984b56caa31c8fcd1fa3589991b9c8e8a68e64b59
+F ext/rbu/rburename.test 8d8a6a6ba896338d0610658e1f60e8055a181d5913e1e21c41b866a8f15bb7cd
+F ext/rbu/rburesume.test 1403752d152b55efb7fc25749c0fccc790061371ec9ffe428cc04f8a69bb834c
+F ext/rbu/rbusave.test 588b618dad9d65c4b13d03a79931de82213503fedc26bdf5789c996ecf427fba
+F ext/rbu/rbusplit.test a6dedd23cf37bcf2e8646d9d7139846e96d60d92f9bc6d6ba6ca8c24c0bd1f72
+F ext/rbu/rbutemplimit.test 4980df2d4b74f4dd982add8f78809106154ef5a3c4bdce747422ab0b0481e029
+F ext/rbu/rbuvacuum.test 542561741ff2b262e3694bc6012b44694ee62c545845319a06f323783b15311e
+F ext/rbu/rbuvacuum2.test ae097d04feb041446a74fac94b24bffeb3fdd60e32b848c5611e507ab702b81b
+F ext/rbu/rbuvacuum3.test 3ce42695fdf21aaa3499e857d7d4253bc499ad759bcd6c9362042c13cd37d8de
+F ext/rbu/rbuvacuum4.test ffccd22f67e2d0b380d2889685742159dfe0d19a3880ca3d2d1d69eefaebb205
F ext/rbu/sqlite3rbu.c 348bb6251e6ec459de102f8b2dd50789a98643ef7a28e56e4c787ac9659c15ea
F ext/rbu/sqlite3rbu.h 9d923eb135c5d04aa6afd7c39ca47b0d1d0707c100e02f19fdde6a494e414304
F ext/rbu/test_rbu.c ee6ede75147bc081fe9bc3931e6b206277418d14d3fbceea6fdc6216d9b47055
F ext/recover/dbdata.c dc25628e405c86936c597e28f3e6f56a257029c3034c5ef7f6b10f7c02f41018
-F ext/recover/recover1.test 2a2df2943d6696f9487e75868feae4b1511c4a511b102854ba0d2af0326d9dfb
+F ext/recover/recover1.test 2072993624d5e32fef20ae03b17fc06c02bcb344421fe17bb329b24d2a51e647
F ext/recover/recover_common.tcl a61306c1eb45c0c3fc45652c35b2d4ec19729e340bdf65a272ce4c229cefd85a
F ext/recover/recoverclobber.test 3ba6c0c373c5c63d17e82eced64c05c57ccaf26c1abe1ca7141334022a79f32e
F ext/recover/recovercorrupt.test 64c081ad1200ae77b447da99eb724785d6bf71715f394543dc7689642e92bf49
@@ -413,7 +414,7 @@ F ext/rtree/rtreeH.test 0885151ee8429242625600ae47142cca935332c70a06737f35af53a7
F ext/rtree/rtreeI.test 608e77f7fde9be5a12eae316baef640fffaafcfa90a3d67443e78123e19c4ca4
F ext/rtree/rtree_perf.tcl 6c18c1f23cd48e0f948930c98dfdd37dfccb5195
F ext/rtree/rtree_util.tcl db734b4c5e75fed6acc56d9701f2235345acfdec750b5fc7b587936f5f6bceed
-F ext/rtree/rtreecheck.test e53fc47fb727d7ffa17ea79fecfe3e709815b65233c11464a0b8f1f4ac0cb50a
+F ext/rtree/rtreecheck.test 4e859a9cd49d2353ff10c122f72183ec37b400e35d2b0349b2e9696649b6a00e
F ext/rtree/rtreecirc.test aec664eb21ae943aeb344191407afff5d392d3ae9d12b9a112ced0d9c5de298e
F ext/rtree/rtreeconnect.test 225ad3fcb483d36cbee423a25052a6bbae762c9576ae9268332360c68c170d3d
F ext/rtree/rtreedoc.test 27a5703cb1200f6f69051de68da546cef3dfdcf59be73afadfc50b9f9c9960d9
@@ -461,38 +462,38 @@ F ext/session/sessionstat1.test 218d351cf9fcd6648f125a26b607b140310160184723c266
F ext/session/sessionwor.test 6fd9a2256442cebde5b2284936ae9e0d54bde692d0f5fd009ecef8511f4cf3fc
F ext/session/sqlite3session.c 13bdc093416cd284d4075328dd8599eb59bcedc23a21d561a15d78805c5866bf
F ext/session/sqlite3session.h 0907de79bc13a2e3af30a6dc29acc60792a3eaf7d33d44cf52500d0f3c2b2171
-F ext/session/test_session.c 94364b91cf4571d320ef5b1e04075d2c58c79b63afdf20c9e470555a691ca5b1
+F ext/session/test_session.c 2de472b4d7e62e85ca1992094612725e2450a77dbf7523db64de94197812462e
F ext/userauth/sqlite3userauth.h 7f3ea8c4686db8e40b0a0e7a8e0b00fac13aa7a3
F ext/userauth/user-auth.txt e6641021a9210364665fe625d067617d03f27b04
F ext/userauth/userauth.c 7f00cded7dcaa5d47f54539b290a43d2e59f4b1eb5f447545fa865f002fc80cb
F ext/wasm/EXPORTED_FUNCTIONS.fiddle.in 27450c8b8c70875a260aca55435ec927068b34cef801a96205adb81bdcefc65c
-F ext/wasm/GNUmakefile 4ce83fdda22c6fde2bd311e87d6bec7469ca3859e758d1f34cd601e64c539efa
-F ext/wasm/README-dist.txt dab111337028af58ec11cb35c2e1a82398217c399c7499fefab0509a0499a5d7
+F ext/wasm/GNUmakefile 5418b4702f4ad0f2162a7e0d128042e8d9219827e3d36978bd2dd6e26ce8f68e
+F ext/wasm/README-dist.txt 6382cb9548076fca472fb3330bbdba3a55c1ea0b180ff9253f084f07ff383576
F ext/wasm/README.md ef39861aa21632fdbca0bdd469f78f0096f6449a720f3f39642594af503030e9
F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-api d6a5078f48a5301ed17b9a30331075d9b2506e1360c1f0dee0c7816c10acd9ab
F ext/wasm/api/EXPORTED_RUNTIME_METHODS.sqlite3-api 1ec3c73e7d66e95529c3c64ac3de2470b0e9e7fbf7a5b41261c367cf4f1b7287
F ext/wasm/api/README.md 77a2f1f2fc60a35def7455dffc8d3f2c56385d6ac5c6cecc60fa938252ea2c54
-F ext/wasm/api/extern-post-js.c-pp.js 8923f76c3d2213159e12d641dc750523ead5c848185dc4996fae5cc12397f88d
+F ext/wasm/api/extern-post-js.c-pp.js 44a3a169f55a8dba42cf688954b2625b9b9e6174f2ff02d4918a2ca8c3beab7f
F ext/wasm/api/extern-pre-js.js cc61c09c7a24a07dbecb4c352453c3985170cec12b4e7e7e7a4d11d43c5c8f41
F ext/wasm/api/post-js-footer.js cd0a8ec768501d9bd45d325ab0442037fb0e33d1f3b4f08902f15c34720ee4a1
F ext/wasm/api/post-js-header.js 47b6b281f39ad59fa6e8b658308cd98ea292c286a68407b35ff3ed9cfd281a62
-F ext/wasm/api/pre-js.c-pp.js b88499dc303c21fc3f55f2c364a0f814f587b60a95784303881169f9e91c1d5f
-F ext/wasm/api/sqlite3-api-cleanup.js 680d5ccfff54459db136a49b2199d9f879c8405d9c99af1dda0cc5e7c29056f4
+F ext/wasm/api/pre-js.c-pp.js 9ece5de1bb0509f0a8a360712fcc9c1291b9516c0be5bd66acedd6edbcec37a1
+F ext/wasm/api/sqlite3-api-cleanup.js 2d63eb84267a1d15ce002e083d6396a521471da8af3afa76846d50f39a54d65e
F ext/wasm/api/sqlite3-api-glue.js 0a93e58aabf52b32ddccbb107a1fd4552f2505e103ab63396c4d0a0743704785
-F ext/wasm/api/sqlite3-api-oo1.js e9fba119e9b1716b3f731838ed1ab18741401bcf4c51d2a4a6e9d1d23cf9d771
-F ext/wasm/api/sqlite3-api-prologue.js 69a74f2777aaafafc07ad2c922674fe3197ef63c921a3262b4772f937e7eb14a
-F ext/wasm/api/sqlite3-api-worker1.js c462199c40358f00f93e326206bddc756c52b93f2cb60ffb63f54fe4f9a9e977
+F ext/wasm/api/sqlite3-api-oo1.js 9b50c188513c70438a497914089cfeac79b6ac2d73501775538f9e467325ea15
+F ext/wasm/api/sqlite3-api-prologue.js 5cc817b67a774bfa3c47d4c2fa484b10b24b5529a66094b35546f3ebba1ef646
+F ext/wasm/api/sqlite3-api-worker1.js 9551f04cdfcde354e5a6ccb48951e007d618abb4e95758297b7fd44ccffdf89f
F ext/wasm/api/sqlite3-license-version-header.js a661182fc93fc2cf212dfd0b987f8e138a3ac98f850b1112e29b5fbdaecc87c3
F ext/wasm/api/sqlite3-opfs-async-proxy.js 7795b84b66a7a8dedc791340709b310bb497c3c72a80bef364fa2a58e2ddae3f
F ext/wasm/api/sqlite3-v-helper.js 6f6c3e390a72e08b0a5b16a0d567d7af3c04d172831853a29d72a6f1dd40ff24
-F ext/wasm/api/sqlite3-vfs-opfs.c-pp.js 50e4f6103dc65556e3e040f9e80eb8f14bfc6f979fa018952859f7755e201b27
+F ext/wasm/api/sqlite3-vfs-opfs.c-pp.js ca291837840b3eae3a60810721a7970c98f7c7cd3ee1c879acb7e91f1e3fe65a
F ext/wasm/api/sqlite3-wasi.h 25356084cfe0d40458a902afb465df8c21fc4152c1d0a59b563a3fba59a068f9
F ext/wasm/api/sqlite3-wasm.c 76625a70937a8522d014ef686c32db5b53a3ee61850323f5c601d2ac39fe52fe
-F ext/wasm/api/sqlite3-worker1-promiser.js 0c7a9826dbf82a5ed4e4f7bf7816e825a52aff253afbf3350431f5773faf0e4b
-F ext/wasm/api/sqlite3-worker1.js 9d3d3dfc70bff8998c1d8ff6d881cf1c3d52468d635417f02796151fe6b31cd7
+F ext/wasm/api/sqlite3-worker1-promiser.c-pp.js c5ac33e39f21a3481812d7333ca6e18853640d423a01960ca8dbc6e7c5c3c21c w ext/wasm/api/sqlite3-worker1-promiser.js
+F ext/wasm/api/sqlite3-worker1.c-pp.js 77b3835192469e9da23926ec8f78fb0b114a51d048dc54388709ac22b5c5f0a0 w ext/wasm/api/sqlite3-worker1.js
F ext/wasm/batch-runner.html 4deeed44fe41496dc6898d9fb17938ea3291f40f4bfb977e29d0cef96fbbe4c8
F ext/wasm/batch-runner.js 0dad6a02ad796f1003d3b7048947d275c4d6277f63767b8e685c27df8fdac93e
-F ext/wasm/c-pp.c 92285f7bce67ed7b7020b40fde8ed0982c442b63dc33df9dfd4b658d4a6c0779
+F ext/wasm/c-pp.c 6d80d8569d85713effe8b0818a3cf51dc779e3f0bf8dc88771b8998552ee25b4
F ext/wasm/common/SqliteTestUtil.js d8bf97ecb0705a2299765c8fc9e11b1a5ac7f10988bbf375a6558b7ca287067b
F ext/wasm/common/emscripten.css 11bd104b6c0d597c67d40cc8ecc0a60dae2b965151e3b6a37fa5708bac3acd15
F ext/wasm/common/testing.css 0ff15602a3ab2bad8aef2c3bd120c7ee3fd1c2054ad2ace7e214187ae68d926f
@@ -506,14 +507,14 @@ F ext/wasm/demo-worker1-promiser.html 1de7c248c7c2cfd4a5783d2aa154bce62d74c6de98
F ext/wasm/demo-worker1-promiser.js b99c550763fa792c204e9a7cceadd976004036d9fc3e22fab7051712e30d207d
F ext/wasm/demo-worker1.html 2c178c1890a2beb5a5fecb1453e796d067a4b8d3d2a04d65ca2eb1ab2c68ef5d
F ext/wasm/demo-worker1.js a619adffc98b75b66c633b00f747b856449a134a9a0357909287d80a182d70fa
-F ext/wasm/dist.make 5523b02e824db5ab8176e3eedc2e709fe1204d8f4d6e52e8321cdf6830114b72
+F ext/wasm/dist.make f55f9c9e1980ea11a59964e59535c66175a17f004d1c2e274522c3366b3a084a
F ext/wasm/fiddle.make d5308b5c35f691758ef20badd25f91f3780b20415760daf0d98afbe4f24921b9
F ext/wasm/fiddle/emscripten.css 3d253a6fdb8983a2ac983855bfbdd4b6fa1ff267c28d69513dd6ef1f289ada3f
F ext/wasm/fiddle/fiddle-worker.js b4a0c8ab6c0983218543ca771c45f6075449f63a1dcf290ae5a681b2cba8800d
F ext/wasm/fiddle/fiddle.js 974b995119ac443685d7d94d3b3c58c6a36540e9eb3fed7069d5653284071715
F ext/wasm/fiddle/index.html 5daf54e8f3d7777cbb1ca4f93affe28858dbfff25841cb4ab81d694efed28ec2
F ext/wasm/index-dist.html c806b6005145b71d64240606e9c6e0bf56878ee8829c66fe7486cebf34b0e6b1
-F ext/wasm/index.html cc8b174ff01be282b399e64b58bdf3c921d7020da5d4e22e88bbbb4a6787a209
+F ext/wasm/index.html 6b7139e64eef500aee9315deac5e4ac84ef31453aaf053b794bb0505859dcde5
F ext/wasm/jaccwabyt/jaccwabyt.js 06f2ef1ad640c26c593def3d960336e9bb789819b920516480895c38ed5f58fa
F ext/wasm/jaccwabyt/jaccwabyt.md 37911f00db12cbcca73aa1ed72594430365f30aafae2fa9c886961de74e5e0eb
F ext/wasm/module-symbols.html 841de62fc198988b8330e238c260e70ec93028b096e1a1234db31b187a899d10
@@ -528,10 +529,10 @@ F ext/wasm/sql/000-mandelbrot.sql 775337a4b80938ac8146aedf88808282f04d02d983d826
F ext/wasm/sql/001-sudoku.sql 35b7cb7239ba5d5f193bc05ec379bcf66891bce6f2a5b3879f2f78d0917299b5
F ext/wasm/test-opfs-vfs.html 1f2d672f3f3fce810dfd48a8d56914aba22e45c6834e262555e685bce3da8c3f
F ext/wasm/test-opfs-vfs.js f09266873e1a34d9bdb6d3981ec8c9e382f31f215c9fd2f9016d2394b8ae9b7b
-F ext/wasm/tester1-worker.html d43f3c131d88f10d00aff3e328fed13c858d674ea2ff1ff90225506137f85aa9
-F ext/wasm/tester1.c-pp.html d34bef3d48e5cbc1c7c06882ad240fec49bf88f5f65696cc2c72c416933aa406
-F ext/wasm/tester1.c-pp.js 7786fa3bdf074be8935e3a77b1ca135fd36ef6f87823c0695deaca585b133d06
-F ext/wasm/tests/opfs/concurrency/index.html 86d8ac435074d1e7007b91105f4897f368c165e8cecb6a9aa3d81f5cf5dcbe70
+F ext/wasm/tester1-worker.html 258d08f1ba9cc2d455958751e26be833893cf9ff7853e9436e593e1f778a386b
+F ext/wasm/tester1.c-pp.html 1c1bc78b858af2019e663b1a31e76657b73dc24bede28ca92fbe917c3a972af2
+F ext/wasm/tester1.c-pp.js 9844c675bd1f2353deabd7847d10c4fa55ff78a5c773073a239197d186123de7
+F ext/wasm/tests/opfs/concurrency/index.html 0802373d57034d51835ff6041cda438c7a982deea6079efd98098d3e42fbcbc1
F ext/wasm/tests/opfs/concurrency/test.js a98016113eaf71e81ddbf71655aa29b0fed9a8b79a3cdd3620d1658eb1cc9a5d
F ext/wasm/tests/opfs/concurrency/worker.js 0a8c1a3e6ebb38aabbee24f122693f1fb29d599948915c76906681bb7da1d3d2
F ext/wasm/version-info.c 3b36468a90faf1bbd59c65fd0eb66522d9f941eedd364fabccd72273503ae7d5
@@ -539,7 +540,7 @@ F ext/wasm/wasmfs.make cf9a68162d92ca2bcb0b9528b244cb36d5cc2d84ccc9c2d398461927d
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
F magic.txt 5ade0bc977aa135e79e3faaea894d5671b26107cc91e70783aa7dc83f22f3ba0
-F main.mk e8aca588ea9b98108e303972fbe6fa08d0481afbad21e81c288ef44a9a695dab
+F main.mk ac6b13f8ecc43f377e9912380ea4cf366051d7f784cf61c8886e03e1cf0fbefa
F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83
F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
@@ -553,13 +554,13 @@ F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
F sqlite_cfg.h.in baf2e409c63d4e7a765e17769b6ff17c5a82bbd9cbf1e284fd2e4cefaff3fcf2
F src/alter.c 3ca2f449c890f8b86ec9e06f0c4fccf0648941c3308a16904cb2852227db83f7
-F src/analyze.c d2fce73f6a024897593012c6ca25368629fa4aeb49960d88a52fac664582e483
+F src/analyze.c b597c382f23b19cce563211181e84b7e8edddd6871d5f630bbadedb57e562806
F src/attach.c cc9d00d30da916ff656038211410ccf04ed784b7564639b9b61d1839ed69fd39
F src/auth.c f4fa91b6a90bbc8e0d0f738aa284551739c9543a367071f55574681e0f24f8cf
F src/backup.c a2891172438e385fdbe97c11c9745676bec54f518d4447090af97189fd8e52d7
F src/bitvec.c 7c849aac407230278445cb069bebc5f89bf2ddd87c5ed9459b070a9175707b3d
F src/btmutex.c 6ffb0a22c19e2f9110be0964d0731d2ef1c67b5f7fabfbaeb7b9dabc4b7740ca
-F src/btree.c 8b776a47d1e791ca78b539b8356cf32e449a613201cf64b87e7f01c62f79bd1b
+F src/btree.c 2f012aea074de6319c191cbf5c45034de79bf1c762826e381b1cf75421d8d831
F src/btree.h aa354b9bad4120af71e214666b35132712b8f2ec11869cb2315c52c81fad45cc
F src/btreeInt.h 06bb2c1a07172d5a1cd27a2a5d617b93b1e976c5873709c31964786f86365a6e
F src/build.c c55ab6d1b089ceef57160e840f05f692955ac90944c3d04fcf01d97fd7bfd08d
@@ -567,7 +568,7 @@ F src/callback.c 4cd7225b26a97f7de5fee5ae10464bed5a78f2adefe19534cc2095b3a8ca484
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
F src/ctime.c 20507cc0b0a6c19cd882fcd0eaeda32ae6a4229fb4b024cfdf3183043d9b703d
F src/date.c 94ce83b4cd848a387680a5f920c9018c16655db778c4d36525af0a0f34679ac5
-F src/dbpage.c 254e3a228892ab6139beda795ebc9c60b876aae59eb9cd9290d11dc261c8d824
+F src/dbpage.c d47549716549311f79dc39fe5c8fb19390a6eb2c960f8e37c89a9c4de0c1052e
F src/dbstat.c ec92074baa61d883de58c945162d9e666c13cd7cf3a23bc38b4d1c4d0b2c2bef
F src/delete.c 86573edae75e3d3e9a8b590d87db8e47222103029df4f3e11fa56044459b514e
F src/expr.c 204af6a83c191f5ac19ec4af6ecc546f188cc2dd1c76fc5280982f710ec4b9c4
@@ -604,24 +605,24 @@ F src/os.h 1ff5ae51d339d0e30d8a9d814f4b8f8e448169304d83a7ed9db66a65732f3e63
F src/os_common.h 6c0eb8dd40ef3e12fe585a13e709710267a258e2c8dd1c40b1948a1d14582e06
F src/os_kv.c 4d39e1f1c180b11162c6dc4aa8ad34053873a639bac6baae23272fc03349986a
F src/os_setup.h 6011ad7af5db4e05155f385eb3a9b4470688de6f65d6166b8956e58a3d872107
-F src/os_unix.c 2ab48df80d598e11fe216dcae5cdf28d2b4c7ab195a685bd4047b9e534c3aaf6
+F src/os_unix.c 90c4fa0a88c8b0817c7ce4dbea0ac3aebfd7deb0797945ac34dfd25006ba393a
F src/os_win.c 295fe45f18bd86f2477f4cd79f3377c6f883ceb941b1f46808665c73747f2345
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
-F src/pager.c fc6d3ec7017d7369ab5dc5421ad1763ff224551c9381866b6da69040db62e406
+F src/pager.c 7d1e34befba172b7f84b53c0c714e06661b22742312ad2fbb0a3bbd2d5d4f939
F src/pager.h f82e9844166e1585f5786837ddc7709966138ced17f568c16af7ccf946c2baa3
F src/parse.y 8e67d820030d2655b9942ffe61c1e7e6b96cea2f2f72183533299393907d0564
F src/pcache.c f4268f7f73c6a3db12ce22fd25bc68dc42315d19599414ab1207d7cf32f79197
F src/pcache.h 4f87acd914cef5016fae3030343540d75f5b85a1877eed1a2a19b9f284248586
F src/pcache1.c dee95e3cd2b61e6512dc814c5ab76d5eb36f0bfc9441dbb4260fccc0d12bbddc
-F src/pragma.c 23e74aaa441a03e6d97098db5883f53ee50cc50d294ecefb916437b8484012b3
+F src/pragma.c 82d5090a35eac75876d3b41f48d06b2370553c9576bf2942233c462e03eb94c9
F src/pragma.h e690a356c18e98414d2e870ea791c1be1545a714ba623719deb63f7f226d8bb7
F src/prepare.c ce87a08cfddd45a147150db34190b1986f2d4a0e0828858cb6bd908c78fb02e3
F src/printf.c ff4b05e38bf928ff1b80d3dda4f977b10fe39ecbfe69c018224c7e5594fb2455
F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c
-F src/resolve.c 5a98a7bf277aa60584b6bb4c5dd6a9ef2b19537910612c34f596e2901e88596d
+F src/resolve.c d62c5665279cc7485f9d45b5e20911cc7b19c203f268321a90d05d74f4725750
F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92
-F src/select.c d389ccdb96855dbfaadc22d936889e1f0652ffca17e31a6b6522b45d99daa8ce
-F src/shell.c.in afe1b3762f7f33752d9c51ebc92c9ba8de21c3470af9ae03e961b380d1521ecf
+F src/select.c c3ce1b49cca2c66c8c88fe7d9e1f3db23590deb4dd631619ad90e1e5d21bcf1f
+F src/shell.c.in 623d793be69c1d9592447fa6e1dbabfce46758821f2b63d6cde2c8cd1d472641
F src/sqlite.h.in 2b41f4908dd16cecb3754fe3fa2287a27ee825fb75d508ff2d7546b14e5a6ae6
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h da473ce2b3d0ae407a6300c4a164589b9a6bfdbec9462688a8593ff16f3bb6e4
@@ -636,7 +637,6 @@ F src/test3.c 61798bb0d38b915067a8c8e03f5a534b431181f802659a6616f9b4ff7d872644
F src/test4.c 4533b76419e7feb41b40582554663ed3cd77aaa54e135cf76b3205098cd6e664
F src/test5.c 328aae2c010c57a9829d255dc099d6899311672d
F src/test6.c ae73a3a42bbc982fb9e301b84d30bda65a307be48c6dff20aba1461e17a9b0ce
-F src/test7.c 5612e9aecf934d6df7bba6ce861fdf5ba5456010
F src/test8.c 0c856d6ff6b0d2ff6696addc467a15ed17c6910f14475302cd5b3b4e54406161
F src/test9.c 12e5ba554d2d1cbe0158f6ab3f7ffcd7a86ee4e5
F src/test_async.c 195ab49da082053fdb0f949c114b806a49ca770a
@@ -669,15 +669,14 @@ F src/test_quota.c 6cb9297115b551f433a9ad1741817a9831abed99
F src/test_quota.h 2a8ad1952d1d2ca9af0ce0465e56e6c023b5e15d
F src/test_rtree.c 671f3fae50ff116ef2e32a3bf1fe21b5615b4b7b
F src/test_schema.c f5d6067dfc2f2845c4dd56df63e66ee826fb23877855c785f75cc2ca83fd0c1b
-F src/test_server.c a2615049954cbb9cfb4a62e18e2f0616e4dc38fe
F src/test_sqllog.c 540feaea7280cd5f926168aee9deb1065ae136d0bbbe7361e2ef3541783e187a
F src/test_superlock.c 4839644b9201da822f181c5bc406c0b2385f672e
F src/test_syscall.c 1073306ba2e9bfc886771871a13d3de281ed3939
-F src/test_tclsh.c 7dd98be675a1dc0d1fd302b8247bab992c909db384df054381a2279ad76f9b0e
+F src/test_tclsh.c 3ff5d188a72f00807425954ea3b493dfd3a4b890ecc6700ea83bad2fd1332ecf
F src/test_tclvar.c 33ff42149494a39c5fbb0df3d25d6fafb2f668888e41c0688d07273dcb268dfc
-F src/test_thread.c 269ea9e1fa5828dba550eb26f619aa18aedbc29fd92f8a5f6b93521fbb74a61c
+F src/test_thread.c 7ddcf0c8b79fa3c1d172f82f322302c963d923cdb503c6171f3c8081586d0b01
F src/test_vdbecov.c f60c6f135ec42c0de013a1d5136777aa328a776d33277f92abac648930453d43
-F src/test_vfs.c 2cc38a79892017702d13da79ad5152c196eec19bbd67fbde4d88065aac894a84
+F src/test_vfs.c 193c18da3dbf62a0e33ae7a240bbef938a50846672ee947664512b77d853fe81
F src/test_vfstrace.c bab9594adc976cbe696ff3970728830b4c5ed698
F src/test_windirent.c a895e2c068a06644eef91a7f0a32182445a893b9a0f33d0cdb4283dca2486ac1
F src/test_windirent.h 90dfbe95442c9762357fe128dc7ae3dc199d006de93eb33ba3972e0a90484215
@@ -685,7 +684,7 @@ F src/test_window.c cdae419fdcea5bad6dcd9368c685abdad6deb59e9fc8b84b153de513d394
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
F src/tokenize.c 1305797eab3542a0896b552c6e7669c972c1468e11e92b370533c1f37a37082b
-F src/treeview.c 29b1dc7e0f84ba090734febe27393d4719682af0cae1b902d5ebf0236ecebea4
+F src/treeview.c fccf3b8c517c1f55cb380c1522febe6921fcb2bd800c16c78cab571d0eb0ccbd
F src/trigger.c 5e68b790f022b8dafbfb0eb244786512a95c9575fc198719d2557d73e5795858
F src/update.c f118e51768d2c1309e3c81e9f91141b22b8a1339cbc5969b1b2d810feaa25b22
F src/upsert.c 5303dc6c518fa7d4b280ec65170f465c7a70b7ac2b22491598f6d0b4875b3145
@@ -698,7 +697,7 @@ F src/vdbeInt.h a4147a4ddf613cb1bcb555ace9e9e74a9c099d65facd88155f191b1fb4d74cfb
F src/vdbeapi.c 40c47b1528d308a322203de21d2e0d711753257ed9771771b6129214b1d65932
F src/vdbeaux.c 3f9e3b6585e7434aa11300169dd66ddf0fc963a0c6f7940bdc058335dadeb353
F src/vdbeblob.c 5e61ce31aca17db8fb60395407457a8c1c7fb471dde405e0cd675974611dcfcd
-F src/vdbemem.c 316d518115f3720b4097f0231e2a3d6eefd06c787eccf44972f8d8f462153421
+F src/vdbemem.c 87d3811aabb68eb9210c14c9a8b5e8ec3acb7ba787beb80a4323af54fb6013f7
F src/vdbesort.c 43756031ca7430f7aec3ef904824a7883c4ede783e51f280d99b9b65c0796e35
F src/vdbetrace.c fe0bc29ebd4e02c8bc5c1945f1d2e6be5927ec12c06d89b03ef2a4def34bf823
F src/vdbevtab.c aae4bd769410eb7e1d02c42613eec961d514459b1c3c1c63cfc84e92a137daac
@@ -707,11 +706,11 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
F src/wal.c b9df133a705093da8977da5eb202eaadb844839f1c7297c08d33471f5491843d
F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a
F src/walker.c f890a3298418d7cba3b69b8803594fdc484ea241206a8dfa99db6dd36f8cbb3b
-F src/where.c e75ca01cc4025c0023a4e32c137ad933ecaf1d5fbaf9f88ffae7db216ac2f762
+F src/where.c 3bbca705410258969d6d2e0c54b468de9674445d41b67714bb4fc3f1edef41d2
F src/whereInt.h e25203e5bfee149f5f1225ae0166cfb4f1e65490c998a024249e98bb0647377c
F src/wherecode.c 76bca3379219880d2527493b71a3be49e696f75396d3481e4de5d4ceec7886b2
F src/whereexpr.c 7c5671a04b00c876bec5e99fd4e6f688065feb4773160fbf76fd7900d2901777
-F src/window.c 9ea4dc243420e029586c8e1ed5929fad2eae438279341ae9defc66e8f905aabc
+F src/window.c 76a27cff9ea2ded0c2c3527187029259440fabcc4cc4c07b11d942c78494a614
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/affinity2.test ce1aafc86e110685b324e9a763eab4f2a73f737842ec3b687bd965867de90627
F test/affinity3.test f094773025eddf31135c7ad4cde722b7696f8eb07b97511f98585addf2a510a9
@@ -768,7 +767,7 @@ F test/attach2.test 6d1e3a457ce260d6fc8e5945c07fba6c76dc2aa90e1c701f067b50ee88f7
F test/attach3.test c59d92791070c59272e00183b7353eeb94915976
F test/attach4.test 00e754484859998d124d144de6d114d920f2ed6ca2f961e6a7f4183c714f885e
F test/attachmalloc.test 67309af95c6b765c13e7d2279d7fccbef78e6eb0565d75d51cefd5dc88784549
-F test/auth.test 4fbeaa283637dd06e1bec5bf92dc9c39e27ef83fd20844bdcf1a85c0e6fc160d
+F test/auth.test 5b8558a40571ebc55c1581cb7cec3b2348a699542a0a51b83ef21c6a953d95e3
F test/auth2.test 9eb7fce9f34bf1f50d3f366fb3e606be5a2000a1
F test/auth3.test 76d20a7fa136d63bcfcf8bcb65c0b1455ed71078d81f22bcd0550d3eb18594ab
F test/autoanalyze1.test b9cc3f32a990fa56669b668d237c6d53e983554ae80c0604992e18869a0b2dec
@@ -815,7 +814,7 @@ F test/bind2.test 918bc35135f4141809ead7585909cde57d44db90a7a62aef540127148f91aa
F test/bindxfer.test efecd12c580c14df5f4ad3b3e83c667744a4f7e0
F test/bitvec.test 75894a880520164d73b1305c1c3f96882615e142
F test/blob.test e7ac6c7d3a985cc4678c64f325292529a69ae252
-F test/bloom1.test 5318eb0648dff073ca9b9a54387ec2c0a7a07ed3490461fe2db0d074b2eb0e7f
+F test/bloom1.test 2785a190fcc2a5e170e5d38b08aca8ff0f3e3b4a74d47453d6ac1bd355180a6a
F test/boundary1.tcl 6421b2d920d8b09539503a8673339d32f7609eb1
F test/boundary1.test 66d7f4706ccdb42d58eafdb081de07b0eb42d77b
F test/boundary2.tcl e34ef4e930cf1083150d4d2c603e146bd3b76bcb
@@ -839,7 +838,7 @@ F test/capi3c.test 31d3a6778f2d06f2d9222bd7660c41a516d1518a059b069e96ebbeadb5a49
F test/capi3d.test 8b778794af891b0dca3d900bd345fbc8ebd2aa2aae425a9dccdd10d5233dfbde
F test/capi3e.test 3d49c01ef2a1a55f41d73cba2b23b5059ec460fe
F test/carray01.test 23ed7074307c4a829ba5ff2970993a9d87db7c5cdbbe1a2cbef672d0df6d6e31
-F test/cast.test e3a7e452f37efec0df0a89e55aa2f04861ba6613deb16075101414668bf4bb24
+F test/cast.test af2286fdd28f3470b7dcad23977282b8cc117747ad55acff74a770dad3b19398
F test/cffault.test 9d6b20606afe712374952eec4f8fd74b1a8097ef
F test/changes.test 9dd8e597d84072122fc8a4fcdea837f4a54a461e6e536053ea984303e8ca937b
F test/changes2.test d222c0cbf5ab0ac4d7c180594e486c1bf20b2098d33e56ce33b8e12eba6823b9
@@ -920,7 +919,7 @@ F test/dbfuzz001.test 55e1a3504f8dea84155e09912fe3b1c3ad77e0b1a938ec42ca03b8e51b
F test/dbfuzz2-seed1.db e6225c6f3d7b63f9c5b6867146a5f329d997ab105bee64644dc2b3a2f2aebaee
F test/dbfuzz2.c 4b3c12de4d98b1b2d908ab03d217d4619e47c8b23d5e67f8a6f2b1bdee7cae23
F test/dbpage.test fce29035c7566fd7835ec0f19422cb4b9c6944ce0e1b936ff8452443f92e887d
-F test/dbpagefault.test b893e9e43d55edc0cdf3f71ae093802f80f0fb517d839eefeae5647c49a41f36
+F test/dbpagefault.test d9111a62f3601d3efc6841ace3940181937342d245f92a1cca6cba8206d4f58a
F test/dbstatus.test 4a4221a883025ffd39696b3d1b3910b928fb097d77e671351acb35f3aed42759
F test/dbstatus2.test f5fe0afed3fa45e57cfa70d1147606c20d2ba23feac78e9a172f2fe8ab5b78ef
F test/decimal.test fcf403fd5585f47342234e153c4a4338cd737b8e0884ac66fc484df47dbcf1a7
@@ -936,7 +935,7 @@ F test/descidx3.test 953c831df7ea219c73826dfbf2f6ee02d95040725aa88ccb4fa43d1a199
F test/diskfull.test 106391384780753ea6896b7b4f005d10e9866b6e
F test/distinct.test a7687c2fb50c93f6a486936c51439a93221c6e1188f9bc7b27b3ec26f9c58b1e
F test/distinct2.test cd1d15a4a2abf579298f7161e821ed50c0119136fe0424db85c52cf0adc230d1
-F test/distinctagg.test d76ef2e91fe810630c176d6bd0a58c14d5851c3125f0a1d977db87ba76359639
+F test/distinctagg.test 14ec5026e684eddd414c61c08692b43773e224ac92efbed6ec08c6994bc39723
F test/e_blobbytes.test 4c01dfe4f12087b92b20705a3fdfded45dc4ed16d5a211fed4e1d2786ba68a52
F test/e_blobclose.test 692fc02a058476c2222a63d97e3f3b2b809c1842e5525ded7f854d540ac2e075
F test/e_blobopen.test 29f6055ee453b8e679fe9570c4d3acfedbef821622c5dad16875148c5952ef50
@@ -1139,7 +1138,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 30475c820dc5ab8a87fa3be1fe8ba8199ebfe2544508a759d653688d8d168766
+F test/fuzzcheck.c 0b8543d29c6f529cb73937607c8649f685510838e40c6287f06df083433c93b6
F test/fuzzdata1.db 3e86d9cf5aea68ddb8e27c02d7dfdaa226347426c7eb814918e4d95475bf8517
F test/fuzzdata2.db 128b3feeb78918d075c9b14b48610145a0dd4c8d6f1ca7c2870c7e425f5bf31f
F test/fuzzdata3.db c6586d3e3cef0fbc18108f9bb649aa77bfc38aba
@@ -1219,10 +1218,10 @@ F test/join.test e32cb9b1491eed682489e2cde33a22a4eb7611fe5aa3b0aa4b275fe27ab3f3a
F test/join2.test 466b07233820f5deee66a6c3bf6e4500c8bbf7b83649e67606f5f649c07928c0
F test/join3.test 6f0c774ff1ba0489e6c88a3e77b9d3528fb4fda0
F test/join4.test 1a352e4e267114444c29266ce79e941af5885916
-F test/join5.test d22b6cba8fb59ab3f1c82701434c360705eb12d4ce200c449f37b018fc47681a
+F test/join5.test 91f1f4c7d81fd87b58e9ba7cf4a2b5d39e3583b4f8e498a162722a60259c5208
F test/join6.test f809c025fa253f9e150c0e9afd4cef8813257bceeb6f46e04041228c9403cc2c
F test/join7.test 2268dcbb54b724391dda3748ea95c60d960607ffeed67885675998e7117697f6
-F test/join8.test ef5fb09a7ce6b59addb8bd16e11607db6c44a0afcac5774a5dc03193fd0a1df5
+F test/join8.test 40bdf5612444e986187edc5fd5ea9094cb7975b78cac563a97f1f7aefde34ba6
F test/join9.test 9056ddd3b0c0f4f9d658f4521038d9a37dc23ead8ca9a505d0b0db2b6a471e05
F test/joinA.test 7eab225dc1c1ab258a5e62513a4ed7cabbd3db971d59d5d92f4fb6fa14c12f6a
F test/joinB.test 1b2ba3fc8568b49411787fccbf540570c148e9b6a53a30f80691cb6268098ded
@@ -1298,7 +1297,7 @@ F test/memjournal.test 70f3a00c7f84ee2978ad14e831231caa1e7f23915a2c54b4f775a021d
F test/memjournal2.test 6b9083cfaab9a3281ec545c3da2487999e8025fb7501bbae10f713f80c56454c
F test/memleak.test 10b9c6c57e19fc68c32941495e9ba1c50123f6e2
F test/memsubsys1.test 86b8158752af9188ed5b32a30674a1ef71183e6bc4e6808e815cd658ca9058a6
-F test/memsubsys2.test 3e4a8d0c05fd3e5fa92017c64666730a520c7e08
+F test/memsubsys2.test 774b93cb09ca50d1b759bb7c645baa2a9ce172edc3a3da67d5150a26a9fc2a08
F test/merge1.test 2de6d6ef8d25402764b1aab49d8f9d7f89208c89a6674e437f76de4c812157b8
F test/minmax.test fe638b55d77d2375531a8f549b338eafcd9adfbd2f72df37ed77d9b26ca0a71a
F test/minmax2.test cf9311babb6f0518d04e42fd6a42c619531c4309a9dd790a2c4e9b3bc595e0de
@@ -1324,7 +1323,7 @@ F test/multiplex.test d74c034e52805f6de8cc5432cef8c9eb774bb64ec29b83a22effc8ca4d
F test/multiplex2.test 580ca5817c7edbe4cc68fa150609c9473393003a
F test/multiplex3.test fac575e0b1b852025575a6a8357701d80933e98b5d2fe6d35ddaa68f92f6a1f7
F test/multiplex4.test e8ae4c4bd70606a5727743241f13b5701990abe4
-F test/mutex1.test 177db2e4edb530f2ff21edc52ac79a412dbe63e4c47c3ae9504d3fb4f1ce81fa
+F test/mutex1.test 4d7ecb155ae5ba9ca6f1817c1c74d51b5bb284d7f599de1859a9f2c9a1ca0d38
F test/mutex2.test bfeaeac2e73095b2ac32285d2756e3a65e681660
F test/nan.test 437d40e6d0778b050d7750726c0cbd2c9936b81962926e8f8c48ca698f00f4d1
F test/nockpt.test 8c43b25af63b0bd620cf1b003529e37b6f1dc53bd22690e96a1bd73f78dde53a
@@ -1360,7 +1359,7 @@ F test/ossfuzz.c 9636dad2092a05a32110df0ca06713038dd0c43dd89a77dabe4b8b0d7109671
F test/ossshell.c f125c5bd16e537a2549aa579b328dd1c59905e7ab1338dfc210e755bb7b69f17
F test/ovfl.test 199c482696defceacee8c8e0e0ef36da62726b2f
F test/pager1.test ffd885cdc98b986c9f746496508c0c4810ed0eaade3575ddf53c222e85880552
-F test/pager2.test 67b8f40ae98112bcdba1f2b2d03ea83266418c71
+F test/pager2.test 57ce815e31a7509fcdf7c5474577fd2e9cfee1281d45601e0f7a3bd5534d70a4
F test/pager3.test 4e9a83d6ca0838d7c602c9eb93d1357562d9059c1e02ffb138a8271020838370
F test/pager4.test a122e9e6925d5b23b31e3dfef8c6a44bbf19590e
F test/pagerfault.test 63c5da625562c66345ab4528790327ca63db2f6f9cbae2aba8cb7c51de3d1628
@@ -1371,10 +1370,11 @@ F test/pagesize.test 5769fc62d8c890a83a503f67d47508dfdc543305
F test/parser1.test 6ccdf5e459a5dc4673d3273dc311a7e9742ca952dd0551a6a6320d27035ce4b3
F test/pcache.test c8acbedd3b6fd0f9a7ca887a83b11d24a007972b
F test/pcache2.test af7f3deb1a819f77a6d0d81534e97d1cf62cd442
+F test/pendingrace.test cbdf0f74bc939fb43cebad64dda7a0b5a3941a10b7e9cc2b596ff3e423a18156
F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff
-F test/permutations.test 4705a032bbfef531bb3fd98b8c6ba4a739998949eae9ac0ea97c8696b331211d
+F test/permutations.test 8bd6b6db541e2a7f9bb894be99ef5c00526b23762c4a00c574e1cba697495125
F test/pg_common.tcl 3b27542224db1e713ae387459b5d117c836a5f6e328846922993b6d2b7640d9f
-F test/pragma.test a74a9c9642e5d7e32f5a2aa77a2ed64ec5b69fecff39d52c4daf5945a2a4de65
+F test/pragma.test aeefa47ba5ebbf4ffc6addc223568d2a95dc7ec3ba3e3c4a26b199e805f94514
F test/pragma2.test e5d5c176360c321344249354c0c16aec46214c9f
F test/pragma3.test 92a46bbea12322dd94a404f49edcfbfc913a2c98115f0d030a7459bb4712ef31
F test/pragma4.test ca5e4dfc46adfe490f75d73734f70349d95a199e6510973899e502eef2c8b1f8
@@ -1388,6 +1388,7 @@ F test/ptrchng.test ef1aa72d6cf35a2bbd0869a649b744e9d84977fc
F test/pushdown.test f270b8071c02efc218430e0d388c155e1962eaa1d3a3ab186dd38ad6d7e178a4
F test/queryonly.test 5f653159e0f552f0552d43259890c1089391dcca
F test/quick.test 1681febc928d686362d50057c642f77a02c62e57
+F test/quickcheck.test f86b25b33455af0189b4d3fe7bd6e553115e80b2d7ec9bbe9a6b37fce0881bfe
F test/quota-glob.test 32901e9eed6705d68ca3faee2a06b73b57cb3c26
F test/quota.test bfb269ce81ea52f593f9648316cd5013d766dd2a
F test/quota2.test 7dc12e08b11cbc4c16c9ba2aa2e040ea8d8ab4b8
@@ -1400,7 +1401,7 @@ F test/recover.test fd5199f928757cb308661b5fdca1abc19398a798ff7f24b57c3071e9f8e0
F test/regexp1.test 8f2a8bc1569666e29a4cee6c1a666cd224eb6d50e2470d1dc1df995170f3e0f1
F test/regexp2.test 55ed41da802b0e284ac7e2fe944be3948f93ff25abbca0361a609acfed1368b5
F test/reindex.test cd9d6021729910ece82267b4f5e1b5ac2911a7566c43b43c176a6a4732e2118d
-F test/releasetest_data.tcl 0db8aee0c348090fd06da47020ab4ed8ec692e0723427b2f3947d4dfb806f3b0
+F test/releasetest_data.tcl b550dd1b122a9c969df794d05ea272df535f10ff1a245062e7ba080822378016
F test/resetdb.test 54c06f18bc832ac6d6319e5ab23d5c8dd49fdbeec7c696d791682a8006bd5fc3
F test/resolver01.test f4022acafda7f4d40eca94dbf16bc5fc4ac30ceb
F test/returning1.test 3ef7b264598b3292be0cdb028e4acb7524c5fd409b33b78449f894dfd68db334
@@ -1433,8 +1434,8 @@ F test/savepoint5.test 0735db177e0ebbaedc39812c8d065075d563c4fd
F test/savepoint6.test f41279c5e137139fa5c21485773332c7adb98cd7
F test/savepoint7.test cde525ea3075283eb950cdcdefe23ead4f700daa
F test/savepointfault.test f044eac64b59f09746c7020ee261734de82bf9b2
-F test/scanstatus.test 7dbcfd6adc6a8df6abc59f83d6da5a27e1bce0b2f6fa55147c8176d7c44e0450
-F test/scanstatus2.test 719c87a0ac817a67899d3e859923c8bb297ac655617b2dcfb602eb25dd829d45
+F test/scanstatus.test 74391c2c0926994bf0962db6c04c9ff5b95d15a41d2e076fe011b73f92815e70
+F test/scanstatus2.test ca6c258425977e5935f0ff3a8670d9b5d813dd5b83cf0bbe39acfc0fd2b5a0b1
F test/schema.test 5dd11c96ba64744de955315d2e4f8992e447533690153b93377dffb2a5ef5431
F test/schema2.test 906408621ea881fdb496d878b1822572a34e32c5
F test/schema3.test 8ed4ae66e082cdd8b1b1f22d8549e1e7a0db4527a8e6ee8b6193053ee1e5c9ce
@@ -1461,7 +1462,6 @@ F test/selectD.test 6d1909b49970bf92f45ce657505befcef5fc7cbc13544e18103a316d3218
F test/selectE.test a8730ca330fcf40ace158f134f4fe0eb00c7edbf
F test/selectF.test 21c94e6438f76537b72532fa9fd4710cdd455fc3
F test/selectG.test 089f7d3d7e6db91566f00b036cb353107a2cca6220eb1cb264085a836dae8840
-F test/server1.test c2b00864514a68a0e6fd518659dc95d0050307a357a08969872bef027d785dc4
F test/session.test 78fa2365e93d3663a6e933f86e7afc395adf18be
F test/sessionfuzz-data1.db 1f8d5def831f19b1c74571037f0d53a588ea49a6c4ca2a028fc0c27ef896dbcb
F test/sessionfuzz.c 5eef09af01eeff6f20250ae4c0112c2e576e4d2f2026cc9a49dc5be6886fa6ee
@@ -1488,7 +1488,7 @@ F test/shell8.test 3fd093d481aaa94dc77fb73f1044c1f19c7efe3477a395cc4f7450133bc54
F test/shmlock.test 3dbf017d34ab0c60abe6a44e447d3552154bd0c87b41eaf5ceacd408dd13fda5
F test/shortread1.test bb591ef20f0fd9ed26d0d12e80eee6d7ac8897a3
F test/show_speedtest1_rtree.tcl 32e6c5f073d7426148a6936a0408f4b5b169aba5
-F test/shrink.test 9521e5e0d74c0b6192794f3de3a3e5e3190d465527ae365d96763ef753c7229c
+F test/shrink.test 2668e607dcdfa19c52828c09b69685b38da793856582ae31debf79d90c7bbbdc
F test/sidedelete.test f0ad71abe6233e3b153100f3b8d679b19a488329
F test/skipscan1.test 1a9972e1dc15ca3887f306d3cd9a29679afb382eca0f3539f3b746f3c2ccaf68
F test/skipscan2.test b032ed3e0ba5caa4df6c43ef22c31566aac67783bc031869155989a7ccdb5bd5
@@ -1506,13 +1506,13 @@ F test/softheap1.test 843cd84db9891b2d01b9ab64cef3e9020f98d087
F test/sort.test f86751134159abb5e5fd4381a0d7038c91013638cd1e3fa1d7850901f6df6196
F test/sort2.test cc23b7c19d684657559e8a55b02f7fcee03851d0
F test/sort3.test 1480ed7c4c157682542224e05e3b75faf4a149e5
-F test/sort4.test 5c34d9623a4ae5921d956dfa2b70e77ed0fc6e5c
+F test/sort4.test cca6f4b0b5255882645bbbe346a6a9f4a5c7b6a18513a6a7bf4ac1c4761ddc19
F test/sort5.test 6b43ae0e2169b5ceed441844492e55ba7f1ae0790528395ddf7888ab3094525d
F test/sorterref.test 9a606c86a4c682db5eeaaefa0565b52102778db53e48ca7101cd4f9ebcc0ad94
F test/sortfault.test d4ccf606a0c77498e2beb542764fd9394acb4d66
-F test/speed1.test f2974a91d79f58507ada01864c0e323093065452
+F test/speed1.test 0381cfd05e5e7ccfd5eb570976f9075c67ab3e34991a1addf80663b184395219
F test/speed1p.explain d841e650a04728b39e6740296b852dccdca9b2cb
-F test/speed1p.test b180e98609c7677382cf618c0ec9b69f789033a8
+F test/speed1p.test 7191cec2aaf8876317bec58cf9c0f3750ab8b9bc23fc8a4000b77da578c7aadc
F test/speed2.test 53177056baf6556dcbdcf032bbdfc41c1aa74ded
F test/speed3.test 694affeb9100526007436334cf7d08f3d74b85ef
F test/speed4.test abc0ad3399dcf9703abed2fff8705e4f8e416715
@@ -1524,7 +1524,7 @@ F test/spellfix2.test dfc8f519a3fc204cb2dfa8b4f29821ae90f6f8c3
F test/spellfix3.test 0f9efaaa502a0e0a09848028518a6fb096c8ad33
F test/spellfix4.test 51c7c26514ade169855c66bcf130bd5acfb4d7fd090cc624645ab275ae6a41fb
F test/sqldiff1.test 182058e09c7082de5c6a470ff9c291337bbeb650052c2cc68fbb3d7e25861d91
-F test/sqllimits1.test 69d110987dbdb4bea9dbc3f151c93b4697ae6cd7e6c3a519119dc1140c8607fd
+F test/sqllimits1.test b28e5cc8d337aaf290614d96a47e8fbfb720bb7ad35620c9d5432996fd413ac4
F test/sqllog.test 6af6cb0b09f4e44e1917e06ce85be7670302517a
F test/startup.c 1beb5ca66fcc0fce95c3444db9d1674f90fc605499a574ae2434dcfc10d22805
F test/stat.test 123212a20ceb496893d5254a5f6c76442ce549fdc08d1702d8288a2bbaac8408
@@ -1562,8 +1562,9 @@ F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30
F test/temptable2.test 76821347810ecc88203e6ef0dd6897b6036ac788e9dd3e6b04fd4d1631311a16
F test/temptable3.test d11a0974e52b347e45ee54ef1923c91ed91e4637
F test/temptrigger.test 38f0ca479b1822d3117069e014daabcaacefffcc
-F test/tester.tcl e72c337f01e47c2833c83288b60e0a1730165cc7de7b59724e925c4ce026c0a1
-F test/testrunner.tcl 407fc02be0c859ef7a85b9431de9c5aa79363cab822ecbee3500a0daeb6b82cd
+F test/tester.tcl 8d54d40a55e12554b4509bc12078b201b233c8e842a7543629094a21b1ba956d
+F test/testrunner.tcl cd6fbd8c0fdb61b3b3cdd732c2d4fa9065b1b976815145b8cfdcb7ddad2a0bef
+F test/testrunner_data.tcl 8169c68654ac8906833b8a6aadca973358a441ebf88270dd05c153e5f96f76b8
F test/thread001.test a0985c117eab62c0c65526e9fa5d1360dd1cac5b03bde223902763274ce21899
F test/thread002.test c24c83408e35ba5a952a3638b7ac03ccdf1ce4409289c54a050ac4c5f1de7502
F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7
@@ -1799,7 +1800,7 @@ F test/veryquick.test 57ab846bacf7b90cf4e9a672721ea5c5b669b661
F test/view.test d4c4281e1679245829db35597817282f60dc513fc39cc5439078f009bd118487
F test/view2.test db32c8138b5b556f610b35dfddd38c5a58a292f07fda5281eedb0851b2672679
F test/view3.test ad8a8290ee2b55ff6ce66c9ef1ce3f1e47926273a3814e1c425293e128a95456
-F test/vt02.c 33ecddc0832d4cd24e9e9fa83d868981b1e049462f4ec9080710353f6479a534
+F test/vt02.c 86253b57d6bc2170dfca33f45fd099b66d0bf874e95ecd7786dcbb134f179469
F test/vtab1.test 09a72330d0f31eda2ffaa828b06a6b917fb86250ee72de0301570af725774c07
F test/vtab2.test 14d4ab26cee13ba6cf5c5601b158e4f57552d3b055cdd9406cf7f711e9c84082
F test/vtab3.test b45f47d20f225ccc9c28dc915d92740c2dee311e
@@ -1863,7 +1864,7 @@ F test/walthread.test 14b20fcfa6ae152f5d8e12f5dc8a8a724b7ef189f5d8ef1e2ceab79f2a
F test/walvfs.test e1a6ad0f3c78e98b55c3d5f0889cf366cc0d0a1cb2bccb44ac9ec67384adc4a1
F test/wapp.tcl b440cd8cf57953d3a49e7ee81e6a18f18efdaf113b69f7d8482b0710a64566ec
F test/wapptest.tcl 1bea58a6a8e68a73f542ee4fca28b771b84ed803bd0c9e385087070b3d747b3c x
-F test/where.test 3954cf22ba7b17f9606e177001d2963bcd1ecfbc6e1e7caadb14462f7eecd099
+F test/where.test 59abb854eee24f166b5f7ba9d17eb250abc59ce0a66c48912ffb10763648196d
F test/where2.test 03c21a11e7b90e2845fc3c8b4002fc44cc2797fa74c86ee47d70bd7ea4f29ed6
F test/where3.test 5b4ffc0ac2ea0fe92f02b1244b7531522fe4d7bccf6fa8741d54e82c10e67753
F test/where4.test 4a371bfcc607f41d233701bdec33ac2972908ba8
@@ -1909,7 +1910,7 @@ F test/window8.tcl 5e02e41d9d9a80f597063aed1a381eb19d1d0ef677a4f0df352c5365cf23f
F test/window8.test 4ab16817414af0c904abe2ebdf88eb6c2b00058b84f9748c6174ff11fc45f1ed
F test/window9.test 349c71eab4288a1ffc19e2f65872ec2c37e6cf8a1dda2ad300364b7450ae4836
F test/windowA.test 6d63dc1260daa17141a55007600581778523a8b420629f1282d2acfc36af23be
-F test/windowB.test 57f9fb931ed5e04f17db4fcb7059e76026079daf451aac27e54d41217078039b
+F test/windowB.test aad7c31739999f68a98a813cfd78390918fc70f56d2d925317a1523cab548ecf
F test/windowC.test 6fd75f5bb2f1343d34e470e36e68f0ff638d8a42f6aa7d99471261b31a0d42f2
F test/windowD.test 65cf5a765fb8072450e8a0de2979ce7f09a38d87724fe1280c6444073e3da49b
F test/windowE.test 6ba0c8048e4cc02b942e56640f8fcd50fd7ca72c876656c40f6baf42e316684c
@@ -1922,7 +1923,7 @@ F test/with2.test a1df41b987198383b9b70bf5e5fda390582e46398653858dbc6ceb24253b28
F test/with3.test e7bf809bf75c1f44f98bca78bc331dbf542002c5227bf53c1261144db4e824c8
F test/with4.test 257be66c0c67fee1defbbac0f685c3465e2cad037f21ce65f23f86084f198205
F test/with5.test 6248213c41fab36290b5b73aa3f937309dfba337004d9d8434c3fabc8c7d4be8
-F test/with6.test ae570b31bf1f6fab6210fb1caf6dfa9a6d69c0e6633beb905583bb158a5e309e
+F test/with6.test 7afab289442bd0a023c18deef854642932294fa63cdb885a4b4db69e28c5fbf9
F test/withM.test 693b61765f2b387b5e3e24a4536e2e82de15ff64
F test/without_rowid1.test a5210b8770dc4736bca4e74bc96588f43025ad03ad6a80f885afd36d9890e217
F test/without_rowid2.test af260339f79d13cb220288b67cd287fbcf81ad99
@@ -1993,12 +1994,12 @@ F tool/replace.tcl 937c931ad560688e85bdd6258bdc754371bb1e2732e1fb28ef441e44c9228
F tool/restore_jrnl.tcl 6957a34f8f1f0f8285e07536225ec3b292a9024a
F tool/rollback-test.c 9fc98427d1e23e84429d7e6d07d9094fbdec65a5
F tool/run-speed-test.sh f95d19fd669b68c4c38b6b475242841d47c66076
-F tool/showdb.c 72239e95e1d05a2941c6a1d86b4d857812be4dadd71f24e381db572f350fc172
+F tool/showdb.c 495a43b759ae37a0c4561a557a70090cb79b8c1601204e5a77e8b5360e65a954
F tool/showjournal.c 5bad7ae8784a43d2b270d953060423b8bd480818
F tool/showlocks.c 9cc5e66d4ebbf2d194f39db2527ece92077e86ae627ddd233ee48e16e8142564
F tool/showshm.c a0ab6ec32dd1f11218ca2a4018f8fb875b59414801ab8ceed8b2e69b7b45a809
F tool/showstat4.c 0682ebea7abf4d3657f53c4a243f2e7eab48eab344ed36a94bb75dcd19a5c2a1
-F tool/showwal.c 0253c187ae16fdae9cde89e63e1dfcd3bb35e5416d066415f99e2f8cac6ab03d
+F tool/showwal.c 4699048f68b6dd7b451011abfff404b8890d5a0b7dab78d2ad50d018116239d5
F tool/soak1.tcl 8d407956e1a45b485a8e072470a3e629a27037fe
F tool/spaceanal.tcl 1b5be34c6223cb1af06da2a10fb77863eb869b1962d055820b0a11cf2336ab45
F tool/speed-check.sh 9b27e158330a6587e92214b2344cc6fadde514996c0648fc0de7955ef7a79d77
@@ -2044,8 +2045,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 6fc20d75d49310aedbc3351a4a5f1aa9ef5b4100501c7bfbe556aca2be2e44d7 9a26fae545b9c97129893b83ff97e62b1c477eccd1379af1dce4a3cc4fa9f932
-R 145aa0c23a71f0a1d2cc97d60c0a4a1e
+P 2ce89f5efcdb8b4c58eb2d30833a76d79ae0134c31d5ab8564be9e1cf5a1f4f0 90b12211376eb445df7221b3d3593394ff651ef93f4218492c6208bc74b8fc63
+R 2e77a26949b44b09dd8f8ca35737dffa
U stephan
-Z ecd9a24931c0cd6ff26d46c7f1fc2570
+Z 44d444cd7a6c34a7e1e49f10a3684c72
# Remove this line to create a well-formed Fossil manifest.
diff --git a/manifest.uuid b/manifest.uuid
index baa286d94..0b3d7aac5 100644
--- a/manifest.uuid
+++ b/manifest.uuid
@@ -1 +1 @@
-2ce89f5efcdb8b4c58eb2d30833a76d79ae0134c31d5ab8564be9e1cf5a1f4f0 \ No newline at end of file
+656d36f50f630da68262469087bad1ac71b10325e233a7963103c8cbc232f61a \ No newline at end of file
diff --git a/src/analyze.c b/src/analyze.c
index 8562b9d7f..f3356ea3c 100644
--- a/src/analyze.c
+++ b/src/analyze.c
@@ -1597,6 +1597,8 @@ static int analysisLoader(void *pData, int argc, char **argv, char **NotUsed){
** and its contents.
*/
void sqlite3DeleteIndexSamples(sqlite3 *db, Index *pIdx){
+ assert( db!=0 );
+ assert( pIdx!=0 );
#ifdef SQLITE_ENABLE_STAT4
if( pIdx->aSample ){
int j;
@@ -1606,7 +1608,7 @@ void sqlite3DeleteIndexSamples(sqlite3 *db, Index *pIdx){
}
sqlite3DbFree(db, pIdx->aSample);
}
- if( db && db->pnBytesFreed==0 ){
+ if( db->pnBytesFreed==0 ){
pIdx->nSample = 0;
pIdx->aSample = 0;
}
diff --git a/src/btree.c b/src/btree.c
index fae572536..4fbe0b3db 100644
--- a/src/btree.c
+++ b/src/btree.c
@@ -10410,7 +10410,9 @@ static void checkList(
** lower 16 bits are the index of the last byte of that range.
*/
static void btreeHeapInsert(u32 *aHeap, u32 x){
- u32 j, i = ++aHeap[0];
+ u32 j, i;
+ assert( aHeap!=0 );
+ i = ++aHeap[0];
aHeap[i] = x;
while( (j = i/2)>0 && aHeap[j]>aHeap[i] ){
x = aHeap[j];
diff --git a/src/dbpage.c b/src/dbpage.c
index 9378dd4fc..17e5f44f5 100644
--- a/src/dbpage.c
+++ b/src/dbpage.c
@@ -246,7 +246,7 @@ static int dbpageFilter(
pCsr->iDb = 0;
}
pBt = db->aDb[pCsr->iDb].pBt;
- if( pBt==0 ) return SQLITE_OK;
+ if( NEVER(pBt==0) ) return SQLITE_OK;
pCsr->pPager = sqlite3BtreePager(pBt);
pCsr->szPage = sqlite3BtreeGetPageSize(pBt);
pCsr->mxPgno = sqlite3BtreeLastPage(pBt);
@@ -337,18 +337,20 @@ static int dbpageUpdate(
goto update_fail;
}
pgno = sqlite3_value_int(argv[0]);
- if( (Pgno)sqlite3_value_int(argv[1])!=pgno ){
+ if( sqlite3_value_type(argv[0])==SQLITE_NULL
+ || (Pgno)sqlite3_value_int(argv[1])!=pgno
+ ){
zErr = "cannot insert";
goto update_fail;
}
zSchema = (const char*)sqlite3_value_text(argv[4]);
- iDb = zSchema ? sqlite3FindDbName(pTab->db, zSchema) : -1;
- if( iDb<0 ){
+ iDb = ALWAYS(zSchema) ? sqlite3FindDbName(pTab->db, zSchema) : -1;
+ if( NEVER(iDb<0) ){
zErr = "no such schema";
goto update_fail;
}
pBt = pTab->db->aDb[iDb].pBt;
- if( pgno<1 || pBt==0 || pgno>sqlite3BtreeLastPage(pBt) ){
+ if( NEVER(pgno<1) || NEVER(pBt==0) || NEVER(pgno>sqlite3BtreeLastPage(pBt)) ){
zErr = "bad page number";
goto update_fail;
}
@@ -387,12 +389,11 @@ static int dbpageBegin(sqlite3_vtab *pVtab){
DbpageTable *pTab = (DbpageTable *)pVtab;
sqlite3 *db = pTab->db;
int i;
- int rc = SQLITE_OK;
- for(i=0; rc==SQLITE_OK && i<db->nDb; i++){
+ for(i=0; i<db->nDb; i++){
Btree *pBt = db->aDb[i].pBt;
- if( pBt ) rc = sqlite3BtreeBeginTrans(pBt, 1, 0);
+ if( pBt ) (void)sqlite3BtreeBeginTrans(pBt, 1, 0);
}
- return rc;
+ return SQLITE_OK;
}
diff --git a/src/os_unix.c b/src/os_unix.c
index e430e5df3..6e9ee3263 100644
--- a/src/os_unix.c
+++ b/src/os_unix.c
@@ -1695,7 +1695,7 @@ static int unixFileLock(unixFile *pFile, struct flock *pLock){
**
** UNLOCKED -> SHARED
** SHARED -> RESERVED
-** SHARED -> (PENDING) -> EXCLUSIVE
+** SHARED -> EXCLUSIVE
** RESERVED -> (PENDING) -> EXCLUSIVE
** PENDING -> EXCLUSIVE
**
@@ -1728,19 +1728,20 @@ static int unixLock(sqlite3_file *id, int eFileLock){
** A RESERVED lock is implemented by grabbing a write-lock on the
** 'reserved byte'.
**
- ** A process may only obtain a PENDING lock after it has obtained a
- ** SHARED lock. A PENDING lock is implemented by obtaining a write-lock
- ** on the 'pending byte'. This ensures that no new SHARED locks can be
- ** obtained, but existing SHARED locks are allowed to persist. A process
- ** does not have to obtain a RESERVED lock on the way to a PENDING lock.
- ** This property is used by the algorithm for rolling back a journal file
- ** after a crash.
+ ** An EXCLUSIVE lock may only be requested after either a SHARED or
+ ** RESERVED lock is held. An EXCLUSIVE lock is implemented by obtaining
+ ** a write-lock on the entire 'shared byte range'. Since all other locks
+ ** require a read-lock on one of the bytes within this range, this ensures
+ ** that no other locks are held on the database.
**
- ** An EXCLUSIVE lock, obtained after a PENDING lock is held, is
- ** implemented by obtaining a write-lock on the entire 'shared byte
- ** range'. Since all other locks require a read-lock on one of the bytes
- ** within this range, this ensures that no other locks are held on the
- ** database.
+ ** If a process that holds a RESERVED lock requests an EXCLUSIVE, then
+ ** a PENDING lock is obtained first. A PENDING lock is implemented by
+ ** obtaining a write-lock on the 'pending byte'. This ensures that no new
+ ** SHARED locks can be obtained, but existing SHARED locks are allowed to
+ ** persist. If the call to this function fails to obtain the EXCLUSIVE
+ ** lock in this case, it holds the PENDING lock intead. The client may
+ ** then re-attempt the EXCLUSIVE lock later on, after existing SHARED
+ ** locks have cleared.
*/
int rc = SQLITE_OK;
unixFile *pFile = (unixFile*)id;
@@ -1811,7 +1812,7 @@ static int unixLock(sqlite3_file *id, int eFileLock){
lock.l_len = 1L;
lock.l_whence = SEEK_SET;
if( eFileLock==SHARED_LOCK
- || (eFileLock==EXCLUSIVE_LOCK && pFile->eFileLock<PENDING_LOCK)
+ || (eFileLock==EXCLUSIVE_LOCK && pFile->eFileLock==RESERVED_LOCK)
){
lock.l_type = (eFileLock==SHARED_LOCK?F_RDLCK:F_WRLCK);
lock.l_start = PENDING_BYTE;
@@ -1822,6 +1823,9 @@ static int unixLock(sqlite3_file *id, int eFileLock){
storeLastErrno(pFile, tErrno);
}
goto end_lock;
+ }else if( eFileLock==EXCLUSIVE_LOCK ){
+ pFile->eFileLock = PENDING_LOCK;
+ pInode->eFileLock = PENDING_LOCK;
}
}
@@ -1909,13 +1913,9 @@ static int unixLock(sqlite3_file *id, int eFileLock){
}
#endif
-
if( rc==SQLITE_OK ){
pFile->eFileLock = eFileLock;
pInode->eFileLock = eFileLock;
- }else if( eFileLock==EXCLUSIVE_LOCK ){
- pFile->eFileLock = PENDING_LOCK;
- pInode->eFileLock = PENDING_LOCK;
}
end_lock:
diff --git a/src/pager.c b/src/pager.c
index 6e6527e15..5f6e975fd 100644
--- a/src/pager.c
+++ b/src/pager.c
@@ -4693,7 +4693,6 @@ int sqlite3PagerOpen(
u32 szPageDflt = SQLITE_DEFAULT_PAGE_SIZE; /* Default page size */
const char *zUri = 0; /* URI args to copy */
int nUriByte = 1; /* Number of bytes of URI args at *zUri */
- int nUri = 0; /* Number of URI parameters */
/* Figure out how much space is required for each journal file-handle
** (there are two of them, the main journal and the sub-journal). */
@@ -4741,7 +4740,6 @@ int sqlite3PagerOpen(
while( *z ){
z += strlen(z)+1;
z += strlen(z)+1;
- nUri++;
}
nUriByte = (int)(&z[1] - zUri);
assert( nUriByte>=1 );
@@ -6269,7 +6267,7 @@ static int pager_incr_changecounter(Pager *pPager, int isDirectMode){
# define DIRECT_MODE isDirectMode
#endif
- if( !pPager->changeCountDone && ALWAYS(pPager->dbSize>0) ){
+ if( !pPager->changeCountDone && pPager->dbSize>0 ){
PgHdr *pPgHdr; /* Reference to page 1 */
assert( !pPager->tempFile && isOpen(pPager->fd) );
diff --git a/src/pragma.c b/src/pragma.c
index 527b2a734..522a12d33 100644
--- a/src/pragma.c
+++ b/src/pragma.c
@@ -1785,12 +1785,21 @@ void sqlite3Pragma(
** will also prepopulate the cursor column cache that is used
** by the OP_IsType code, so it is a required step.
*/
- mxCol = pTab->nCol-1;
- while( mxCol>=0
- && ((pTab->aCol[mxCol].colFlags & COLFLAG_VIRTUAL)!=0
- || pTab->iPKey==mxCol) ) mxCol--;
+ assert( !IsVirtual(pTab) );
+ if( HasRowid(pTab) ){
+ mxCol = -1;
+ for(j=0; j<pTab->nCol; j++){
+ if( (pTab->aCol[j].colFlags & COLFLAG_VIRTUAL)==0 ) mxCol++;
+ }
+ if( mxCol==pTab->iPKey ) mxCol--;
+ }else{
+ /* COLFLAG_VIRTUAL columns are not included in the WITHOUT ROWID
+ ** PK index column-count, so there is no need to account for them
+ ** in this case. */
+ mxCol = sqlite3PrimaryKeyIndex(pTab)->nColumn-1;
+ }
if( mxCol>=0 ){
- sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, mxCol, 3);
+ sqlite3VdbeAddOp3(v, OP_Column, iDataCur, mxCol, 3);
sqlite3VdbeTypeofColumn(v, 3);
}
diff --git a/src/resolve.c b/src/resolve.c
index 0d196ac37..9677f9de9 100644
--- a/src/resolve.c
+++ b/src/resolve.c
@@ -203,6 +203,32 @@ static void extendFJMatch(
}
/*
+** Return TRUE (non-zero) if zTab is a valid name for the schema table pTab.
+*/
+static SQLITE_NOINLINE int isValidSchemaTableName(
+ const char *zTab, /* Name as it appears in the SQL */
+ Table *pTab, /* The schema table we are trying to match */
+ Schema *pSchema /* non-NULL if a database qualifier is present */
+){
+ const char *zLegacy;
+ assert( pTab!=0 );
+ assert( pTab->tnum==1 );
+ if( sqlite3StrNICmp(zTab, "sqlite_", 7)!=0 ) return 0;
+ zLegacy = pTab->zName;
+ if( strcmp(zLegacy+7, &LEGACY_TEMP_SCHEMA_TABLE[7])==0 ){
+ if( sqlite3StrICmp(zTab+7, &PREFERRED_TEMP_SCHEMA_TABLE[7])==0 ){
+ return 1;
+ }
+ if( pSchema==0 ) return 0;
+ if( sqlite3StrICmp(zTab+7, &LEGACY_SCHEMA_TABLE[7])==0 ) return 1;
+ if( sqlite3StrICmp(zTab+7, &PREFERRED_SCHEMA_TABLE[7])==0 ) return 1;
+ }else{
+ if( sqlite3StrICmp(zTab+7, &PREFERRED_SCHEMA_TABLE[7])==0 ) return 1;
+ }
+ return 0;
+}
+
+/*
** Given the name of a column of the form X.Y.Z or Y.Z or just Z, look up
** that name in the set of source tables in pSrcList and make the pExpr
** expression node refer back to that source column. The following changes
@@ -355,15 +381,17 @@ static int lookupName(
}
assert( zDb==0 || zTab!=0 );
if( zTab ){
- const char *zTabName;
if( zDb ){
if( pTab->pSchema!=pSchema ) continue;
if( pSchema==0 && strcmp(zDb,"*")!=0 ) continue;
}
- zTabName = pItem->zAlias ? pItem->zAlias : pTab->zName;
- assert( zTabName!=0 );
- if( sqlite3StrICmp(zTabName, zTab)!=0 ){
- continue;
+ if( pItem->zAlias!=0 ){
+ if( sqlite3StrICmp(zTab, pItem->zAlias)!=0 ){
+ continue;
+ }
+ }else if( sqlite3StrICmp(zTab, pTab->zName)!=0 ){
+ if( pTab->tnum!=1 ) continue;
+ if( !isValidSchemaTableName(zTab, pTab, pSchema) ) continue;
}
assert( ExprUseYTab(pExpr) );
if( IN_RENAME_OBJECT && pItem->zAlias ){
diff --git a/src/select.c b/src/select.c
index d27bed026..b0e303066 100644
--- a/src/select.c
+++ b/src/select.c
@@ -5626,9 +5626,6 @@ static int resolveFromTermToCte(
pFrom->fg.isCte = 1;
pFrom->u2.pCteUse = pCteUse;
pCteUse->nUse++;
- if( pCteUse->nUse>=2 && pCteUse->eM10d==M10d_Any ){
- pCteUse->eM10d = M10d_Yes;
- }
/* Check if this is a recursive CTE. */
pRecTerm = pSel = pFrom->pSelect;
@@ -6911,8 +6908,10 @@ static int sameSrcAlias(SrcItem *p0, SrcList *pSrc){
** being used as the outer loop if the sqlite3WhereBegin()
** routine nominates it to that position.
** (iii) The query is not a UPDATE ... FROM
-** (2) The subquery is not a CTE that should be materialized because of
-** the AS MATERIALIZED keywords
+** (2) The subquery is not a CTE that should be materialized because
+** (a) the AS MATERIALIZED keyword is used, or
+** (b) the CTE is used multiple times and does not have the
+** NOT MATERIALIZED keyword
** (3) The subquery is not part of a left operand for a RIGHT JOIN
** (4) The SQLITE_Coroutine optimization disable flag is not set
** (5) The subquery is not self-joined
@@ -6924,9 +6923,13 @@ static int fromClauseTermCanBeCoroutine(
int selFlags /* Flags on the SELECT statement */
){
SrcItem *pItem = &pTabList->a[i];
- if( pItem->fg.isCte && pItem->u2.pCteUse->eM10d==M10d_Yes ) return 0;/* (2) */
- if( pTabList->a[0].fg.jointype & JT_LTORJ ) return 0; /* (3) */
- if( OptimizationDisabled(pParse->db, SQLITE_Coroutines) ) return 0; /* (4) */
+ if( pItem->fg.isCte ){
+ const CteUse *pCteUse = pItem->u2.pCteUse;
+ if( pCteUse->eM10d==M10d_Yes ) return 0; /* (2a) */
+ if( pCteUse->nUse>=2 && pCteUse->eM10d!=M10d_No ) return 0; /* (2b) */
+ }
+ if( pTabList->a[0].fg.jointype & JT_LTORJ ) return 0; /* (3) */
+ if( OptimizationDisabled(pParse->db, SQLITE_Coroutines) ) return 0; /* (4) */
if( isSelfJoinView(pTabList, pItem, i+1, pTabList->nSrc)!=0 ){
return 0; /* (5) */
}
diff --git a/src/shell.c.in b/src/shell.c.in
index 3da0bf3b9..f5a354a2e 100644
--- a/src/shell.c.in
+++ b/src/shell.c.in
@@ -5685,10 +5685,13 @@ static int sql_trace_callback(
/*
** A no-op routine that runs with the ".breakpoint" doc-command. This is
** a useful spot to set a debugger breakpoint.
+**
+** This routine does not do anything practical. The code are there simply
+** to prevent the compiler from optimizing this routine out.
*/
static void test_breakpoint(void){
- static int nCall = 0;
- nCall++;
+ static unsigned int nCall = 0;
+ if( (nCall++)==0xffffffff ) printf("Many .breakpoints have run\n");
}
/*
diff --git a/src/test7.c b/src/test7.c
deleted file mode 100644
index d57e4b826..000000000
--- a/src/test7.c
+++ /dev/null
@@ -1,718 +0,0 @@
-/*
-** 2006 January 09
-**
-** 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.
-**
-*************************************************************************
-** Code for testing the client/server version of the SQLite library.
-** Derived from test4.c.
-*/
-#include "sqliteInt.h"
-#if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
-#else
-# include "tcl.h"
-#endif
-
-/*
-** This test only works on UNIX with a SQLITE_THREADSAFE build that includes
-** the SQLITE_SERVER option.
-*/
-#if defined(SQLITE_SERVER) && !defined(SQLITE_OMIT_SHARED_CACHE) && \
- SQLITE_OS_UNIX && SQLITE_THREADSAFE
-
-#include <stdlib.h>
-#include <string.h>
-#include <pthread.h>
-#include <sched.h>
-#include <ctype.h>
-
-/*
-** Interfaces defined in server.c
-*/
-int sqlite3_client_open(const char*, sqlite3**);
-int sqlite3_client_prepare(sqlite3*,const char*,int,
- sqlite3_stmt**,const char**);
-int sqlite3_client_step(sqlite3_stmt*);
-int sqlite3_client_reset(sqlite3_stmt*);
-int sqlite3_client_finalize(sqlite3_stmt*);
-int sqlite3_client_close(sqlite3*);
-int sqlite3_server_start(void);
-int sqlite3_server_stop(void);
-void sqlite3_server_start2(int *pnDecr);
-
-/*
-** Each thread is controlled by an instance of the following
-** structure.
-*/
-typedef struct Thread Thread;
-struct Thread {
- /* The first group of fields are writable by the supervisor thread
- ** and read-only to the client threads
- */
- char *zFilename; /* Name of database file */
- void (*xOp)(Thread*); /* next operation to do */
- char *zArg; /* argument usable by xOp */
- volatile int opnum; /* Operation number */
- volatile int busy; /* True if this thread is in use */
-
- /* The next group of fields are writable by the client threads
- ** but read-only to the superviser thread.
- */
- volatile int completed; /* Number of operations completed */
- sqlite3 *db; /* Open database */
- sqlite3_stmt *pStmt; /* Pending operation */
- char *zErr; /* operation error */
- char *zStaticErr; /* Static error message */
- int rc; /* operation return code */
- int argc; /* number of columns in result */
- const char *argv[100]; /* result columns */
- const char *colv[100]; /* result column names */
-
- /* Initialized to 1 by the supervisor thread when the client is
- ** created, and then deemed read-only to the supervisor thread.
- ** Is set to 0 by the server thread belonging to this client
- ** just before it exits.
- */
- int nServer; /* Number of server threads running */
-};
-
-/*
-** There can be as many as 26 threads running at once. Each is named
-** by a capital letter: A, B, C, ..., Y, Z.
-*/
-#define N_THREAD 26
-static Thread threadset[N_THREAD];
-
-/*
-** The main loop for a thread. Threads use busy waiting.
-*/
-static void *client_main(void *pArg){
- Thread *p = (Thread*)pArg;
- if( p->db ){
- sqlite3_client_close(p->db);
- }
- sqlite3_client_open(p->zFilename, &p->db);
- if( SQLITE_OK!=sqlite3_errcode(p->db) ){
- p->zErr = strdup(sqlite3_errmsg(p->db));
- sqlite3_client_close(p->db);
- p->db = 0;
- }
- p->pStmt = 0;
- p->completed = 1;
- while( p->opnum<=p->completed ) sched_yield();
- while( p->xOp ){
- if( p->zErr && p->zErr!=p->zStaticErr ){
- sqlite3_free(p->zErr);
- p->zErr = 0;
- }
- (*p->xOp)(p);
- p->completed++;
- while( p->opnum<=p->completed ) sched_yield();
- }
- if( p->pStmt ){
- sqlite3_client_finalize(p->pStmt);
- p->pStmt = 0;
- }
- if( p->db ){
- sqlite3_client_close(p->db);
- p->db = 0;
- }
- if( p->zErr && p->zErr!=p->zStaticErr ){
- sqlite3_free(p->zErr);
- p->zErr = 0;
- }
- p->completed++;
-#ifndef SQLITE_OMIT_DEPRECATED
- sqlite3_thread_cleanup();
-#endif
- return 0;
-}
-
-/*
-** Get a thread ID which is an upper case letter. Return the index.
-** If the argument is not a valid thread ID put an error message in
-** the interpreter and return -1.
-*/
-static int parse_client_id(Tcl_Interp *interp, const char *zArg){
- if( zArg==0 || zArg[0]==0 || zArg[1]!=0 || !isupper((unsigned char)zArg[0]) ){
- Tcl_AppendResult(interp, "thread ID must be an upper case letter", 0);
- return -1;
- }
- return zArg[0] - 'A';
-}
-
-/*
-** Usage: client_create NAME FILENAME
-**
-** NAME should be an upper case letter. Start the thread running with
-** an open connection to the given database.
-*/
-static int SQLITE_TCLAPI tcl_client_create(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- const char **argv /* Text of each argument */
-){
- int i;
- pthread_t x;
- int rc;
-
- if( argc!=3 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " ID FILENAME", 0);
- return TCL_ERROR;
- }
- i = parse_client_id(interp, argv[1]);
- if( i<0 ) return TCL_ERROR;
- if( threadset[i].busy ){
- Tcl_AppendResult(interp, "thread ", argv[1], " is already running", 0);
- return TCL_ERROR;
- }
- threadset[i].busy = 1;
- sqlite3_free(threadset[i].zFilename);
- threadset[i].zFilename = sqlite3_mprintf("%s", argv[2]);
- threadset[i].opnum = 1;
- threadset[i].completed = 0;
- rc = pthread_create(&x, 0, client_main, &threadset[i]);
- if( rc ){
- Tcl_AppendResult(interp, "failed to create the thread", 0);
- sqlite3_free(threadset[i].zFilename);
- threadset[i].busy = 0;
- return TCL_ERROR;
- }
- pthread_detach(x);
- if( threadset[i].nServer==0 ){
- threadset[i].nServer = 1;
- sqlite3_server_start2(&threadset[i].nServer);
- }
- return TCL_OK;
-}
-
-/*
-** Wait for a thread to reach its idle state.
-*/
-static void client_wait(Thread *p){
- while( p->opnum>p->completed ) sched_yield();
-}
-
-/*
-** Usage: client_wait ID
-**
-** Wait on thread ID to reach its idle state.
-*/
-static int SQLITE_TCLAPI tcl_client_wait(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- const char **argv /* Text of each argument */
-){
- int i;
-
- if( argc!=2 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " ID", 0);
- return TCL_ERROR;
- }
- i = parse_client_id(interp, argv[1]);
- if( i<0 ) return TCL_ERROR;
- if( !threadset[i].busy ){
- Tcl_AppendResult(interp, "no such thread", 0);
- return TCL_ERROR;
- }
- client_wait(&threadset[i]);
- return TCL_OK;
-}
-
-/*
-** Stop a thread.
-*/
-static void stop_thread(Thread *p){
- client_wait(p);
- p->xOp = 0;
- p->opnum++;
- client_wait(p);
- sqlite3_free(p->zArg);
- p->zArg = 0;
- sqlite3_free(p->zFilename);
- p->zFilename = 0;
- p->busy = 0;
-}
-
-/*
-** Usage: client_halt ID
-**
-** Cause a client thread to shut itself down. Wait for the shutdown to be
-** completed. If ID is "*" then stop all client threads.
-*/
-static int SQLITE_TCLAPI tcl_client_halt(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- const char **argv /* Text of each argument */
-){
- int i;
-
- if( argc!=2 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " ID", 0);
- return TCL_ERROR;
- }
- if( argv[1][0]=='*' && argv[1][1]==0 ){
- for(i=0; i<N_THREAD; i++){
- if( threadset[i].busy ){
- stop_thread(&threadset[i]);
- }
- }
- }else{
- i = parse_client_id(interp, argv[1]);
- if( i<0 ) return TCL_ERROR;
- if( !threadset[i].busy ){
- Tcl_AppendResult(interp, "no such thread", 0);
- return TCL_ERROR;
- }
- stop_thread(&threadset[i]);
- }
-
- /* If no client threads are still running, also stop the server */
- for(i=0; i<N_THREAD && threadset[i].busy==0; i++){}
- if( i>=N_THREAD ){
- sqlite3_server_stop();
- while( 1 ){
- for(i=0; i<N_THREAD && threadset[i].nServer==0; i++);
- if( i==N_THREAD ) break;
- sched_yield();
- }
- }
- return TCL_OK;
-}
-
-/*
-** Usage: client_argc ID
-**
-** Wait on the most recent client_step to complete, then return the
-** number of columns in the result set.
-*/
-static int SQLITE_TCLAPI tcl_client_argc(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- const char **argv /* Text of each argument */
-){
- int i;
- char zBuf[100];
-
- if( argc!=2 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " ID", 0);
- return TCL_ERROR;
- }
- i = parse_client_id(interp, argv[1]);
- if( i<0 ) return TCL_ERROR;
- if( !threadset[i].busy ){
- Tcl_AppendResult(interp, "no such thread", 0);
- return TCL_ERROR;
- }
- client_wait(&threadset[i]);
- sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", threadset[i].argc);
- Tcl_AppendResult(interp, zBuf, 0);
- return TCL_OK;
-}
-
-/*
-** Usage: client_argv ID N
-**
-** Wait on the most recent client_step to complete, then return the
-** value of the N-th columns in the result set.
-*/
-static int SQLITE_TCLAPI tcl_client_argv(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- const char **argv /* Text of each argument */
-){
- int i;
- int n;
-
- if( argc!=3 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " ID N", 0);
- return TCL_ERROR;
- }
- i = parse_client_id(interp, argv[1]);
- if( i<0 ) return TCL_ERROR;
- if( !threadset[i].busy ){
- Tcl_AppendResult(interp, "no such thread", 0);
- return TCL_ERROR;
- }
- if( Tcl_GetInt(interp, argv[2], &n) ) return TCL_ERROR;
- client_wait(&threadset[i]);
- if( n<0 || n>=threadset[i].argc ){
- Tcl_AppendResult(interp, "column number out of range", 0);
- return TCL_ERROR;
- }
- Tcl_AppendResult(interp, threadset[i].argv[n], 0);
- return TCL_OK;
-}
-
-/*
-** Usage: client_colname ID N
-**
-** Wait on the most recent client_step to complete, then return the
-** name of the N-th columns in the result set.
-*/
-static int SQLITE_TCLAPI tcl_client_colname(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- const char **argv /* Text of each argument */
-){
- int i;
- int n;
-
- if( argc!=3 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " ID N", 0);
- return TCL_ERROR;
- }
- i = parse_client_id(interp, argv[1]);
- if( i<0 ) return TCL_ERROR;
- if( !threadset[i].busy ){
- Tcl_AppendResult(interp, "no such thread", 0);
- return TCL_ERROR;
- }
- if( Tcl_GetInt(interp, argv[2], &n) ) return TCL_ERROR;
- client_wait(&threadset[i]);
- if( n<0 || n>=threadset[i].argc ){
- Tcl_AppendResult(interp, "column number out of range", 0);
- return TCL_ERROR;
- }
- Tcl_AppendResult(interp, threadset[i].colv[n], 0);
- return TCL_OK;
-}
-
-extern const char *sqlite3ErrName(int);
-
-/*
-** Usage: client_result ID
-**
-** Wait on the most recent operation to complete, then return the
-** result code from that operation.
-*/
-static int SQLITE_TCLAPI tcl_client_result(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- const char **argv /* Text of each argument */
-){
- int i;
- const char *zName;
-
- if( argc!=2 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " ID", 0);
- return TCL_ERROR;
- }
- i = parse_client_id(interp, argv[1]);
- if( i<0 ) return TCL_ERROR;
- if( !threadset[i].busy ){
- Tcl_AppendResult(interp, "no such thread", 0);
- return TCL_ERROR;
- }
- client_wait(&threadset[i]);
- zName = sqlite3ErrName(threadset[i].rc);
- Tcl_AppendResult(interp, zName, 0);
- return TCL_OK;
-}
-
-/*
-** Usage: client_error ID
-**
-** Wait on the most recent operation to complete, then return the
-** error string.
-*/
-static int SQLITE_TCLAPI tcl_client_error(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- const char **argv /* Text of each argument */
-){
- int i;
-
- if( argc!=2 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " ID", 0);
- return TCL_ERROR;
- }
- i = parse_client_id(interp, argv[1]);
- if( i<0 ) return TCL_ERROR;
- if( !threadset[i].busy ){
- Tcl_AppendResult(interp, "no such thread", 0);
- return TCL_ERROR;
- }
- client_wait(&threadset[i]);
- Tcl_AppendResult(interp, threadset[i].zErr, 0);
- return TCL_OK;
-}
-
-/*
-** This procedure runs in the thread to compile an SQL statement.
-*/
-static void do_compile(Thread *p){
- if( p->db==0 ){
- p->zErr = p->zStaticErr = "no database is open";
- p->rc = SQLITE_ERROR;
- return;
- }
- if( p->pStmt ){
- sqlite3_client_finalize(p->pStmt);
- p->pStmt = 0;
- }
- p->rc = sqlite3_client_prepare(p->db, p->zArg, -1, &p->pStmt, 0);
-}
-
-/*
-** Usage: client_compile ID SQL
-**
-** Compile a new virtual machine.
-*/
-static int SQLITE_TCLAPI tcl_client_compile(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- const char **argv /* Text of each argument */
-){
- int i;
- if( argc!=3 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " ID SQL", 0);
- return TCL_ERROR;
- }
- i = parse_client_id(interp, argv[1]);
- if( i<0 ) return TCL_ERROR;
- if( !threadset[i].busy ){
- Tcl_AppendResult(interp, "no such thread", 0);
- return TCL_ERROR;
- }
- client_wait(&threadset[i]);
- threadset[i].xOp = do_compile;
- sqlite3_free(threadset[i].zArg);
- threadset[i].zArg = sqlite3_mprintf("%s", argv[2]);
- threadset[i].opnum++;
- return TCL_OK;
-}
-
-/*
-** This procedure runs in the thread to step the virtual machine.
-*/
-static void do_step(Thread *p){
- int i;
- if( p->pStmt==0 ){
- p->zErr = p->zStaticErr = "no virtual machine available";
- p->rc = SQLITE_ERROR;
- return;
- }
- p->rc = sqlite3_client_step(p->pStmt);
- if( p->rc==SQLITE_ROW ){
- p->argc = sqlite3_column_count(p->pStmt);
- for(i=0; i<sqlite3_data_count(p->pStmt); i++){
- p->argv[i] = (char*)sqlite3_column_text(p->pStmt, i);
- }
- for(i=0; i<p->argc; i++){
- p->colv[i] = sqlite3_column_name(p->pStmt, i);
- }
- }
-}
-
-/*
-** Usage: client_step ID
-**
-** Advance the virtual machine by one step
-*/
-static int SQLITE_TCLAPI tcl_client_step(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- const char **argv /* Text of each argument */
-){
- int i;
- if( argc!=2 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " IDL", 0);
- return TCL_ERROR;
- }
- i = parse_client_id(interp, argv[1]);
- if( i<0 ) return TCL_ERROR;
- if( !threadset[i].busy ){
- Tcl_AppendResult(interp, "no such thread", 0);
- return TCL_ERROR;
- }
- client_wait(&threadset[i]);
- threadset[i].xOp = do_step;
- threadset[i].opnum++;
- return TCL_OK;
-}
-
-/*
-** This procedure runs in the thread to finalize a virtual machine.
-*/
-static void do_finalize(Thread *p){
- if( p->pStmt==0 ){
- p->zErr = p->zStaticErr = "no virtual machine available";
- p->rc = SQLITE_ERROR;
- return;
- }
- p->rc = sqlite3_client_finalize(p->pStmt);
- p->pStmt = 0;
-}
-
-/*
-** Usage: client_finalize ID
-**
-** Finalize the virtual machine.
-*/
-static int SQLITE_TCLAPI tcl_client_finalize(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- const char **argv /* Text of each argument */
-){
- int i;
- if( argc!=2 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " IDL", 0);
- return TCL_ERROR;
- }
- i = parse_client_id(interp, argv[1]);
- if( i<0 ) return TCL_ERROR;
- if( !threadset[i].busy ){
- Tcl_AppendResult(interp, "no such thread", 0);
- return TCL_ERROR;
- }
- client_wait(&threadset[i]);
- threadset[i].xOp = do_finalize;
- sqlite3_free(threadset[i].zArg);
- threadset[i].zArg = 0;
- threadset[i].opnum++;
- return TCL_OK;
-}
-
-/*
-** This procedure runs in the thread to reset a virtual machine.
-*/
-static void do_reset(Thread *p){
- if( p->pStmt==0 ){
- p->zErr = p->zStaticErr = "no virtual machine available";
- p->rc = SQLITE_ERROR;
- return;
- }
- p->rc = sqlite3_client_reset(p->pStmt);
- p->pStmt = 0;
-}
-
-/*
-** Usage: client_reset ID
-**
-** Finalize the virtual machine.
-*/
-static int SQLITE_TCLAPI tcl_client_reset(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- const char **argv /* Text of each argument */
-){
- int i;
- if( argc!=2 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " IDL", 0);
- return TCL_ERROR;
- }
- i = parse_client_id(interp, argv[1]);
- if( i<0 ) return TCL_ERROR;
- if( !threadset[i].busy ){
- Tcl_AppendResult(interp, "no such thread", 0);
- return TCL_ERROR;
- }
- client_wait(&threadset[i]);
- threadset[i].xOp = do_reset;
- sqlite3_free(threadset[i].zArg);
- threadset[i].zArg = 0;
- threadset[i].opnum++;
- return TCL_OK;
-}
-
-/*
-** Usage: client_swap ID ID
-**
-** Interchange the sqlite* pointer between two threads.
-*/
-static int SQLITE_TCLAPI tcl_client_swap(
- void *NotUsed,
- Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
- int argc, /* Number of arguments */
- const char **argv /* Text of each argument */
-){
- int i, j;
- sqlite3 *temp;
- if( argc!=3 ){
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " ID1 ID2", 0);
- return TCL_ERROR;
- }
- i = parse_client_id(interp, argv[1]);
- if( i<0 ) return TCL_ERROR;
- if( !threadset[i].busy ){
- Tcl_AppendResult(interp, "no such thread", 0);
- return TCL_ERROR;
- }
- client_wait(&threadset[i]);
- j = parse_client_id(interp, argv[2]);
- if( j<0 ) return TCL_ERROR;
- if( !threadset[j].busy ){
- Tcl_AppendResult(interp, "no such thread", 0);
- return TCL_ERROR;
- }
- client_wait(&threadset[j]);
- temp = threadset[i].db;
- threadset[i].db = threadset[j].db;
- threadset[j].db = temp;
- return TCL_OK;
-}
-
-/*
-** Register commands with the TCL interpreter.
-*/
-int Sqlitetest7_Init(Tcl_Interp *interp){
- static struct {
- char *zName;
- Tcl_CmdProc *xProc;
- } aCmd[] = {
- { "client_create", (Tcl_CmdProc*)tcl_client_create },
- { "client_wait", (Tcl_CmdProc*)tcl_client_wait },
- { "client_halt", (Tcl_CmdProc*)tcl_client_halt },
- { "client_argc", (Tcl_CmdProc*)tcl_client_argc },
- { "client_argv", (Tcl_CmdProc*)tcl_client_argv },
- { "client_colname", (Tcl_CmdProc*)tcl_client_colname },
- { "client_result", (Tcl_CmdProc*)tcl_client_result },
- { "client_error", (Tcl_CmdProc*)tcl_client_error },
- { "client_compile", (Tcl_CmdProc*)tcl_client_compile },
- { "client_step", (Tcl_CmdProc*)tcl_client_step },
- { "client_reset", (Tcl_CmdProc*)tcl_client_reset },
- { "client_finalize", (Tcl_CmdProc*)tcl_client_finalize },
- { "client_swap", (Tcl_CmdProc*)tcl_client_swap },
- };
- int i;
-
- for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){
- Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0);
- }
- return TCL_OK;
-}
-#else
-int Sqlitetest7_Init(Tcl_Interp *interp){ return TCL_OK; }
-#endif /* SQLITE_OS_UNIX */
diff --git a/src/test_server.c b/src/test_server.c
deleted file mode 100644
index 4eb1cf196..000000000
--- a/src/test_server.c
+++ /dev/null
@@ -1,516 +0,0 @@
-/*
-** 2006 January 07
-**
-** 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 contains demonstration code. Nothing in this file gets compiled
-** or linked into the SQLite library unless you use a non-standard option:
-**
-** -DSQLITE_SERVER=1
-**
-** The configure script will never generate a Makefile with the option
-** above. You will need to manually modify the Makefile if you want to
-** include any of the code from this file in your project. Or, at your
-** option, you may copy and paste the code from this file and
-** thereby avoiding a recompile of SQLite.
-**
-**
-** This source file demonstrates how to use SQLite to create an SQL database
-** server thread in a multiple-threaded program. One or more client threads
-** send messages to the server thread and the server thread processes those
-** messages in the order received and returns the results to the client.
-**
-** One might ask: "Why bother? Why not just let each thread connect
-** to the database directly?" There are a several of reasons to
-** prefer the client/server approach.
-**
-** (1) Some systems (ex: Redhat9) have broken threading implementations
-** that prevent SQLite database connections from being used in
-** a thread different from the one where they were created. With
-** the client/server approach, all database connections are created
-** and used within the server thread. Client calls to the database
-** can be made from multiple threads (though not at the same time!)
-**
-** (2) Beginning with SQLite version 3.3.0, when two or more
-** connections to the same database occur within the same thread,
-** they can optionally share their database cache. This reduces
-** I/O and memory requirements. Cache shared is controlled using
-** the sqlite3_enable_shared_cache() API.
-**
-** (3) Database connections on a shared cache use table-level locking
-** instead of file-level locking for improved concurrency.
-**
-** (4) Database connections on a shared cache can by optionally
-** set to READ UNCOMMITTED isolation. (The default isolation for
-** SQLite is SERIALIZABLE.) When this occurs, readers will
-** never be blocked by a writer and writers will not be
-** blocked by readers. There can still only be a single writer
-** at a time, but multiple readers can simultaneously exist with
-** that writer. This is a huge increase in concurrency.
-**
-** To summarize the rational for using a client/server approach: prior
-** to SQLite version 3.3.0 it probably was not worth the trouble. But
-** with SQLite version 3.3.0 and beyond you can get significant performance
-** and concurrency improvements and memory usage reductions by going
-** client/server.
-**
-** Note: The extra features of version 3.3.0 described by points (2)
-** through (4) above are only available if you compile without the
-** option -DSQLITE_OMIT_SHARED_CACHE.
-**
-** Here is how the client/server approach works: The database server
-** thread is started on this procedure:
-**
-** void *sqlite3_server(void *NotUsed);
-**
-** The sqlite_server procedure runs as long as the g.serverHalt variable
-** is false. A mutex is used to make sure no more than one server runs
-** at a time. The server waits for messages to arrive on a message
-** queue and processes the messages in order.
-**
-** Two convenience routines are provided for starting and stopping the
-** server thread:
-**
-** void sqlite3_server_start(void);
-** void sqlite3_server_stop(void);
-**
-** Both of the convenience routines return immediately. Neither will
-** ever give an error. If a server is already started or already halted,
-** then the routines are effectively no-ops.
-**
-** Clients use the following interfaces:
-**
-** sqlite3_client_open
-** sqlite3_client_prepare
-** sqlite3_client_step
-** sqlite3_client_reset
-** sqlite3_client_finalize
-** sqlite3_client_close
-**
-** These interfaces work exactly like the standard core SQLite interfaces
-** having the same names without the "_client_" infix. Many other SQLite
-** interfaces can be used directly without having to send messages to the
-** server as long as SQLITE_ENABLE_MEMORY_MANAGEMENT is not defined.
-** The following interfaces fall into this second category:
-**
-** sqlite3_bind_*
-** sqlite3_changes
-** sqlite3_clear_bindings
-** sqlite3_column_*
-** sqlite3_complete
-** sqlite3_create_collation
-** sqlite3_create_function
-** sqlite3_data_count
-** sqlite3_db_handle
-** sqlite3_errcode
-** sqlite3_errmsg
-** sqlite3_last_insert_rowid
-** sqlite3_total_changes
-** sqlite3_transfer_bindings
-**
-** A single SQLite connection (an sqlite3* object) or an SQLite statement
-** (an sqlite3_stmt* object) should only be passed to a single interface
-** function at a time. The connections and statements can be passed from
-** any thread to any of the functions listed in the second group above as
-** long as the same connection is not in use by two threads at once and
-** as long as SQLITE_ENABLE_MEMORY_MANAGEMENT is not defined. Additional
-** information about the SQLITE_ENABLE_MEMORY_MANAGEMENT constraint is
-** below.
-**
-** The busy handler for all database connections should remain turned
-** off. That means that any lock contention will cause the associated
-** sqlite3_client_step() call to return immediately with an SQLITE_BUSY
-** error code. If a busy handler is enabled and lock contention occurs,
-** then the entire server thread will block. This will cause not only
-** the requesting client to block but every other database client as
-** well. It is possible to enhance the code below so that lock
-** contention will cause the message to be placed back on the top of
-** the queue to be tried again later. But such enhanced processing is
-** not included here, in order to keep the example simple.
-**
-** This example code assumes the use of pthreads. Pthreads
-** implementations are available for windows. (See, for example
-** http://sourceware.org/pthreads-win32/announcement.html.) Or, you
-** can translate the locking and thread synchronization code to use
-** windows primitives easily enough. The details are left as an
-** exercise to the reader.
-**
-**** Restrictions Associated With SQLITE_ENABLE_MEMORY_MANAGEMENT ****
-**
-** If you compile with SQLITE_ENABLE_MEMORY_MANAGEMENT defined, then
-** SQLite includes code that tracks how much memory is being used by
-** each thread. These memory counts can become confused if memory
-** is allocated by one thread and then freed by another. For that
-** reason, when SQLITE_ENABLE_MEMORY_MANAGEMENT is used, all operations
-** that might allocate or free memory should be performanced in the same
-** thread that originally created the database connection. In that case,
-** many of the operations that are listed above as safe to be performed
-** in separate threads would need to be sent over to the server to be
-** done there. If SQLITE_ENABLE_MEMORY_MANAGEMENT is defined, then
-** the following functions can be used safely from different threads
-** without messing up the allocation counts:
-**
-** sqlite3_bind_parameter_name
-** sqlite3_bind_parameter_index
-** sqlite3_changes
-** sqlite3_column_blob
-** sqlite3_column_count
-** sqlite3_complete
-** sqlite3_data_count
-** sqlite3_db_handle
-** sqlite3_errcode
-** sqlite3_errmsg
-** sqlite3_last_insert_rowid
-** sqlite3_total_changes
-**
-** The remaining functions are not thread-safe when memory management
-** is enabled. So one would have to define some new interface routines
-** along the following lines:
-**
-** sqlite3_client_bind_*
-** sqlite3_client_clear_bindings
-** sqlite3_client_column_*
-** sqlite3_client_create_collation
-** sqlite3_client_create_function
-** sqlite3_client_transfer_bindings
-**
-** The example code in this file is intended for use with memory
-** management turned off. So the implementation of these additional
-** client interfaces is left as an exercise to the reader.
-**
-** It may seem surprising to the reader that the list of safe functions
-** above does not include things like sqlite3_bind_int() or
-** sqlite3_column_int(). But those routines might, in fact, allocate
-** or deallocate memory. In the case of sqlite3_bind_int(), if the
-** parameter was previously bound to a string that string might need
-** to be deallocated before the new integer value is inserted. In
-** the case of sqlite3_column_int(), the value of the column might be
-** a UTF-16 string which will need to be converted to UTF-8 then into
-** an integer.
-*/
-
-/* Include this to get the definition of SQLITE_THREADSAFE, in the
-** case that default values are used.
-*/
-#include "sqliteInt.h"
-
-/*
-** Only compile the code in this file on UNIX with a SQLITE_THREADSAFE build
-** and only if the SQLITE_SERVER macro is defined.
-*/
-#if defined(SQLITE_SERVER) && !defined(SQLITE_OMIT_SHARED_CACHE)
-#if SQLITE_OS_UNIX && SQLITE_THREADSAFE
-
-/*
-** We require only pthreads and the public interface of SQLite.
-*/
-#include <pthread.h>
-#include "sqlite3.h"
-
-/*
-** Messages are passed from client to server and back again as
-** instances of the following structure.
-*/
-typedef struct SqlMessage SqlMessage;
-struct SqlMessage {
- int op; /* Opcode for the message */
- sqlite3 *pDb; /* The SQLite connection */
- sqlite3_stmt *pStmt; /* A specific statement */
- int errCode; /* Error code returned */
- const char *zIn; /* Input filename or SQL statement */
- int nByte; /* Size of the zIn parameter for prepare() */
- const char *zOut; /* Tail of the SQL statement */
- SqlMessage *pNext; /* Next message in the queue */
- SqlMessage *pPrev; /* Previous message in the queue */
- pthread_mutex_t clientMutex; /* Hold this mutex to access the message */
- pthread_cond_t clientWakeup; /* Signal to wake up the client */
-};
-
-/*
-** Legal values for SqlMessage.op
-*/
-#define MSG_Open 1 /* sqlite3_open(zIn, &pDb) */
-#define MSG_Prepare 2 /* sqlite3_prepare(pDb, zIn, nByte, &pStmt, &zOut) */
-#define MSG_Step 3 /* sqlite3_step(pStmt) */
-#define MSG_Reset 4 /* sqlite3_reset(pStmt) */
-#define MSG_Finalize 5 /* sqlite3_finalize(pStmt) */
-#define MSG_Close 6 /* sqlite3_close(pDb) */
-#define MSG_Done 7 /* Server has finished with this message */
-
-
-/*
-** State information about the server is stored in a static variable
-** named "g" as follows:
-*/
-static struct ServerState {
- pthread_mutex_t queueMutex; /* Hold this mutex to access the msg queue */
- pthread_mutex_t serverMutex; /* Held by the server while it is running */
- pthread_cond_t serverWakeup; /* Signal this condvar to wake up the server */
- volatile int serverHalt; /* Server halts itself when true */
- SqlMessage *pQueueHead; /* Head of the message queue */
- SqlMessage *pQueueTail; /* Tail of the message queue */
-} g = {
- PTHREAD_MUTEX_INITIALIZER,
- PTHREAD_MUTEX_INITIALIZER,
- PTHREAD_COND_INITIALIZER,
-};
-
-/*
-** Send a message to the server. Block until we get a reply.
-**
-** The mutex and condition variable in the message are uninitialized
-** when this routine is called. This routine takes care of
-** initializing them and destroying them when it has finished.
-*/
-static void sendToServer(SqlMessage *pMsg){
- /* Initialize the mutex and condition variable on the message
- */
- pthread_mutex_init(&pMsg->clientMutex, 0);
- pthread_cond_init(&pMsg->clientWakeup, 0);
-
- /* Add the message to the head of the server's message queue.
- */
- pthread_mutex_lock(&g.queueMutex);
- pMsg->pNext = g.pQueueHead;
- if( g.pQueueHead==0 ){
- g.pQueueTail = pMsg;
- }else{
- g.pQueueHead->pPrev = pMsg;
- }
- pMsg->pPrev = 0;
- g.pQueueHead = pMsg;
- pthread_mutex_unlock(&g.queueMutex);
-
- /* Signal the server that the new message has be queued, then
- ** block waiting for the server to process the message.
- */
- pthread_mutex_lock(&pMsg->clientMutex);
- pthread_cond_signal(&g.serverWakeup);
- while( pMsg->op!=MSG_Done ){
- pthread_cond_wait(&pMsg->clientWakeup, &pMsg->clientMutex);
- }
- pthread_mutex_unlock(&pMsg->clientMutex);
-
- /* Destroy the mutex and condition variable of the message.
- */
- pthread_mutex_destroy(&pMsg->clientMutex);
- pthread_cond_destroy(&pMsg->clientWakeup);
-}
-
-/*
-** The following 6 routines are client-side implementations of the
-** core SQLite interfaces:
-**
-** sqlite3_open
-** sqlite3_prepare
-** sqlite3_step
-** sqlite3_reset
-** sqlite3_finalize
-** sqlite3_close
-**
-** Clients should use the following client-side routines instead of
-** the core routines above.
-**
-** sqlite3_client_open
-** sqlite3_client_prepare
-** sqlite3_client_step
-** sqlite3_client_reset
-** sqlite3_client_finalize
-** sqlite3_client_close
-**
-** Each of these routines creates a message for the desired operation,
-** sends that message to the server, waits for the server to process
-** then message and return a response.
-*/
-int sqlite3_client_open(const char *zDatabaseName, sqlite3 **ppDb){
- SqlMessage msg;
- msg.op = MSG_Open;
- msg.zIn = zDatabaseName;
- sendToServer(&msg);
- *ppDb = msg.pDb;
- return msg.errCode;
-}
-int sqlite3_client_prepare(
- sqlite3 *pDb,
- const char *zSql,
- int nByte,
- sqlite3_stmt **ppStmt,
- const char **pzTail
-){
- SqlMessage msg;
- msg.op = MSG_Prepare;
- msg.pDb = pDb;
- msg.zIn = zSql;
- msg.nByte = nByte;
- sendToServer(&msg);
- *ppStmt = msg.pStmt;
- if( pzTail ) *pzTail = msg.zOut;
- return msg.errCode;
-}
-int sqlite3_client_step(sqlite3_stmt *pStmt){
- SqlMessage msg;
- msg.op = MSG_Step;
- msg.pStmt = pStmt;
- sendToServer(&msg);
- return msg.errCode;
-}
-int sqlite3_client_reset(sqlite3_stmt *pStmt){
- SqlMessage msg;
- msg.op = MSG_Reset;
- msg.pStmt = pStmt;
- sendToServer(&msg);
- return msg.errCode;
-}
-int sqlite3_client_finalize(sqlite3_stmt *pStmt){
- SqlMessage msg;
- msg.op = MSG_Finalize;
- msg.pStmt = pStmt;
- sendToServer(&msg);
- return msg.errCode;
-}
-int sqlite3_client_close(sqlite3 *pDb){
- SqlMessage msg;
- msg.op = MSG_Close;
- msg.pDb = pDb;
- sendToServer(&msg);
- return msg.errCode;
-}
-
-/*
-** This routine implements the server. To start the server, first
-** make sure g.serverHalt is false, then create a new detached thread
-** on this procedure. See the sqlite3_server_start() routine below
-** for an example. This procedure loops until g.serverHalt becomes
-** true.
-*/
-void *sqlite3_server(void *NotUsed){
- if( pthread_mutex_trylock(&g.serverMutex) ){
- return 0; /* Another server is already running */
- }
- sqlite3_enable_shared_cache(1);
- while( !g.serverHalt ){
- SqlMessage *pMsg;
-
- /* Remove the last message from the message queue.
- */
- pthread_mutex_lock(&g.queueMutex);
- while( g.pQueueTail==0 && g.serverHalt==0 ){
- pthread_cond_wait(&g.serverWakeup, &g.queueMutex);
- }
- pMsg = g.pQueueTail;
- if( pMsg ){
- if( pMsg->pPrev ){
- pMsg->pPrev->pNext = 0;
- }else{
- g.pQueueHead = 0;
- }
- g.pQueueTail = pMsg->pPrev;
- }
- pthread_mutex_unlock(&g.queueMutex);
- if( pMsg==0 ) break;
-
- /* Process the message just removed
- */
- pthread_mutex_lock(&pMsg->clientMutex);
- switch( pMsg->op ){
- case MSG_Open: {
- pMsg->errCode = sqlite3_open(pMsg->zIn, &pMsg->pDb);
- break;
- }
- case MSG_Prepare: {
- pMsg->errCode = sqlite3_prepare(pMsg->pDb, pMsg->zIn, pMsg->nByte,
- &pMsg->pStmt, &pMsg->zOut);
- break;
- }
- case MSG_Step: {
- pMsg->errCode = sqlite3_step(pMsg->pStmt);
- break;
- }
- case MSG_Reset: {
- pMsg->errCode = sqlite3_reset(pMsg->pStmt);
- break;
- }
- case MSG_Finalize: {
- pMsg->errCode = sqlite3_finalize(pMsg->pStmt);
- break;
- }
- case MSG_Close: {
- pMsg->errCode = sqlite3_close(pMsg->pDb);
- break;
- }
- }
-
- /* Signal the client that the message has been processed.
- */
- pMsg->op = MSG_Done;
- pthread_mutex_unlock(&pMsg->clientMutex);
- pthread_cond_signal(&pMsg->clientWakeup);
- }
- pthread_mutex_unlock(&g.serverMutex);
- return 0;
-}
-
-/*
-** Start a server thread if one is not already running. If there
-** is aleady a server thread running, the new thread will quickly
-** die and this routine is effectively a no-op.
-*/
-void sqlite3_server_start(void){
- pthread_t x;
- int rc;
- g.serverHalt = 0;
- rc = pthread_create(&x, 0, sqlite3_server, 0);
- if( rc==0 ){
- pthread_detach(x);
- }
-}
-
-/*
-** A wrapper around sqlite3_server() that decrements the int variable
-** pointed to by the first argument after the sqlite3_server() call
-** returns.
-*/
-static void *serverWrapper(void *pnDecr){
- void *p = sqlite3_server(0);
- (*(int*)pnDecr)--;
- return p;
-}
-
-/*
-** This function is the similar to sqlite3_server_start(), except that
-** the integer pointed to by the first argument is decremented when
-** the server thread exits.
-*/
-void sqlite3_server_start2(int *pnDecr){
- pthread_t x;
- int rc;
- g.serverHalt = 0;
- rc = pthread_create(&x, 0, serverWrapper, (void*)pnDecr);
- if( rc==0 ){
- pthread_detach(x);
- }
-}
-
-/*
-** If a server thread is running, then stop it. If no server is
-** running, this routine is effectively a no-op.
-**
-** This routine waits until the server has actually stopped before
-** returning.
-*/
-void sqlite3_server_stop(void){
- g.serverHalt = 1;
- pthread_cond_broadcast(&g.serverWakeup);
- pthread_mutex_lock(&g.serverMutex);
- pthread_mutex_unlock(&g.serverMutex);
-}
-
-#endif /* SQLITE_OS_UNIX && SQLITE_THREADSAFE */
-#endif /* defined(SQLITE_SERVER) */
diff --git a/src/test_tclsh.c b/src/test_tclsh.c
index c133deca2..32aee4267 100644
--- a/src/test_tclsh.c
+++ b/src/test_tclsh.c
@@ -64,7 +64,6 @@ const char *sqlite3TestInit(Tcl_Interp *interp){
extern int Sqlitetest4_Init(Tcl_Interp*);
extern int Sqlitetest5_Init(Tcl_Interp*);
extern int Sqlitetest6_Init(Tcl_Interp*);
- extern int Sqlitetest7_Init(Tcl_Interp*);
extern int Sqlitetest8_Init(Tcl_Interp*);
extern int Sqlitetest9_Init(Tcl_Interp*);
extern int Sqlitetestasync_Init(Tcl_Interp*);
@@ -136,7 +135,6 @@ const char *sqlite3TestInit(Tcl_Interp *interp){
Sqlitetest4_Init(interp);
Sqlitetest5_Init(interp);
Sqlitetest6_Init(interp);
- Sqlitetest7_Init(interp);
Sqlitetest8_Init(interp);
Sqlitetest9_Init(interp);
Sqlitetestasync_Init(interp);
diff --git a/src/test_thread.c b/src/test_thread.c
index de0fdb434..126fd9836 100644
--- a/src/test_thread.c
+++ b/src/test_thread.c
@@ -384,6 +384,27 @@ static int SQLITE_TCLAPI clock_seconds_proc(
return TCL_OK;
}
+/*
+** The [clock_milliseconds] command. This is more or less the same as the
+** regular tcl [clock milliseconds].
+*/
+static int SQLITE_TCLAPI clock_milliseconds_proc(
+ ClientData clientData,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *CONST objv[]
+){
+ Tcl_Time now;
+ Tcl_GetTime(&now);
+ Tcl_SetObjResult(interp, Tcl_NewWideIntObj(
+ ((Tcl_WideInt)now.sec * 1000) + (now.usec / 1000)
+ ));
+ UNUSED_PARAMETER(clientData);
+ UNUSED_PARAMETER(objc);
+ UNUSED_PARAMETER(objv);
+ return TCL_OK;
+}
+
/*************************************************************************
** This block contains the implementation of the [sqlite3_blocking_step]
** command available to threads created by [sqlthread spawn] commands. It
@@ -617,15 +638,26 @@ static int SQLITE_TCLAPI blocking_prepare_v2_proc(
** Register commands with the TCL interpreter.
*/
int SqlitetestThread_Init(Tcl_Interp *interp){
- Tcl_CreateObjCommand(interp, "sqlthread", sqlthread_proc, 0, 0);
- Tcl_CreateObjCommand(interp, "clock_seconds", clock_seconds_proc, 0, 0);
+ struct TclCmd {
+ int (*xProc)(void*, Tcl_Interp*, int, Tcl_Obj*const*);
+ const char *zName;
+ int iCtx;
+ } aCmd[] = {
+ { sqlthread_proc, "sqlthread", 0 },
+ { clock_seconds_proc, "clock_second", 0 },
+ { clock_milliseconds_proc, "clock_milliseconds", 0 },
#if SQLITE_OS_UNIX && defined(SQLITE_ENABLE_UNLOCK_NOTIFY)
- Tcl_CreateObjCommand(interp, "sqlite3_blocking_step", blocking_step_proc,0,0);
- Tcl_CreateObjCommand(interp,
- "sqlite3_blocking_prepare_v2", blocking_prepare_v2_proc, (void *)1, 0);
- Tcl_CreateObjCommand(interp,
- "sqlite3_nonblocking_prepare_v2", blocking_prepare_v2_proc, 0, 0);
+ { blocking_step_proc, "sqlite3_blocking_step", 0 },
+ { blocking_prepare_v2_proc, "sqlite3_blocking_prepare_v2", 1 },
+ { blocking_prepare_v2_proc, "sqlite3_nonblocking_prepare_v2", 0 },
#endif
+ };
+ int ii;
+
+ for(ii=0; ii<sizeof(aCmd)/sizeof(aCmd[0]); ii++){
+ void *p = SQLITE_INT_TO_PTR(aCmd[ii].iCtx);
+ Tcl_CreateObjCommand(interp, aCmd[ii].zName, aCmd[ii].xProc, p, 0);
+ }
return TCL_OK;
}
#else
diff --git a/src/test_vfs.c b/src/test_vfs.c
index f3e8297ac..312e1a1be 100644
--- a/src/test_vfs.c
+++ b/src/test_vfs.c
@@ -485,6 +485,9 @@ static int tvfsLock(sqlite3_file *pFile, int eLock){
tvfsExecTcl(p, "xLock", Tcl_NewStringObj(pFd->zFilename, -1),
Tcl_NewStringObj(zLock, -1), 0, 0);
}
+ if( p->mask&TESTVFS_LOCK_MASK && tvfsInjectIoerr(p) ){
+ return SQLITE_IOERR_LOCK;
+ }
return sqlite3OsLock(pFd->pReal, eLock);
}
@@ -500,7 +503,7 @@ static int tvfsUnlock(sqlite3_file *pFile, int eLock){
tvfsExecTcl(p, "xUnlock", Tcl_NewStringObj(pFd->zFilename, -1),
Tcl_NewStringObj(zLock, -1), 0, 0);
}
- if( p->mask&TESTVFS_WRITE_MASK && tvfsInjectIoerr(p) ){
+ if( p->mask&TESTVFS_UNLOCK_MASK && tvfsInjectIoerr(p) ){
return SQLITE_IOERR_UNLOCK;
}
return sqlite3OsUnlock(pFd->pReal, eLock);
diff --git a/src/treeview.c b/src/treeview.c
index 9df16a12b..9f630b156 100644
--- a/src/treeview.c
+++ b/src/treeview.c
@@ -218,6 +218,13 @@ void sqlite3TreeViewSrcList(TreeView *pView, const SrcList *pSrc){
if( pItem->fg.isOn || (pItem->fg.isUsing==0 && pItem->u3.pOn!=0) ){
sqlite3_str_appendf(&x, " ON");
}
+ if( pItem->fg.isTabFunc ) sqlite3_str_appendf(&x, " isTabFunc");
+ if( pItem->fg.isCorrelated ) sqlite3_str_appendf(&x, " isCorrelated");
+ if( pItem->fg.isMaterialized ) sqlite3_str_appendf(&x, " isMaterialized");
+ if( pItem->fg.viaCoroutine ) sqlite3_str_appendf(&x, " viaCoroutine");
+ if( pItem->fg.notCte ) sqlite3_str_appendf(&x, " notCte");
+ if( pItem->fg.isNestedFrom ) sqlite3_str_appendf(&x, " isNestedFrom");
+
sqlite3StrAccumFinish(&x);
sqlite3TreeViewItem(pView, zLine, i<pSrc->nSrc-1);
n = 0;
diff --git a/src/vdbemem.c b/src/vdbemem.c
index d9909decc..d415f9f72 100644
--- a/src/vdbemem.c
+++ b/src/vdbemem.c
@@ -1508,8 +1508,6 @@ static int valueFromFunction(
goto value_from_function_out;
}
- testcase( pCtx->pParse->rc==SQLITE_ERROR );
- testcase( pCtx->pParse->rc==SQLITE_OK );
memset(&ctx, 0, sizeof(ctx));
ctx.pOut = pVal;
ctx.pFunc = pFunc;
@@ -1521,11 +1519,14 @@ static int valueFromFunction(
}else{
sqlite3ValueApplyAffinity(pVal, aff, SQLITE_UTF8);
assert( rc==SQLITE_OK );
+ assert( enc==pVal->enc || db->mallocFailed );
+#if 0 /* Not reachable except after a prior failure */
rc = sqlite3VdbeChangeEncoding(pVal, enc);
if( rc==SQLITE_OK && sqlite3VdbeMemTooBig(pVal) ){
rc = SQLITE_TOOBIG;
pCtx->pParse->nErr++;
}
+#endif
}
pCtx->pParse->rc = rc;
diff --git a/src/where.c b/src/where.c
index 6a9edd028..df2a13b66 100644
--- a/src/where.c
+++ b/src/where.c
@@ -3595,7 +3595,8 @@ static int whereLoopAddBtree(
if( !IsView(pTab) && (pTab->tabFlags & TF_Ephemeral)==0 ){
pNew->rSetup += 28;
}else{
- pNew->rSetup -= 10;
+ pNew->rSetup -= 25; /* Greatly reduced setup cost for auto indexes
+ ** on ephemeral materializations of views */
}
ApplyCostMultiplier(pNew->rSetup, pTab->costMult);
if( pNew->rSetup<0 ) pNew->rSetup = 0;
@@ -5595,24 +5596,23 @@ static SQLITE_NOINLINE void whereCheckIfBloomFilterIsUseful(
const WhereInfo *pWInfo
){
int i;
- LogEst nSearch;
+ LogEst nSearch = 0;
assert( pWInfo->nLevel>=2 );
assert( OptimizationEnabled(pWInfo->pParse->db, SQLITE_BloomFilter) );
- nSearch = pWInfo->a[0].pWLoop->nOut;
- for(i=1; i<pWInfo->nLevel; i++){
+ for(i=0; i<pWInfo->nLevel; i++){
WhereLoop *pLoop = pWInfo->a[i].pWLoop;
const unsigned int reqFlags = (WHERE_SELFCULL|WHERE_COLUMN_EQ);
- if( (pLoop->wsFlags & reqFlags)==reqFlags
+ SrcItem *pItem = &pWInfo->pTabList->a[pLoop->iTab];
+ Table *pTab = pItem->pTab;
+ if( (pTab->tabFlags & TF_HasStat1)==0 ) break;
+ pTab->tabFlags |= TF_StatsUsed;
+ if( i>=1
+ && (pLoop->wsFlags & reqFlags)==reqFlags
/* vvvvvv--- Always the case if WHERE_COLUMN_EQ is defined */
&& ALWAYS((pLoop->wsFlags & (WHERE_IPK|WHERE_INDEXED))!=0)
){
- SrcItem *pItem = &pWInfo->pTabList->a[pLoop->iTab];
- Table *pTab = pItem->pTab;
- pTab->tabFlags |= TF_StatsUsed;
- if( nSearch > pTab->nRowLogEst
- && (pTab->tabFlags & TF_HasStat1)!=0
- ){
+ if( nSearch > pTab->nRowLogEst ){
testcase( pItem->fg.jointype & JT_LEFT );
pLoop->wsFlags |= WHERE_BLOOMFILTER;
pLoop->wsFlags &= ~WHERE_IDX_ONLY;
diff --git a/src/window.c b/src/window.c
index 8dd35ee30..56de38ba3 100644
--- a/src/window.c
+++ b/src/window.c
@@ -1079,6 +1079,7 @@ int sqlite3WindowRewrite(Parse *pParse, Select *p){
if( p->pSrc ){
Table *pTab2;
p->pSrc->a[0].pSelect = pSub;
+ p->pSrc->a[0].fg.isCorrelated = 1;
sqlite3SrcListAssignCursors(pParse, p->pSrc);
pSub->selFlags |= SF_Expanded|SF_OrderByReqd;
pTab2 = sqlite3ResultSetOfSelect(pParse, pSub, SQLITE_AFF_NONE);
diff --git a/test/auth.test b/test/auth.test
index 7df9ad373..1d56f7034 100644
--- a/test/auth.test
+++ b/test/auth.test
@@ -2250,15 +2250,17 @@ ifcapable altertable&&vtab {
# The sqlite3_declare_vtab() call that occurs during pragma_table_list
# should not cause an authentication failure.
#
-do_test auth-1.359 {
- proc auth {code arg1 arg2 arg3 arg4 args} {
- if {$code=="SQLITE_UPDATE"} {
- return SQLITE_DENY
+ifcapable vtab {
+ do_test auth-1.359 {
+ proc auth {code arg1 arg2 arg3 arg4 args} {
+ if {$code=="SQLITE_UPDATE"} {
+ return SQLITE_DENY
+ }
+ return SQLITE_OK
}
- return SQLITE_OK
- }
- catchsql {SELECT * FROM pragma_table_list WHERE name='xyzzy';}
-} {0 {}}
+ catchsql {SELECT * FROM pragma_table_list WHERE name='xyzzy';}
+ } {0 {}}
+}
do_test auth-2.1 {
proc auth {code arg1 arg2 arg3 arg4 args} {
diff --git a/test/bloom1.test b/test/bloom1.test
index 12b53ddf1..1846e4d63 100644
--- a/test/bloom1.test
+++ b/test/bloom1.test
@@ -66,5 +66,39 @@ do_execsql_test 1.5 {
AND t3.e=t1.b AND t3.f!='silly'
} {result}
-finish_test
+# 2023-02-05
+# https://sqlite.org/forum/forumpost/56de336385
+#
+# Do not employ a Bloom filter if the table being filtered or any table
+# wo the left of the table being filtered lacks STAT1 data, since we
+# cannot make a good Bloom filter usefulness determination without STAT1
+# data.
+#
+reset_db
+do_execsql_test 2.0 {
+ CREATE TABLE objs(c INTEGER, s INTEGER, p INTEGER, o INTEGER);
+ CREATE UNIQUE INDEX objs_cspo ON objs(o,p,c,s);
+ ANALYZE;
+ DELETE FROM sqlite_stat1;
+ INSERT INTO sqlite_stat1 VALUES('objs','objs_cspo','520138 21 20 19 1');
+ ANALYZE sqlite_schema;
+}
+do_eqp_test 2.1 {
+ WITH RECURSIVE transit(x) AS (
+ SELECT s FROM objs WHERE p=9 AND o=32805
+ UNION
+ SELECT objs.s FROM objs, transit WHERE objs.p=9 AND objs.o=transit.x
+ )
+ SELECT x FROM transit;
+} {
+ QUERY PLAN
+ |--CO-ROUTINE transit
+ | |--SETUP
+ | | `--SEARCH objs USING COVERING INDEX objs_cspo (o=? AND p=?)
+ | `--RECURSIVE STEP
+ | |--SCAN transit
+ | `--SEARCH objs USING COVERING INDEX objs_cspo (o=? AND p=?)
+ `--SCAN transit
+}
+finish_test
diff --git a/test/cast.test b/test/cast.test
index 7f7be8b62..ebfea5aa0 100644
--- a/test/cast.test
+++ b/test/cast.test
@@ -539,20 +539,22 @@ do_execsql_test cast-10.6 {
SELECT * FROM dual CROSS JOIN (SELECT CAST(44 AS REAL) AS 'm'
UNION ALL SELECT 55);
} {X 44.0 X 55}
-do_execsql_test cast-10.7 {
- DROP VIEW v1;
- CREATE VIEW v1 AS SELECT CAST(44 AS REAL) AS 'm' UNION ALL SELECT 55;
- SELECT name, type FROM pragma_table_info('v1');
-} {m NUM}
-do_execsql_test cast-10.8 {
- CREATE VIEW v2 AS VALUES(CAST(44 AS REAL)),(55);
- SELECT type FROM pragma_table_info('v2');
-} {NUM}
-do_execsql_test cast-10.9 {
- SELECT * FROM v1;
-} {44.0 55}
-do_execsql_test cast-10.10 {
- SELECT * FROM v2;
-} {44.0 55}
+ifcapable vtab {
+ do_execsql_test cast-10.7 {
+ DROP VIEW v1;
+ CREATE VIEW v1 AS SELECT CAST(44 AS REAL) AS 'm' UNION ALL SELECT 55;
+ SELECT name, type FROM pragma_table_info('v1');
+ } {m NUM}
+ do_execsql_test cast-10.8 {
+ CREATE VIEW v2 AS VALUES(CAST(44 AS REAL)),(55);
+ SELECT type FROM pragma_table_info('v2');
+ } {NUM}
+ do_execsql_test cast-10.9 {
+ SELECT * FROM v1;
+ } {44.0 55}
+ do_execsql_test cast-10.10 {
+ SELECT * FROM v2;
+ } {44.0 55}
+}
finish_test
diff --git a/test/dbpagefault.test b/test/dbpagefault.test
index b41ac6623..544d279ce 100644
--- a/test/dbpagefault.test
+++ b/test/dbpagefault.test
@@ -46,11 +46,11 @@ do_faultsim_test 2 -prep {
} -body {
execsql {
CREATE VIRTUAL TABLE t1 USING sqlite_dbpage();
- INSERT INTO t1 DEFAULT VALUES;
+ UPDATE t1 SET data=zeroblob(1024) WHERE pgno=1 AND schema='aux';
}
} -test {
execsql { PRAGMA journal_mode = off }
- faultsim_test_result {1 {no such schema}} {1 {SQL logic error}}
+ faultsim_test_result {0 {}} {1 {no such schema}} {1 {SQL logic error}} {1 {unable to open a temporary database file for storing temporary tables}}
}
reset_db
diff --git a/test/distinctagg.test b/test/distinctagg.test
index a34312ef9..6e46c8861 100644
--- a/test/distinctagg.test
+++ b/test/distinctagg.test
@@ -184,6 +184,7 @@ foreach {tn use_t3 sql res} {
10 1 "SELECT count(DISTINCT x) FROM t1 LEFT JOIN t3 ON (t3.x=0)" 0
} {
+ unset -nocomplain a
do_test 5.$tn.1 {
set bUse 0
db eval "EXPLAIN $sql" a {
diff --git a/test/fuzzcheck.c b/test/fuzzcheck.c
index a0bcc3bf0..ee7749d96 100644
--- a/test/fuzzcheck.c
+++ b/test/fuzzcheck.c
@@ -1963,13 +1963,13 @@ int main(int argc, char **argv){
quietFlag = 0;
verboseFlag++;
eVerbosity++;
- if( verboseFlag>1 ) runFlags |= SQL_TRACE;
+ if( verboseFlag>2 ) runFlags |= SQL_TRACE;
}else
if( (nV = numberOfVChar(z))>=1 ){
quietFlag = 0;
verboseFlag += nV;
eVerbosity += nV;
- if( verboseFlag>1 ) runFlags |= SQL_TRACE;
+ if( verboseFlag>2 ) runFlags |= SQL_TRACE;
}else
if( strcmp(z,"version")==0 ){
int ii;
@@ -2114,11 +2114,11 @@ int main(int argc, char **argv){
if( zName==0 ) continue;
if( strcmp(zName, "oss-fuzz")==0 ){
ossFuzzThisDb = sqlite3_column_int(pStmt,1);
- if( verboseFlag ) printf("Config: oss-fuzz=%d\n", ossFuzzThisDb);
+ if( verboseFlag>1 ) printf("Config: oss-fuzz=%d\n", ossFuzzThisDb);
}
if( strcmp(zName, "limit-mem")==0 ){
nMemThisDb = sqlite3_column_int(pStmt,1);
- if( verboseFlag ) printf("Config: limit-mem=%d\n", nMemThisDb);
+ if( verboseFlag>1 ) printf("Config: limit-mem=%d\n", nMemThisDb);
}
}
sqlite3_finalize(pStmt);
@@ -2144,14 +2144,14 @@ int main(int argc, char **argv){
size_t kk = strlen(zLine);
while( kk>0 && zLine[kk-1]<=' ' ) kk--;
sqlite3_bind_text(pStmt, 1, zLine, (int)kk, SQLITE_STATIC);
- if( verboseFlag ) printf("loading %.*s\n", (int)kk, zLine);
+ if( verboseFlag>1 ) 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]);
+ if( verboseFlag>1 ) printf("loading %s\n", argv[i]);
sqlite3_step(pStmt);
rc = sqlite3_reset(pStmt);
if( rc ) fatalError("insert failed for %s", argv[i]);
@@ -2235,11 +2235,13 @@ int main(int argc, char **argv){
i = (int)strlen(zDbName) - 1;
while( i>0 && zDbName[i-1]!='/' && zDbName[i-1]!='\\' ){ i--; }
zDbName += i;
- sqlite3_prepare_v2(db, "SELECT msg FROM readme", -1, &pStmt, 0);
- if( pStmt && sqlite3_step(pStmt)==SQLITE_ROW ){
- printf("%s: %s\n", zDbName, sqlite3_column_text(pStmt,0));
+ if( verboseFlag ){
+ sqlite3_prepare_v2(db, "SELECT msg FROM readme", -1, &pStmt, 0);
+ if( pStmt && sqlite3_step(pStmt)==SQLITE_ROW ){
+ printf("%s: %s\n", zDbName, sqlite3_column_text(pStmt,0));
+ }
+ sqlite3_finalize(pStmt);
}
- sqlite3_finalize(pStmt);
}
/* Rebuild the database, if requested */
@@ -2287,7 +2289,7 @@ int main(int argc, char **argv){
/* Run a test using each SQL script against each database.
*/
- if( !verboseFlag && !quietFlag && !bSpinner && !bScript ){
+ if( verboseFlag<2 && !quietFlag && !bSpinner && !bScript ){
printf("%s:", zDbName);
}
for(pSql=g.pFirstSql; pSql; pSql=pSql->pNext){
@@ -2301,7 +2303,7 @@ int main(int argc, char **argv){
int idx = pSql->seq;
printf("\r%s: %d/%d ", zDbName, idx, nTotal);
fflush(stdout);
- }else if( verboseFlag ){
+ }else if( verboseFlag>1 ){
printf("%s\n", g.zTestName);
fflush(stdout);
}else if( !quietFlag ){
@@ -2340,7 +2342,7 @@ int main(int argc, char **argv){
int idx = pSql->seq*g.nDb + pDb->id - 1;
printf("\r%s: %d/%d ", zDbName, idx, nTotal);
fflush(stdout);
- }else if( verboseFlag ){
+ }else if( verboseFlag>1 ){
printf("%s\n", g.zTestName);
fflush(stdout);
}else if( !quietFlag ){
@@ -2442,7 +2444,7 @@ int main(int argc, char **argv){
}else if( bSpinner ){
int nTotal = g.nDb*g.nSql;
printf("\r%s: %d/%d \n", zDbName, nTotal, nTotal);
- }else if( !quietFlag && !verboseFlag ){
+ }else if( !quietFlag && verboseFlag<2 ){
printf(" 100%% - %d tests\n", g.nDb*g.nSql);
}
diff --git a/test/join5.test b/test/join5.test
index 2ffe3f8ac..85e09c57d 100644
--- a/test/join5.test
+++ b/test/join5.test
@@ -287,6 +287,8 @@ do_eqp_test 7.2 {
do_execsql_test 7.3 {
CREATE TABLE t3(x);
+ INSERT INTO t3(x) VALUES(1);
+ CREATE INDEX t3x ON t3(x);
CREATE TABLE t4(x, y, z);
CREATE INDEX t4xy ON t4(x, y);
@@ -296,6 +298,8 @@ do_execsql_test 7.3 {
INSERT INTO t4 SELECT i/10, i, i FROM s;
ANALYZE;
+ UPDATE sqlite_stat1 SET stat='1000000 10 1' WHERE idx='t3x';
+ ANALYZE sqlite_schema;
}
do_eqp_test 7.4 {
diff --git a/test/join8.test b/test/join8.test
index 481430556..1140c104f 100644
--- a/test/join8.test
+++ b/test/join8.test
@@ -258,7 +258,7 @@ do_execsql_test join8-7020 {
)
SELECT * FROM t0 FULL JOIN t4 ON t0.a=t4.d AND t4.z>0
ORDER BY coalesce(t0.a, t0.y+200, t4.d);
-} {/.*BLOOM FILTER ON t2.*BLOOM FILTER ON t3.*BLOOM FILTER ON t4.*/}
+} {/.*BLOOM FILTER ON t2.*BLOOM FILTER ON t3.*/}
# 2022-05-12 Difference with PG found (by Dan) while exploring
# https://sqlite.org/forum/forumpost/677a0ab93fcd9ccd
diff --git a/test/memsubsys2.test b/test/memsubsys2.test
index 68e4e22d3..9085dd295 100644
--- a/test/memsubsys2.test
+++ b/test/memsubsys2.test
@@ -74,18 +74,23 @@ do_test memsubsys2-1.2 {
# Test 2: Verify that the highwater mark increases after a large
# allocation.
#
-sqlite3_memory_highwater 1
-set highwater [sqlite3_memory_highwater 0]
-do_test memsubsys2-2.1 {
- sqlite3_free [set x [sqlite3_malloc 100000]]
- expr {$x!="0"}
-} {1}
-do_test memsubsys2-2.2.1 {
- expr {[sqlite3_memory_highwater 0]>=[sqlite3_memory_used]+100000}
-} {1}
-do_test memsubsys2-2.2.2 {
- expr {[sqlite3_memory_highwater 0]>=$highwater+50000}
-} {1}
+# Do not run this if [sqlite3_memory_used] returns 0. This indicates
+# an SQLITE_DEFAULT_MEMSTATUS=0 build.
+#
+if {[sqlite3_memory_used]!=0} {
+ sqlite3_memory_highwater 1
+ set highwater [sqlite3_memory_highwater 0]
+ do_test memsubsys2-2.1 {
+ sqlite3_free [set x [sqlite3_malloc 100000]]
+ expr {$x!="0"}
+ } {1}
+ do_test memsubsys2-2.2.1 {
+ expr {[sqlite3_memory_highwater 0]>=[sqlite3_memory_used]+100000}
+ } {1}
+ do_test memsubsys2-2.2.2 {
+ expr {[sqlite3_memory_highwater 0]>=$highwater+50000}
+ } {1}
+}
# Test 3: Verify that turning of memstatus disables the statistics
# tracking.
diff --git a/test/mutex1.test b/test/mutex1.test
index aac04bf49..0fc8368f7 100644
--- a/test/mutex1.test
+++ b/test/mutex1.test
@@ -118,6 +118,7 @@ ifcapable threadsafe1&&shared_cache {
do_test mutex1.2.$mode.1 {
catch {db close}
sqlite3_shutdown
+ sqlite3_config_memstatus 1
sqlite3_config $mode
} SQLITE_OK
diff --git a/test/pager2.test b/test/pager2.test
index 0e2b33b83..1d78b30f5 100644
--- a/test/pager2.test
+++ b/test/pager2.test
@@ -165,4 +165,6 @@ do_test pager2-3.1 {
list [catch { db3 eval { INSERT INTO t1 VALUES(3, 4) } } msg] $msg
} {1 {no such table: t1}}
+db1 close
+
finish_test
diff --git a/test/pendingrace.test b/test/pendingrace.test
new file mode 100644
index 000000000..f0e1a18ff
--- /dev/null
+++ b/test/pendingrace.test
@@ -0,0 +1,126 @@
+# 2023 January 31
+#
+# The author disclaims copyright to this source code. In place of
+# a legal notice, here is a blessing:
+#
+# May you do good and not evil.
+# May you find forgiveness for yourself and forgive others.
+# May you share freely, never taking more than you give.
+#
+#***********************************************************************
+#
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+set testprefix pendingrace
+
+# This test file tests that a race condition surrounding hot-journal
+# rollback that once existed has been resolved. The problem was that
+# if, when attempting to upgrade from a SHARED to EXCLUSIVE lock in
+# order to roll back a hot journal, a connection failed to take the
+# lock, the file-descriptor was left holding a PENDING lock for
+# a very short amount of time. In a multi-threaded deployment, this
+# could allow a second connection to read the database without rolling
+# back the hot journal.
+#
+
+testvfs tvfs
+db close
+sqlite3 db test.db -vfs tvfs
+
+# Create a 20 page database using connection [db]. Connection [db] uses
+# Tcl VFS wrapper "tvfs", but it is configured to do straight pass-through
+# for now.
+#
+do_execsql_test 1.0 {
+ PRAGMA cache_size = 5;
+ CREATE TABLE t1(a, b);
+ CREATE INDEX i1 ON t1(a, b);
+ WITH s(i) AS (
+ SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<10
+ )
+ INSERT INTO t1 SELECT hex(randomblob(100)), hex(randomblob(100)) FROM s;
+} {}
+do_test 1.1a {
+ set nPg [db one { PRAGMA page_count }]
+ expr ($nPg==20 || $nPg==21)
+} 1
+
+# Simulate a crash in another process. This leaves the db with a hot-journal.
+# Without the journal the db is corrupt.
+#
+sqlite3 db2 test.db
+do_execsql_test -db db2 1.1 {
+ PRAGMA cache_size = 5;
+ BEGIN;
+ UPDATE t1 SET b=hex(randomblob(100));
+}
+db_save
+db2 close
+proc my_db_restore {} {
+ forcecopy sv_test.db-journal test.db-journal
+
+ set fd1 [open sv_test.db r]
+ fconfigure $fd1 -encoding binary -translation binary
+ set data [read $fd1]
+ close $fd1
+
+ set fd1 [open test.db w]
+ fconfigure $fd1 -encoding binary -translation binary
+ puts -nonewline $fd1 $data
+ close $fd1
+}
+my_db_restore
+do_test 1.2 {
+ file exists test.db-journal
+} {1}
+
+# Set up connection [db2] to use Tcl VFS wrapper [tvfs2]. Which is configured
+# so that the first call to xUnlock() fails. And then all VFS calls thereafter
+# fail as well.
+#
+testvfs tvfs2
+tvfs2 filter xUnlock
+tvfs2 script xUnlock
+set ::seen_unlock 0
+proc xUnlock {args} {
+ if {$::seen_unlock==0} {
+ set ::seen_unlock 1
+ tvfs2 ioerr 1 1
+ tvfs2 filter {xLock xUnlock}
+ }
+ return ""
+}
+sqlite3 db2 test.db -vfs tvfs2
+
+# Configure [tvfs] (used by [db]) so that within the first call to xAccess,
+# [db2] attempts to read the db. This causes [db2] to fail to upgrade to
+# EXCLUSIVE, leaving it with a PENDING lock. Which it holds on to,
+# as the xUnlock() and all subsequent VFS calls fail.
+#
+tvfs filter xAccess
+tvfs script xAccess
+set ::seen_access 0
+proc xAccess {args} {
+ if {$::seen_access==0} {
+ set ::seen_access 1
+ catch { db2 eval { SELECT count(*)+0 FROM t1 } }
+ breakpoint
+ }
+ return ""
+}
+
+# Run an integrity check using [db].
+do_catchsql_test 1.3 {
+ PRAGMA integrity_check
+} {1 {database is locked}}
+
+db close
+db2 close
+tvfs delete
+tvfs2 delete
+
+finish_test
+
+
+
diff --git a/test/permutations.test b/test/permutations.test
index 1b44ba52b..eb173f79b 100644
--- a/test/permutations.test
+++ b/test/permutations.test
@@ -99,6 +99,7 @@ foreach f [glob -nocomplain \
foreach f [glob -nocomplain $testdir/../ext/session/*.test] {
lappend alltests $f
}
+unset f
if {$::tcl_platform(platform)!="unix"} {
set alltests [test_set $alltests -exclude crash.test crash2.test]
@@ -115,7 +116,7 @@ set allquicktests [test_set $alltests -exclude {
corruptC.test crash.test crash2.test crash3.test crash4.test crash5.test
crash6.test crash7.test delete3.test e_fts3.test fts3rnd.test
fkey_malloc.test fuzz.test fuzz3.test fuzz_malloc.test in2.test loadext.test
- misc7.test mutex2.test notify2.test onefile.test pagerfault2.test
+ misc7.test mutex2.test onefile.test pagerfault2.test
savepoint4.test savepoint6.test select9.test
speed1.test speed1p.test speed2.test speed3.test speed4.test
speed4p.test sqllimits1.test tkt2686.test thread001.test thread002.test
@@ -784,6 +785,7 @@ test_suite "inmemory_journal" -description {
pager.test exclusive.test jrnlmode.test sync.test misc1.test
journal1.test conflict.test crash8.test tkt3457.test io.test
journal3.test 8_3_names.test shmlock.test
+ pendingrace.test
pager1.test async4.test corrupt.test filefmt.test pager2.test
corrupt5.test corruptA.test pageropt.test
@@ -915,6 +917,8 @@ ifcapable threadsafe {
autoinstall_test_functions
} -shutdown {
catch {db close}
+ catch {db2 close}
+ catch {db3 close}
sqlite3_shutdown
install_mutex_counters 0
sqlite3_initialize
diff --git a/test/pragma.test b/test/pragma.test
index 32e8fbef6..9ab332c3f 100644
--- a/test/pragma.test
+++ b/test/pragma.test
@@ -622,16 +622,20 @@ do_execsql_test pragma-3.40 {
SET rootpage=(SELECT rootpage FROM saved_schema WHERE name='t1bcd')
WHERE name='t2bcd';
PRAGMA Writable_schema=RESET;
- SELECT integrity_check AS x FROM pragma_integrity_check ORDER BY 1;
-} {
- {row 2 missing from index t1bcd}
- {row 2 missing from index t2bcd}
- {row 3 values differ from index t1bcd}
- {row 3 values differ from index t2bcd}
- {row 4 values differ from index t1bcd}
- {row 4 values differ from index t2bcd}
- {row 5 values differ from index t1bcd}
- {row 5 values differ from index t2bcd}
+}
+ifcapable vtab {
+ do_execsql_test pragma-3.41 {
+ SELECT integrity_check AS x FROM pragma_integrity_check ORDER BY 1;
+ } {
+ {row 2 missing from index t1bcd}
+ {row 2 missing from index t2bcd}
+ {row 3 values differ from index t1bcd}
+ {row 3 values differ from index t2bcd}
+ {row 4 values differ from index t1bcd}
+ {row 4 values differ from index t2bcd}
+ {row 5 values differ from index t1bcd}
+ {row 5 values differ from index t2bcd}
+ }
}
db eval {DROP TABLE t2}
diff --git a/test/quickcheck.test b/test/quickcheck.test
new file mode 100644
index 000000000..94016e845
--- /dev/null
+++ b/test/quickcheck.test
@@ -0,0 +1,34 @@
+# 2023 January 28
+#
+# The author disclaims copyright to this source code. In place of
+# a legal notice, here is a blessing:
+#
+# May you do good and not evil.
+# May you find forgiveness for yourself and forgive others.
+# May you share freely, never taking more than you give.
+#
+#***********************************************************************
+#
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+set testprefix quickcheck
+
+do_execsql_test 1.0 {
+ CREATE TABLE t1(
+ a INTEGER NOT NULL, b INTEGER NOT NULL, c AS (a+1),
+ PRIMARY KEY(b, a)
+ ) WITHOUT ROWID;
+
+ INSERT INTO t1 VALUES(1, 2);
+ INSERT INTO t1 VALUES(3, 4);
+}
+
+do_execsql_test 1.1 {
+ PRAGMA quick_check
+} {
+ ok
+}
+
+finish_test
+
diff --git a/test/releasetest_data.tcl b/test/releasetest_data.tcl
index 6efc44b92..2f4e71e8c 100644
--- a/test/releasetest_data.tcl
+++ b/test/releasetest_data.tcl
@@ -570,6 +570,174 @@ proc main_script {args} {
}
}
+proc main_trscript {args} {
+ set bMsvc 0
+ set nArg [llength $args]
+ if {$nArg==3} {
+ if {![is_prefix [lindex $args 0] -msvc 2]} usage
+ set bMsvc 1
+ } elseif {$nArg<2 || $nArg>3} {
+ usage
+ }
+ set config [lindex $args end-1]
+ set srcdir [lindex $args end]
+
+ set opts [list] ;# OPTS value
+ set cflags [expr {$bMsvc ? "-Zi" : "-g"}] ;# CFLAGS value
+ set makeOpts [list] ;# Extra args for [make]
+ set configOpts [list] ;# Extra args for [configure]
+
+ if {$::tcl_platform(platform)=="windows" || $bMsvc} {
+ lappend opts -DSQLITE_OS_WIN=1
+ } else {
+ lappend opts -DSQLITE_OS_UNIX=1
+ }
+
+ # Figure out if this is a synthetic ndebug or debug configuration.
+ #
+ set bRemoveDebug 0
+ if {[string match *-ndebug $config]} {
+ set bRemoveDebug 1
+ set config [string range $config 0 end-7]
+ }
+ if {[string match *-debug $config]} {
+ lappend opts -DSQLITE_DEBUG
+ lappend opts -DSQLITE_EXTRA_IFNULLROW
+ set config [string range $config 0 end-6]
+ }
+ regexp {^(.*)-[0-9]+} $config -> config
+
+ # Ensure that the named configuration exists.
+ #
+ if {![info exists ::Configs($config)]} {
+ puts stderr "No such config: $config"
+ exit 1
+ }
+
+ # Loop through the parameters of the nominated configuration, updating
+ # $opts, $cflags, $makeOpts and $configOpts along the way. Rules are as
+ # follows:
+ #
+ # 1. If the parameter begins with a "*", discard it.
+ #
+ # 2. If $bRemoveDebug is set and the parameter is -DSQLITE_DEBUG or
+ # -DSQLITE_DEBUG=1, discard it
+ #
+ # 3. If the parameter begins with "-D", add it to $opts.
+ #
+ # 4. If the parameter begins with "--" add it to $configOpts. Unless
+ # this command is preparing a script for MSVC - then add an
+ # equivalent to $makeOpts or $opts.
+ #
+ # 5. If the parameter begins with "-" add it to $cflags. If in MSVC
+ # mode and the parameter is an -O<integer> option, instead add
+ # an OPTIMIZATIONS=<integer> switch to $makeOpts.
+ #
+ # 6. If none of the above apply, add the parameter to $makeOpts
+ #
+ foreach param $::Configs($config) {
+ if {[string range $param 0 0]=="*"} continue
+
+ if {$bRemoveDebug} {
+ if {$param=="-DSQLITE_DEBUG" || $param=="-DSQLITE_DEBUG=1"
+ || $param=="-DSQLITE_MEMDEBUG" || $param=="-DSQLITE_MEMDEBUG=1"
+ || $param=="--enable-debug"
+ } {
+ continue
+ }
+ }
+
+ if {[string range $param 0 1]=="-D"} {
+ lappend opts $param
+ continue
+ }
+
+ if {[string range $param 0 1]=="--"} {
+ if {$bMsvc} {
+ switch -- $param {
+ --disable-amalgamation {
+ lappend makeOpts USE_AMALGAMATION=0
+ }
+ --disable-shared {
+ lappend makeOpts USE_CRT_DLL=0 DYNAMIC_SHELL=0
+ }
+ --enable-fts5 {
+ lappend opts -DSQLITE_ENABLE_FTS5
+ }
+ --enable-shared {
+ lappend makeOpts USE_CRT_DLL=1 DYNAMIC_SHELL=1
+ }
+ --enable-session {
+ lappend opts -DSQLITE_ENABLE_PREUPDATE_HOOK
+ lappend opts -DSQLITE_ENABLE_SESSION
+ }
+ default {
+ error "Cannot translate $param for MSVC"
+ }
+ }
+ } else {
+ lappend configOpts $param
+ }
+
+ continue
+ }
+
+ if {[string range $param 0 0]=="-"} {
+ if {$bMsvc && [regexp -- {^-O(\d+)$} $param -> level]} {
+ lappend makeOpts OPTIMIZATIONS=$level
+ } else {
+ lappend cflags $param
+ }
+ continue
+ }
+
+ lappend makeOpts $param
+ }
+
+ # Some configurations specify -DHAVE_USLEEP=0. For all others, add
+ # -DHAVE_USLEEP=1.
+ #
+ if {[lsearch $opts "-DHAVE_USLEEP=0"]<0} {
+ lappend opts -DHAVE_USLEEP=1
+ }
+
+ if {$bMsvc==0} {
+ puts {set -e}
+ puts {}
+ puts {if [ "$#" -ne 1 ] ; then}
+ puts { echo "Usage: $0 <target>" }
+ puts { exit -1 }
+ puts {fi }
+ puts "SRCDIR=\"$srcdir\""
+ puts {}
+ puts "TCL=\"[::tcl::pkgconfig get libdir,install]\""
+
+ puts {if [ ! -f Makefile ] ; then}
+ puts " \$SRCDIR/configure --with-tcl=\$TCL $configOpts"
+ puts {fi}
+ puts {}
+ puts {OPTS=" -DSQLITE_NO_SYNC=1"}
+ foreach o $opts {
+ puts "OPTS=\"\$OPTS $o\""
+ }
+ puts {}
+ puts "CFLAGS=\"$cflags\""
+ puts {}
+ puts "make \$1 \"CFLAGS=\$CFLAGS\" \"OPTS=\$OPTS\" $makeOpts"
+ } else {
+
+ set srcdir [file nativename [file normalize $srcdir]]
+ # set srcdir [string map [list "\\" "\\\\"] $srcdir]
+
+ puts {set TARGET=%1}
+ set makecmd "nmake /f $srcdir\\Makefile.msc TOP=\"$srcdir\" %TARGET% "
+ append makecmd "\"CFLAGS=$cflags\" \"OPTS=$opts\" $makeOpts"
+
+ puts "set TMP=%CD%"
+ puts $makecmd
+ }
+}
+
proc main_tests {args} {
set bNodebug 0
set nArg [llength $args]
@@ -648,6 +816,8 @@ if {[string match ${cmd}* configurations] && $n==0} {
main_configurations
} elseif {[string match ${cmd}* script]} {
main_script {*}[lrange $argv 1 end]
+} elseif {[string match ${cmd}* trscript]} {
+ main_trscript {*}[lrange $argv 1 end]
} elseif {[string match ${cmd}* platforms] && $n==0} {
main_platforms
} elseif {[string match ${cmd}* tests]} {
diff --git a/test/scanstatus.test b/test/scanstatus.test
index caad70c5b..fa00a356b 100644
--- a/test/scanstatus.test
+++ b/test/scanstatus.test
@@ -313,11 +313,13 @@ do_execsql_test 5.0 {
do_execsql_test 5.1.1 {
SELECT count(*) FROM t1 WHERE a IN (SELECT b FROM t1 AS ii)
} {2}
-do_scanstatus_test 5.1.2 {
- nLoop 1 nVisit 10 nEst 10.0 zName t1
- zExplain {SCAN ii}
- nLoop 1 nVisit 2 nEst 8.0 zName sqlite_autoindex_t1_1
- zExplain {SEARCH t1 USING COVERING INDEX sqlite_autoindex_t1_1 (a=?)}
+ifcapable stat4 {
+ do_scanstatus_test 5.1.2 {
+ nLoop 1 nVisit 10 nEst 10.0 zName t1
+ zExplain {SCAN ii}
+ nLoop 1 nVisit 2 nEst 8.0 zName sqlite_autoindex_t1_1
+ zExplain {SEARCH t1 USING COVERING INDEX sqlite_autoindex_t1_1 (a=?)}
+ }
}
do_execsql_test 5.2.1 {
@@ -339,21 +341,23 @@ do_scanstatus_test 5.3.3 {
{SEARCH t2 USING COVERING INDEX t2xy (ANY(x) AND y=?)}
}
-do_eqp_test 5.4.1 {
- SELECT count(*) FROM t1, t2 WHERE y = c;
-} {
- QUERY PLAN
- |--SCAN t1
- `--SEARCH t2 USING COVERING INDEX t2xy (ANY(x) AND y=?)
-}
-do_execsql_test 5.4.2 {
- SELECT count(*) FROM t1, t2 WHERE y = c;
-} {200}
-do_scanstatus_test 5.4.3 {
- nLoop 1 nVisit 10 nEst 10.0 zName t1
- zExplain {SCAN t1}
- nLoop 10 nVisit 200 nEst 56.0 zName t2xy
- zExplain {SEARCH t2 USING COVERING INDEX t2xy (ANY(x) AND y=?)}
+ifcapable stat4 {
+ do_eqp_test 5.4.1 {
+ SELECT count(*) FROM t1, t2 WHERE y = c;
+ } {
+ QUERY PLAN
+ |--SCAN t1
+ `--SEARCH t2 USING COVERING INDEX t2xy (ANY(x) AND y=?)
+ }
+ do_execsql_test 5.4.2 {
+ SELECT count(*) FROM t1, t2 WHERE y = c;
+ } {200}
+ do_scanstatus_test 5.4.3 {
+ nLoop 1 nVisit 10 nEst 10.0 zName t1
+ zExplain {SCAN t1}
+ nLoop 10 nVisit 200 nEst 56.0 zName t2xy
+ zExplain {SEARCH t2 USING COVERING INDEX t2xy (ANY(x) AND y=?)}
+ }
}
do_eqp_test 5.5.1 {
diff --git a/test/scanstatus2.test b/test/scanstatus2.test
index 301c19e28..497cbe67d 100644
--- a/test/scanstatus2.test
+++ b/test/scanstatus2.test
@@ -139,19 +139,21 @@ QUERY (nCycle=nnn)
}
#-------------------------------------------------------------------------
-reset_db
-do_execsql_test 2.0 {
- CREATE VIRTUAL TABLE ft USING fts5(a);
- INSERT INTO ft VALUES('abc');
- INSERT INTO ft VALUES('def');
- INSERT INTO ft VALUES('ghi');
-}
-
-do_graph_test 2.1 {
- SELECT * FROM ft('def')
-} {
+ifcapable fts5 {
+ reset_db
+ do_execsql_test 2.0 {
+ CREATE VIRTUAL TABLE ft USING fts5(a);
+ INSERT INTO ft VALUES('abc');
+ INSERT INTO ft VALUES('def');
+ INSERT INTO ft VALUES('ghi');
+ }
+
+ do_graph_test 2.1 {
+ SELECT * FROM ft('def')
+ } {
QUERY (nCycle=nnn)
--SCAN ft VIRTUAL TABLE INDEX 0:M1 (nCycle=nnn)
+ }
}
#-------------------------------------------------------------------------
diff --git a/test/server1.test b/test/server1.test
deleted file mode 100644
index c80921709..000000000
--- a/test/server1.test
+++ /dev/null
@@ -1,180 +0,0 @@
-# 2006 January 09
-#
-# The author disclaims copyright to this source code. In place of
-# a legal notice, here is a blessing:
-#
-# May you do good and not evil.
-# May you find forgiveness for yourself and forgive others.
-# May you share freely, never taking more than you give.
-#
-#***********************************************************************
-# This file implements regression tests for SQLite library. The
-# focus of this script is testing the server mode of SQLite.
-#
-# This file is derived from thread1.test
-#
-# $Id: server1.test,v 1.5 2007/08/29 18:20:17 drh Exp $
-
-
-set testdir [file dirname $argv0]
-source $testdir/tester.tcl
-
-# Skip this whole file if the server testing code is not enabled
-#
-if {[llength [info command client_step]]==0 || [sqlite3 -has-codec]} {
- finish_test
- return
-}
-
-# This test does not work on older PPC Macs due to problems in the
-# pthreads library. So skip it.
-#
-if {$tcl_platform(machine)=="Power Macintosh" &&
- $tcl_platform(byteOrder)=="bigEndian"} {
- finish_test
- return
-}
-
-# The sample server implementation does not work right when memory
-# management is enabled.
-#
-ifcapable (memorymanage||mutex_noop) {
- finish_test
- return
-}
-
-# Create some data to work with
-#
-do_test server1-1.1 {
- execsql {
- CREATE TABLE t1(a,b);
- INSERT INTO t1 VALUES(1,'abcdefgh');
- INSERT INTO t1 SELECT a+1, b||b FROM t1;
- INSERT INTO t1 SELECT a+2, b||b FROM t1;
- INSERT INTO t1 SELECT a+4, b||b FROM t1;
- SELECT count(*), max(length(b)) FROM t1;
- }
-} {8 64}
-
-# Interleave two threads on read access. Then make sure a third
-# thread can write the database. In other words:
-#
-# read-lock A
-# read-lock B
-# unlock A
-# unlock B
-# write-lock C
-#
-do_test server1-1.2 {
- client_create A test.db
- client_create B test.db
- client_create C test.db
- client_compile A {SELECT a FROM t1}
- client_step A
- client_result A
-} SQLITE_ROW
-do_test server1-1.3 {
- client_argc A
-} 1
-do_test server1-1.4 {
- client_argv A 0
-} 1
-do_test server1-1.5 {
- client_compile B {SELECT b FROM t1}
- client_step B
- client_result B
-} SQLITE_ROW
-do_test server1-1.6 {
- client_argc B
-} 1
-do_test server1-1.7 {
- client_argv B 0
-} abcdefgh
-do_test server1-1.8 {
- client_finalize A
- client_result A
-} SQLITE_OK
-do_test server1-1.9 {
- client_finalize B
- client_result B
-} SQLITE_OK
-do_test server1-1.10 {
- client_compile C {CREATE TABLE t2(x,y)}
- client_step C
- client_result C
-} SQLITE_DONE
-do_test server1-1.11 {
- client_finalize C
- client_result C
-} SQLITE_OK
-do_test server1-1.12 {
- catchsql {SELECT name FROM sqlite_master}
- execsql {SELECT name FROM sqlite_master}
-} {t1 t2}
-
-
-# Read from table t1. Do not finalize the statement. This
-# will leave the lock pending.
-#
-do_test server1-2.1 {
- client_halt *
- client_create A test.db
- client_compile A {SELECT a FROM t1}
- client_step A
- client_result A
-} SQLITE_ROW
-
-# Read from the same table from another thread. This is allows.
-#
-do_test server1-2.2 {
- client_create B test.db
- client_compile B {SELECT b FROM t1}
- client_step B
- client_result B
-} SQLITE_ROW
-
-# Write to a different table from another thread. This is allowed
-# because in server mode with a shared cache we have table-level locking.
-#
-do_test server1-2.3 {
- client_create C test.db
- client_compile C {INSERT INTO t2 VALUES(98,99)}
- client_step C
- client_result C
- client_finalize C
- client_result C
-} SQLITE_OK
-
-# But we cannot insert into table t1 because threads A and B have it locked.
-#
-do_test server1-2.4 {
- client_compile C {INSERT INTO t1 VALUES(98,99)}
- client_step C
- client_result C
- client_finalize C
- client_result C
-} SQLITE_LOCKED
-do_test server1-2.5 {
- client_finalize B
- client_wait B
- client_compile C {INSERT INTO t1 VALUES(98,99)}
- client_step C
- client_result C
- client_finalize C
- client_result C
-} SQLITE_LOCKED
-
-# Insert into t1 is successful after finishing the other two threads.
-do_test server1-2.6 {
- client_finalize A
- client_wait A
- client_compile C {INSERT INTO t1 VALUES(98,99)}
- client_step C
- client_result C
- client_finalize C
- client_result C
-} SQLITE_OK
-
-client_halt *
-sqlite3_enable_shared_cache 0
-finish_test
diff --git a/test/shrink.test b/test/shrink.test
index bc4a707bf..cee6919e8 100644
--- a/test/shrink.test
+++ b/test/shrink.test
@@ -17,6 +17,13 @@ set testdir [file dirname $argv0]
source $testdir/tester.tcl
test_set_config_pagecache 0 0
+if {[sqlite3_memory_used]==0} {
+ # SQLITE_DEFAULT_MEMSTATUS=0 build.
+ finish_test
+ return
+}
+
+
unset -nocomplain baseline
do_test shrink-1.1 {
db eval {
diff --git a/test/sort4.test b/test/sort4.test
index 13d9a5999..84125885a 100644
--- a/test/sort4.test
+++ b/test/sort4.test
@@ -8,6 +8,8 @@
# May you share freely, never taking more than you give.
#
#***********************************************************************
+# TESTRUNNER: superslow
+#
# This file implements regression tests for SQLite library.
#
# The tests in this file are brute force tests of the multi-threaded
diff --git a/test/speed1.test b/test/speed1.test
index 86d13ba4a..0dec3ba83 100644
--- a/test/speed1.test
+++ b/test/speed1.test
@@ -14,12 +14,14 @@
# $Id: speed1.test,v 1.11 2009/04/09 01:23:49 drh Exp $
#
+catch {db close}
sqlite3_shutdown
#sqlite3_config_scratch 29000 1
set old_lookaside [sqlite3_config_lookaside 1000 300]
#sqlite3_config_pagecache 1024 10000
set testdir [file dirname $argv0]
source $testdir/tester.tcl
+reset_db
speed_trial_init speed1
# Set a uniform random seed
diff --git a/test/speed1p.test b/test/speed1p.test
index 6bf7b10e1..fc05067e3 100644
--- a/test/speed1p.test
+++ b/test/speed1p.test
@@ -16,12 +16,14 @@
# $Id: speed1p.test,v 1.7 2009/04/09 01:23:49 drh Exp $
#
+catch { db close }
sqlite3_shutdown
#sqlite3_config_scratch 29000 1
set old_lookaside [sqlite3_config_lookaside 2048 300]
#sqlite3_config_pagecache 1024 11000
set testdir [file dirname $argv0]
source $testdir/tester.tcl
+reset_db
speed_trial_init speed1
sqlite3_memdebug_vfs_oom_test 0
diff --git a/test/sqllimits1.test b/test/sqllimits1.test
index 1c3f66b7f..f16208f23 100644
--- a/test/sqllimits1.test
+++ b/test/sqllimits1.test
@@ -16,6 +16,7 @@
set testdir [file dirname $argv0]
source $testdir/tester.tcl
+set testprefix sqllimits1
# Verify that the default per-connection limits are the same as
# the compile-time hard limits.
@@ -347,7 +348,7 @@ do_test sqllimits1-5.14.6 {
} {SQLITE_TOOBIG}
ifcapable utf16 {
do_test sqllimits1-5.14.7 {
- catch {sqlite3_bind_text16 $::STMT 1 $::str1 $np1} res
+ catch {sqlite3_bind_text16 $::STMT 1 $::str1 [expr $np1+1]} res
set res
} {SQLITE_TOOBIG}
}
@@ -923,4 +924,55 @@ do_catchsql_test sqllimits1-18.2 {
UNION VALUES(11);
} {1 {too many terms in compound SELECT}}
+#-------------------------------------------------------------------------
+#
+reset_db
+ifcapable utf16 {
+ do_execsql_test 19.0 {
+ PRAGMA encoding = 'utf16';
+ }
+ set bigstr [string repeat abcdefghij 5000]
+ set bigstr16 [encoding convertto unicode $bigstr]
+
+ do_test 19.1 {
+ string length $bigstr16
+ } {100000}
+
+ do_test 19.2 {
+ set ::stmt [sqlite3_prepare db "SELECT length( ? )" -1 TAIL]
+ sqlite3_bind_text16 $::stmt 1 $bigstr16 100000
+ sqlite3_step $::stmt
+ set val [sqlite3_column_int $::stmt 0]
+ sqlite3_finalize $::stmt
+ set val
+ } {50000}
+
+ sqlite3_limit db SQLITE_LIMIT_LENGTH 100000
+
+ do_test 19.3 {
+ set ::stmt [sqlite3_prepare db "SELECT length( ? )" -1 TAIL]
+ sqlite3_bind_text16 $::stmt 1 $bigstr16 100000
+ sqlite3_step $::stmt
+ set val [sqlite3_column_int $::stmt 0]
+ sqlite3_finalize $::stmt
+ set val
+ } {50000}
+
+ sqlite3_limit db SQLITE_LIMIT_LENGTH 99999
+
+ do_test 19.4 {
+ set ::stmt [sqlite3_prepare db "SELECT length( ? )" -1 TAIL]
+ list [catch { sqlite3_bind_text16 $::stmt 1 $bigstr16 100000 } msg] $msg
+ } {1 SQLITE_TOOBIG}
+ sqlite3_finalize $::stmt
+
+ sqlite3_limit db SQLITE_LIMIT_LENGTH 100000
+
+ do_test 19.5 {
+ set ::stmt [sqlite3_prepare db "SELECT length( ? )" -1 TAIL]
+ list [catch { sqlite3_bind_text16 $::stmt 1 $bigstr16 100002 } msg] $msg
+ } {1 SQLITE_TOOBIG}
+ sqlite3_finalize $::stmt
+}
+
finish_test
diff --git a/test/tester.tcl b/test/tester.tcl
index 022dad900..4658590cf 100644
--- a/test/tester.tcl
+++ b/test/tester.tcl
@@ -552,6 +552,7 @@ if {[info exists cmdlinearg]==0} {
}
}
}
+ unset -nocomplain a
set testdir [file normalize $testdir]
set cmdlinearg(TESTFIXTURE_HOME) [pwd]
set cmdlinearg(INFO_SCRIPT) [file normalize [info script]]
@@ -1318,9 +1319,11 @@ proc finalize_testing {} {
if {$::cmdlinearg(binarylog)} {
vfslog finalize binarylog
}
- if {$sqlite_open_file_count} {
- output2 "$sqlite_open_file_count files were left open"
- incr nErr
+ if {[info exists ::run_thread_tests_called]==0} {
+ if {$sqlite_open_file_count} {
+ output2 "$sqlite_open_file_count files were left open"
+ incr nErr
+ }
}
if {[lindex [sqlite3_status SQLITE_STATUS_MALLOC_COUNT 0] 1]>0 ||
[sqlite3_memory_used]>0} {
@@ -2502,8 +2505,10 @@ proc test_restore_config_pagecache {} {
catch {db3 close}
sqlite3_shutdown
- eval sqlite3_config_pagecache $::old_pagecache_config
- unset ::old_pagecache_config
+ if {[info exists ::old_pagecache_config]} {
+ eval sqlite3_config_pagecache $::old_pagecache_config
+ unset ::old_pagecache_config
+ }
sqlite3_initialize
autoinstall_test_functions
sqlite3 db test.db
diff --git a/test/testrunner.tcl b/test/testrunner.tcl
index 48afff47e..9d06ba1c1 100644
--- a/test/testrunner.tcl
+++ b/test/testrunner.tcl
@@ -1,88 +1,68 @@
+set dir [pwd]
+set testdir [file dirname $argv0]
+set saved $argv
+set argv [list]
+source [file join $testdir testrunner_data.tcl]
+source [file join $testdir permutations.test]
+set argv $saved
+cd $dir
+
#-------------------------------------------------------------------------
# Usage:
#
proc usage {} {
- set a0 testrunner.tcl
-
- set ::argv [list]
- uplevel [list source $::testdir/permutations.test]
-
- puts stderr "Usage: $a0 ?SWITCHES? ?PERMUTATION? ?PATTERNS?"
- puts stderr ""
- puts stderr "where SWITCHES are:"
- puts stderr " --jobs NUMBER-OF-JOBS"
- puts stderr ""
- puts stderr "available PERMUTATION values are:"
- set ii 0
- foreach name [lsort [array names ::testspec]] {
- if {($ii % 3)==0} { puts -nonewline stderr " " }
- puts -nonewline stderr [format "% -22s" $name]
- if {($ii % 3)==2} { puts stderr "" }
- incr ii
- }
- puts stderr ""
- puts stderr ""
- puts stderr "Examples:"
- puts stderr " 1) Run the veryquick tests:"
- puts stderr " $a0"
- puts stderr " 2) Run all test scripts in the source tree:"
- puts stderr " $a0 full"
- puts stderr " 2) Run the 'memsubsys1' permutation:"
- puts stderr " $a0 memsubsys1"
- puts stderr " 3) Run all permutations usually run by \[make fulltest\]"
- puts stderr " $a0 release"
- puts stderr " 4) Run all scripts that match the pattern 'select%':"
- puts stderr " $a0 select%"
- puts stderr " $a0 all select%"
- puts stderr " $a0 full select%"
- puts stderr " 5) Run all scripts that are part of the veryquick permutation and match the pattern 'select%':"
- puts stderr " $a0 veryquick select%"
- puts stderr " 6) Run the 'memsubsys1' permutation, but just those scripts that match 'window%':"
- puts stderr " $a0 memsubsys1 window%"
- puts stderr " 7) Run all the permutations, but only the scripts that match either 'fts5%' or 'rtree%':"
- puts stderr " $a0 release fts5% rtree%"
+ set a0 [file tail $::argv0]
+
+ puts stderr [string trim [subst -nocommands {
+Usage:
+ $a0 ?SWITCHES? ?PERMUTATION? ?PATTERNS?
+ $a0 PERMUTATION FILE
+ $a0 njob ?NJOB?
+ $a0 status
+
+ where SWITCHES are:
+ --jobs NUMBER-OF-JOBS
+ --fuzztest
+
+Interesting values for PERMUTATION are:
+
+ veryquick - a fast subset of the tcl test scripts. This is the default.
+ full - all tcl test scripts.
+ all - all tcl test scripts, plus a subset of test scripts rerun
+ with various permutations.
+ release - full release test with various builds.
+
+If no PATTERN arguments are present, all tests specified by the PERMUTATION
+are run. Otherwise, each pattern is interpreted as a glob pattern. Only
+those tcl tests for which the final component of the filename matches at
+least one specified pattern are run.
+
+If no PATTERN arguments are present, then various fuzztest, threadtest
+and other tests are run as part of the "release" permutation. These are
+omitted if any PATTERN arguments are specified on the command line.
+
+If a PERMUTATION is specified and is followed by the path to a Tcl script
+instead of a list of patterns, then that single Tcl test script is run
+with the specified permutation.
+
+The --fuzztest option is ignored if the PERMUTATION is "release". Otherwise,
+if it is present, then "make -C <dir> fuzztest" is run as part of the tests,
+where <dir> is the directory containing the testfixture binary used to
+run the script.
+
+The "status" and "njob" commands are designed to be run from the same
+directory as a running testrunner.tcl script that is running tests. The
+"status" command prints a report describing the current state and progress
+of the tests. The "njob" command may be used to query or modify the number
+of sub-processes the test script uses to run tests.
+ }]]
exit 1
}
#-------------------------------------------------------------------------
#-------------------------------------------------------------------------
-# The database schema used by the testrunner.db database.
-#
-set R(schema) {
- DROP TABLE IF EXISTS script;
- DROP TABLE IF EXISTS msg;
- DROP TABLE IF EXISTS malloc;
-
- CREATE TABLE script(
- config TEXT,
- filename TEXT, -- full path to test script
- slow BOOLEAN, -- true if script is "slow"
- state TEXT CHECK( state IN ('ready', 'running', 'done') ),
- testfixtureid, -- Id of process that ran script
- time INTEGER, -- Time in ms
- nerr INTEGER, -- if 'done', the number of errors
- ntest INTEGER, -- if 'done', the number of tests
- output TEXT, -- full output of test script
- PRIMARY KEY(config, filename)
- );
-
- CREATE TABLE malloc(
- id INTEGER PRIMARY KEY,
- nmalloc INTEGER,
- nbyte INTEGER,
- leaker TEXT
- );
-
- CREATE TABLE msg(
- id INTEGER PRIMARY KEY,
- msg TEXT
- );
-}
-#-------------------------------------------------------------------------
-
-#-------------------------------------------------------------------------
# Try to estimate a the number of processes to use.
#
# Command [guess_number_of_cores] attempts to glean the number of logical
@@ -113,593 +93,776 @@ proc default_njob {} {
}
#-------------------------------------------------------------------------
+#-------------------------------------------------------------------------
+# Setup various default values in the global TRG() array.
+#
+set TRG(dbname) [file normalize testrunner.db]
+set TRG(logname) [file normalize testrunner.log]
+set TRG(build.logname) [file normalize testrunner_build.log]
+set TRG(info_script) [file normalize [info script]]
+set TRG(timeout) 10000 ;# Default busy-timeout for testrunner.db
+set TRG(nJob) [default_njob] ;# Default number of helper processes
+set TRG(patternlist) [list]
+set TRG(cmdline) $argv
+set TRG(reporttime) 2000
+set TRG(fuzztest) 0 ;# is the fuzztest option present.
+
+switch -nocase -glob -- $tcl_platform(os) {
+ *darwin* {
+ set TRG(platform) osx
+ set TRG(make) make.sh
+ set TRG(makecmd) "bash make.sh"
+ }
+ *linux* {
+ set TRG(platform) linux
+ set TRG(make) make.sh
+ set TRG(makecmd) "bash make.sh"
+ }
+ *win* {
+ set TRG(platform) win
+ set TRG(make) make.bat
+ set TRG(makecmd) make.bat
+ }
+ default {
+ error "cannot determine platform!"
+ }
+}
+#-------------------------------------------------------------------------
-set R(dbname) [file normalize testrunner.db]
-set R(logname) [file normalize testrunner.log]
-set R(info_script) [file normalize [info script]]
-set R(timeout) 10000 ;# Default busy-timeout for testrunner.db
-set R(nJob) [default_njob] ;# Default number of helper processes
-set R(leaker) "" ;# Name of first script to leak memory
+#-------------------------------------------------------------------------
+# The database schema used by the testrunner.db database.
+#
+set TRG(schema) {
+ DROP TABLE IF EXISTS script;
+ DROP TABLE IF EXISTS config;
-set R(patternlist) [list]
+ CREATE TABLE script(
+ build TEXT DEFAULT '',
+ config TEXT,
+ filename TEXT, -- full path to test script
+ slow BOOLEAN, -- true if script is "slow"
+ state TEXT CHECK( state IN ('', 'ready', 'running', 'done', 'failed') ),
+ time INTEGER, -- Time in ms
+ output TEXT, -- full output of test script
+ priority AS ((config='make') + ((config='build')*2) + (slow*4)),
+ jobtype AS (
+ CASE WHEN config IN ('build', 'make') THEN config ELSE 'script' END
+ ),
+ PRIMARY KEY(build, config, filename)
+ );
-set testdir [file dirname $argv0]
+ CREATE TABLE config(
+ name TEXT COLLATE nocase PRIMARY KEY,
+ value
+ ) WITHOUT ROWID;
-# Parse the command line options. There are two ways to invoke this
-# script - to create a helper or coordinator process. If there are
-# no helper processes, the coordinator runs test scripts.
-#
-# To create a helper process:
-#
-# testrunner.tcl helper ID
+ CREATE INDEX i1 ON script(state, jobtype);
+ CREATE INDEX i2 ON script(state, priority);
+}
+#-------------------------------------------------------------------------
+
+#--------------------------------------------------------------------------
+# Check if this script is being invoked to run a single file. If so,
+# run it.
#
-# where ID is an integer greater than 0. The process will create and
-# run tests in the "testdir$ID" directory. Helper processes are only
-# created by coordinators - there is no need for a user to create
-# helper processes manually.
+if {[llength $argv]==2
+ && ([lindex $argv 0]=="" || [info exists ::testspec([lindex $argv 0])])
+ && [file exists [lindex $argv 1]]
+} {
+ set permutation [lindex $argv 0]
+ set script [file normalize [lindex $argv 1]]
+ set ::argv [list]
+
+ if {$permutation=="full"} {
+
+ set testdir [file dirname $argv0]
+ source $::testdir/tester.tcl
+ unset -nocomplain ::G(isquick)
+ reset_db
+
+ } elseif {$permutation!="default" && $permutation!=""} {
+
+ if {[info exists ::testspec($permutation)]==0} {
+ error "no such permutation: $permutation"
+ }
+
+ array set O $::testspec($permutation)
+ set ::G(perm:name) $permutation
+ set ::G(perm:prefix) $O(-prefix)
+ set ::G(isquick) 1
+ set ::G(perm:dbconfig) $O(-dbconfig)
+ set ::G(perm:presql) $O(-presql)
+
+ rename finish_test helper_finish_test
+ proc finish_test {} "
+ uplevel {
+ $O(-shutdown)
+ }
+ helper_finish_test
+ "
+
+ eval $O(-initialize)
+ }
+
+ reset_db
+ source $script
+ exit
+}
+#--------------------------------------------------------------------------
+
+#--------------------------------------------------------------------------
+# Check if this is the "njob" command:
#
-# If the first argument is anything other than "helper", then a coordinator
-# process is started. See the implementation of the [usage] proc above for
-# details.
+if {([llength $argv]==2 || [llength $argv]==1)
+ && [string compare -nocase njob [lindex $argv 0]]==0
+} {
+ sqlite3 mydb $TRG(dbname)
+ if {[llength $argv]==2} {
+ set param [lindex $argv 1]
+ if {[string is integer $param]==0 || $param<1 || $param>128} {
+ puts stderr "parameter must be an integer between 1 and 128"
+ exit 1
+ }
+
+ mydb eval { REPLACE INTO config VALUES('njob', $param); }
+ }
+ set res [mydb one { SELECT value FROM config WHERE name='njob' }]
+ mydb close
+ puts "$res"
+ exit
+}
+#--------------------------------------------------------------------------
+
+#--------------------------------------------------------------------------
+# Check if this is the "status" command:
#
-switch -- [lindex $argv 0] {
- helper {
- set R(helper) 1
- set R(helper_id) [lindex $argv 1]
- set argv [list --testdir=testdir$R(helper_id)]
+if {[llength $argv]==1
+ && [string compare -nocase status [lindex $argv 0]]==0
+} {
+
+ proc display_job {build config filename {tm ""}} {
+ if {$config=="build"} {
+ set fname "build: $filename"
+ set config ""
+ } elseif {$config=="make"} {
+ set fname "make: $filename"
+ set config ""
+ } else {
+ set fname [file normalize $filename]
+ if {[string first $::srcdir $fname]==0} {
+ set fname [string range $fname [string length $::srcdir]+1 end]
+ }
+ }
+ set dfname [format %-33s $fname]
+
+ set dbuild ""
+ set dconfig ""
+ set dparams ""
+ set dtm ""
+ if {$build!=""} { set dbuild $build }
+ if {$config!="" && $config!="full"} { set dconfig $config }
+ if {$dbuild!="" || $dconfig!=""} {
+ append dparams "("
+ if {$dbuild!=""} {append dparams "build=$dbuild"}
+ if {$dbuild!="" && $dconfig!=""} {append dparams " "}
+ if {$dconfig!=""} {append dparams "config=$dconfig"}
+ append dparams ")"
+ set dparams [format %-33s $dparams]
+ }
+ if {$tm!=""} {
+ set dtm "\[${tm}ms\]"
+ }
+ puts " $dfname $dparams $dtm"
}
- default {
- set R(helper) 0
- set R(helper_id) 0
+ sqlite3 mydb $TRG(dbname)
+ mydb timeout 1000
+ mydb eval BEGIN
+
+ set cmdline [mydb one { SELECT value FROM config WHERE name='cmdline' }]
+ set nJob [mydb one { SELECT value FROM config WHERE name='njob' }]
+ set tm [expr [clock_milliseconds] - [mydb one {
+ SELECT value FROM config WHERE name='start'
+ }]]
+ set total 0
+ foreach s {"" ready running done failed} { set S($s) 0 }
+ mydb eval {
+ SELECT state, count(*) AS cnt FROM script GROUP BY 1
+ } {
+ incr S($state) $cnt
+ incr total $cnt
+ }
+ set fin [expr $S(done)+$S(failed)]
+ if {$cmdline!=""} {set cmdline " $cmdline"}
+
+ set f ""
+ if {$S(failed)>0} {
+ set f "$S(failed) FAILED, "
+ }
+ puts "Command line: \[testrunner.tcl$cmdline\]"
+ puts "Jobs: $nJob"
+ puts "Summary: ${tm}ms, ($fin/$total) finished, ${f}$S(running) running"
+
+ set srcdir [file dirname [file dirname $TRG(info_script)]]
+ if {$S(running)>0} {
+ puts "Running: "
+ set now [clock_milliseconds]
+ mydb eval {
+ SELECT build, config, filename, time FROM script WHERE state='running'
+ ORDER BY time
+ } {
+ display_job $build $config $filename [expr $now-$time]
+ }
}
+ if {$S(failed)>0} {
+ puts "Failures: "
+ mydb eval {
+ SELECT build, config, filename FROM script WHERE state='failed'
+ ORDER BY 3
+ } {
+ display_job $build $config $filename
+ }
+ }
+
+ mydb close
+ exit
}
-if {$R(helper)==0} {
- for {set ii 0} {$ii < [llength $argv]} {incr ii} {
- set a [lindex $argv $ii]
- set n [string length $a]
-
- if {[string range $a 0 0]=="-"} {
- if {($n>2 && [string match "$a*" --jobs]) || $a=="-j"} {
- incr ii
- set R(nJob) [lindex $argv $ii]
- } else {
- usage
- }
+
+#-------------------------------------------------------------------------
+# Parse the command line.
+#
+for {set ii 0} {$ii < [llength $argv]} {incr ii} {
+ set isLast [expr $ii==([llength $argv]-1)]
+ set a [lindex $argv $ii]
+ set n [string length $a]
+
+ if {[string range $a 0 0]=="-"} {
+ if {($n>2 && [string match "$a*" --jobs]) || $a=="-j"} {
+ incr ii
+ set TRG(nJob) [lindex $argv $ii]
+ if {$isLast} { usage }
+ } elseif {($n>2 && [string match "$a*" --fuzztest]) || $a=="-f"} {
+ set TRG(fuzztest) 1
} else {
- lappend R(patternlist) [string map {% *} $a]
+ usage
}
+ } else {
+ lappend TRG(patternlist) [string map {% *} $a]
}
+}
+set argv [list]
+
+
- set argv [list]
+# This script runs individual tests - tcl scripts or [make xyz] commands -
+# in directories named "testdir$N", where $N is an integer. This variable
+# contains a list of integers indicating the directories in use.
+#
+# This variable is accessed only via the following commands:
+#
+# dirs_nHelper
+# Return the number of entries currently in the list.
+#
+# dirs_freeDir IDIR
+# Remove value IDIR from the list. It is an error if it is not present.
+#
+# dirs_allocDir
+# Select a value that is not already in the list. Add it to the list
+# and return it.
+#
+set TRG(dirs_in_use) [list]
+
+proc dirs_nHelper {} {
+ global TRG
+ llength $TRG(dirs_in_use)
+}
+proc dirs_freeDir {iDir} {
+ global TRG
+ set out [list]
+ foreach d $TRG(dirs_in_use) {
+ if {$iDir!=$d} { lappend out $d }
+ }
+ if {[llength $out]!=[llength $TRG(dirs_in_use)]-1} {
+ error "dirs_freeDir could not find $iDir"
+ }
+ set TRG(dirs_in_use) $out
+}
+proc dirs_allocDir {} {
+ global TRG
+ array set inuse [list]
+ foreach d $TRG(dirs_in_use) {
+ set inuse($d) 1
+ }
+ for {set iRet 0} {[info exists inuse($iRet)]} {incr iRet} { }
+ lappend TRG(dirs_in_use) $iRet
+ return $iRet
+}
+
+set testdir [file dirname $argv0]
+
+# Check that directory $dir exists. If it does not, create it. If
+# it does, delete its contents.
+#
+proc create_or_clear_dir {dir} {
+ set dir [file normalize $dir]
+ catch { file mkdir $dir }
+ foreach f [glob -nocomplain [file join $dir *]] {
+ catch { file delete -force $f }
+ }
+}
+
+proc copy_dir {from to} {
+ foreach f [glob -nocomplain [file join $from *]] {
+ catch { file copy -force $f $to }
+ }
+}
+
+proc build_to_dirname {bname} {
+ set fold [string tolower [string map {- _} $bname]]
+ return "testrunner_build_$fold"
}
-source $testdir/permutations.test
#-------------------------------------------------------------------------
# Return a list of tests to run. Each element of the list is itself a
# list of two elements - the name of a permuations.test configuration
# followed by the full path to a test script. i.e.:
#
-# {CONFIG FILENAME} {CONFIG FILENAME} ...
+# {BUILD CONFIG FILENAME} {BUILD CONFIG FILENAME} ...
#
proc testset_patternlist {patternlist} {
+ global TRG
+
+ set testset [list] ;# return value
set first [lindex $patternlist 0]
- if {$first=="all"} { set first "full" }
if {$first=="release"} {
+ set platform $::TRG(platform)
+
+ set patternlist [lrange $patternlist 1 end]
+ foreach b [trd_builds $platform] {
+ foreach c [trd_configs $platform $b] {
+ testset_append testset $b $c $patternlist
+ }
- # The following mirrors the set of test suites invoked by "all.test".
- #
- set clist {
- full
- no_optimization memsubsys1 memsubsys2 singlethread
- multithread onefile utf16 exclusive persistent_journal
- persistent_journal_error no_journal no_journal_error
- autovacuum_ioerr no_mutex_try fullmutex journaltest
- inmemory_journal pcache0 pcache10 pcache50 pcache90
- pcache100 prepare mmap
+ if {[llength $patternlist]==0 || $b=="User-Auth"} {
+ set target testfixture
+ } else {
+ set target coretestprogs
+ }
+ lappend testset [list $b build $target]
}
- ifcapable rbu { lappend clist rbu }
- if {$::tcl_platform(platform)=="unix"} {
- ifcapable !default_autovacuum {
- lappend clist autovacuum_crash
+
+ if {[llength $patternlist]==0} {
+ foreach b [trd_builds $platform] {
+ foreach e [trd_extras $platform $b] {
+ lappend testset [list $b make $e]
+ }
}
}
+
+ set TRG(fuzztest) 0 ;# ignore --fuzztest option in this case
+
+ } elseif {$first=="all"} {
+
+ set clist [trd_all_configs]
set patternlist [lrange $patternlist 1 end]
+ foreach c $clist {
+ testset_append testset "" $c $patternlist
+ }
} elseif {[info exists ::testspec($first)]} {
set clist $first
- set patternlist [lrange $patternlist 1 end]
+ testset_append testset "" $first [lrange $patternlist 1 end]
} elseif { [llength $patternlist]==0 } {
- set clist veryquick
+ testset_append testset "" veryquick $patternlist
} else {
- set clist full
+ testset_append testset "" full $patternlist
+ }
+ if {$TRG(fuzztest)} {
+ if {$TRG(platform)=="win"} { error "todo" }
+ lappend testset [list "" make fuzztest]
}
- set testset [list]
+ set testset
+}
- foreach config $clist {
- catch { array unset O }
- array set O $::testspec($config)
- foreach f $O(-files) {
- if {[file pathtype $f]!="absolute"} {
- set f [file join $::testdir $f]
- }
- lappend testset [list $config [file normalize $f]]
- }
- }
+proc testset_append {listvar build config patternlist} {
+ upvar $listvar lvar
+
+ catch { array unset O }
+ array set O $::testspec($config)
- if {[llength $patternlist]>0} {
- foreach t $testset {
- set tail [file tail [lindex $t 1]]
+ foreach f $O(-files) {
+ if {[llength $patternlist]>0} {
+ set bMatch 0
foreach p $patternlist {
- if {[string match $p $tail]} {
- lappend ret $t
- break;
+ if {[string match $p [file tail $f]]} {
+ set bMatch 1
+ break
}
}
+ if {$bMatch==0} continue
}
- } else {
- set ret $testset
- }
- set ret
+ if {[file pathtype $f]!="absolute"} {
+ set f [file join $::testdir $f]
+ }
+ lappend lvar [list $build $config $f]
+ }
}
+
#--------------------------------------------------------------------------
proc r_write_db {tcl} {
- global R
-
- sqlite3_test_control_pending_byte 0x010000
- sqlite3 db $R(dbname)
- db timeout $R(timeout)
- db eval { BEGIN EXCLUSIVE }
-
+ trdb eval { BEGIN EXCLUSIVE }
uplevel $tcl
-
- db eval { COMMIT }
- db close
-}
-
-proc make_new_testset {} {
- global R
-
- set tests [testset_patternlist $R(patternlist)]
- r_write_db {
- db eval $R(schema)
- foreach t $tests {
- foreach {c s} $t {}
- set slow 0
-
- set fd [open $s]
- for {set ii 0} {$ii<100 && ![eof $fd]} {incr ii} {
- set line [gets $fd]
- if {[string match -nocase *testrunner:* $line]} {
- regexp -nocase {.*testrunner:(.*)} $line -> properties
- foreach p $properties {
- if {$p=="slow"} { set slow 1 }
- }
- }
- }
- close $fd
-
- db eval {
- INSERT INTO script(config, filename, slow, state)
- VALUES ($c, $s, $slow, 'ready')
- }
- }
- }
+ trdb eval { COMMIT }
}
-# Find the next job in the database and mark it as 'running'. Then return
-# a list consisting of the
+# Obtain a new job to be run by worker $iJob (an integer). A job is
+# returned as a three element list:
#
-# CONFIG FILENAME
+# {$build $config $file}
#
-# pair for the test.
-#
-proc get_next_test {} {
- global R
- set myid $R(helper_id)
+proc r_get_next_job {iJob} {
+ global T
+
+ if {($iJob%2)} {
+ set orderby "ORDER BY priority ASC"
+ } else {
+ set orderby "ORDER BY priority DESC"
+ }
r_write_db {
set f ""
set c ""
- db eval {
- SELECT config, filename FROM script WHERE state='ready'
- ORDER BY
- (slow * (($myid+1) % 2)) DESC,
- config!='full',
- config,
- filename
- LIMIT 1
- } {
+ trdb eval "
+ SELECT build, config, filename
+ FROM script
+ WHERE state='ready'
+ $orderby LIMIT 1
+ " {
+ set b $build
set c $config
set f $filename
}
if {$f!=""} {
- db eval {
- UPDATE script SET state='running', testfixtureid=$myid
- WHERE (config, filename) = ($c, $f)
+ set tm [clock_milliseconds]
+ set T($iJob) $tm
+ trdb eval {
+ UPDATE script SET state='running', time=$tm
+ WHERE (build, config, filename) = ($b, $c, $f)
}
}
}
if {$f==""} { return "" }
- list $c $f
-}
-
-proc r_testname {config filename} {
- set name [file tail $filename]
- if {$config!="" && $config!="full" && $config!="veryquick"} {
- set name "$config-$name"
- }
- return $name
+ list $b $c $f
}
-proc r_set_test_result {config filename ms nerr ntest output} {
- global R
+#rename r_get_next_job r_get_next_job_r
+#proc r_get_next_job {iJob} {
+# puts [time { set res [r_get_next_job_r $iJob] }]
+# set res
+#}
- set f [r_testname $config $filename]
- if {$nerr==0} {
- set msg "$f... Ok"
- } else {
- set msg "$f... FAILED - $nerr errors of $ntest tests"
- }
- append msg " (${ms}ms)"
- if {$R(helper)} {
- append msg " (helper $R(helper_id))"
- }
-
- sqlite3_shutdown
- set nMalloc [lindex [sqlite3_status SQLITE_STATUS_MALLOC_COUNT 0] 1]
- set nByte [sqlite3_memory_used]
- if {($nByte>0 || $nMalloc>0) && $R(leaker)==""} {
- set R(leaker) $f
- }
+proc make_new_testset {} {
+ global TRG
+ set tests [testset_patternlist $TRG(patternlist)]
r_write_db {
- db eval {
- UPDATE script
- SET state='done', output=$output, nerr=$nerr, ntest=$ntest, time=$ms
- WHERE (config, filename)=($config, $filename);
- INSERT INTO msg(msg) VALUES ($msg);
- }
- }
-}
+ trdb eval $TRG(schema)
+ set nJob $TRG(nJob)
+ set cmdline $TRG(cmdline)
+ set tm [clock_milliseconds]
+ trdb eval { REPLACE INTO config VALUES('njob', $nJob ); }
+ trdb eval { REPLACE INTO config VALUES('cmdline', $cmdline ); }
+ trdb eval { REPLACE INTO config VALUES('start', $tm ); }
-set R(iNextMsg) 1
-proc r_get_messages {{db ""}} {
- global R
+ foreach t $tests {
+ foreach {b c s} $t {}
+ set slow 0
- sqlite3_test_control_pending_byte 0x010000
+ if {$c!="make" && $c!="build"} {
+ set fd [open $s]
+ for {set ii 0} {$ii<100 && ![eof $fd]} {incr ii} {
+ set line [gets $fd]
+ if {[string match -nocase *testrunner:* $line]} {
+ regexp -nocase {.*testrunner:(.*)} $line -> properties
+ foreach p $properties {
+ if {$p=="slow"} { set slow 1 }
+ if {$p=="superslow"} { set slow 2 }
+ }
+ }
+ }
+ close $fd
+ }
- if {$db==""} {
- sqlite3 rgmhandle $R(dbname)
- set dbhandle rgmhandle
- $dbhandle timeout $R(timeout)
- } else {
- set dbhandle $db
- }
+ if {$c=="make" && $b==""} {
+ # --fuzztest option
+ set slow 1
+ }
- $dbhandle transaction {
- set next $R(iNextMsg)
- set ret [$dbhandle eval {SELECT msg FROM msg WHERE id>=$next}]
- set R(iNextMsg) [$dbhandle one {SELECT COALESCE(max(id), 0)+1 FROM msg}]
- }
+ if {$c=="veryquick"} {
+ set c ""
+ }
- if {$db==""} {
- rgmhandle close
- }
+ set state ready
+ if {$b!="" && $c!="build"} {
+ set state ""
+ }
- set ret
+ trdb eval {
+ INSERT INTO script(build, config, filename, slow, state)
+ VALUES ($b, $c, $s, $slow, $state)
+ }
+ }
+ }
}
-# This is called after all tests have been run to write the leaked memory
-# report into the malloc table of testrunner.db.
-#
-proc r_memory_report {} {
- global R
+proc script_input_ready {fd iJob b c f} {
+ global TRG
+ global O
+ global T
+
+ if {[eof $fd]} {
+ set ::done 1
+ fconfigure $fd -blocking 1
+ set state "done"
+ set rc [catch { close $fd } msg]
+ if {$rc} {
+ puts "FAILED: $b $c $f"
+ set state "failed"
+ }
- sqlite3_shutdown
+ set tm [expr [clock_milliseconds] - $T($iJob)]
- set nMalloc [lindex [sqlite3_status SQLITE_STATUS_MALLOC_COUNT 0] 1]
- set nByte [sqlite3_memory_used]
- set id $R(helper_id)
- set leaker $R(leaker)
+ puts $TRG(log) "### $b ### $c ### $f ${tm}ms ($state)"
+ puts $TRG(log) [string trim $O($iJob)]
- r_write_db {
- db eval {
- INSERT INTO malloc(id, nMalloc, nByte, leaker)
- VALUES($id, $nMalloc, $nByte, $leaker)
+ r_write_db {
+ set output $O($iJob)
+ trdb eval {
+ UPDATE script SET output = $output, state=$state, time=$tm
+ WHERE (build, config, filename) = ($b, $c, $f)
+ }
+ if {$state=="done" && $c=="build"} {
+ trdb eval {
+ UPDATE script SET state = 'ready' WHERE (build, state)==($b, '')
+ }
+ }
}
- }
-}
-
-#--------------------------------------------------------------------------
-#
-set ::R_INSTALL_PUTS_WRAPPER {
- proc puts_sts_wrapper {args} {
- set n [llength $args]
- if {$n==1 || ($n==2 && [string first [lindex $args 0] -nonewline]==0)} {
- uplevel puts_into_caller $args
- } else {
- # A channel was explicitly specified.
- uplevel puts_sts_original $args
+ dirs_freeDir $iJob
+ launch_some_jobs
+ incr ::wakeup
+ } else {
+ set rc [catch { gets $fd line } res]
+ if {$rc} {
+ puts "ERROR $res"
+ }
+ if {$res>=0} {
+ append O($iJob) "$line\n"
}
}
- rename puts puts_sts_original
- proc puts {args} { uplevel puts_sts_wrapper $args }
-}
-proc r_install_puts_wrapper {} $::R_INSTALL_PUTS_WRAPPER
-proc r_uninstall_puts_wrapper {} {
- rename puts ""
- rename puts_sts_original puts
}
-proc slave_test_script {script} {
-
- # Create the interpreter used to run the test script.
- interp create tinterp
+proc dirname {ii} {
+ return "testdir$ii"
+}
- # Populate some global variables that tester.tcl expects to see.
- foreach {var value} [list \
- ::argv0 $::argv0 \
- ::argv {} \
- ::SLAVE 1 \
- ] {
- interp eval tinterp [list set $var $value]
- }
+proc launch_another_job {iJob} {
+ global TRG
+ global O
+ global T
- # The alias used to access the global test counters.
- tinterp alias set_test_counter set_test_counter
+ set testfixture [info nameofexec]
+ set script $TRG(info_script)
- # Set up an empty ::cmdlinearg array in the slave.
- interp eval tinterp [list array set ::cmdlinearg [array get ::cmdlinearg]]
+ set dir [dirname $iJob]
+ create_or_clear_dir $dir
- # Set up the ::G array in the slave.
- interp eval tinterp [list array set ::G [array get ::G]]
- interp eval tinterp [list set ::G(runner.tcl) 1]
+ set O($iJob) ""
+
+ set job [r_get_next_job $iJob]
+ if {$job==""} { return 0 }
+
+ foreach {b c f} $job {}
+
+ if {$c=="build"} {
+ set testdir [file dirname $TRG(info_script)]
+ set srcdir [file dirname $testdir]
+ set builddir [build_to_dirname $b]
+ create_or_clear_dir $builddir
+
+ set cmd [info nameofexec]
+ lappend cmd [file join $testdir releasetest_data.tcl]
+ lappend cmd trscript
+ if {$TRG(platform)=="win"} { lappend cmd -msvc }
+ lappend cmd $b $srcdir
+
+ set script [exec {*}$cmd]
+ set fd [open [file join $builddir $TRG(make)] w]
+ puts $fd $script
+ close $fd
- interp eval tinterp $::R_INSTALL_PUTS_WRAPPER
- tinterp alias puts_into_caller puts_into_caller
+ puts "Launching build \"$b\" in directory $builddir..."
+ set target coretestprogs
+ if {$b=="User-Auth"} { set target testfixture }
- # Load the various test interfaces implemented in C.
- load_testfixture_extensions tinterp
+ set cmd "$TRG(makecmd) $target"
+ set dir $builddir
- # Run the test script.
- set rc [catch { interp eval tinterp $script } msg opt]
- if {$rc} {
- puts_into_caller $msg
- puts_into_caller [dict get $opt -errorinfo]
- incr ::TC(errors)
- }
+ } elseif {$c=="make"} {
+ if {$b==""} {
+ if {$f!="fuzztest"} { error "corruption in testrunner.db!" }
+ # Special case - run [make fuzztest]
+ set makedir [file dirname $testfixture]
+ if {$TRG(platform)=="win"} {
+ error "how?"
+ } else {
+ set cmd [list make -C $makedir fuzztest]
+ }
+ } else {
+ set builddir [build_to_dirname $b]
+ copy_dir $builddir $dir
+ set cmd "$TRG(makecmd) $f"
+ }
+ } else {
+ if {$b==""} {
+ set testfixture [info nameofexec]
+ } else {
+ set tail testfixture
+ if {$TRG(platform)=="win"} { set tail testfixture.exe }
+ set testfixture [file normalize [file join [build_to_dirname $b] $tail]]
+ }
- # Check if the interpreter call [run_thread_tests]
- if { [interp eval tinterp {info exists ::run_thread_tests_called}] } {
- set ::run_thread_tests_called 1
+ if {$c=="valgrind"} {
+ set testfixture "valgrind -v --error-exitcode=1 $testfixture"
+ set ::env(OMIT_MISUSE) 1
+ }
+ set cmd [concat $testfixture [list $script $c $f]]
}
- # Delete the interpreter used to run the test script.
- interp delete tinterp
-}
-
-proc slave_test_file {zFile} {
- set tail [file tail $zFile]
+ set pwd [pwd]
+ cd $dir
+ set fd [open "|$cmd 2>@1" r]
+ cd $pwd
+ set pid [pid $fd]
- # Remember the value of the shared-cache setting. So that it is possible
- # to check afterwards that it was not modified by the test script.
- #
- ifcapable shared_cache { set scs [sqlite3_enable_shared_cache] }
-
- # Run the test script in a slave interpreter.
- #
- unset -nocomplain ::run_thread_tests_called
- reset_prng_state
- set ::sqlite_open_file_count 0
- set time [time { slave_test_script [list source $zFile] }]
- set ms [expr [lindex $time 0] / 1000]
-
- r_install_puts_wrapper
-
- # Test that all files opened by the test script were closed. Omit this
- # if the test script has "thread" in its name. The open file counter
- # is not thread-safe.
- #
- if {[info exists ::run_thread_tests_called]==0} {
- do_test ${tail}-closeallfiles { expr {$::sqlite_open_file_count>0} } {0}
- }
- set ::sqlite_open_file_count 0
+ fconfigure $fd -blocking false
+ fileevent $fd readable [list script_input_ready $fd $iJob $b $c $f]
+ unset -nocomplain ::env(OMIT_MISUSE)
- # Test that the global "shared-cache" setting was not altered by
- # the test script.
- #
- ifcapable shared_cache {
- set res [expr {[sqlite3_enable_shared_cache] == $scs}]
- do_test ${tail}-sharedcachesetting [list set {} $res] 1
- }
+ return 1
+}
- # Add some info to the output.
- #
- output2 "Time: $tail $ms ms"
- show_memstats
+proc one_line_report {} {
+ global TRG
- r_uninstall_puts_wrapper
- return $ms
-}
+ set tm [expr [clock_milliseconds] - $TRG(starttime)]
+ set tm [format "%d" [expr int($tm/1000.0 + 0.5)]]
-proc puts_into_caller {args} {
- global R
- if {[llength $args]==1} {
- append R(output) [lindex $args 0]
- append R(output) "\n"
- } else {
- append R(output) [lindex $args 1]
+ foreach s {ready running done failed} {
+ set v($s,build) 0
+ set v($s,make) 0
+ set v($s,script) 0
}
-}
-#-------------------------------------------------------------------------
-#
-proc r_final_report {} {
- global R
-
- sqlite3_test_control_pending_byte 0x010000
- sqlite3 db $R(dbname)
-
- db timeout $R(timeout)
-
- set errcode 0
-
- # Create the text log file. This is just the concatenation of the
- # 'output' column of the database for every script that was run.
- set fd [open $R(logname) w]
- db eval {SELECT output FROM script ORDER BY config!='full',config,filename} {
- puts $fd $output
- }
- close $fd
-
- # Check if any scripts reported errors. If so, print one line noting
- # how many errors, and another identifying the scripts in which they
- # occured. Or, if no errors occurred, print out "no errors at all!".
- sqlite3 db $R(dbname)
- db timeout $R(timeout)
- db eval { SELECT sum(nerr) AS nerr, sum(ntest) AS ntest FROM script } { }
- puts "$nerr errors from $ntest tests."
- if {$nerr>0} {
- db eval { SELECT config, filename FROM script WHERE nerr>0 } {
- lappend errlist [r_testname $config $filename]
+ r_write_db {
+ trdb eval {
+ SELECT state, jobtype, count(*) AS cnt
+ FROM script
+ GROUP BY state, jobtype
+ } {
+ set v($state,$jobtype) $cnt
+ if {[info exists t($jobtype)]} {
+ incr t($jobtype) $cnt
+ } else {
+ set t($jobtype) $cnt
+ }
}
- puts "Errors in: $errlist"
- set errcode 1
}
- # Check if any scripts were not run or did not finish. Print out a
- # line identifying them if there are any.
- set errlist [list]
- db eval { SELECT config, filename FROM script WHERE state!='done' } {
- lappend errlist [r_testname $config $filename]
- }
- if {$errlist!=[list]} {
- puts "Tests DID NOT FINISH (crashed?): $errlist"
- set errcode 1
+ set text ""
+ foreach j [array names t] {
+ set fin [expr $v(done,$j) + $v(failed,$j)]
+ lappend text "$j ($fin/$t($j)) f=$v(failed,$j) r=$v(running,$j)"
}
- set bLeak 0
- db eval {
- SELECT id, nmalloc, nbyte, leaker FROM malloc
- WHERE nmalloc>0 OR nbyte>0
- } {
- if {$id==0} {
- set line "This process "
- } else {
- set line "Helper $id "
- }
- append line "leaked $nbyte byte in $nmalloc allocations"
- if {$leaker!=""} { append line " (perhaps in [file tail $leaker])" }
- puts $line
- set bLeak 1
+ if {[info exists TRG(reportlength)]} {
+ puts -nonewline "[string repeat " " $TRG(reportlength)]\r"
}
- if {$bLeak==0} {
- puts "No leaks - all allocations freed."
- }
-
- db close
-
- puts "Test database is $R(dbname)"
- puts "Test log file is $R(logname)"
- if {$errcode} {
- puts "This test has FAILED."
+ set report "${tm}s: [join $text { }]"
+ set TRG(reportlength) [string length $report]
+ if {[string length $report]<80} {
+ puts -nonewline "$report\r"
+ flush stdout
+ } else {
+ puts $report
}
- return $errcode
-}
-
-if {$R(helper)==0} {
- make_new_testset
+ after $TRG(reporttime) one_line_report
}
-set R(nHelperRunning) 0
-if {$R(helper)==0 && $R(nJob)>1} {
- cd $cmdlinearg(TESTFIXTURE_HOME)
- for {set ii 1} {$ii <= $R(nJob)} {incr ii} {
- set cmd "[info nameofexec] $R(info_script) helper $ii 2>@1"
- puts "Launching helper $ii ($cmd)"
- set chan [open "|$cmd" r]
- fconfigure $chan -blocking false
- fileevent $chan readable [list r_helper_readable $ii $chan]
- incr R(nHelperRunning)
- }
- cd $cmdlinearg(testdir)
-}
-
-proc r_helper_readable {id chan} {
- set data [gets $chan]
- if {$data!=""} { puts "helper $id:$data" }
- if {[eof $chan]} {
- puts "helper $id is finished"
- incr ::R(nHelperRunning) -1
- close $chan
+proc launch_some_jobs {} {
+ global TRG
+ r_write_db {
+ set nJob [trdb one { SELECT value FROM config WHERE name='njob' }]
+ }
+ while {[dirs_nHelper]<$nJob} {
+ set iDir [dirs_allocDir]
+ if {0==[launch_another_job $iDir]} {
+ dirs_freeDir $iDir
+ break;
+ }
}
}
-if {$R(nHelperRunning)==0} {
- while { ""!=[set t [get_next_test]] } {
- set R(output) ""
- set TC(count) 0
- set TC(errors) 0
-
- foreach {config filename} $t {}
-
- array set O $::testspec($config)
- set ::G(perm:name) $config
- set ::G(perm:prefix) $O(-prefix)
- set ::G(isquick) 1
- set ::G(perm:dbconfig) $O(-dbconfig)
- set ::G(perm:presql) $O(-presql)
+proc run_testset {} {
+ global TRG
+ set ii 0
- eval $O(-initialize)
- set ms [slave_test_file $filename]
- eval $O(-shutdown)
+ set TRG(starttime) [clock_milliseconds]
+ set TRG(log) [open $TRG(logname) w]
- unset -nocomplain ::G(perm:sqlite3_args)
- unset ::G(perm:name)
- unset ::G(perm:prefix)
- unset ::G(perm:dbconfig)
- unset ::G(perm:presql)
+ launch_some_jobs
+ # launch_another_job $ii
- r_set_test_result $config $filename $ms $TC(errors) $TC(count) $R(output)
-
- if {$R(helper)==0} {
- foreach msg [r_get_messages] { puts $msg }
- }
+ one_line_report
+ while {[dirs_nHelper]>0} {
+ after 500 {incr ::wakeup}
+ vwait ::wakeup
}
+ close $TRG(log)
+ one_line_report
- # Tests are finished - write a record into testrunner.db describing
- # any memory leaks.
- r_memory_report
-
-} else {
- set TTT 0
- sqlite3 db $R(dbname)
- db timeout $R(timeout)
- while {$R(nHelperRunning)>0} {
- after 250 { incr TTT }
- vwait TTT
- foreach msg [r_get_messages db] { puts $msg }
+ r_write_db {
+ set nErr [trdb one {SELECT count(*) FROM script WHERE state='failed'}]
+ if {$nErr>0} {
+ puts "$nErr failures:"
+ trdb eval {
+ SELECT build, config, filename FROM script WHERE state='failed'
+ } {
+ puts "FAILED: $build $config $filename"
+ }
+ }
}
- db close
-}
-set errcode 0
-if {$R(helper)==0} {
- set errcode [r_final_report]
+ puts "\nTest database is $TRG(dbname)"
+ puts "Test log is $TRG(logname)"
}
-exit $errcode
+sqlite3 trdb $TRG(dbname)
+trdb timeout $TRG(timeout)
+set tm [lindex [time { make_new_testset }] 0]
+puts "built testset in [expr $tm/1000]ms.."
+run_testset
+trdb close
+#puts [pwd]
diff --git a/test/testrunner_data.tcl b/test/testrunner_data.tcl
new file mode 100644
index 000000000..f74ee146c
--- /dev/null
+++ b/test/testrunner_data.tcl
@@ -0,0 +1,143 @@
+
+
+
+namespace eval trd {
+ variable tcltest
+ variable extra
+ variable all_configs
+
+
+ # Tcl tests to run for various builds.
+ #
+ set tcltest(linux.Fast-One) veryquick
+ set tcltest(linux.Debug-One) veryquick
+ set tcltest(linux.Debug-Two) veryquick
+ set tcltest(linux.Have-Not) veryquick
+ set tcltest(linux.Secure-Delete) veryquick
+ set tcltest(linux.Unlock-Notify) veryquick
+ set tcltest(linux.User-Auth) veryquick
+ set tcltest(linux.Update-Delete-Limit) veryquick
+ set tcltest(linux.Extra-Robustness) veryquick
+ set tcltest(linux.Device-Two) veryquick
+ set tcltest(linux.No-lookaside) veryquick
+ set tcltest(linux.Devkit) veryquick
+ set tcltest(linux.Apple) veryquick
+ set tcltest(linux.Sanitize) veryquick
+ set tcltest(linux.Device-One) all
+ set tcltest(linux.Default) all_plus_autovacuum_crash
+ set tcltest(linux.Valgrind) valgrind
+
+ set tcltest(osx.Locking-Style) veryquick
+ set tcltest(osx.Have-Not) veryquick
+ set tcltest(osx.Apple) all
+
+ set tcltest(win.Stdcall) veryquick
+ set tcltest(win.Have-Not) veryquick
+ set tcltest(win.Windows-Memdebug) veryquick
+ set tcltest(win.Windows-Win32Heap) veryquick
+ set tcltest(win.Default) full
+
+ # Extra [make xyz] tests that should be run for various builds.
+ #
+ set extra(linux.Check-Symbols) checksymbols
+ set extra(linux.Fast-One) {fuzztest sourcetest}
+ set extra(linux.Debug-One) {fuzztest sourcetest mptest}
+ set extra(linux.Debug-Two) {fuzztest sourcetest}
+ set extra(linux.Have-Not) {fuzztest sourcetest}
+ set extra(linux.Secure-Delete) {fuzztest sourcetest}
+ set extra(linux.Unlock-Notify) {fuzztest sourcetest}
+ set extra(linux.Update-Delete-Limit) {fuzztest sourcetest}
+ set extra(linux.Extra-Robustness) {fuzztest sourcetest}
+ set extra(linux.Device-Two) {fuzztest sourcetest threadtest}
+ set extra(linux.No-lookaside) {fuzztest sourcetest}
+ set extra(linux.Devkit) {fuzztest sourcetest}
+ set extra(linux.Apple) {fuzztest sourcetest}
+ set extra(linux.Sanitize) {fuzztest sourcetest}
+ set extra(linux.Default) {fuzztest sourcetest threadtest}
+
+ set extra(osx.Apple) {fuzztest threadtest}
+ set extra(osx.Have-Not) {fuzztest sourcetest}
+ set extra(osx.Locking-Style) {mptest fuzztest sourcetest}
+
+ set extra(win.Default) mptest
+ set extra(win.Stdcall) {fuzztest sourcetest}
+ set extra(win.Windows-Memdebug) {fuzztest sourcetest}
+ set extra(win.Windows-Win32Heap) {fuzztest sourcetest}
+ set extra(win.Have-Not) {fuzztest sourcetest}
+
+ # The following mirrors the set of test suites invoked by "all.test".
+ #
+ set all_configs {
+ full no_optimization memsubsys1 memsubsys2 singlethread
+ multithread onefile utf16 exclusive persistent_journal
+ persistent_journal_error no_journal no_journal_error
+ autovacuum_ioerr no_mutex_try fullmutex journaltest
+ inmemory_journal pcache0 pcache10 pcache50 pcache90
+ pcache100 prepare mmap
+ }
+}
+
+
+#-------------------------------------------------------------------------
+proc trd_import {} {
+ uplevel {
+ variable ::trd::tcltest
+ variable ::trd::extra
+ variable ::trd::all_configs
+ }
+}
+
+proc trd_builds {platform} {
+ trd_import
+
+ set klist [lsort -uniq [concat \
+ [array names tcltest ${platform}.*] \
+ [array names extra ${platform}.*] \
+ ]]
+ if {[llength $klist]==0} {
+ error "no such platform: $platform"
+ }
+
+ set ret ""
+ foreach k $klist {
+ foreach {p c} [split $k "."] {}
+ lappend ret $c
+ }
+ set ret
+}
+
+proc trd_configs {platform build} {
+ trd_import
+
+ set clist [list]
+
+ if {[info exists tcltest($platform.$build)]} {
+ set clist $tcltest($platform.$build)
+ if {$clist=="all"} {
+ set clist $all_configs
+ } elseif {$clist=="all_plus_autovacuum_crash"} {
+ set clist [concat $all_configs autovacuum_crash]
+ }
+ }
+
+ set clist
+}
+
+proc trd_extras {platform build} {
+ trd_import
+
+ set elist [list]
+ if {[info exists extra($platform.$build)]} {
+ set elist $extra($platform.$build)
+ }
+
+ set elist
+}
+
+proc trd_all_configs {} {
+ trd_import
+ set all_configs
+}
+
+
+
diff --git a/test/vt02.c b/test/vt02.c
index 40bd6fcb3..f83fc9af9 100644
--- a/test/vt02.c
+++ b/test/vt02.c
@@ -177,6 +177,8 @@
#include <assert.h>
#endif
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+
/* Forward declarations */
typedef struct vt02_vtab vt02_vtab;
typedef struct vt02_cur vt02_cur;
@@ -999,6 +1001,10 @@ static void vt02CoreInit(sqlite3 *db){
sqlite3_create_module(db, "vt02pkabcd", &vt02Module, (void*)zPkABCDSchema);
}
+#else
+# define vt02CoreInit(db)
+#endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */
+
#ifdef TH3_VERSION
static void vt02_init(th3state *p, int iDb, char *zArg){
vt02CoreInit(th3dbPointer(p, iDb));
diff --git a/test/where.test b/test/where.test
index 4f7c2f84b..0a8cfd572 100644
--- a/test/where.test
+++ b/test/where.test
@@ -1620,10 +1620,11 @@ do_execsql_test where-28.1 {
# 2022-12-07 Yong Heng [https://sqlite.org/forum/forumpost/dfe8084751]
#
-do_execsql_test where-29.1 {
- SELECT DISTINCT 'xyz' FROM pragma_cache_size
- WHERE rowid OR abs(0)
- ORDER BY
+ifcapable vtab {
+ do_execsql_test where-29.1 {
+ SELECT DISTINCT 'xyz' FROM pragma_cache_size
+ WHERE rowid OR abs(0)
+ ORDER BY
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
@@ -1631,6 +1632,76 @@ do_execsql_test where-29.1 {
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1;
-} {xyz}
+ } {xyz}
+}
+
+# 2023-01-30
+# Tests case for the query planner performance issue reported by
+# https://sqlite.org/forum/forumpost/1d571c0296
+#
+# The fix was to adjust the cost of computing an automatic index for
+# ephemeral tables, to help ensure that they are generated if they are
+# needed. The test case below only looks at the query plan. But 12x
+# improved performance has been verified by populating the "raw" table
+# with 100K rows of random data and running actual speed tests.
+#
+do_test where-30.1 {
+ unset -nocomplain res
+ set res {}
+ db eval {CREATE TABLE raw(country,date,total,delta, UNIQUE(country,date));}
+ db eval {
+ EXPLAIN QUERY PLAN
+ WITH
+ -- Find the country and min/max date
+ init(country, date, fin) AS (SELECT country, min(date), max(date)
+ FROM raw WHERE total > 0 GROUP BY country),
+
+ -- Generate the date stream for each country
+ src(country, date) AS (SELECT raw.country, raw.date
+ FROM raw JOIN init i on raw.country = i.country AND raw.date > i.date
+ ORDER BY raw.country, raw.date),
+
+ -- Generate the x & y for each entry in the country/date stream
+ vals(country, date, x, y) AS (SELECT src.country, src.date,
+ julianday(raw.date) - julianday(src.date), log(delta+1)
+ FROM src JOIN raw on raw.country = src.country
+ AND raw.date > date(src.date,'-7 days')
+ AND raw.date <= src.date AND delta >= 0),
+
+ -- Accumulate the data we need
+ sums(country, date, x2, x, n, xy, y) AS (SELECT country, date,
+ sum(x*x*1.0), sum(x*1.0), sum(1.0), sum(x*y*1.0), sum(y*1.0)
+ FROM vals GROUP BY 1, 2),
+
+ -- use these to calculate to divisor for the inverse matrix
+ mult(country, date, m) AS (SELECT country, date, 1.0/(x2 * n - x * x)
+ FROM sums),
+
+ -- Build the inverse matrix
+ inv(country, date, a,b,c,d) AS (SELECT mult.country, mult.date, n * m,
+ -x * m, -x * m, x2 * m
+ FROM mult JOIN sums on sums.country=mult.country
+ AND mult.date=sums.date),
+
+ -- Calculate the coefficients for the least squares fit
+ fit(country, date, a, b) AS (SELECT inv.country, inv.date,
+ a * xy + b * y, c * xy + d * y
+ FROM inv
+ JOIN mult on mult.country = inv.country AND mult.date = inv.date
+ JOIN sums on sums.country = mult.country AND sums.date = mult.date
+ )
+ SELECT *, nFin/nPrev - 1 AS growth, log(2)/log(nFin/nPrev) AS doubling
+ FROM (SELECT f.*, exp(b) - 1 AS nFin, exp(a* (-1) + b) - 1 AS nPrev
+ FROM fit f JOIN init i on i.country = f.country
+ AND f.date <= date(i.fin,'-3 days'))
+ WHERE nPrev > 0 AND nFin > 0;
+ } {
+ if {$parent!=0} continue
+ if {![string match SCAN* $detail]} continue
+ lappend res SCAN
+ }
+ set res
+} {SCAN}
+# ^^^^^^-- there should only be one top-level table scan in the query plan.
finish_test
diff --git a/test/windowB.test b/test/windowB.test
index 254816595..32193a378 100644
--- a/test/windowB.test
+++ b/test/windowB.test
@@ -410,7 +410,8 @@ do_execsql_test 10.3 {
one,two
}
-ifcapable json1 {
+ifcapable json1&&vtab {
+if {[permutation]!="no_optimization"} {
do_execsql_test 11.0 {
SELECT value FROM json_each('[1,2,3,4,5]');
@@ -479,7 +480,7 @@ ifcapable json1 {
| `--USE TEMP B-TREE FOR ORDER BY
`--SCAN (subquery-xxxxxx)
}
-}
+}}
finish_test
diff --git a/test/with6.test b/test/with6.test
index 7fce34687..91d64fa29 100644
--- a/test/with6.test
+++ b/test/with6.test
@@ -318,5 +318,56 @@ do_eqp_test 331 {
`--SCAN t3
}
+# 2023-02-01
+# https://sqlite.org/forum/forumpost/1d571c02963355ed
+#
+# Just because a CTE is used more than once, does not mean it should be
+# marked with M10d_Yes and hence prohibited from participating in the
+# query flattening optimization.
+#
+reset_db
+db eval {
+ CREATE TABLE raw(country,date,total,delta, UNIQUE(country,date));
+}
+do_eqp_test 400 {
+ with recursive
+ init(country, date, fin) AS (SELECT country, min(date), max(date) FROM raw WHERE total > 0 GROUP BY country),
+ src(country, date) AS (SELECT raw.country, raw.date
+ FROM raw JOIN init i on raw.country = i.country AND raw.date > i.date
+ ORDER BY raw.country, raw.date),
+ vals(country, date, x, y) AS (SELECT src.country, src.date, julianday(raw.date) - julianday(src.date), log(delta+1)
+ FROM src JOIN raw on raw.country = src.country AND raw.date > date(src.date,'-7 days') AND raw.date <= src.date AND delta >= 0),
+ sums(country, date, x2, x, n, xy, y) AS (SELECT country, date, sum(x*x*1.0), sum(x*1.0), sum(1.0), sum(x*y*1.0), sum(y*1.0) FROM vals GROUP BY 1, 2),
+ mult(country, date, m) AS (SELECT country, date, 1.0/(x2 * n - x * x) FROM sums),
+ inv(country, date, a,b,c,d) AS (SELECT mult.country, mult.date, n * m, -x * m, -x * m, x2 * m
+ FROM mult JOIN sums on sums.country=mult.country AND mult.date=sums.date),
+ fit(country, date, a, b) AS (SELECT inv.country, inv.date, a * xy + b * y, c * xy + d * y
+ FROM inv
+ JOIN mult on mult.country = inv.country AND mult.date = inv.date
+ JOIN sums on sums.country = mult.country AND sums.date = mult.date
+ )
+ SELECT *, nFin/nPrev - 1 AS growth, log(2)/log(nFin/nPrev) AS doubling
+ FROM (SELECT f.*, exp(b) - 1 AS nFin, exp(a* (-1) + b) - 1 AS nPrev
+ FROM fit f JOIN init i on i.country = f.country AND f.date <= date(i.fin,'-3 days'))
+ WHERE nPrev > 0 AND nFin > 0;
+} {
+ QUERY PLAN
+ |--MATERIALIZE sums
+ | |--MATERIALIZE src
+ | | |--MATERIALIZE init
+ | | | `--SCAN raw USING INDEX sqlite_autoindex_raw_1
+ | | |--SCAN i
+ | | |--SEARCH raw USING COVERING INDEX sqlite_autoindex_raw_1 (country=? AND date>?)
+ | | `--USE TEMP B-TREE FOR ORDER BY
+ | |--SCAN src
+ | |--SEARCH raw USING INDEX sqlite_autoindex_raw_1 (country=? AND date>? AND date<?)
+ | `--USE TEMP B-TREE FOR GROUP BY
+ |--SCAN sums
+ |--SEARCH sums USING AUTOMATIC COVERING INDEX (country=? AND date=?)
+ |--SEARCH sums USING AUTOMATIC COVERING INDEX (country=? AND date=?)
+ |--SEARCH sums USING AUTOMATIC COVERING INDEX (country=? AND date=?)
+ `--SEARCH i USING AUTOMATIC COVERING INDEX (country=?)
+}
+
finish_test
diff --git a/tool/showdb.c b/tool/showdb.c
index 611e603fe..0e99331d7 100644
--- a/tool/showdb.c
+++ b/tool/showdb.c
@@ -1097,6 +1097,18 @@ static void ptrmap_coverage_report(const char *zDbName){
}
/*
+** Check the range validity for a page number. Print an error and
+** exit if the page is out of range.
+*/
+static void checkPageValidity(int iPage){
+ if( iPage<1 || iPage>g.mxPage ){
+ fprintf(stderr, "Invalid page number %d: valid range is 1..%d\n",
+ iPage, g.mxPage);
+ exit(1);
+ }
+}
+
+/*
** Print a usage comment
*/
static void usage(const char *argv0){
@@ -1184,10 +1196,12 @@ int main(int argc, char **argv){
continue;
}
iStart = strtoul(azArg[i], &zLeft, 0);
+ checkPageValidity(iStart);
if( zLeft && strcmp(zLeft,"..end")==0 ){
iEnd = g.mxPage;
}else if( zLeft && zLeft[0]=='.' && zLeft[1]=='.' ){
iEnd = strtol(&zLeft[2], 0, 0);
+ checkPageValidity(iEnd);
}else if( zLeft && zLeft[0]=='b' ){
int ofst, nByte, hdrSize;
unsigned char *a;
diff --git a/tool/showwal.c b/tool/showwal.c
index bc7406dc1..84e4afa13 100644
--- a/tool/showwal.c
+++ b/tool/showwal.c
@@ -512,6 +512,18 @@ static void decode_btree_page(
}
}
+/*
+** Check the range validity for a page number. Print an error and
+** exit if the page is out of range.
+*/
+static void checkPageValidity(int iPage, int mxPage){
+ if( iPage<1 || iPage>mxPage ){
+ fprintf(stderr, "Invalid page number %d: valid range is 1..%d\n",
+ iPage, mxPage);
+ exit(1);
+ }
+}
+
int main(int argc, char **argv){
struct stat sbuf;
unsigned char zPgSz[4];
@@ -559,10 +571,12 @@ int main(int argc, char **argv){
continue;
}
iStart = strtol(argv[i], &zLeft, 0);
+ checkPageValidity(iStart, mxFrame);
if( zLeft && strcmp(zLeft,"..end")==0 ){
iEnd = mxFrame;
}else if( zLeft && zLeft[0]=='.' && zLeft[1]=='.' ){
iEnd = strtol(&zLeft[2], 0, 0);
+ checkPageValidity(iEnd, mxFrame);
}else if( zLeft && zLeft[0]=='b' ){
i64 ofst;
int nByte, hdrSize;