Compare commits
273 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 93c803e960 | |||
| d30830e42d | |||
| 2cc8f4831e | |||
| d42d8ae337 | |||
| 42a0dbfe92 | |||
| b5a4a7053b | |||
| 3c6de3266e | |||
| 2d44d556b5 | |||
| 86c369428f | |||
| 1e9c47be1e | |||
| 8bbddd8049 | |||
| 9f2b04533e | |||
| b39161647e | |||
| 3571e7bf4c | |||
| 093d63bf34 | |||
| 20a1f35928 | |||
| 15ca9e3e8c | |||
| ffc78a41ea | |||
| 68cf69ed8d | |||
| 58db4c760f | |||
| 840c300f4a | |||
| ffdab721a3 | |||
| 42f3c5ff25 | |||
| 41a6f2cb6d | |||
| 70acb0aa6b | |||
| ef29f73479 | |||
| 69d2d35523 | |||
| 1bf208c701 | |||
| 393344f928 | |||
| a10b999d14 | |||
| 2d066bbfd8 | |||
| 6131adc074 | |||
| 980e2cd39a | |||
| 6630f9407c | |||
| 3baed31edc | |||
| 8368692815 | |||
| 7bdbe301f6 | |||
| f7c8a35b8d | |||
| 069720ea8b | |||
| 98cb7a4894 | |||
| f94c1902b9 | |||
| 391ac1b959 | |||
| 45fb850b35 | |||
| b649be3c3b | |||
| 23355215fb | |||
| ac8ba26ecb | |||
| b0f0dc3073 | |||
| 4811a710af | |||
| 9c6396ecc7 | |||
| 8784efaea9 | |||
| 14714167f7 | |||
| a48b020ddd | |||
| 5f9d192de9 | |||
| bcdb28dff3 | |||
| 49cc2f3b9c | |||
| 8d43d8443d | |||
| 6344edda80 | |||
| ad7fd5d096 | |||
| 93b7731485 | |||
| da57d9676a | |||
| f111203287 | |||
| 9c42626e43 | |||
| f0cb61d6c2 | |||
| 302ce47519 | |||
| b2194cea4e | |||
| 5e9825ecc4 | |||
| e341ec699f | |||
| 2825e4ebb1 | |||
| dd8a4af8e7 | |||
| bda30ce4d8 | |||
| 6a8a629e6b | |||
| d7fd899eeb | |||
| 5597cd42b8 | |||
| 96acafbea7 | |||
| e39ef31cd6 | |||
| 43c4ac8bfe | |||
| 171d16bb21 | |||
| 3432821192 | |||
| 8abed7b907 | |||
| 6bd4140d33 | |||
| f7e867c347 | |||
| bc8f68a3a0 | |||
| 1fcfa7240f | |||
| 007c843b0f | |||
| 5facffbc70 | |||
| fda0867873 | |||
| 4f46b58a2d | |||
| d6ec7a6ab3 | |||
| c0ec2f7762 | |||
| 8d3e15eec4 | |||
| 4f4e49a98b | |||
| 2e178d7321 | |||
| 7436f1e491 | |||
| 3993678d3d | |||
| cc398969e0 | |||
| b0b6f8783c | |||
| 57a93fa38c | |||
| a15a7c352c | |||
| 57f29b7bfb | |||
| cf7c8370d1 | |||
| 136102beda | |||
| 57e3ba7623 | |||
| 62856465f2 | |||
| 26f625fbf4 | |||
| a224ee2a1b | |||
| e28eb64d09 | |||
| 091881bbb0 | |||
| c551550808 | |||
| 713f34ace9 | |||
| f4bc6c43d7 | |||
| 46e835a2c4 | |||
| 501ea05630 | |||
| ee269a60c9 | |||
| d9274a8ae3 | |||
| 0fae06fcb6 | |||
| 4e6e5cef6c | |||
| e2d27e0259 | |||
| a9abfb1e6c | |||
| 4d1c6845ff | |||
| d446e79545 | |||
| e84c498be1 | |||
| c083cb4422 | |||
| 35043cc32a | |||
| 1db7db1f03 | |||
| 00c3ef2df9 | |||
| c86d82f27d | |||
| f313952097 | |||
| 510fea885e | |||
| 91347c066b | |||
| 54cfb492b7 | |||
| 2a86110a6c | |||
| b189e4101c | |||
| eab0e10304 | |||
| fa68815fa3 | |||
| bc6b8d7359 | |||
| 435666e26d | |||
| 561158937b | |||
| d1317095b5 | |||
| 60d72b9bab | |||
| 4b18c1d53a | |||
| 97f9059eee | |||
| 001f52ed7d | |||
| 3944cf8de3 | |||
| 1dff328119 | |||
| 668845bb0b | |||
| 15daa6b53e | |||
| 563ddbe54d | |||
| c3ef23a1c9 | |||
| 06b3bd5b7a | |||
| f8c3a2f3cf | |||
| cfaffad65c | |||
| 44091ed368 | |||
| 5cd253423b | |||
| 4ea48144f9 | |||
| 04a28c3b6d | |||
| 099fa84727 | |||
| 2f7260deba | |||
| fdcd9d4e6c | |||
| ea4125bbef | |||
| f8c4b99a02 | |||
| 8433e7166b | |||
| 26e731cc88 | |||
| a07aa8d397 | |||
| 26333ee3ca | |||
| 1822ebf9b1 | |||
| c9f3db33d5 | |||
| 33f10207aa | |||
| c86caa58cd | |||
| 33f763d154 | |||
| 8005d60587 | |||
| 4eb57ceffc | |||
| 8558ef2e19 | |||
| cad42838d7 | |||
| 9f8952390a | |||
| 1a0e5b37b2 | |||
| da6bc6792f | |||
| fe875027d7 | |||
| 31a13548f8 | |||
| a8519d79b9 | |||
| 4d6d872c49 | |||
| a87f8ce262 | |||
| b9f4799b55 | |||
| 93117f0c4b | |||
| 9ccc0fd1f9 | |||
| 0aac5613d9 | |||
| 56f1774603 | |||
| 5347f3c111 | |||
| 588049cc99 | |||
| 21d5978422 | |||
| d15046ac08 | |||
| a916b57013 | |||
| 61d04974f0 | |||
| b8fff29c68 | |||
| 8d7f163015 | |||
| 176b3a09b2 | |||
| 7ea3469e53 | |||
| f09ac0b336 | |||
| fa3d785580 | |||
| b71aa0955b | |||
| 138d4f8de2 | |||
| 8bfe66a9c4 | |||
| 3a9b9b7749 | |||
| 88284b0dc3 | |||
| 2f94935409 | |||
| 1a3a308616 | |||
| 5a7da86f5b | |||
| 80db2d6521 | |||
| b8a0fb75db | |||
| cae5b9feac | |||
| e3ca3831ba | |||
| 4b3931ef33 | |||
| d1cccf19b5 | |||
| 1611e5a301 | |||
| 3dc9727782 | |||
| 3739f29807 | |||
| 61c758b53a | |||
| 26893c98d2 | |||
| b968518559 | |||
| f193937620 | |||
| 30fe26c47f | |||
| 98e2cb8bd1 | |||
| 5685257b83 | |||
| 824f28426a | |||
| 2879952faa | |||
| 8c9e30ba2f | |||
| 2d9e8c55da | |||
| 4a4532bbb7 | |||
| 4bd387495f | |||
| eb0b6f364e | |||
| 70bc717c0e | |||
| 0ed2fd8a25 | |||
| fff5367c24 | |||
| 194a17bbb7 | |||
| 0c2ba13e02 | |||
| ded2d99d73 | |||
| 2d620070b9 | |||
| 89fa746941 | |||
| a9be508a97 | |||
| b058d05452 | |||
| eb54500419 | |||
| f42884c307 | |||
| cdb60978b9 | |||
| 098728fc9c | |||
| 2483a111db | |||
| 69aedc8db4 | |||
| 2034353db4 | |||
| 76506cd3a7 | |||
| 9df81a2989 | |||
| 41fb367a2c | |||
| ce2fbd1b02 | |||
| 4ec6f3a075 | |||
| 5871318407 | |||
| 84ebe2b303 | |||
| 3f975373ce | |||
| f3e3dfe96c | |||
| 614efe2b4b | |||
| 6ac7303e1a | |||
| f225059b8b | |||
| afd4eef575 | |||
| 66a3a91aa6 | |||
| 5e9bbe1924 | |||
| 91694dbdd2 | |||
| d19866bb98 | |||
| ef42481224 | |||
| a41f2855e9 | |||
| e616735cb1 | |||
| a5bb43518b | |||
| 99abe5c478 | |||
| 3ec8665e22 | |||
| cb7d541d3a | |||
| 4dcac40e3d | |||
| 7de2c3e5ee | |||
| ac442f41c1 |
+16
-4
@@ -180,7 +180,7 @@ LIBOBJS0 = alter.lo analyze.lo attach.lo auth.lo \
|
||||
func.lo global.lo hash.lo \
|
||||
icu.lo insert.lo json1.lo legacy.lo loadext.lo \
|
||||
main.lo malloc.lo mem0.lo mem1.lo mem2.lo mem3.lo mem5.lo \
|
||||
memjournal.lo \
|
||||
memdb.lo memjournal.lo \
|
||||
mutex.lo mutex_noop.lo mutex_unix.lo mutex_w32.lo \
|
||||
notify.lo opcodes.lo os.lo os_unix.lo os_win.lo \
|
||||
pager.lo parse.lo pcache.lo pcache1.lo pragma.lo prepare.lo printf.lo \
|
||||
@@ -240,6 +240,7 @@ SRC = \
|
||||
$(TOP)/src/mem2.c \
|
||||
$(TOP)/src/mem3.c \
|
||||
$(TOP)/src/mem5.c \
|
||||
$(TOP)/src/memdb.c \
|
||||
$(TOP)/src/memjournal.c \
|
||||
$(TOP)/src/msvc.h \
|
||||
$(TOP)/src/mutex.c \
|
||||
@@ -440,6 +441,7 @@ TESTSRC += \
|
||||
$(TOP)/ext/misc/ieee754.c \
|
||||
$(TOP)/ext/misc/mmapwarm.c \
|
||||
$(TOP)/ext/misc/nextchar.c \
|
||||
$(TOP)/ext/misc/normalize.c \
|
||||
$(TOP)/ext/misc/percentile.c \
|
||||
$(TOP)/ext/misc/regexp.c \
|
||||
$(TOP)/ext/misc/remember.c \
|
||||
@@ -590,6 +592,7 @@ SHELL_OPT += -DSQLITE_INTROSPECTION_PRAGMAS
|
||||
FUZZERSHELL_OPT = -DSQLITE_ENABLE_JSON1
|
||||
FUZZCHECK_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5 -DSQLITE_OSS_FUZZ
|
||||
FUZZCHECK_OPT += -DSQLITE_MAX_MEMORY=50000000
|
||||
FUZZCHECK_OPT += -DSQLITE_PRINTF_PRECISION_LIMIT=1000
|
||||
FUZZCHECK_SRC = $(TOP)/test/fuzzcheck.c $(TOP)/test/ossfuzz.c
|
||||
DBFUZZ_OPT =
|
||||
|
||||
@@ -647,6 +650,9 @@ ossshell$(TEXE): $(TOP)/test/ossfuzz.c $(TOP)/test/ossshell.c sqlite3.c sqlite3.
|
||||
$(LTLINK) -o $@ $(FUZZCHECK_OPT) $(TOP)/test/ossshell.c \
|
||||
$(TOP)/test/ossfuzz.c sqlite3.c $(TLIBS)
|
||||
|
||||
sessionfuzz$(TEXE): $(TOP)/test/sessionfuzz.c sqlite3.c sqlite3.h
|
||||
$(CC) $(CFLAGS) -I. -o $@ $(TOP)/test/sessionfuzz.c $(TLIBS)
|
||||
|
||||
dbfuzz$(TEXE): $(TOP)/test/dbfuzz.c sqlite3.c sqlite3.h
|
||||
$(LTLINK) -o $@ $(DBFUZZ_OPT) $(TOP)/test/dbfuzz.c sqlite3.c $(TLIBS)
|
||||
|
||||
@@ -827,6 +833,9 @@ mem3.lo: $(TOP)/src/mem3.c $(HDR)
|
||||
mem5.lo: $(TOP)/src/mem5.c $(HDR)
|
||||
$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/mem5.c
|
||||
|
||||
memdb.lo: $(TOP)/src/memdb.c $(HDR)
|
||||
$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/memdb.c
|
||||
|
||||
memjournal.lo: $(TOP)/src/memjournal.c $(HDR)
|
||||
$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/memjournal.c
|
||||
|
||||
@@ -1160,14 +1169,17 @@ fulltestonly: $(TESTPROGS) fuzztest
|
||||
./testfixture$(TEXE) $(TOP)/test/full.test
|
||||
|
||||
# Fuzz testing
|
||||
fuzztest: fuzzcheck$(TEXE) $(FUZZDATA)
|
||||
fuzztest: fuzzcheck$(TEXE) $(FUZZDATA) sessionfuzz$(TEXE) $(TOP)/test/sessionfuzz-data1.db
|
||||
./fuzzcheck$(TEXE) $(FUZZDATA)
|
||||
./sessionfuzz$(TEXE) run $(TOP)/test/sessionfuzz-data1.db
|
||||
|
||||
fastfuzztest: fuzzcheck$(TEXE) $(FUZZDATA)
|
||||
fastfuzztest: fuzzcheck$(TEXE) $(FUZZDATA) sessionfuzz$(TEXE) $(TOP)/test/sessionfuzz-data1.db
|
||||
./fuzzcheck$(TEXE) --limit-mem 100M $(FUZZDATA)
|
||||
./sessionfuzz$(TEXE) run $(TOP)/test/sessionfuzz-data1.db
|
||||
|
||||
valgrindfuzz: fuzzcheck$(TEXT) $(FUZZDATA)
|
||||
valgrindfuzz: fuzzcheck$(TEXT) $(FUZZDATA) sessionfuzz$(TEXE) $(TOP)/test/sessionfuzz-data1.db
|
||||
valgrind ./fuzzcheck$(TEXE) --cell-size-check --limit-mem 10M --timeout 600 $(FUZZDATA)
|
||||
valgrind ./sessionfuzz$(TEXE) run $(TOP)/test/sessionfuzz-data1.db
|
||||
|
||||
# The veryquick.test TCL tests.
|
||||
#
|
||||
|
||||
+19
-11
@@ -1186,7 +1186,7 @@ LIBOBJS0 = vdbe.lo parse.lo alter.lo analyze.lo attach.lo auth.lo \
|
||||
func.lo global.lo hash.lo \
|
||||
icu.lo insert.lo legacy.lo loadext.lo \
|
||||
main.lo malloc.lo mem0.lo mem1.lo mem2.lo mem3.lo mem5.lo \
|
||||
memjournal.lo \
|
||||
memdb.lo memjournal.lo \
|
||||
mutex.lo mutex_noop.lo mutex_unix.lo mutex_w32.lo \
|
||||
notify.lo opcodes.lo os.lo os_unix.lo os_win.lo \
|
||||
pager.lo pcache.lo pcache1.lo pragma.lo prepare.lo printf.lo \
|
||||
@@ -1259,6 +1259,7 @@ SRC00 = \
|
||||
$(TOP)\src\mem2.c \
|
||||
$(TOP)\src\mem3.c \
|
||||
$(TOP)\src\mem5.c \
|
||||
$(TOP)\src\memdb.c \
|
||||
$(TOP)\src\memjournal.c \
|
||||
$(TOP)\src\mutex.c \
|
||||
$(TOP)\src\mutex_noop.c \
|
||||
@@ -1500,6 +1501,7 @@ TESTEXT = \
|
||||
$(TOP)\ext\misc\ieee754.c \
|
||||
$(TOP)\ext\misc\mmapwarm.c \
|
||||
$(TOP)\ext\misc\nextchar.c \
|
||||
$(TOP)\ext\misc\normalize.c \
|
||||
$(TOP)\ext\misc\percentile.c \
|
||||
$(TOP)\ext\misc\regexp.c \
|
||||
$(TOP)\ext\misc\remember.c \
|
||||
@@ -1614,12 +1616,11 @@ SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_RTREE
|
||||
#
|
||||
MPTESTER_COMPILE_OPTS = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5
|
||||
FUZZERSHELL_COMPILE_OPTS = -DSQLITE_ENABLE_JSON1
|
||||
FUZZCHECK_COMPILE_OPTS = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5 -DSQLITE_OSS_FUZZ -DSQLITE_MAX_MEMORY=50000000
|
||||
FUZZCHECK_COMPILE_OPTS = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5 -DSQLITE_OSS_FUZZ -DSQLITE_MAX_MEMORY=50000000 -DSQLITE_PRINTF_PRECISION_LIMIT=1000
|
||||
FUZZCHECK_SRC = $(TOP)\test\fuzzcheck.c $(TOP)\test\ossfuzz.c
|
||||
OSSSHELL_SRC = $(TOP)\test\ossshell.c $(TOP)\test\ossfuzz.c
|
||||
DBFUZZ_COMPILE_OPTS = -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION
|
||||
KV_COMPILE_OPTS = -DSQLITE_THREADSAFE=0 -DSQLITE_DIRECT_OVERFLOW_READ
|
||||
DBSELFTEST_COMPILE_OPTS = -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_ENABLE_RTREE -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_FTS5
|
||||
ST_COMPILE_OPTS = -DSQLITE_THREADSAFE=0
|
||||
|
||||
# Standard options to testfixture.
|
||||
@@ -1687,7 +1688,7 @@ dbhash.exe: $(TOP)\tool\dbhash.c $(SQLITE3C) $(SQLITE3H)
|
||||
$(LTLINK) $(NO_WARN) $(TOP)\tool\dbhash.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
||||
|
||||
scrub.exe: $(TOP)\ext\misc\scrub.c $(SQLITE3C) $(SQLITE3H)
|
||||
$(LTLINK) $(NO_WARN) $(TOP)\ext\misc\scrub.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
||||
$(LTLINK) $(NO_WARN) -DSCRUB_STANDALONE=1 $(TOP)\ext\misc\scrub.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
||||
|
||||
srcck1.exe: $(TOP)\tool\srcck1.c
|
||||
$(BCC) $(NO_WARN) -Fe$@ $(TOP)\tool\srcck1.c
|
||||
@@ -1707,6 +1708,9 @@ fuzzcheck.exe: $(FUZZCHECK_SRC) $(SQLITE3C) $(SQLITE3H)
|
||||
ossshell.exe: $(OSSSHELL_SRC) $(SQLITE3C) $(SQLITE3H)
|
||||
$(LTLINK) $(NO_WARN) $(FUZZCHECK_COMPILE_OPTS) $(OSSSHELL_SRC) $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
||||
|
||||
sessionfuzz.exe: zlib $(TOP)\test\sessionfuzz.c $(SQLITE3C) $(SQLITE3H)
|
||||
$(LTLINK) $(NO_WARN) -I$(ZLIBINCDIR) $(TOP)\test\sessionfuzz.c /link $(LDFLAGS) $(LTLINKOPTS) /LIBPATH:$(ZLIBLIBDIR) $(ZLIBLIB)
|
||||
|
||||
mptester.exe: $(TOP)\mptest\mptest.c $(SQLITE3C) $(SQLITE3H)
|
||||
$(LTLINK) $(NO_WARN) $(MPTESTER_COMPILE_OPTS) $(TOP)\mptest\mptest.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
||||
|
||||
@@ -1908,6 +1912,9 @@ mem3.lo: $(TOP)\src\mem3.c $(HDR)
|
||||
mem5.lo: $(TOP)\src\mem5.c $(HDR)
|
||||
$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\mem5.c
|
||||
|
||||
memdb.lo: $(TOP)\src\memdb.c $(HDR)
|
||||
$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\memdb.c
|
||||
|
||||
memjournal.lo: $(TOP)\src\memjournal.c $(HDR)
|
||||
$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\memjournal.c
|
||||
|
||||
@@ -2084,7 +2091,7 @@ keywordhash.h: $(TOP)\tool\mkkeywordhash.c mkkeywordhash.exe
|
||||
# Source files that go into making shell.c
|
||||
SHELL_SRC = \
|
||||
$(TOP)\src\shell.c.in \
|
||||
$(TOP)\ext\misc\appendvfs.c \
|
||||
$(TOP)\ext\misc\appendvfs.c \
|
||||
$(TOP)\ext\misc\shathree.c \
|
||||
$(TOP)\ext\misc\fileio.c \
|
||||
$(TOP)\ext\misc\completion.c \
|
||||
@@ -2251,6 +2258,7 @@ TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_SERIES_CONSTRAINT_VERIFY=1
|
||||
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_DEFAULT_PAGE_SIZE=1024
|
||||
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_ENABLE_STMTVTAB
|
||||
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_ENABLE_DBPAGE_VTAB
|
||||
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_ENABLE_JSON1
|
||||
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) $(TEST_CCONV_OPTS)
|
||||
|
||||
TESTFIXTURE_SRC0 = $(TESTEXT) $(TESTSRC2)
|
||||
@@ -2364,11 +2372,11 @@ sqlite3_checker.exe: sqlite3_checker.c $(LIBRESOBJS)
|
||||
$(LTLINK) $(NO_WARN) -DBUILD_sqlite -I$(TCLINCDIR) sqlite3_checker.c \
|
||||
/link $(LDFLAGS) $(LTLINKOPTS) $(TCLLIBPATHS) $(LTLIBPATHS) $(LIBRESOBJS) $(TCLLIBS) $(LTLIBS) $(TLIBS)
|
||||
|
||||
dbdump.exe: $(TOP)\ext\misc\dbdump.c $(SQLITE3C) $(SQLITE3H)
|
||||
dbdump.exe: $(TOP)\ext\misc\dbdump.c $(SQLITE3C) $(SQLITE3H) $(LIBRESOBJS)
|
||||
$(LTLINK) $(NO_WARN) -DDBDUMP_STANDALONE $(TOP)\ext\misc\dbdump.c $(SQLITE3C) \
|
||||
/link $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LTLIBS)
|
||||
|
||||
testloadext.lo: $(TOP)\src\test_loadext.c
|
||||
testloadext.lo: $(TOP)\src\test_loadext.c $(SQLITE3H)
|
||||
$(LTCOMPILE) $(NO_WARN) -c $(TOP)\src\test_loadext.c
|
||||
|
||||
testloadext.dll: testloadext.lo
|
||||
@@ -2421,9 +2429,6 @@ kvtest.exe: $(TOP)\test\kvtest.c $(SQLITE3C) $(SQLITE3H)
|
||||
$(LTLINK) $(NO_WARN) $(KV_COMPILE_OPTS) \
|
||||
$(TOP)\test\kvtest.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
||||
|
||||
dbselftest.exe: $(TOP)\test\dbselftest.c $(SQLITE3C) $(SQLITE3H)
|
||||
$(LTLINK) $(NO_WARN) $(DBSELFTEST_COMPILE_OPTS) $(TOP)\test\dbselftest.c $(SQLITE3C)
|
||||
|
||||
rbu.exe: $(TOP)\ext\rbu\rbu.c $(TOP)\ext\rbu\sqlite3rbu.c $(SQLITE3C) $(SQLITE3H)
|
||||
$(LTLINK) $(NO_WARN) -DSQLITE_ENABLE_RBU \
|
||||
$(TOP)\ext\rbu\rbu.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
||||
@@ -2463,7 +2468,10 @@ clean:
|
||||
del /Q sqlite3_analyzer.exe sqlite3_analyzer.c 2>NUL
|
||||
del /Q sqlite-*-output.vsix 2>NUL
|
||||
del /Q fuzzershell.exe fuzzcheck.exe sqldiff.exe dbhash.exe 2>NUL
|
||||
del /Q sqltclsh.exe 2>NUL
|
||||
del /Q sqltclsh.* 2>NUL
|
||||
del /Q dbfuzz.exe sessionfuzz.exe 2>NUL
|
||||
del /Q kvtest.exe ossshell.exe scrub.exe 2>NUL
|
||||
del /Q showshm.exe sqlite3_checker.* sqlite3_expert.exe 2>NUL
|
||||
del /Q fts5.* fts5parse.* 2>NUL
|
||||
del /Q lsm.h lsm1.c 2>NUL
|
||||
# <</mark>>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<h1 align="center">SQLite Source Repository</h1>
|
||||
|
||||
This repository contains the complete source code for the SQLite database
|
||||
engine. Some test scripts are also include. However, many other test scripts
|
||||
engine. Some test scripts are also included. However, many other test scripts
|
||||
and most of the documentation are managed separately.
|
||||
|
||||
If you are reading this on a Git mirror someplace, you are doing it wrong.
|
||||
@@ -14,15 +14,17 @@ SQLite sources are managed using the
|
||||
[Fossil](https://www.fossil-scm.org/), a distributed version control system
|
||||
that was specifically designed to support SQLite development.
|
||||
If you do not want to use Fossil, you can download tarballs or ZIP
|
||||
archives as follows:
|
||||
archives or [SQLite archives](https://sqlite.org/cli.html#sqlar) as follows:
|
||||
|
||||
* Lastest trunk check-in:
|
||||
<https://www.sqlite.org/src/tarball/sqlite.tar.gz> or
|
||||
<https://www.sqlite.org/src/zip/sqlite.zip>.
|
||||
* Lastest trunk check-in as
|
||||
[Tarball](https://www.sqlite.org/src/tarball/sqlite.tar.gz),
|
||||
[ZIP-archive](https://www.sqlite.org/src/zip/sqlite.zip), or
|
||||
[SQLite-archive](https://www.sqlite.org/src/sqlar/sqlite.sqlar).
|
||||
|
||||
* Latest release:
|
||||
<https://www.sqlite.org/src/tarball/sqlite.tar.gz?r=release> or
|
||||
<https://www.sqlite.org/src/zip/sqlite.zip?r=release>.
|
||||
* Latest release as
|
||||
[Tarball](https://www.sqlite.org/src/tarball/sqlite.tar.gz?r=release),
|
||||
[ZIP-archive](https://www.sqlite.org/src/zip/sqlite.zip?r=release), or
|
||||
[SQLite-archive](https://www.sqlite.org/src/sqlar/sqlite.sqlar?r=release).
|
||||
|
||||
* For other check-ins, substitute an appropriate branch name or
|
||||
tag or hash prefix for "release" in the URLs of the previous
|
||||
@@ -104,7 +106,6 @@ recommended.
|
||||
SQLite does not require [Tcl](http://www.tcl.tk/) to run, but a Tcl installation
|
||||
is required by the makefiles (including those for MSVC). SQLite contains
|
||||
a lot of generated code and Tcl is used to do much of that code generation.
|
||||
The makefiles also require AWK.
|
||||
|
||||
## Source Code Tour
|
||||
|
||||
@@ -116,7 +117,7 @@ The **src/** also contains the "shell.c" file
|
||||
which is the main program for the "sqlite3.exe"
|
||||
[command-line shell](https://sqlite.org/cli.html) and
|
||||
the "tclsqlite.c" file which implements the
|
||||
[TCL bindings](https://sqlite.org/tclsqlite.html) for SQLite.
|
||||
[Tcl bindings](https://sqlite.org/tclsqlite.html) for SQLite.
|
||||
(Historical note: SQLite began as a Tcl
|
||||
extension and only later escaped to the wild as an independent library.)
|
||||
|
||||
@@ -163,14 +164,14 @@ template for generating its parser.
|
||||
|
||||
Lemon also generates the **parse.h** header file, at the same time it
|
||||
generates parse.c. But the parse.h header file is
|
||||
modified further (to add additional symbols) using the ./addopcodes.awk
|
||||
AWK script.
|
||||
modified further (to add additional symbols) using the ./addopcodes.tcl
|
||||
Tcl script.
|
||||
|
||||
The **opcodes.h** header file contains macros that define the numbers
|
||||
corresponding to opcodes in the "VDBE" virtual machine. The opcodes.h
|
||||
file is generated by the scanning the src/vdbe.c source file. The
|
||||
AWK script at ./mkopcodeh.awk does this scan and generates opcodes.h.
|
||||
A second AWK script, ./mkopcodec.awk, then scans opcodes.h to generate
|
||||
Tcl script at ./mkopcodeh.tcl does this scan and generates opcodes.h.
|
||||
A second Tcl script, ./mkopcodec.tcl, then scans opcodes.h to generate
|
||||
the **opcodes.c** source file, which contains a reverse mapping from
|
||||
opcode-number to opcode-name that is used for EXPLAIN output.
|
||||
|
||||
@@ -280,7 +281,7 @@ Key files:
|
||||
|
||||
* **test*.c** - Files in the src/ folder that begin with "test" go into
|
||||
building the "testfixture.exe" program. The testfixture.exe program is
|
||||
an enhanced TCL shell. The testfixture.exe program runs scripts in the
|
||||
an enhanced Tcl shell. The testfixture.exe program runs scripts in the
|
||||
test/ folder to validate the core SQLite code. The testfixture program
|
||||
(and some other test programs too) is build and run when you type
|
||||
"make test".
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
AM_CFLAGS = @THREADSAFE_FLAGS@ @DYNAMIC_EXTENSION_FLAGS@ @FTS5_FLAGS@ @JSON1_FLAGS@ @SESSION_FLAGS@ -DSQLITE_ENABLE_FTS3 -DSQLITE_ENABLE_RTREE
|
||||
AM_CFLAGS = @THREADSAFE_FLAGS@ @DYNAMIC_EXTENSION_FLAGS@ @FTS5_FLAGS@ @JSON1_FLAGS@ @ZLIB_FLAGS@ @SESSION_FLAGS@ -DSQLITE_ENABLE_FTS3 -DSQLITE_ENABLE_RTREE
|
||||
|
||||
lib_LTLIBRARIES = libsqlite3.la
|
||||
libsqlite3_la_SOURCES = sqlite3.c
|
||||
@@ -10,7 +10,7 @@ sqlite3_SOURCES = shell.c sqlite3.h
|
||||
EXTRA_sqlite3_SOURCES = sqlite3.c
|
||||
sqlite3_LDADD = @EXTRA_SHELL_OBJ@ @READLINE_LIBS@
|
||||
sqlite3_DEPENDENCIES = @EXTRA_SHELL_OBJ@
|
||||
sqlite3_CFLAGS = $(AM_CFLAGS) -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_ENABLE_STMTVTAB -DSQLITE_ENABLE_DBSTAT_VTAB
|
||||
sqlite3_CFLAGS = $(AM_CFLAGS) -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_ENABLE_STMTVTAB -DSQLITE_ENABLE_DBSTAT_VTAB $(SHELL_CFLAGS)
|
||||
|
||||
include_HEADERS = sqlite3.h sqlite3ext.h
|
||||
|
||||
|
||||
@@ -931,6 +931,7 @@ LIBRESOBJS =
|
||||
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_STMTVTAB
|
||||
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_ENABLE_DBSTAT_VTAB
|
||||
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_OFFSET_SQL_FUNC -DSQLITE_INTROSPECTION_PRAGMAS
|
||||
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_RTREE
|
||||
!ENDIF
|
||||
|
||||
|
||||
|
||||
@@ -164,6 +164,13 @@ AC_SUBST(EXTRA_SHELL_OBJ)
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
AC_CHECK_FUNCS(posix_fallocate)
|
||||
AC_CHECK_HEADERS(zlib.h,[
|
||||
AC_SEARCH_LIBS(deflate,z,[ZLIB_FLAGS="-DSQLITE_HAVE_ZLIB"])
|
||||
])
|
||||
AC_SUBST(ZLIB_FLAGS)
|
||||
|
||||
AC_SEARCH_LIBS(system,,,[SHELL_CFLAGS="-DSQLITE_NOHAVE_SYSTEM"])
|
||||
AC_SUBST(SHELL_CFLAGS)
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# UPDATE: Maybe it's better if users just set CFLAGS before invoking
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#! /bin/sh
|
||||
# Guess values for system-dependent variables and create Makefiles.
|
||||
# Generated by GNU Autoconf 2.69 for sqlite 3.22.0.
|
||||
# Generated by GNU Autoconf 2.69 for sqlite 3.23.0.
|
||||
#
|
||||
#
|
||||
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
|
||||
@@ -726,8 +726,8 @@ MAKEFLAGS=
|
||||
# Identity of this package.
|
||||
PACKAGE_NAME='sqlite'
|
||||
PACKAGE_TARNAME='sqlite'
|
||||
PACKAGE_VERSION='3.22.0'
|
||||
PACKAGE_STRING='sqlite 3.22.0'
|
||||
PACKAGE_VERSION='3.23.0'
|
||||
PACKAGE_STRING='sqlite 3.23.0'
|
||||
PACKAGE_BUGREPORT=''
|
||||
PACKAGE_URL=''
|
||||
|
||||
@@ -1465,7 +1465,7 @@ if test "$ac_init_help" = "long"; then
|
||||
# Omit some internal or obsolete options to make the list less imposing.
|
||||
# This message is too long to be a string in the A/UX 3.1 sh.
|
||||
cat <<_ACEOF
|
||||
\`configure' configures sqlite 3.22.0 to adapt to many kinds of systems.
|
||||
\`configure' configures sqlite 3.23.0 to adapt to many kinds of systems.
|
||||
|
||||
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||
|
||||
@@ -1530,7 +1530,7 @@ fi
|
||||
|
||||
if test -n "$ac_init_help"; then
|
||||
case $ac_init_help in
|
||||
short | recursive ) echo "Configuration of sqlite 3.22.0:";;
|
||||
short | recursive ) echo "Configuration of sqlite 3.23.0:";;
|
||||
esac
|
||||
cat <<\_ACEOF
|
||||
|
||||
@@ -1655,7 +1655,7 @@ fi
|
||||
test -n "$ac_init_help" && exit $ac_status
|
||||
if $ac_init_version; then
|
||||
cat <<\_ACEOF
|
||||
sqlite configure 3.22.0
|
||||
sqlite configure 3.23.0
|
||||
generated by GNU Autoconf 2.69
|
||||
|
||||
Copyright (C) 2012 Free Software Foundation, Inc.
|
||||
@@ -2074,7 +2074,7 @@ cat >config.log <<_ACEOF
|
||||
This file contains any messages produced by compilers while
|
||||
running configure, to aid debugging if configure makes a mistake.
|
||||
|
||||
It was created by sqlite $as_me 3.22.0, which was
|
||||
It was created by sqlite $as_me 3.23.0, which was
|
||||
generated by GNU Autoconf 2.69. Invocation command line was
|
||||
|
||||
$ $0 $@
|
||||
@@ -12242,7 +12242,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
|
||||
# report actual input values of CONFIG_FILES etc. instead of their
|
||||
# values after options handling.
|
||||
ac_log="
|
||||
This file was extended by sqlite $as_me 3.22.0, which was
|
||||
This file was extended by sqlite $as_me 3.23.0, which was
|
||||
generated by GNU Autoconf 2.69. Invocation command line was
|
||||
|
||||
CONFIG_FILES = $CONFIG_FILES
|
||||
@@ -12308,7 +12308,7 @@ _ACEOF
|
||||
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
||||
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
|
||||
ac_cs_version="\\
|
||||
sqlite config.status 3.22.0
|
||||
sqlite config.status 3.23.0
|
||||
configured by $0, generated by GNU Autoconf 2.69,
|
||||
with options \\"\$ac_cs_config\\"
|
||||
|
||||
|
||||
+2
-1
@@ -93,8 +93,9 @@ int main(int argc, char **argv){
|
||||
}else{
|
||||
for(i=1; i<(argc-1); i++){
|
||||
char *zArg = argv[i];
|
||||
int nArg;
|
||||
if( zArg[0]=='-' && zArg[1]=='-' && zArg[2]!=0 ) zArg++;
|
||||
int nArg = (int)strlen(zArg);
|
||||
nArg = (int)strlen(zArg);
|
||||
if( nArg>=2 && 0==sqlite3_strnicmp(zArg, "-file", nArg) ){
|
||||
if( ++i==(argc-1) ) option_requires_argument("-file");
|
||||
rc = readSqlFromFile(p, argv[i], &zErr);
|
||||
|
||||
@@ -507,6 +507,10 @@ static int expertUpdate(
|
||||
sqlite3_value **azData,
|
||||
sqlite_int64 *pRowid
|
||||
){
|
||||
(void)pVtab;
|
||||
(void)nData;
|
||||
(void)azData;
|
||||
(void)pRowid;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
@@ -516,6 +520,7 @@ static int expertUpdate(
|
||||
static int expertOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
|
||||
int rc = SQLITE_OK;
|
||||
ExpertCsr *pCsr;
|
||||
(void)pVTab;
|
||||
pCsr = idxMalloc(&rc, sizeof(ExpertCsr));
|
||||
*ppCursor = (sqlite3_vtab_cursor*)pCsr;
|
||||
return rc;
|
||||
@@ -565,6 +570,7 @@ static int expertNext(sqlite3_vtab_cursor *cur){
|
||||
** Virtual table module xRowid method.
|
||||
*/
|
||||
static int expertRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
|
||||
(void)cur;
|
||||
*pRowid = 0;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
@@ -595,6 +601,10 @@ static int expertFilter(
|
||||
sqlite3expert *pExpert = pVtab->pExpert;
|
||||
int rc;
|
||||
|
||||
(void)idxNum;
|
||||
(void)idxStr;
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
rc = sqlite3_finalize(pCsr->pData);
|
||||
pCsr->pData = 0;
|
||||
if( rc==SQLITE_OK ){
|
||||
@@ -1005,7 +1015,7 @@ static int idxCreateFromWhere(
|
||||
** Create candidate indexes in database [dbm] based on the data in
|
||||
** linked-list pScan.
|
||||
*/
|
||||
static int idxCreateCandidates(sqlite3expert *p, char **pzErr){
|
||||
static int idxCreateCandidates(sqlite3expert *p){
|
||||
int rc = SQLITE_OK;
|
||||
IdxScan *pIter;
|
||||
|
||||
@@ -1168,6 +1178,8 @@ static int idxAuthCallback(
|
||||
const char *zTrigger
|
||||
){
|
||||
int rc = SQLITE_OK;
|
||||
(void)z4;
|
||||
(void)zTrigger;
|
||||
if( eOp==SQLITE_INSERT || eOp==SQLITE_UPDATE || eOp==SQLITE_DELETE ){
|
||||
if( sqlite3_stricmp(zDb, "main")==0 ){
|
||||
sqlite3expert *p = (sqlite3expert*)pCtx;
|
||||
@@ -1370,6 +1382,7 @@ static void idxSampleFunc(
|
||||
struct IdxSampleCtx *p = (struct IdxSampleCtx*)sqlite3_user_data(pCtx);
|
||||
int bRet;
|
||||
|
||||
(void)argv;
|
||||
assert( argc==0 );
|
||||
if( p->nRow==0.0 ){
|
||||
bRet = 1;
|
||||
@@ -1855,7 +1868,7 @@ int sqlite3_expert_analyze(sqlite3expert *p, char **pzErr){
|
||||
|
||||
/* Create candidate indexes within the in-memory database file */
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = idxCreateCandidates(p, pzErr);
|
||||
rc = idxCreateCandidates(p);
|
||||
}
|
||||
|
||||
/* Generate the stat1 data */
|
||||
|
||||
@@ -1908,6 +1908,7 @@ static int fts3WriteSegment(
|
||||
sqlite3_bind_blob(pStmt, 2, z, n, SQLITE_STATIC);
|
||||
sqlite3_step(pStmt);
|
||||
rc = sqlite3_reset(pStmt);
|
||||
sqlite3_bind_null(pStmt, 2);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
@@ -1964,6 +1965,7 @@ static int fts3WriteSegdir(
|
||||
sqlite3_bind_blob(pStmt, 6, zRoot, nRoot, SQLITE_STATIC);
|
||||
sqlite3_step(pStmt);
|
||||
rc = sqlite3_reset(pStmt);
|
||||
sqlite3_bind_null(pStmt, 6);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
@@ -3443,6 +3445,7 @@ static void fts3UpdateDocTotals(
|
||||
sqlite3_bind_blob(pStmt, 2, pBlob, nBlob, SQLITE_STATIC);
|
||||
sqlite3_step(pStmt);
|
||||
*pRC = sqlite3_reset(pStmt);
|
||||
sqlite3_bind_null(pStmt, 2);
|
||||
sqlite3_free(a);
|
||||
}
|
||||
|
||||
@@ -4631,6 +4634,7 @@ static int fts3TruncateSegment(
|
||||
sqlite3_bind_int(pChomp, 4, iIdx);
|
||||
sqlite3_step(pChomp);
|
||||
rc = sqlite3_reset(pChomp);
|
||||
sqlite3_bind_null(pChomp, 2);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4710,6 +4714,7 @@ static int fts3IncrmergeHintStore(Fts3Table *p, Blob *pHint){
|
||||
sqlite3_bind_blob(pReplace, 2, pHint->a, pHint->n, SQLITE_STATIC);
|
||||
sqlite3_step(pReplace);
|
||||
rc = sqlite3_reset(pReplace);
|
||||
sqlite3_bind_null(pReplace, 2);
|
||||
}
|
||||
|
||||
return rc;
|
||||
@@ -5524,7 +5529,6 @@ int sqlite3Fts3UpdateMethod(
|
||||
){
|
||||
Fts3Table *p = (Fts3Table *)pVtab;
|
||||
int rc = SQLITE_OK; /* Return Code */
|
||||
int isRemove = 0; /* True for an UPDATE or DELETE */
|
||||
u32 *aSzIns = 0; /* Sizes of inserted documents */
|
||||
u32 *aSzDel = 0; /* Sizes of deleted documents */
|
||||
int nChng = 0; /* Net change in number of documents */
|
||||
@@ -5622,7 +5626,6 @@ int sqlite3Fts3UpdateMethod(
|
||||
if( sqlite3_value_type(apVal[0])!=SQLITE_NULL ){
|
||||
assert( sqlite3_value_type(apVal[0])==SQLITE_INTEGER );
|
||||
rc = fts3DeleteByRowid(p, apVal[0], &nChng, aSzDel);
|
||||
isRemove = 1;
|
||||
}
|
||||
|
||||
/* If this is an INSERT or UPDATE operation, insert the new record. */
|
||||
@@ -5634,7 +5637,7 @@ int sqlite3Fts3UpdateMethod(
|
||||
rc = FTS_CORRUPT_VTAB;
|
||||
}
|
||||
}
|
||||
if( rc==SQLITE_OK && (!isRemove || *pRowid!=p->iPrevDocid ) ){
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = fts3PendingTermsDocid(p, 0, iLangid, *pRowid);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
|
||||
@@ -1676,7 +1676,7 @@ Fts5ExprPhrase *sqlite3Fts5ParseTerm(
|
||||
** no token characters at all. (e.g ... MATCH '""'). */
|
||||
sCtx.pPhrase = sqlite3Fts5MallocZero(&pParse->rc, sizeof(Fts5ExprPhrase));
|
||||
}else if( sCtx.pPhrase->nTerm ){
|
||||
sCtx.pPhrase->aTerm[sCtx.pPhrase->nTerm-1].bPrefix = bPrefix;
|
||||
sCtx.pPhrase->aTerm[sCtx.pPhrase->nTerm-1].bPrefix = (u8)bPrefix;
|
||||
}
|
||||
pParse->apPhrase[pParse->nPhrase-1] = sCtx.pPhrase;
|
||||
}
|
||||
|
||||
@@ -758,6 +758,7 @@ static void fts5DataWrite(Fts5Index *p, i64 iRowid, const u8 *pData, int nData){
|
||||
sqlite3_bind_blob(p->pWriter, 2, pData, nData, SQLITE_STATIC);
|
||||
sqlite3_step(p->pWriter);
|
||||
p->rc = sqlite3_reset(p->pWriter);
|
||||
sqlite3_bind_null(p->pWriter, 2);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2386,6 +2387,7 @@ static void fts5SegIterSeekInit(
|
||||
bDlidx = (val & 0x0001);
|
||||
}
|
||||
p->rc = sqlite3_reset(pIdxSelect);
|
||||
sqlite3_bind_null(pIdxSelect, 2);
|
||||
|
||||
if( iPg<pSeg->pgnoFirst ){
|
||||
iPg = pSeg->pgnoFirst;
|
||||
@@ -3598,6 +3600,7 @@ static int fts5AllocateSegid(Fts5Index *p, Fts5Structure *pStruct){
|
||||
sqlite3_bind_blob(pIdxSelect, 2, aBlob, 2, SQLITE_STATIC);
|
||||
assert( sqlite3_step(pIdxSelect)!=SQLITE_ROW );
|
||||
p->rc = sqlite3_reset(pIdxSelect);
|
||||
sqlite3_bind_null(pIdxSelect, 2);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -3724,6 +3727,7 @@ static void fts5WriteFlushBtree(Fts5Index *p, Fts5SegWriter *pWriter){
|
||||
sqlite3_bind_int64(p->pIdxWriter, 3, bFlag + ((i64)pWriter->iBtPage<<1));
|
||||
sqlite3_step(p->pIdxWriter);
|
||||
p->rc = sqlite3_reset(p->pIdxWriter);
|
||||
sqlite3_bind_null(p->pIdxWriter, 2);
|
||||
}
|
||||
pWriter->iBtPage = 0;
|
||||
}
|
||||
|
||||
@@ -458,6 +458,7 @@ static int fts5StorageInsertDocsize(
|
||||
sqlite3_bind_blob(pReplace, 2, pBuf->p, pBuf->n, SQLITE_STATIC);
|
||||
sqlite3_step(pReplace);
|
||||
rc = sqlite3_reset(pReplace);
|
||||
sqlite3_bind_null(pReplace, 2);
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
@@ -1118,6 +1119,7 @@ int sqlite3Fts5StorageConfigValue(
|
||||
}
|
||||
sqlite3_step(pReplace);
|
||||
rc = sqlite3_reset(pReplace);
|
||||
sqlite3_bind_null(pReplace, 1);
|
||||
}
|
||||
if( rc==SQLITE_OK && pVal ){
|
||||
int iNew = p->pConfig->iCookie + 1;
|
||||
|
||||
+2
-2
@@ -482,7 +482,7 @@ static int SQLITE_TCLAPI xF5tApi(
|
||||
|
||||
rc = p->pApi->xPhraseFirstColumn(p->pFts, iPhrase, &iter, &iCol);
|
||||
if( rc!=SQLITE_OK ){
|
||||
Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
|
||||
Tcl_SetResult(interp, (char*)sqlite3ErrName(rc), TCL_VOLATILE);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
for( ; iCol>=0; p->pApi->xPhraseNextColumn(p->pFts, &iter, &iCol)){
|
||||
@@ -924,7 +924,7 @@ static int SQLITE_TCLAPI f5tTokenizerReturn(
|
||||
|
||||
rc = p->xToken(p->pCtx, tflags, zToken, nToken, iStart, iEnd);
|
||||
Tcl_SetResult(interp, (char*)sqlite3ErrName(rc), TCL_VOLATILE);
|
||||
return TCL_OK;
|
||||
return rc==SQLITE_OK ? TCL_OK : TCL_ERROR;
|
||||
|
||||
usage:
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "?-colocated? TEXT START END");
|
||||
|
||||
@@ -593,5 +593,5 @@ do_execsql_test 22.1 {
|
||||
|
||||
}
|
||||
|
||||
|
||||
expand_all_sql db
|
||||
finish_test
|
||||
|
||||
@@ -253,7 +253,7 @@ do_faultsim_test 5.2 -faults oom* -prep {
|
||||
SELECT rowid, mit(matchinfo(t1, 'x')) FROM t1 WHERE t1 MATCH 'a AND c'
|
||||
}
|
||||
} -test {
|
||||
faultsim_test_result [list 0 $::res]
|
||||
faultsim_test_result [list 0 $::res] {1 {SQL logic error}}
|
||||
}
|
||||
|
||||
do_faultsim_test 5.3 -faults oom* -prep {
|
||||
@@ -264,7 +264,7 @@ do_faultsim_test 5.3 -faults oom* -prep {
|
||||
SELECT count(*) FROM t1 WHERE t1 MATCH 'd AND e AND f'
|
||||
}
|
||||
} -test {
|
||||
faultsim_test_result {0 29}
|
||||
faultsim_test_result {0 29} {1 {SQL logic error}}
|
||||
}
|
||||
|
||||
do_faultsim_test 5.4 -faults oom* -prep {
|
||||
@@ -275,7 +275,7 @@ do_faultsim_test 5.4 -faults oom* -prep {
|
||||
SELECT count(*) FROM t1 WHERE t1 MATCH 'x + e'
|
||||
}
|
||||
} -test {
|
||||
faultsim_test_result {0 1}
|
||||
faultsim_test_result {0 1} {1 {SQL logic error}}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
@@ -24,6 +24,8 @@ ifcapable !fts5 {
|
||||
|
||||
foreach_detail_mode $testprefix {
|
||||
|
||||
if {"%DETAIL%" != "none"} continue
|
||||
|
||||
fts5_aux_test_functions db
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
@@ -98,14 +100,16 @@ do_faultsim_test 4.1 -faults oom-t* -body {
|
||||
execsql { SELECT rowid, fts5_test_collist(t4) FROM t4('2') }
|
||||
} -test {
|
||||
faultsim_test_result \
|
||||
{0 {1 {0.0 0.1 0.2} 2 {0.0 0.1 0.2} 3 {0.0 0.1 0.2}}} {1 SQLITE_NOMEM}
|
||||
{0 {1 {0.0 0.1 0.2} 2 {0.0 0.1 0.2} 3 {0.0 0.1 0.2}}} \
|
||||
{1 SQLITE_NOMEM} {1 SQLITE_ERROR} {1 {SQL logic error}}
|
||||
}
|
||||
|
||||
do_faultsim_test 4.2 -faults oom-t* -body {
|
||||
execsql { SELECT rowid, fts5_test_collist(t4) FROM t4('a5 OR b5 OR c5') }
|
||||
} -test {
|
||||
faultsim_test_result \
|
||||
{0 {4 {0.0 0.1 0.2} 5 {1.0 1.1 1.2} 6 {2.0 2.1 2.2}}} {1 SQLITE_NOMEM}
|
||||
{0 {4 {0.0 0.1 0.2} 5 {1.0 1.1 1.2} 6 {2.0 2.1 2.2}}} \
|
||||
{1 SQLITE_NOMEM} {1 SQLITE_ERROR} {1 {SQL logic error}}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -548,6 +548,8 @@ int sqlite3_appendvfs_init(
|
||||
int rc = SQLITE_OK;
|
||||
sqlite3_vfs *pOrig;
|
||||
SQLITE_EXTENSION_INIT2(pApi);
|
||||
(void)pzErrMsg;
|
||||
(void)db;
|
||||
pOrig = sqlite3_vfs_find(0);
|
||||
apnd_vfs.iVersion = pOrig->iVersion;
|
||||
apnd_vfs.pAppData = pOrig;
|
||||
|
||||
@@ -339,7 +339,8 @@ static int binfoColumn(
|
||||
sqlite3 *db = sqlite3_context_db_handle(ctx);
|
||||
int rc = binfoCompute(db, pgno, pCsr);
|
||||
if( rc ){
|
||||
return rc;
|
||||
pCursor->pVtab->zErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(db));
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
}
|
||||
switch( i ){
|
||||
|
||||
+14
-15
@@ -293,7 +293,6 @@ static char **tableColumnList(DState *p, const char *zTab){
|
||||
** ordinary column in the table. Verify that azRowid[j] is a valid
|
||||
** name for the rowid before adding it to azCol[0]. WITHOUT ROWID
|
||||
** tables will fail this last check */
|
||||
int rc;
|
||||
rc = sqlite3_table_column_metadata(p->db,0,zTab,azRowid[j],0,0,0,0,0);
|
||||
if( rc==SQLITE_OK ) azCol[0] = azRowid[j];
|
||||
break;
|
||||
@@ -455,12 +454,12 @@ static int dump_callback(void *pArg, int nArg, char **azArg, char **azCol){
|
||||
if( strcmp(zType, "table")==0 ){
|
||||
DText sSelect;
|
||||
DText sTable;
|
||||
char **azCol;
|
||||
char **azTCol;
|
||||
int i;
|
||||
int nCol;
|
||||
|
||||
azCol = tableColumnList(p, zTable);
|
||||
if( azCol==0 ) return 0;
|
||||
azTCol = tableColumnList(p, zTable);
|
||||
if( azTCol==0 ) return 0;
|
||||
|
||||
initText(&sTable);
|
||||
appendText(&sTable, "INSERT INTO ", 0);
|
||||
@@ -473,12 +472,12 @@ static int dump_callback(void *pArg, int nArg, char **azArg, char **azCol){
|
||||
** In other words: "INSERT INTO tab(rowid,a,b,c,...) VALUES(...)"
|
||||
** instead of the usual "INSERT INTO tab VALUES(...)".
|
||||
*/
|
||||
if( azCol[0] ){
|
||||
if( azTCol[0] ){
|
||||
appendText(&sTable, "(", 0);
|
||||
appendText(&sTable, azCol[0], 0);
|
||||
for(i=1; azCol[i]; i++){
|
||||
appendText(&sTable, azTCol[0], 0);
|
||||
for(i=1; azTCol[i]; i++){
|
||||
appendText(&sTable, ",", 0);
|
||||
appendText(&sTable, azCol[i], quoteChar(azCol[i]));
|
||||
appendText(&sTable, azTCol[i], quoteChar(azTCol[i]));
|
||||
}
|
||||
appendText(&sTable, ")", 0);
|
||||
}
|
||||
@@ -487,19 +486,19 @@ static int dump_callback(void *pArg, int nArg, char **azArg, char **azCol){
|
||||
/* Build an appropriate SELECT statement */
|
||||
initText(&sSelect);
|
||||
appendText(&sSelect, "SELECT ", 0);
|
||||
if( azCol[0] ){
|
||||
appendText(&sSelect, azCol[0], 0);
|
||||
if( azTCol[0] ){
|
||||
appendText(&sSelect, azTCol[0], 0);
|
||||
appendText(&sSelect, ",", 0);
|
||||
}
|
||||
for(i=1; azCol[i]; i++){
|
||||
appendText(&sSelect, azCol[i], quoteChar(azCol[i]));
|
||||
if( azCol[i+1] ){
|
||||
for(i=1; azTCol[i]; i++){
|
||||
appendText(&sSelect, azTCol[i], quoteChar(azTCol[i]));
|
||||
if( azTCol[i+1] ){
|
||||
appendText(&sSelect, ",", 0);
|
||||
}
|
||||
}
|
||||
nCol = i;
|
||||
if( azCol[0]==0 ) nCol--;
|
||||
freeColumnList(azCol);
|
||||
if( azTCol[0]==0 ) nCol--;
|
||||
freeColumnList(azTCol);
|
||||
appendText(&sSelect, " FROM ", 0);
|
||||
appendText(&sSelect, zTable, quoteChar(zTable));
|
||||
|
||||
|
||||
+121
-11
@@ -86,6 +86,7 @@ SQLITE_EXTENSION_INIT1
|
||||
# include <unistd.h>
|
||||
# include <dirent.h>
|
||||
# include <utime.h>
|
||||
# include <sys/time.h>
|
||||
#else
|
||||
# include "windows.h"
|
||||
# include <io.h>
|
||||
@@ -158,6 +159,97 @@ static void ctxErrorMsg(sqlite3_context *ctx, const char *zFmt, ...){
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
#if defined(_WIN32)
|
||||
/*
|
||||
** This function is designed to convert a Win32 FILETIME structure into the
|
||||
** number of seconds since the Unix Epoch (1970-01-01 00:00:00 UTC).
|
||||
*/
|
||||
static sqlite3_uint64 fileTimeToUnixTime(
|
||||
LPFILETIME pFileTime
|
||||
){
|
||||
SYSTEMTIME epochSystemTime;
|
||||
ULARGE_INTEGER epochIntervals;
|
||||
FILETIME epochFileTime;
|
||||
ULARGE_INTEGER fileIntervals;
|
||||
|
||||
memset(&epochSystemTime, 0, sizeof(SYSTEMTIME));
|
||||
epochSystemTime.wYear = 1970;
|
||||
epochSystemTime.wMonth = 1;
|
||||
epochSystemTime.wDay = 1;
|
||||
SystemTimeToFileTime(&epochSystemTime, &epochFileTime);
|
||||
epochIntervals.LowPart = epochFileTime.dwLowDateTime;
|
||||
epochIntervals.HighPart = epochFileTime.dwHighDateTime;
|
||||
|
||||
fileIntervals.LowPart = pFileTime->dwLowDateTime;
|
||||
fileIntervals.HighPart = pFileTime->dwHighDateTime;
|
||||
|
||||
return (fileIntervals.QuadPart - epochIntervals.QuadPart) / 10000000;
|
||||
}
|
||||
|
||||
/*
|
||||
** This function attempts to normalize the time values found in the stat()
|
||||
** buffer to UTC. This is necessary on Win32, where the runtime library
|
||||
** appears to return these values as local times.
|
||||
*/
|
||||
static void statTimesToUtc(
|
||||
const char *zPath,
|
||||
struct stat *pStatBuf
|
||||
){
|
||||
HANDLE hFindFile;
|
||||
WIN32_FIND_DATAW fd;
|
||||
LPWSTR zUnicodeName;
|
||||
extern LPWSTR sqlite3_win32_utf8_to_unicode(const char*);
|
||||
zUnicodeName = sqlite3_win32_utf8_to_unicode(zPath);
|
||||
if( zUnicodeName ){
|
||||
memset(&fd, 0, sizeof(WIN32_FIND_DATA));
|
||||
hFindFile = FindFirstFileW(zUnicodeName, &fd);
|
||||
if( hFindFile!=NULL ){
|
||||
pStatBuf->st_ctime = (time_t)fileTimeToUnixTime(&fd.ftCreationTime);
|
||||
pStatBuf->st_atime = (time_t)fileTimeToUnixTime(&fd.ftLastAccessTime);
|
||||
pStatBuf->st_mtime = (time_t)fileTimeToUnixTime(&fd.ftLastWriteTime);
|
||||
FindClose(hFindFile);
|
||||
}
|
||||
sqlite3_free(zUnicodeName);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** This function is used in place of stat(). On Windows, special handling
|
||||
** is required in order for the included time to be returned as UTC. On all
|
||||
** other systems, this function simply calls stat().
|
||||
*/
|
||||
static int fileStat(
|
||||
const char *zPath,
|
||||
struct stat *pStatBuf
|
||||
){
|
||||
#if defined(_WIN32)
|
||||
int rc = stat(zPath, pStatBuf);
|
||||
if( rc==0 ) statTimesToUtc(zPath, pStatBuf);
|
||||
return rc;
|
||||
#else
|
||||
return stat(zPath, pStatBuf);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
** This function is used in place of lstat(). On Windows, special handling
|
||||
** is required in order for the included time to be returned as UTC. On all
|
||||
** other systems, this function simply calls lstat().
|
||||
*/
|
||||
static int fileLinkStat(
|
||||
const char *zPath,
|
||||
struct stat *pStatBuf
|
||||
){
|
||||
#if defined(_WIN32)
|
||||
int rc = lstat(zPath, pStatBuf);
|
||||
if( rc==0 ) statTimesToUtc(zPath, pStatBuf);
|
||||
return rc;
|
||||
#else
|
||||
return lstat(zPath, pStatBuf);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
** Argument zFile is the name of a file that will be created and/or written
|
||||
** by SQL function writefile(). This function ensures that the directory
|
||||
@@ -189,7 +281,7 @@ static int makeDirectory(
|
||||
if( i==nCopy ) break;
|
||||
zCopy[i] = '\0';
|
||||
|
||||
rc2 = stat(zCopy, &sStat);
|
||||
rc2 = fileStat(zCopy, &sStat);
|
||||
if( rc2!=0 ){
|
||||
if( mkdir(zCopy, mode & 0777) ) rc = SQLITE_ERROR;
|
||||
}else{
|
||||
@@ -231,7 +323,7 @@ static int writeFile(
|
||||
** to do so using chmod(), it is not an error. */
|
||||
struct stat sStat;
|
||||
if( errno!=EEXIST
|
||||
|| 0!=stat(zFile, &sStat)
|
||||
|| 0!=fileStat(zFile, &sStat)
|
||||
|| !S_ISDIR(sStat.st_mode)
|
||||
|| ((sStat.st_mode&0777)!=(mode&0777) && 0!=chmod(zFile, mode&0777))
|
||||
){
|
||||
@@ -269,15 +361,23 @@ static int writeFile(
|
||||
SYSTEMTIME currentTime;
|
||||
LONGLONG intervals;
|
||||
HANDLE hFile;
|
||||
LPWSTR zUnicodeName;
|
||||
extern LPWSTR sqlite3_win32_utf8_to_unicode(const char*);
|
||||
|
||||
GetSystemTime(¤tTime);
|
||||
SystemTimeToFileTime(¤tTime, &lastAccess);
|
||||
intervals = Int32x32To64(mtime, 10000000) + 116444736000000000;
|
||||
lastWrite.dwLowDateTime = (DWORD)intervals;
|
||||
lastWrite.dwHighDateTime = intervals >> 32;
|
||||
hFile = CreateFile(
|
||||
zFile, FILE_WRITE_ATTRIBUTES, 0, NULL, OPEN_EXISTING,
|
||||
zUnicodeName = sqlite3_win32_utf8_to_unicode(zFile);
|
||||
if( zUnicodeName==0 ){
|
||||
return 1;
|
||||
}
|
||||
hFile = CreateFileW(
|
||||
zUnicodeName, FILE_WRITE_ATTRIBUTES, 0, NULL, OPEN_EXISTING,
|
||||
FILE_FLAG_BACKUP_SEMANTICS, NULL
|
||||
);
|
||||
sqlite3_free(zUnicodeName);
|
||||
if( hFile!=INVALID_HANDLE_VALUE ){
|
||||
BOOL bResult = SetFileTime(hFile, NULL, &lastAccess, &lastWrite);
|
||||
CloseHandle(hFile);
|
||||
@@ -285,7 +385,7 @@ static int writeFile(
|
||||
}else{
|
||||
return 1;
|
||||
}
|
||||
#elif defined(AT_FDCWD)
|
||||
#elif defined(AT_FDCWD) && 0 /* utimensat() is not universally available */
|
||||
/* Recent unix */
|
||||
struct timespec times[2];
|
||||
times[0].tv_nsec = times[1].tv_nsec = 0;
|
||||
@@ -371,6 +471,7 @@ static void lsModeFunc(
|
||||
int i;
|
||||
int iMode = sqlite3_value_int(argv[0]);
|
||||
char z[16];
|
||||
(void)argc;
|
||||
if( S_ISLNK(iMode) ){
|
||||
z[0] = 'l';
|
||||
}else if( S_ISREG(iMode) ){
|
||||
@@ -436,7 +537,10 @@ static int fsdirConnect(
|
||||
){
|
||||
fsdir_tab *pNew = 0;
|
||||
int rc;
|
||||
|
||||
(void)pAux;
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
(void)pzErr;
|
||||
rc = sqlite3_declare_vtab(db, "CREATE TABLE x" FSDIR_SCHEMA);
|
||||
if( rc==SQLITE_OK ){
|
||||
pNew = (fsdir_tab*)sqlite3_malloc( sizeof(*pNew) );
|
||||
@@ -460,6 +564,7 @@ static int fsdirDisconnect(sqlite3_vtab *pVtab){
|
||||
*/
|
||||
static int fsdirOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
|
||||
fsdir_cursor *pCur;
|
||||
(void)p;
|
||||
pCur = sqlite3_malloc( sizeof(*pCur) );
|
||||
if( pCur==0 ) return SQLITE_NOMEM;
|
||||
memset(pCur, 0, sizeof(*pCur));
|
||||
@@ -480,10 +585,12 @@ static void fsdirResetCursor(fsdir_cursor *pCur){
|
||||
sqlite3_free(pLvl->zDir);
|
||||
}
|
||||
sqlite3_free(pCur->zPath);
|
||||
sqlite3_free(pCur->aLvl);
|
||||
pCur->aLvl = 0;
|
||||
pCur->zPath = 0;
|
||||
pCur->zBase = 0;
|
||||
pCur->nBase = 0;
|
||||
pCur->nLvl = 0;
|
||||
pCur->iLvl = -1;
|
||||
pCur->iRowid = 1;
|
||||
}
|
||||
@@ -495,7 +602,6 @@ static int fsdirClose(sqlite3_vtab_cursor *cur){
|
||||
fsdir_cursor *pCur = (fsdir_cursor*)cur;
|
||||
|
||||
fsdirResetCursor(pCur);
|
||||
sqlite3_free(pCur->aLvl);
|
||||
sqlite3_free(pCur);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
@@ -556,7 +662,7 @@ static int fsdirNext(sqlite3_vtab_cursor *cur){
|
||||
sqlite3_free(pCur->zPath);
|
||||
pCur->zPath = sqlite3_mprintf("%s/%s", pLvl->zDir, pEntry->d_name);
|
||||
if( pCur->zPath==0 ) return SQLITE_NOMEM;
|
||||
if( lstat(pCur->zPath, &pCur->sStat) ){
|
||||
if( fileLinkStat(pCur->zPath, &pCur->sStat) ){
|
||||
fsdirSetErrmsg(pCur, "cannot stat file: %s", pCur->zPath);
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
@@ -663,7 +769,7 @@ static int fsdirFilter(
|
||||
){
|
||||
const char *zDir = 0;
|
||||
fsdir_cursor *pCur = (fsdir_cursor*)cur;
|
||||
|
||||
(void)idxStr;
|
||||
fsdirResetCursor(pCur);
|
||||
|
||||
if( idxNum==0 ){
|
||||
@@ -690,7 +796,7 @@ static int fsdirFilter(
|
||||
if( pCur->zPath==0 ){
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
if( lstat(pCur->zPath, &pCur->sStat) ){
|
||||
if( fileLinkStat(pCur->zPath, &pCur->sStat) ){
|
||||
fsdirSetErrmsg(pCur, "cannot stat file: %s", pCur->zPath);
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
@@ -721,8 +827,9 @@ static int fsdirBestIndex(
|
||||
int i; /* Loop over constraints */
|
||||
int idx4 = -1;
|
||||
int idx5 = -1;
|
||||
|
||||
const struct sqlite3_index_constraint *pConstraint;
|
||||
|
||||
(void)tab;
|
||||
pConstraint = pIdxInfo->aConstraint;
|
||||
for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
|
||||
if( pConstraint->usable==0 ) continue;
|
||||
@@ -776,6 +883,9 @@ static int fsdirRegister(sqlite3 *db){
|
||||
0, /* xRollback */
|
||||
0, /* xFindMethod */
|
||||
0, /* xRename */
|
||||
0, /* xSavepoint */
|
||||
0, /* xRelease */
|
||||
0 /* xRollbackTo */
|
||||
};
|
||||
|
||||
int rc = sqlite3_create_module(db, "fsdir", &fsdirModule, 0);
|
||||
|
||||
@@ -0,0 +1,707 @@
|
||||
/*
|
||||
** 2018-01-08
|
||||
**
|
||||
** 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 code to implement the sqlite3_normalize() function.
|
||||
**
|
||||
** char *sqlite3_normalize(const char *zSql);
|
||||
**
|
||||
** This function takes an SQL string as input and returns a "normalized"
|
||||
** version of that string in memory obtained from sqlite3_malloc64(). The
|
||||
** caller is responsible for ensuring that the returned memory is freed.
|
||||
**
|
||||
** If a memory allocation error occurs, this routine returns NULL.
|
||||
**
|
||||
** The normalization consists of the following transformations:
|
||||
**
|
||||
** (1) Convert every literal (string, blob literal, numeric constant,
|
||||
** or "NULL" constant) into a ?
|
||||
**
|
||||
** (2) Remove all superfluous whitespace, including comments. Change
|
||||
** all required whitespace to a single space character.
|
||||
**
|
||||
** (3) Lowercase all ASCII characters.
|
||||
**
|
||||
** (4) If an IN or NOT IN operator is followed by a list of 1 or more
|
||||
** values, convert that list into "(?,?,?)".
|
||||
**
|
||||
** The purpose of normalization is two-fold:
|
||||
**
|
||||
** (1) Sanitize queries by removing potentially private or sensitive
|
||||
** information contained in literals.
|
||||
**
|
||||
** (2) Identify structurally identical queries by comparing their
|
||||
** normalized forms.
|
||||
**
|
||||
** Command-Line Utility
|
||||
** --------------------
|
||||
**
|
||||
** This file also contains code for a command-line utility that converts
|
||||
** SQL queries in text files into their normalized forms. To build the
|
||||
** command-line program, compile this file with -DSQLITE_NORMALIZE_CLI
|
||||
** and link it against the SQLite library.
|
||||
*/
|
||||
#include <sqlite3.h>
|
||||
#include <string.h>
|
||||
|
||||
/*
|
||||
** Implementation note:
|
||||
**
|
||||
** Much of the tokenizer logic is copied out of the tokenize.c source file
|
||||
** of SQLite. That logic could be simplified for this particular application,
|
||||
** but that would impose a risk of introducing subtle errors. It is best to
|
||||
** keep the code as close to the original as possible.
|
||||
**
|
||||
** The tokenize code is in sync with the SQLite core as of 2018-01-08.
|
||||
** Any future changes to the core tokenizer might require corresponding
|
||||
** adjustments to the tokenizer logic in this module.
|
||||
*/
|
||||
|
||||
|
||||
/* Character classes for tokenizing
|
||||
**
|
||||
** In the sqlite3GetToken() function, a switch() on aiClass[c] is implemented
|
||||
** using a lookup table, whereas a switch() directly on c uses a binary search.
|
||||
** The lookup table is much faster. To maximize speed, and to ensure that
|
||||
** a lookup table is used, all of the classes need to be small integers and
|
||||
** all of them need to be used within the switch.
|
||||
*/
|
||||
#define CC_X 0 /* The letter 'x', or start of BLOB literal */
|
||||
#define CC_KYWD 1 /* Alphabetics or '_'. Usable in a keyword */
|
||||
#define CC_ID 2 /* unicode characters usable in IDs */
|
||||
#define CC_DIGIT 3 /* Digits */
|
||||
#define CC_DOLLAR 4 /* '$' */
|
||||
#define CC_VARALPHA 5 /* '@', '#', ':'. Alphabetic SQL variables */
|
||||
#define CC_VARNUM 6 /* '?'. Numeric SQL variables */
|
||||
#define CC_SPACE 7 /* Space characters */
|
||||
#define CC_QUOTE 8 /* '"', '\'', or '`'. String literals, quoted ids */
|
||||
#define CC_QUOTE2 9 /* '['. [...] style quoted ids */
|
||||
#define CC_PIPE 10 /* '|'. Bitwise OR or concatenate */
|
||||
#define CC_MINUS 11 /* '-'. Minus or SQL-style comment */
|
||||
#define CC_LT 12 /* '<'. Part of < or <= or <> */
|
||||
#define CC_GT 13 /* '>'. Part of > or >= */
|
||||
#define CC_EQ 14 /* '='. Part of = or == */
|
||||
#define CC_BANG 15 /* '!'. Part of != */
|
||||
#define CC_SLASH 16 /* '/'. / or c-style comment */
|
||||
#define CC_LP 17 /* '(' */
|
||||
#define CC_RP 18 /* ')' */
|
||||
#define CC_SEMI 19 /* ';' */
|
||||
#define CC_PLUS 20 /* '+' */
|
||||
#define CC_STAR 21 /* '*' */
|
||||
#define CC_PERCENT 22 /* '%' */
|
||||
#define CC_COMMA 23 /* ',' */
|
||||
#define CC_AND 24 /* '&' */
|
||||
#define CC_TILDA 25 /* '~' */
|
||||
#define CC_DOT 26 /* '.' */
|
||||
#define CC_ILLEGAL 27 /* Illegal character */
|
||||
|
||||
static const unsigned char aiClass[] = {
|
||||
/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xa xb xc xd xe xf */
|
||||
/* 0x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 7, 7, 27, 7, 7, 27, 27,
|
||||
/* 1x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
|
||||
/* 2x */ 7, 15, 8, 5, 4, 22, 24, 8, 17, 18, 21, 20, 23, 11, 26, 16,
|
||||
/* 3x */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 19, 12, 14, 13, 6,
|
||||
/* 4x */ 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
/* 5x */ 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 9, 27, 27, 27, 1,
|
||||
/* 6x */ 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
/* 7x */ 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 27, 10, 27, 25, 27,
|
||||
/* 8x */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
/* 9x */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
/* Ax */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
/* Bx */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
/* Cx */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
/* Dx */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
/* Ex */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
/* Fx */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2
|
||||
};
|
||||
|
||||
/* An array to map all upper-case characters into their corresponding
|
||||
** lower-case character.
|
||||
**
|
||||
** SQLite only considers US-ASCII (or EBCDIC) characters. We do not
|
||||
** handle case conversions for the UTF character set since the tables
|
||||
** involved are nearly as big or bigger than SQLite itself.
|
||||
*/
|
||||
static const unsigned char sqlite3UpperToLower[] = {
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
|
||||
18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
|
||||
36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
|
||||
54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 97, 98, 99,100,101,102,103,
|
||||
104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,
|
||||
122, 91, 92, 93, 94, 95, 96, 97, 98, 99,100,101,102,103,104,105,106,107,
|
||||
108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,
|
||||
126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
|
||||
144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,
|
||||
162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,
|
||||
180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,
|
||||
198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,
|
||||
216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,
|
||||
234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,
|
||||
252,253,254,255
|
||||
};
|
||||
|
||||
/*
|
||||
** The following 256 byte lookup table is used to support SQLites built-in
|
||||
** equivalents to the following standard library functions:
|
||||
**
|
||||
** isspace() 0x01
|
||||
** isalpha() 0x02
|
||||
** isdigit() 0x04
|
||||
** isalnum() 0x06
|
||||
** isxdigit() 0x08
|
||||
** toupper() 0x20
|
||||
** SQLite identifier character 0x40
|
||||
** Quote character 0x80
|
||||
**
|
||||
** Bit 0x20 is set if the mapped character requires translation to upper
|
||||
** case. i.e. if the character is a lower-case ASCII character.
|
||||
** If x is a lower-case ASCII character, then its upper-case equivalent
|
||||
** is (x - 0x20). Therefore toupper() can be implemented as:
|
||||
**
|
||||
** (x & ~(map[x]&0x20))
|
||||
**
|
||||
** The equivalent of tolower() is implemented using the sqlite3UpperToLower[]
|
||||
** array. tolower() is used more often than toupper() by SQLite.
|
||||
**
|
||||
** Bit 0x40 is set if the character is non-alphanumeric and can be used in an
|
||||
** SQLite identifier. Identifiers are alphanumerics, "_", "$", and any
|
||||
** non-ASCII UTF character. Hence the test for whether or not a character is
|
||||
** part of an identifier is 0x46.
|
||||
*/
|
||||
static const unsigned char sqlite3CtypeMap[256] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 00..07 ........ */
|
||||
0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, /* 08..0f ........ */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 10..17 ........ */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 18..1f ........ */
|
||||
0x01, 0x00, 0x80, 0x00, 0x40, 0x00, 0x00, 0x80, /* 20..27 !"#$%&' */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 28..2f ()*+,-./ */
|
||||
0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, /* 30..37 01234567 */
|
||||
0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 38..3f 89:;<=>? */
|
||||
|
||||
0x00, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x02, /* 40..47 @ABCDEFG */
|
||||
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, /* 48..4f HIJKLMNO */
|
||||
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, /* 50..57 PQRSTUVW */
|
||||
0x02, 0x02, 0x02, 0x80, 0x00, 0x00, 0x00, 0x40, /* 58..5f XYZ[\]^_ */
|
||||
0x80, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x22, /* 60..67 `abcdefg */
|
||||
0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, /* 68..6f hijklmno */
|
||||
0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, /* 70..77 pqrstuvw */
|
||||
0x22, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, /* 78..7f xyz{|}~. */
|
||||
|
||||
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* 80..87 ........ */
|
||||
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* 88..8f ........ */
|
||||
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* 90..97 ........ */
|
||||
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* 98..9f ........ */
|
||||
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* a0..a7 ........ */
|
||||
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* a8..af ........ */
|
||||
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* b0..b7 ........ */
|
||||
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* b8..bf ........ */
|
||||
|
||||
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* c0..c7 ........ */
|
||||
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* c8..cf ........ */
|
||||
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* d0..d7 ........ */
|
||||
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* d8..df ........ */
|
||||
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* e0..e7 ........ */
|
||||
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* e8..ef ........ */
|
||||
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* f0..f7 ........ */
|
||||
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40 /* f8..ff ........ */
|
||||
};
|
||||
#define sqlite3Toupper(x) ((x)&~(sqlite3CtypeMap[(unsigned char)(x)]&0x20))
|
||||
#define sqlite3Isspace(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x01)
|
||||
#define sqlite3Isalnum(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x06)
|
||||
#define sqlite3Isalpha(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x02)
|
||||
#define sqlite3Isdigit(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x04)
|
||||
#define sqlite3Isxdigit(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x08)
|
||||
#define sqlite3Tolower(x) (sqlite3UpperToLower[(unsigned char)(x)])
|
||||
#define sqlite3Isquote(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x80)
|
||||
|
||||
|
||||
/*
|
||||
** If X is a character that can be used in an identifier then
|
||||
** IdChar(X) will be true. Otherwise it is false.
|
||||
**
|
||||
** For ASCII, any character with the high-order bit set is
|
||||
** allowed in an identifier. For 7-bit characters,
|
||||
** sqlite3IsIdChar[X] must be 1.
|
||||
**
|
||||
** For EBCDIC, the rules are more complex but have the same
|
||||
** end result.
|
||||
**
|
||||
** Ticket #1066. the SQL standard does not allow '$' in the
|
||||
** middle of identifiers. But many SQL implementations do.
|
||||
** SQLite will allow '$' in identifiers for compatibility.
|
||||
** But the feature is undocumented.
|
||||
*/
|
||||
#define IdChar(C) ((sqlite3CtypeMap[(unsigned char)C]&0x46)!=0)
|
||||
|
||||
/*
|
||||
** Ignore testcase() macros
|
||||
*/
|
||||
#define testcase(X)
|
||||
|
||||
/*
|
||||
** Token values
|
||||
*/
|
||||
#define TK_SPACE 0
|
||||
#define TK_NAME 1
|
||||
#define TK_LITERAL 2
|
||||
#define TK_PUNCT 3
|
||||
#define TK_ERROR 4
|
||||
|
||||
#define TK_MINUS TK_PUNCT
|
||||
#define TK_LP TK_PUNCT
|
||||
#define TK_RP TK_PUNCT
|
||||
#define TK_SEMI TK_PUNCT
|
||||
#define TK_PLUS TK_PUNCT
|
||||
#define TK_STAR TK_PUNCT
|
||||
#define TK_SLASH TK_PUNCT
|
||||
#define TK_REM TK_PUNCT
|
||||
#define TK_EQ TK_PUNCT
|
||||
#define TK_LE TK_PUNCT
|
||||
#define TK_NE TK_PUNCT
|
||||
#define TK_LSHIFT TK_PUNCT
|
||||
#define TK_LT TK_PUNCT
|
||||
#define TK_GE TK_PUNCT
|
||||
#define TK_RSHIFT TK_PUNCT
|
||||
#define TK_GT TK_PUNCT
|
||||
#define TK_GE TK_PUNCT
|
||||
#define TK_BITOR TK_PUNCT
|
||||
#define TK_CONCAT TK_PUNCT
|
||||
#define TK_COMMA TK_PUNCT
|
||||
#define TK_BITAND TK_PUNCT
|
||||
#define TK_BITNOT TK_PUNCT
|
||||
#define TK_STRING TK_LITERAL
|
||||
#define TK_ID TK_NAME
|
||||
#define TK_ILLEGAL TK_ERROR
|
||||
#define TK_DOT TK_PUNCT
|
||||
#define TK_INTEGER TK_LITERAL
|
||||
#define TK_FLOAT TK_LITERAL
|
||||
#define TK_VARIABLE TK_LITERAL
|
||||
#define TK_BLOB TK_LITERAL
|
||||
|
||||
/*
|
||||
** Return the length (in bytes) of the token that begins at z[0].
|
||||
** Store the token type in *tokenType before returning.
|
||||
*/
|
||||
static int sqlite3GetToken(const unsigned char *z, int *tokenType){
|
||||
int i, c;
|
||||
switch( aiClass[*z] ){ /* Switch on the character-class of the first byte
|
||||
** of the token. See the comment on the CC_ defines
|
||||
** above. */
|
||||
case CC_SPACE: {
|
||||
for(i=1; sqlite3Isspace(z[i]); i++){}
|
||||
*tokenType = TK_SPACE;
|
||||
return i;
|
||||
}
|
||||
case CC_MINUS: {
|
||||
if( z[1]=='-' ){
|
||||
for(i=2; (c=z[i])!=0 && c!='\n'; i++){}
|
||||
*tokenType = TK_SPACE;
|
||||
return i;
|
||||
}
|
||||
*tokenType = TK_MINUS;
|
||||
return 1;
|
||||
}
|
||||
case CC_LP: {
|
||||
*tokenType = TK_LP;
|
||||
return 1;
|
||||
}
|
||||
case CC_RP: {
|
||||
*tokenType = TK_RP;
|
||||
return 1;
|
||||
}
|
||||
case CC_SEMI: {
|
||||
*tokenType = TK_SEMI;
|
||||
return 1;
|
||||
}
|
||||
case CC_PLUS: {
|
||||
*tokenType = TK_PLUS;
|
||||
return 1;
|
||||
}
|
||||
case CC_STAR: {
|
||||
*tokenType = TK_STAR;
|
||||
return 1;
|
||||
}
|
||||
case CC_SLASH: {
|
||||
if( z[1]!='*' || z[2]==0 ){
|
||||
*tokenType = TK_SLASH;
|
||||
return 1;
|
||||
}
|
||||
for(i=3, c=z[2]; (c!='*' || z[i]!='/') && (c=z[i])!=0; i++){}
|
||||
if( c ) i++;
|
||||
*tokenType = TK_SPACE;
|
||||
return i;
|
||||
}
|
||||
case CC_PERCENT: {
|
||||
*tokenType = TK_REM;
|
||||
return 1;
|
||||
}
|
||||
case CC_EQ: {
|
||||
*tokenType = TK_EQ;
|
||||
return 1 + (z[1]=='=');
|
||||
}
|
||||
case CC_LT: {
|
||||
if( (c=z[1])=='=' ){
|
||||
*tokenType = TK_LE;
|
||||
return 2;
|
||||
}else if( c=='>' ){
|
||||
*tokenType = TK_NE;
|
||||
return 2;
|
||||
}else if( c=='<' ){
|
||||
*tokenType = TK_LSHIFT;
|
||||
return 2;
|
||||
}else{
|
||||
*tokenType = TK_LT;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
case CC_GT: {
|
||||
if( (c=z[1])=='=' ){
|
||||
*tokenType = TK_GE;
|
||||
return 2;
|
||||
}else if( c=='>' ){
|
||||
*tokenType = TK_RSHIFT;
|
||||
return 2;
|
||||
}else{
|
||||
*tokenType = TK_GT;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
case CC_BANG: {
|
||||
if( z[1]!='=' ){
|
||||
*tokenType = TK_ILLEGAL;
|
||||
return 1;
|
||||
}else{
|
||||
*tokenType = TK_NE;
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
case CC_PIPE: {
|
||||
if( z[1]!='|' ){
|
||||
*tokenType = TK_BITOR;
|
||||
return 1;
|
||||
}else{
|
||||
*tokenType = TK_CONCAT;
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
case CC_COMMA: {
|
||||
*tokenType = TK_COMMA;
|
||||
return 1;
|
||||
}
|
||||
case CC_AND: {
|
||||
*tokenType = TK_BITAND;
|
||||
return 1;
|
||||
}
|
||||
case CC_TILDA: {
|
||||
*tokenType = TK_BITNOT;
|
||||
return 1;
|
||||
}
|
||||
case CC_QUOTE: {
|
||||
int delim = z[0];
|
||||
testcase( delim=='`' );
|
||||
testcase( delim=='\'' );
|
||||
testcase( delim=='"' );
|
||||
for(i=1; (c=z[i])!=0; i++){
|
||||
if( c==delim ){
|
||||
if( z[i+1]==delim ){
|
||||
i++;
|
||||
}else{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if( c=='\'' ){
|
||||
*tokenType = TK_STRING;
|
||||
return i+1;
|
||||
}else if( c!=0 ){
|
||||
*tokenType = TK_ID;
|
||||
return i+1;
|
||||
}else{
|
||||
*tokenType = TK_ILLEGAL;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
case CC_DOT: {
|
||||
if( !sqlite3Isdigit(z[1]) ){
|
||||
*tokenType = TK_DOT;
|
||||
return 1;
|
||||
}
|
||||
/* If the next character is a digit, this is a floating point
|
||||
** number that begins with ".". Fall thru into the next case */
|
||||
}
|
||||
case CC_DIGIT: {
|
||||
*tokenType = TK_INTEGER;
|
||||
if( z[0]=='0' && (z[1]=='x' || z[1]=='X') && sqlite3Isxdigit(z[2]) ){
|
||||
for(i=3; sqlite3Isxdigit(z[i]); i++){}
|
||||
return i;
|
||||
}
|
||||
for(i=0; sqlite3Isdigit(z[i]); i++){}
|
||||
if( z[i]=='.' ){
|
||||
i++;
|
||||
while( sqlite3Isdigit(z[i]) ){ i++; }
|
||||
*tokenType = TK_FLOAT;
|
||||
}
|
||||
if( (z[i]=='e' || z[i]=='E') &&
|
||||
( sqlite3Isdigit(z[i+1])
|
||||
|| ((z[i+1]=='+' || z[i+1]=='-') && sqlite3Isdigit(z[i+2]))
|
||||
)
|
||||
){
|
||||
i += 2;
|
||||
while( sqlite3Isdigit(z[i]) ){ i++; }
|
||||
*tokenType = TK_FLOAT;
|
||||
}
|
||||
while( IdChar(z[i]) ){
|
||||
*tokenType = TK_ILLEGAL;
|
||||
i++;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
case CC_QUOTE2: {
|
||||
for(i=1, c=z[0]; c!=']' && (c=z[i])!=0; i++){}
|
||||
*tokenType = c==']' ? TK_ID : TK_ILLEGAL;
|
||||
return i;
|
||||
}
|
||||
case CC_VARNUM: {
|
||||
*tokenType = TK_VARIABLE;
|
||||
for(i=1; sqlite3Isdigit(z[i]); i++){}
|
||||
return i;
|
||||
}
|
||||
case CC_DOLLAR:
|
||||
case CC_VARALPHA: {
|
||||
int n = 0;
|
||||
testcase( z[0]=='$' ); testcase( z[0]=='@' );
|
||||
testcase( z[0]==':' ); testcase( z[0]=='#' );
|
||||
*tokenType = TK_VARIABLE;
|
||||
for(i=1; (c=z[i])!=0; i++){
|
||||
if( IdChar(c) ){
|
||||
n++;
|
||||
}else if( c=='(' && n>0 ){
|
||||
do{
|
||||
i++;
|
||||
}while( (c=z[i])!=0 && !sqlite3Isspace(c) && c!=')' );
|
||||
if( c==')' ){
|
||||
i++;
|
||||
}else{
|
||||
*tokenType = TK_ILLEGAL;
|
||||
}
|
||||
break;
|
||||
}else if( c==':' && z[i+1]==':' ){
|
||||
i++;
|
||||
}else{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( n==0 ) *tokenType = TK_ILLEGAL;
|
||||
return i;
|
||||
}
|
||||
case CC_KYWD: {
|
||||
for(i=1; aiClass[z[i]]<=CC_KYWD; i++){}
|
||||
if( IdChar(z[i]) ){
|
||||
/* This token started out using characters that can appear in keywords,
|
||||
** but z[i] is a character not allowed within keywords, so this must
|
||||
** be an identifier instead */
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
*tokenType = TK_ID;
|
||||
return i;
|
||||
}
|
||||
case CC_X: {
|
||||
testcase( z[0]=='x' ); testcase( z[0]=='X' );
|
||||
if( z[1]=='\'' ){
|
||||
*tokenType = TK_BLOB;
|
||||
for(i=2; sqlite3Isxdigit(z[i]); i++){}
|
||||
if( z[i]!='\'' || i%2 ){
|
||||
*tokenType = TK_ILLEGAL;
|
||||
while( z[i] && z[i]!='\'' ){ i++; }
|
||||
}
|
||||
if( z[i] ) i++;
|
||||
return i;
|
||||
}
|
||||
/* If it is not a BLOB literal, then it must be an ID, since no
|
||||
** SQL keywords start with the letter 'x'. Fall through */
|
||||
}
|
||||
case CC_ID: {
|
||||
i = 1;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
*tokenType = TK_ILLEGAL;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
while( IdChar(z[i]) ){ i++; }
|
||||
*tokenType = TK_ID;
|
||||
return i;
|
||||
}
|
||||
|
||||
char *sqlite3_normalize(const char *zSql){
|
||||
char *z; /* The output string */
|
||||
sqlite3_int64 nZ; /* Size of the output string in bytes */
|
||||
sqlite3_int64 nSql; /* Size of the input string in bytes */
|
||||
int i; /* Next character to read from zSql[] */
|
||||
int j; /* Next slot to fill in on z[] */
|
||||
int tokenType; /* Type of the next token */
|
||||
int n; /* Size of the next token */
|
||||
int k; /* Loop counter */
|
||||
|
||||
nSql = strlen(zSql);
|
||||
nZ = nSql;
|
||||
z = sqlite3_malloc64( nZ+2 );
|
||||
if( z==0 ) return 0;
|
||||
for(i=j=0; zSql[i]; i += n){
|
||||
n = sqlite3GetToken((unsigned char*)zSql+i, &tokenType);
|
||||
switch( tokenType ){
|
||||
case TK_SPACE: {
|
||||
break;
|
||||
}
|
||||
case TK_ERROR: {
|
||||
sqlite3_free(z);
|
||||
return 0;
|
||||
}
|
||||
case TK_LITERAL: {
|
||||
z[j++] = '?';
|
||||
break;
|
||||
}
|
||||
case TK_PUNCT:
|
||||
case TK_NAME: {
|
||||
if( n==4 && sqlite3_strnicmp(zSql+i,"NULL",4)==0 ){
|
||||
if( (j>=3 && strncmp(z+j-2,"is",2)==0 && !IdChar(z[j-3]))
|
||||
|| (j>=4 && strncmp(z+j-3,"not",3)==0 && !IdChar(z[j-4]))
|
||||
){
|
||||
/* NULL is a keyword in this case, not a literal value */
|
||||
}else{
|
||||
/* Here the NULL is a literal value */
|
||||
z[j++] = '?';
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( j>0 && IdChar(z[j-1]) && IdChar(zSql[i]) ) z[j++] = ' ';
|
||||
for(k=0; k<n; k++){
|
||||
z[j++] = sqlite3Tolower(zSql[i+k]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
while( j>0 && z[j-1]==' ' ){ j--; }
|
||||
if( i>0 && z[j-1]!=';' ){ z[j++] = ';'; }
|
||||
z[j] = 0;
|
||||
|
||||
/* Make a second pass converting "in(...)" where the "..." is not a
|
||||
** SELECT statement into "in(?,?,?)" */
|
||||
for(i=0; i<j; i=n){
|
||||
char *zIn = strstr(z+i, "in(");
|
||||
int nParen;
|
||||
if( zIn==0 ) break;
|
||||
n = (int)(zIn-z)+3; /* Index of first char past "in(" */
|
||||
if( n && IdChar(zIn[-1]) ) continue;
|
||||
if( strncmp(zIn, "in(select",9)==0 && !IdChar(zIn[9]) ) continue;
|
||||
if( strncmp(zIn, "in(with",7)==0 && !IdChar(zIn[7]) ) continue;
|
||||
for(nParen=1, k=0; z[n+k]; k++){
|
||||
if( z[n+k]=='(' ) nParen++;
|
||||
if( z[n+k]==')' ){
|
||||
nParen--;
|
||||
if( nParen==0 ) break;
|
||||
}
|
||||
}
|
||||
/* k is the number of bytes in the "..." within "in(...)" */
|
||||
if( k<5 ){
|
||||
z = sqlite3_realloc64(z, j+(5-k)+1);
|
||||
if( z==0 ) return 0;
|
||||
memmove(z+n+5, z+n+k, j-(n+k));
|
||||
}else if( k>5 ){
|
||||
memmove(z+n+5, z+n+k, j-(n+k));
|
||||
}
|
||||
j = j-k+5;
|
||||
z[j] = 0;
|
||||
memcpy(z+n, "?,?,?", 5);
|
||||
}
|
||||
return z;
|
||||
}
|
||||
|
||||
/*
|
||||
** For testing purposes, or to build a stand-alone SQL normalizer program,
|
||||
** compile this one source file with the -DSQLITE_NORMALIZE_CLI and link
|
||||
** it against any SQLite library. The resulting command-line program will
|
||||
** run sqlite3_normalize() over the text of all files named on the command-
|
||||
** line and show the result on standard output.
|
||||
*/
|
||||
#ifdef SQLITE_NORMALIZE_CLI
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/*
|
||||
** Break zIn up into separate SQL statements and run sqlite3_normalize()
|
||||
** on each one. Print the result of each run.
|
||||
*/
|
||||
static void normalizeFile(char *zIn){
|
||||
int i;
|
||||
if( zIn==0 ) return;
|
||||
for(i=0; zIn[i]; i++){
|
||||
char cSaved;
|
||||
if( zIn[i]!=';' ) continue;
|
||||
cSaved = zIn[i+1];
|
||||
zIn[i+1] = 0;
|
||||
if( sqlite3_complete(zIn) ){
|
||||
char *zOut = sqlite3_normalize(zIn);
|
||||
if( zOut ){
|
||||
printf("%s\n", zOut);
|
||||
sqlite3_free(zOut);
|
||||
}else{
|
||||
fprintf(stderr, "ERROR: %s\n", zIn);
|
||||
}
|
||||
zIn[i+1] = cSaved;
|
||||
zIn += i+1;
|
||||
i = -1;
|
||||
}else{
|
||||
zIn[i+1] = cSaved;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** The main routine for "sql_normalize". Read files named on the
|
||||
** command-line and run the text of each through sqlite3_normalize().
|
||||
*/
|
||||
int main(int argc, char **argv){
|
||||
int i;
|
||||
FILE *in;
|
||||
char *zBuf = 0;
|
||||
sqlite3_int64 sz, got;
|
||||
|
||||
for(i=1; i<argc; i++){
|
||||
in = fopen(argv[i], "rb");
|
||||
if( in==0 ){
|
||||
fprintf(stderr, "cannot open \"%s\"\n", argv[i]);
|
||||
continue;
|
||||
}
|
||||
fseek(in, 0, SEEK_END);
|
||||
sz = ftell(in);
|
||||
rewind(in);
|
||||
zBuf = sqlite3_realloc64(zBuf, sz+1);
|
||||
if( zBuf==0 ){
|
||||
fprintf(stderr, "failed to malloc for %lld bytes\n", sz);
|
||||
exit(1);
|
||||
}
|
||||
got = fread(zBuf, 1, sz, in);
|
||||
fclose(in);
|
||||
if( got!=sz ){
|
||||
fprintf(stderr, "only able to read %lld of %lld bytes from \"%s\"\n",
|
||||
got, sz, argv[i]);
|
||||
}else{
|
||||
zBuf[got] = 0;
|
||||
normalizeFile(zBuf);
|
||||
}
|
||||
}
|
||||
sqlite3_free(zBuf);
|
||||
}
|
||||
#endif /* SQLITE_NORMALIZE_CLI */
|
||||
+2
-2
@@ -131,7 +131,7 @@ static void scrubBackupWrite(ScrubState *p, int pgno, const u8 *pData){
|
||||
scrubBackupErr(p, "write failed for page %d", pgno);
|
||||
p->rcErr = SQLITE_IOERR;
|
||||
}
|
||||
if( pgno>p->iLastPage ) p->iLastPage = pgno;
|
||||
if( (u32)pgno>p->iLastPage ) p->iLastPage = pgno;
|
||||
}
|
||||
|
||||
/* Prepare a statement against the "db" database. */
|
||||
@@ -459,7 +459,7 @@ static void scrubBackupBtree(ScrubState *p, int pgno, int iDepth){
|
||||
nLocal = K<=X ? K : M;
|
||||
if( pc+nLocal > p->szUsable-4 ){ ln=__LINE__; goto btree_corrupt; }
|
||||
iChild = scrubBackupInt32(&a[pc+nLocal]);
|
||||
scrubBackupOverflow(p, iChild, P-nLocal);
|
||||
scrubBackupOverflow(p, iChild, (u32)(P-nLocal));
|
||||
}
|
||||
|
||||
/* Walk the right-most tree */
|
||||
|
||||
+527
-424
File diff suppressed because it is too large
Load Diff
+1327
-693
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
** 2018-02-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.
|
||||
**
|
||||
******************************************************************************
|
||||
**
|
||||
** SQL functions for z-order (Morton code) transformations.
|
||||
**
|
||||
** zorder(X0,X0,..,xN) Generate an N+1 dimension Morton code
|
||||
**
|
||||
** unzorder(Z,N,I) Extract the I-th dimension from N-dimensional
|
||||
** Morton code Z.
|
||||
*/
|
||||
#include "sqlite3ext.h"
|
||||
SQLITE_EXTENSION_INIT1
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
/*
|
||||
** Functions: zorder(X0,X1,....)
|
||||
**
|
||||
** Convert integers X0, X1, ... into morton code.
|
||||
**
|
||||
** The output is a signed 64-bit integer. If any argument is too large,
|
||||
** an error is thrown.
|
||||
*/
|
||||
static void zorderFunc(
|
||||
sqlite3_context *context,
|
||||
int argc,
|
||||
sqlite3_value **argv
|
||||
){
|
||||
sqlite3_int64 z, x[63];
|
||||
int i, j;
|
||||
z = 0;
|
||||
for(i=0; i<argc; i++){
|
||||
x[i] = sqlite3_value_int64(argv[i]);
|
||||
}
|
||||
if( argc>0 ){
|
||||
for(i=0; i<63; i++){
|
||||
j = i%argc;
|
||||
z |= (x[j]&1)<<i;
|
||||
x[j] >>= 1;
|
||||
}
|
||||
}
|
||||
sqlite3_result_int64(context, z);
|
||||
for(i=0; i<argc; i++){
|
||||
if( x[i] ){
|
||||
sqlite3_result_error(context, "parameter too large", -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Functions: unzorder(Z,N,I)
|
||||
**
|
||||
** Assuming that Z is an N-dimensional Morton code, extract the I-th
|
||||
** dimension.
|
||||
*/
|
||||
static void unzorderFunc(
|
||||
sqlite3_context *context,
|
||||
int argc,
|
||||
sqlite3_value **argv
|
||||
){
|
||||
sqlite3_int64 z, n, i, x;
|
||||
int j, k;
|
||||
z = sqlite3_value_int64(argv[0]);
|
||||
n = sqlite3_value_int64(argv[1]);
|
||||
i = sqlite3_value_int64(argv[2]);
|
||||
x = 0;
|
||||
for(k=0, j=i; j<63; j+=n, k++){
|
||||
x |= ((z>>j)&1)<<k;
|
||||
}
|
||||
sqlite3_result_int64(context, x);
|
||||
}
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
int sqlite3_zorder_init(
|
||||
sqlite3 *db,
|
||||
char **pzErrMsg,
|
||||
const sqlite3_api_routines *pApi
|
||||
){
|
||||
int rc = SQLITE_OK;
|
||||
SQLITE_EXTENSION_INIT2(pApi);
|
||||
(void)pzErrMsg; /* Unused parameter */
|
||||
rc = sqlite3_create_function(db, "zorder", -1, SQLITE_UTF8, 0,
|
||||
zorderFunc, 0, 0);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3_create_function(db, "unzorder", 3, SQLITE_UTF8, 0,
|
||||
unzorderFunc, 0, 0);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
@@ -0,0 +1,175 @@
|
||||
# 2018 January 11
|
||||
#
|
||||
# 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 tests of multiple RBU operations running
|
||||
# concurrently within the same process.
|
||||
#
|
||||
|
||||
source [file join [file dirname [info script]] rbu_common.tcl]
|
||||
set ::testprefix rbumulti
|
||||
|
||||
db close
|
||||
sqlite3_shutdown
|
||||
sqlite3_config_uri 1
|
||||
|
||||
autoinstall_test_functions
|
||||
|
||||
proc build_db {db} {
|
||||
$db eval {
|
||||
CREATE TABLE t1(a PRIMARY KEY, b, c);
|
||||
CREATE INDEX i1 ON t1(b);
|
||||
CREATE INDEX i2 ON t1(c);
|
||||
|
||||
WITH s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<500 )
|
||||
INSERT INTO t1
|
||||
SELECT randomblob(10), randomblob(100), randomblob(100) FROM s;
|
||||
}
|
||||
}
|
||||
|
||||
proc build_rbu {db} {
|
||||
$db eval {
|
||||
CREATE TABLE data_t1(a, b, c, rbu_control);
|
||||
WITH s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<100 )
|
||||
INSERT INTO data_t1
|
||||
SELECT randomblob(10), randomblob(100), randomblob(100), 0 FROM s;
|
||||
}
|
||||
}
|
||||
|
||||
proc step_rbu2 {bOpenClose openr1 openr2} {
|
||||
|
||||
forcedelete teststate.db1
|
||||
forcedelete teststate.db2
|
||||
|
||||
if {$bOpenClose!=0 && $bOpenClose!=1} { error $bOpenClose }
|
||||
if {$bOpenClose==0} {
|
||||
eval $openr1
|
||||
eval $openr2
|
||||
}
|
||||
|
||||
set b1 0
|
||||
set b2 0
|
||||
|
||||
while {$b1==0 || $b2==0} {
|
||||
if {$bOpenClose==1} {
|
||||
if {$b1==0} { eval $openr1 teststate.db1 }
|
||||
if {$b2==0} { eval $openr2 teststate.db2 }
|
||||
}
|
||||
if {$b1==0} {
|
||||
set rc1 [r1 step]
|
||||
if {$rc1 != "SQLITE_OK"} { set b1 1 }
|
||||
}
|
||||
if {$b2==0} {
|
||||
set rc2 [r2 step]
|
||||
if {$rc2 != "SQLITE_OK"} { set b2 1 }
|
||||
}
|
||||
if {$bOpenClose==1} {
|
||||
if {$b1==0} { r1 close }
|
||||
if {$b2==0} { r2 close }
|
||||
}
|
||||
}
|
||||
|
||||
set rc1 [r1 close]
|
||||
set rc2 [r2 close]
|
||||
|
||||
list $rc1 $rc2
|
||||
}
|
||||
|
||||
|
||||
for {set i 0} {$i<=3} {incr i} {
|
||||
|
||||
if {$i & 0x01} {
|
||||
sqlite3rbu_create_vfs -default myrbu ""
|
||||
}
|
||||
set bOpenClose [expr $i>>1]
|
||||
|
||||
forcedelete test.db
|
||||
forcedelete test.db2
|
||||
forcedelete rbu.db
|
||||
forcedelete rbu.db2
|
||||
|
||||
do_test 1.$i.0 {
|
||||
sqlite3 db test.db
|
||||
sqlite3 db2 test.db2
|
||||
build_db db
|
||||
build_db db2
|
||||
|
||||
sqlite3 rbu1 rbu.db
|
||||
sqlite3 rbu2 rbu.db2
|
||||
|
||||
build_rbu rbu1
|
||||
build_rbu rbu2
|
||||
|
||||
rbu1 close
|
||||
rbu2 close
|
||||
} {}
|
||||
|
||||
set m1 [db eval {SELECT md5sum(a, b, c) FROM t1}]
|
||||
set m2 [db2 eval {SELECT md5sum(a, b, c) FROM t1}]
|
||||
|
||||
do_test 1.$i.1 {
|
||||
step_rbu2 $bOpenClose {
|
||||
sqlite3rbu r1 test.db rbu.db
|
||||
} {
|
||||
sqlite3rbu r2 test.db2 rbu.db2
|
||||
}
|
||||
} {SQLITE_DONE SQLITE_DONE}
|
||||
|
||||
do_execsql_test -db db 1.$i.2.1 { PRAGMA integrity_check } ok
|
||||
do_execsql_test -db db2 1.$i.2.2 { PRAGMA integrity_check } ok
|
||||
|
||||
do_execsql_test -db db 1.$i.3.1 { SELECT md5sum(a, b, c)==$m1 FROM t1 } 0
|
||||
do_execsql_test -db db2 1.$i.3.2 { SELECT md5sum(a, b, c)==$m2 FROM t1 } 0
|
||||
|
||||
catch { db close }
|
||||
catch { db2 close }
|
||||
#-----------------------------------------------------------------------
|
||||
forcedelete test.db2
|
||||
forcedelete test.db
|
||||
forcedelete rbu.db2
|
||||
|
||||
do_test 1.$i.4 {
|
||||
sqlite3 db test.db
|
||||
sqlite3 db2 test.db2
|
||||
build_db db
|
||||
build_db db2
|
||||
sqlite3 rbu2 rbu.db2
|
||||
build_rbu rbu2
|
||||
rbu2 close
|
||||
} {}
|
||||
|
||||
set m1 [db eval {SELECT md5sum(a, b, c) FROM t1}]
|
||||
set m2 [db2 eval {SELECT md5sum(a, b, c) FROM t1}]
|
||||
|
||||
do_test 1.$i.5 {
|
||||
step_rbu2 $bOpenClose {
|
||||
sqlite3rbu_vacuum r1 test.db
|
||||
} {
|
||||
sqlite3rbu r2 test.db2 rbu.db2
|
||||
}
|
||||
} {SQLITE_DONE SQLITE_DONE}
|
||||
|
||||
do_execsql_test -db db 1.$i.6.1 { SELECT md5sum(a, b, c)==$m1 FROM t1 } 1
|
||||
do_execsql_test -db db2 1.$i.6.2 { SELECT md5sum(a, b, c)==$m2 FROM t1 } 0
|
||||
|
||||
do_execsql_test -db db 1.$i.7.1 { PRAGMA integrity_check } ok
|
||||
do_execsql_test -db db2 1.$i.7.2 { PRAGMA integrity_check } ok
|
||||
|
||||
catch { db close }
|
||||
catch { db2 close }
|
||||
if {$i & 0x01} {
|
||||
sqlite3rbu_destroy_vfs myrbu
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -220,7 +220,9 @@ if {[catch {sqlite3 db $file_to_analyze} res]} {
|
||||
if {$bFreelistCheck || $bAll} {
|
||||
puts -nonewline "freelist-check: "
|
||||
flush stdout
|
||||
db eval BEGIN
|
||||
puts [db one {SELECT checkfreelist('main')}]
|
||||
db eval END
|
||||
}
|
||||
if {$bSummary} {
|
||||
set scale 0
|
||||
|
||||
+3
-1
@@ -52,7 +52,8 @@
|
||||
** child page.
|
||||
*/
|
||||
|
||||
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_RTREE)
|
||||
#if !defined(SQLITE_CORE) \
|
||||
|| (defined(SQLITE_ENABLE_RTREE) && !defined(SQLITE_OMIT_VIRTUALTABLE))
|
||||
|
||||
#ifndef SQLITE_CORE
|
||||
#include "sqlite3ext.h"
|
||||
@@ -784,6 +785,7 @@ static int nodeWrite(Rtree *pRtree, RtreeNode *pNode){
|
||||
sqlite3_step(p);
|
||||
pNode->isDirty = 0;
|
||||
rc = sqlite3_reset(p);
|
||||
sqlite3_bind_null(p, 2);
|
||||
if( pNode->iNode==0 && rc==SQLITE_OK ){
|
||||
pNode->iNode = sqlite3_last_insert_rowid(pRtree->db);
|
||||
nodeHashInsert(pRtree, pNode);
|
||||
|
||||
@@ -15,6 +15,10 @@
|
||||
*/
|
||||
#include "sqlite3.h"
|
||||
|
||||
#ifdef SQLITE_OMIT_VIRTUALTABLE
|
||||
# undef SQLITE_ENABLE_RTREE
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
@@ -609,4 +609,5 @@ do_execsql_test 15.2 {
|
||||
COMMIT;
|
||||
}
|
||||
|
||||
expand_all_sql db
|
||||
finish_test
|
||||
|
||||
@@ -250,4 +250,5 @@ for {set nDim 1} {$nDim<=5} {incr nDim} {
|
||||
do_rtree_integrity_test rtree4-$nDim.3 rx
|
||||
}
|
||||
|
||||
expand_all_sql db
|
||||
finish_test
|
||||
|
||||
@@ -79,4 +79,5 @@ do_test rtree5-1.13 {
|
||||
} {2 2147483643 2147483647 -2147483648 -2147483643}
|
||||
do_rtree_integrity_test rtree5-1.14 t1
|
||||
|
||||
expand_all_sql db
|
||||
finish_test
|
||||
|
||||
@@ -158,5 +158,5 @@ do_execsql_test rtree6-3.5 {
|
||||
x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>1.1
|
||||
} {}
|
||||
|
||||
|
||||
expand_all_sql db
|
||||
finish_test
|
||||
|
||||
@@ -59,6 +59,7 @@ do_test rtreeG-1.4log {
|
||||
set ::log
|
||||
} {}
|
||||
|
||||
expand_all_sql db
|
||||
db close
|
||||
sqlite3_shutdown
|
||||
test_sqlite3_log
|
||||
|
||||
@@ -64,4 +64,81 @@ do_test 1.3 {
|
||||
list [catch { sqlite3changeset_apply db $x xConflict } msg] $msg
|
||||
} {1 SQLITE_CORRUPT}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_execsql_test 2.0 {
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY,b,c,d);
|
||||
CREATE TABLE t2(e TEXT PRIMARY KEY NOT NULL,f,g);
|
||||
CREATE TABLE t3(w REAL PRIMARY KEY NOT NULL,x,y);
|
||||
CREATE TABLE t4(z PRIMARY KEY) WITHOUT ROWID;
|
||||
}
|
||||
|
||||
foreach {tn blob} {
|
||||
1 54010174340012000000
|
||||
2 54fefe8bcb0012000300
|
||||
3 5480809280808001017434001200fb
|
||||
4 50af9c939c9c9cb09c9c6400b09c9c6400
|
||||
5 12000300
|
||||
6 09847304
|
||||
7 5401017434001208
|
||||
8 54010174340012fc0386868600
|
||||
9 54010174340012FC0386868600
|
||||
10 548894FEFE
|
||||
11 54010171340012E703ABFA7433FD1200
|
||||
12 540101743400120003FFED00010000000000000002120002400C00000000000054040100000074310017000100000000000000050100000000000000030100000000000000040000010000000000000004010000000000000003001700010000000000000007030378797A01000000000000000F000001000000000000000F030378797A005403010000743200090003037838790100000000800000000200000000000000000900030378327902400C0000000000000304666F7572
|
||||
13 540101743400120003001200010000000000000002120002400C0000000000005404010000007431001700010000000000000005010000000000000003010000000000000004000001000000000000000401000000000000000300170001000000000000000703FC87797A01000000000000000F000001000000000000000F030378797A005403010000743200090003037838790100000000800000000200000000000000000900030378327902400C0000000000000304666F7572
|
||||
14 540101743400120003001200010000000000000002120002400C00000000000054040100000074310017000100000000000000050100000000000000030100000000000000040000010000000000000004010000000000000003001700010000000000000007030378797A01000000000000000F000001000000000000000F03FC87797A005403010000743200090003037838790100000000800000000200000000000000000900030378327902400C0000000000000304666F7572
|
||||
15 540101743400120003001200010000000000000002120002400C00000000000054040100000074310017000100000000000000050100000000000000030100000000000000040000010000000000000004010000000000000003001700010000000000000007030378797A01000000000000000F000001000000000000000F030378797A005403010000743200090003FC8738790100000000800000000200000000000000000900030378327902400C0000000000000304666F7572
|
||||
16 540101743400120003001200010000000000000002120002400C00000000000054040100000074310017000100000000000000050100000000000000030100000000000000040000010000000000000004010000000000000003001700010000000000000007030378797A01000000000000000F000001000000000000000F030378797A00540301000074320009000303783879010000000080000000020000000000000000090003FC87327902400C0000000000000304666F7572
|
||||
17 540101743400120003FFE3000412F7010000E600000000021202120002400C0000000000005B0401000000743100171C0304646F750002400C000000000000540401000000D3310017000100000000000000050100000000000378797A405403000002F10100000100000000000004090001000100000007030378797A0100000000000D0007000001000000002300000F1B0378797A405403013900743200090003038C3879010000000000000000000002120002400C0000000000005B0401000000743117170003047C5E00FF
|
||||
18 54010174340012000300120001000000E6FF100000120002401E00000000000054040100000074310017000100040000010000000000000004FFFF7FFF0000000000010000010000001000000007030378797A01000000000000000F000000000000FA0304666F7572
|
||||
19 540101743400120003001200010000000000000002121B02400C00000000000054040000000074310017000100000000000000050100000000000000030100000000000000040000010000000000000004010000000000000003001700010000000000000007030378817A01000000000000000F000001000000000100000F030378797A005403010000743200090003FFE809000303780000000000000304666F7572
|
||||
20 5401017D3400120003001200010000000000000002120002400CFC00000000005404010000007431001700010000000000000005010000000000000003010000000000000004000001000000000000000401000000000000000300170001000000000000000703FFFF797A01000000000000000F000001000000000000000F030378797A005403010000743200090003037838790100000000800000000200000000000000000900030378326C02400C0000000000000304666F7572
|
||||
21 5401017434001200030012000100FFE20000000002120002400C00000000000054040100E0007431001700010000E99D000000020000000003FFE70009000303783279020004000001030000000000002117000003001700012701000100000000743100000100000000008000090003037F387901000000008000000002000000000400000009005303010A00FF7FFFFF00000000000304664F6572
|
||||
22 540101743400120003FFFF7FFF0000000000000002120002400C00000000000054040100000074310017000100000000000000050100000000000000030100010000000000000000040000010000000000000004010000000000000003001700010000000000000007030378797A01000000000000000F000001000000000000000F030378797A005403010000743200090003037838790100000000800000000200000000000000000900030378327902400C0000000000000304666F7572
|
||||
23 540101742700120100120003F5FF0300
|
||||
24 5401017434E312540101743400120003FFFC00
|
||||
25 540101743400540101743D3D3D3D3D3D3D3D3D3D3D3D3D3400120003FFED000300
|
||||
26 5401017446EA5301743D1D3D3D01743D1D3D3DCF3D3D3D1A3D3D3D3D3400120003FFFF000000
|
||||
27 540101743400540101743D3D3D3D3D3D3D3D3D3D251000120003FF81000000000000
|
||||
28 540101340012000397FF3D7F3D3400120003001200540101743D3D3D3D3D3D393D3D3D12000300
|
||||
29 500174340050010F74340012000300120003FFE5
|
||||
30 5004007233E900177FEF0054257F0002EF001200031E12000300
|
||||
31 5001015001015252525250010174340012EF039A9A0100E351525D52525252525252525252525252525252525250010174340012EF039A0100009A9A9A9A9A9BA3B200120003010040743400
|
||||
32 5401017400123400120003FFFC00
|
||||
33 540101743400120003001200010000000000004002120002400C0000000000005404010000007431001700010000000000000005010000000000000003010000000000000004000001000000000000000401000000000000000300170001000000000000000703FC87797A01000000000000000F000001000000000000000F030378797A005403010000743200090003037838790100000000800000000200000000000000000900030378327902400C0000000000000304666F7572
|
||||
34 54040100000074310017000100000002000015050100000000000000030100000000140000040000010000000000000004010000000000000003001700010000000000000007030378797A01000000000000000F000001000000000000000F030378797A0054030100007432000900030378387901000000008E000000020000000000000000090003FFFF000002400C0000000000000304666F7572
|
||||
35 540101743400120003001200010000000000000002120002400C00000000000050060100000074310017000100000000000000050100000000000000030100000003001700010000666F7572
|
||||
36 540101743400120003001200010000000000000002120002400C00000000000050050100000074310017000100000000000000050100000000000000030100000003001700010000666F7572
|
||||
37 540101743400120003001200010000000000000002120002400C00000000000050040100008074310017000100000000000000050100000000000000030100000003001700010000666F7572
|
||||
38 540101743400120003001200010000000000000002120002400C00000000000050040100000074310017000000000000000000050100000000000000030100000003001700010000666F7572
|
||||
39 540101743400120003001200010000000000000002120002400C00000000000050040100018074310017000100000000000000050100000000000000030100000003001700010000666F7572
|
||||
40 540101743400120003001200010000000000000002120002400C0000000000005004FEFFFFFF74310017000100000000000000050100000000000000030100000003001700010000666F7572
|
||||
41 540101743400120003001200010000000000000002120002400C00000000000050040100000074310017000004000000000000050100000000000000030100000003001700010000666F7572
|
||||
42 540101743400120003001200010000000000000002120002400C0000000000005005FFFF050074310017000100000000000000050100000000000000030100000003001700010000666F7572
|
||||
43 540101743400120003001200010000000000000002120002400C000000000000500401006E0074310017000300000000001221050100000000000000030100000003001700010000666F7572
|
||||
44 540101743400120003001200010000000000020000120002400C00000000000050050100000074310017000100000000000000050100004000000000030100000025001700010000666F7572
|
||||
45 540101743400120003001200010000000000ECFF02120002400C000000000000500401F9FF00743100170001000000000000000500E1000000000000030100000003000000000000666F7572
|
||||
46 54010174340B0B0B0B0B0B0B0B0B0B0B0B0B0B0B00120003001200010000000000000002120002400C00000000000050040100000074310017010000000000000000050100FFE900000000030100000003007F00000000666F7572
|
||||
47 54010103001200010000000000020002120002400C0000000000005004010000F374310017000100000000000000050100000000000000030100000003001700010000666F8E72
|
||||
48 540101743400120003001200010000000000000002120002400C00000000000050030012000174310017000700000000000000050100002000000001000000000003001700010000666F7572
|
||||
49 540101743400120004001200010000000000000002120002400C0000000000005004010000FC733100170001000000000000000501000000000000000301000000F6FF17000100007C6F7572
|
||||
50 54010174FFDDFF8003001200010000100000000002120002400C000000000000500401000000743100170000000005010000000000000000000003010072
|
||||
51 540101743200120003001200010000000000000002120002400C00000000000050040100001074310017000000000003010000120300170100000000000000050100000000000000030100000003001700010000666F7572
|
||||
52 540101745401017434001200010000000000001702120002400C00000000000050040100001A74310017000100000000000100000100000000000000030100000003001700010000666F7572
|
||||
53 540101743400120003001200010000000000000002120002400C000000000000500401000000743100170001000002400C00000000000050040110000074310017000000000000050100000000000000030100000003001700010000666F7572
|
||||
54 540101743400120003001200010000000000000002120002400C000000000002120002400C00000000000050040100000074310017FF0050040100000074310017FF7F00000000000000050100000000000000030100000003001700010000666F7572
|
||||
55 540101743400120003001200010000000000000002120002400C00000000000050040100000074310017000100010080000001000000020003010100000300170100000003001700010000666F7572
|
||||
56 5487ffffff7f
|
||||
} {
|
||||
do_test 2.$tn {
|
||||
set changeset [binary decode hex $blob]
|
||||
#set fd [open x.change w+]
|
||||
#fconfigure $fd -encoding binary -translation binary
|
||||
#puts -nonewline $fd $changeset
|
||||
#close $fd
|
||||
list [catch { sqlite3changeset_apply db $changeset xConflict } msg] $msg
|
||||
} {1 SQLITE_CORRUPT}
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -221,5 +221,38 @@ do_test 4.2.2 {
|
||||
} {1 {SQLITE_SCHEMA - table schemas do not match}}
|
||||
S delete
|
||||
|
||||
do_test 4.3.1 {
|
||||
sqlite3session S db main
|
||||
S attach t4
|
||||
execsql { CREATE TABLE t4(i PRIMARY KEY, b) }
|
||||
list [catch { S diff ixua t4 } msg] $msg
|
||||
} {1 {SQLITE_SCHEMA - table schemas do not match}}
|
||||
S delete
|
||||
do_catchsql_test 4.3.2 {
|
||||
SELECT * FROM ixua.t4;
|
||||
} {1 {no such table: ixua.t4}}
|
||||
|
||||
do_test 4.4.1 {
|
||||
sqlite3session S db main
|
||||
S attach sqlite_stat1
|
||||
execsql { ANALYZE }
|
||||
execsql { DROP TABLE ixua.sqlite_stat1 }
|
||||
list [catch { S diff ixua sqlite_stat1 } msg] $msg
|
||||
} {1 {SQLITE_SCHEMA - table schemas do not match}}
|
||||
S delete
|
||||
do_catchsql_test 4.4.2 {
|
||||
SELECT * FROM ixua.sqlite_stat1;
|
||||
} {1 {no such table: ixua.sqlite_stat1}}
|
||||
|
||||
do_test 4.5.1 {
|
||||
sqlite3session S db main
|
||||
S attach t8
|
||||
list [catch { S diff ixua t8 } msg] $msg
|
||||
} {0 {}}
|
||||
S delete
|
||||
do_catchsql_test 4.5.2 {
|
||||
SELECT * FROM ixua.i8;
|
||||
} {1 {no such table: ixua.i8}}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -173,5 +173,39 @@ do_test 4.3 {
|
||||
compare_db db db2
|
||||
} {}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
catch { db2 close }
|
||||
forcedelete test.db2
|
||||
sqlite3 db2 test.db2
|
||||
|
||||
do_execsql_test 5.0.1 {
|
||||
CREATE TABLE t1(a PRIMARY KEY, b, c);
|
||||
CREATE TABLE t2(a, b, c PRIMARY KEY);
|
||||
CREATE TABLE t3(a, b PRIMARY KEY, c);
|
||||
}
|
||||
do_execsql_test -db db2 5.0.2 {
|
||||
CREATE TABLE t1(a PRIMARY KEY, b, c);
|
||||
CREATE TABLE t2(a, b, c);
|
||||
CREATE TABLE t3(a, b PRIMARY KEY, c);
|
||||
}
|
||||
|
||||
do_test 5.1 {
|
||||
do_then_apply_sql {
|
||||
INSERT INTO t1 VALUES(1, 2, 3);
|
||||
INSERT INTO t2 VALUES(4, 5, 6);
|
||||
INSERT INTO t3 VALUES(7, 8, 9);
|
||||
}
|
||||
|
||||
db2 eval {
|
||||
SELECT * FROM t1;
|
||||
SELECT * FROM t2;
|
||||
SELECT * FROM t3;
|
||||
}
|
||||
} {1 2 3 7 8 9}
|
||||
|
||||
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
# 2018 January 18
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
|
||||
if {![info exists testdir]} {
|
||||
set testdir [file join [file dirname [info script]] .. .. test]
|
||||
}
|
||||
source [file join [file dirname [info script]] session_common.tcl]
|
||||
source $testdir/tester.tcl
|
||||
ifcapable !session {finish_test; return}
|
||||
set testprefix sessionH
|
||||
|
||||
forcedelete test.db2
|
||||
sqlite3 db2 test.db2
|
||||
|
||||
do_test 1.0 {
|
||||
do_common_sql {
|
||||
CREATE TABLE t1(a, b, c, PRIMARY KEY(a, b));
|
||||
}
|
||||
do_then_apply_sql {
|
||||
WITH s(i) AS (
|
||||
VALUES(1) UNION ALL SELECT i+1 FROM s WHERe i<10000
|
||||
)
|
||||
INSERT INTO t1 SELECT 'abcde', randomblob(16), i FROM s;
|
||||
}
|
||||
compare_db db db2
|
||||
} {}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -241,5 +241,9 @@ eval [string map [list %WR% $trailing] {
|
||||
}]
|
||||
}
|
||||
|
||||
catch { db close }
|
||||
catch { db2 close }
|
||||
sqlite3_shutdown
|
||||
test_sqlite3_log
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -0,0 +1,311 @@
|
||||
# 2018 January 12
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
|
||||
if {![info exists testdir]} {
|
||||
set testdir [file join [file dirname [info script]] .. .. test]
|
||||
}
|
||||
source [file join [file dirname [info script]] session_common.tcl]
|
||||
source $testdir/tester.tcl
|
||||
ifcapable !session {finish_test; return}
|
||||
|
||||
set testprefix sessionstat1
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE TABLE t1(a PRIMARY KEY, b, c);
|
||||
CREATE INDEX t1b ON t1(b);
|
||||
CREATE INDEX t1c ON t1(c);
|
||||
|
||||
WITH s(i) AS (
|
||||
SELECT 0 UNION ALL SELECT i+1 FROM s WHERE (i+1)<32
|
||||
)
|
||||
INSERT INTO t1 SELECT i, i%8, i%2 FROM s;
|
||||
}
|
||||
|
||||
do_iterator_test 1.1 {} {
|
||||
ANALYZE
|
||||
} {
|
||||
{INSERT sqlite_stat1 0 XX. {} {t t1 t sqlite_autoindex_t1_1 t {32 1}}}
|
||||
{INSERT sqlite_stat1 0 XX. {} {t t1 t t1b t {32 4}}}
|
||||
{INSERT sqlite_stat1 0 XX. {} {t t1 t t1c t {32 16}}}
|
||||
}
|
||||
|
||||
do_execsql_test 1.2 {
|
||||
WITH s(i) AS (
|
||||
SELECT 32 UNION ALL SELECT i+1 FROM s WHERE (i+1)<64
|
||||
)
|
||||
INSERT INTO t1 SELECT i, i%8, i%2 FROM s;
|
||||
}
|
||||
|
||||
do_iterator_test 1.3 {} {
|
||||
ANALYZE
|
||||
} {
|
||||
{UPDATE sqlite_stat1 0 XX. {t t1 t sqlite_autoindex_t1_1 t {32 1}} {{} {} {} {} t {64 1}}}
|
||||
{UPDATE sqlite_stat1 0 XX. {t t1 t t1b t {32 4}} {{} {} {} {} t {64 8}}}
|
||||
{UPDATE sqlite_stat1 0 XX. {t t1 t t1c t {32 16}} {{} {} {} {} t {64 32}}}
|
||||
}
|
||||
|
||||
do_iterator_test 1.5 {} {
|
||||
DROP INDEX t1b;
|
||||
} {
|
||||
{DELETE sqlite_stat1 0 XX. {t t1 t t1b t {64 8}} {}}
|
||||
}
|
||||
|
||||
do_iterator_test 1.6 {} {
|
||||
DROP TABLE t1;
|
||||
} {
|
||||
{DELETE sqlite_stat1 0 XX. {t t1 t sqlite_autoindex_t1_1 t {64 1}} {}}
|
||||
{DELETE sqlite_stat1 0 XX. {t t1 t t1c t {64 32}} {}}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
catch { db2 close }
|
||||
forcedelete test.db2
|
||||
sqlite3 db2 test.db2
|
||||
|
||||
do_test 2.0 {
|
||||
do_common_sql {
|
||||
CREATE TABLE t1(a PRIMARY KEY, b, c);
|
||||
CREATE INDEX t1b ON t1(b);
|
||||
CREATE INDEX t1c ON t1(c);
|
||||
ANALYZE;
|
||||
}
|
||||
} {}
|
||||
|
||||
do_test 2.1 {
|
||||
do_then_apply_sql {
|
||||
WITH s(i) AS (
|
||||
SELECT 0 UNION ALL SELECT i+1 FROM s WHERE (i+1)<32
|
||||
)
|
||||
INSERT INTO t1 SELECT i, i%8, i%2 FROM s;
|
||||
ANALYZE;
|
||||
}
|
||||
} {}
|
||||
|
||||
do_execsql_test -db db2 2.2 {
|
||||
SELECT * FROM sqlite_stat1
|
||||
} {
|
||||
t1 sqlite_autoindex_t1_1 {32 1}
|
||||
t1 t1b {32 4}
|
||||
t1 t1c {32 16}
|
||||
}
|
||||
|
||||
do_test 2.3 {
|
||||
do_then_apply_sql { DROP INDEX t1c }
|
||||
} {}
|
||||
|
||||
do_execsql_test -db db2 2.4 {
|
||||
SELECT * FROM sqlite_stat1
|
||||
} {
|
||||
t1 sqlite_autoindex_t1_1 {32 1}
|
||||
t1 t1b {32 4}
|
||||
}
|
||||
|
||||
do_test 2.3 {
|
||||
do_then_apply_sql { DROP TABLE t1 }
|
||||
} {}
|
||||
|
||||
do_execsql_test -db db2 2.4 {
|
||||
SELECT * FROM sqlite_stat1
|
||||
} {
|
||||
}
|
||||
|
||||
do_execsql_test -db db2 2.5 { SELECT count(*) FROM t1 } 32
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
db2 close
|
||||
forcedelete test.db2
|
||||
reset_db
|
||||
sqlite3 db2 test.db2
|
||||
|
||||
do_test 3.0 {
|
||||
do_common_sql {
|
||||
CREATE TABLE t1(a, b, c);
|
||||
ANALYZE;
|
||||
DELETE FROM sqlite_stat1;
|
||||
}
|
||||
execsql {
|
||||
INSERT INTO t1 VALUES(1, 1, 1);
|
||||
INSERT INTO t1 VALUES(2, 2, 2);
|
||||
INSERT INTO t1 VALUES(3, 3, 3);
|
||||
INSERT INTO t1 VALUES(4, 4, 4);
|
||||
}
|
||||
} {}
|
||||
|
||||
do_iterator_test 3.1 {} {
|
||||
ANALYZE
|
||||
} {
|
||||
{INSERT sqlite_stat1 0 XX. {} {t t1 b {} t 4}}
|
||||
}
|
||||
db null null
|
||||
db2 null null
|
||||
do_execsql_test 3.2 {
|
||||
SELECT * FROM sqlite_stat1;
|
||||
} {t1 null 4}
|
||||
do_test 3.3 {
|
||||
execsql { DELETE FROM sqlite_stat1 }
|
||||
do_then_apply_sql { ANALYZE }
|
||||
execsql { SELECT * FROM sqlite_stat1 } db2
|
||||
} {t1 null 4}
|
||||
do_test 3.4 {
|
||||
execsql { INSERT INTO t1 VALUES(5,5,5) }
|
||||
do_then_apply_sql { ANALYZE }
|
||||
execsql { SELECT * FROM sqlite_stat1 } db2
|
||||
} {t1 null 5}
|
||||
do_test 3.5 {
|
||||
do_then_apply_sql { DROP TABLE t1 }
|
||||
execsql { SELECT * FROM sqlite_stat1 } db2
|
||||
} {}
|
||||
|
||||
do_test 3.6.1 {
|
||||
execsql {
|
||||
CREATE TABLE t1(a, b, c);
|
||||
CREATE TABLE t2(x, y, z);
|
||||
INSERT INTO t1 VALUES(1,1,1), (2,2,2), (3,3,3), (4,4,4), (5,5,5);
|
||||
INSERT INTO t2 SELECT * FROM t1;
|
||||
DELETE FROM sqlite_stat1;
|
||||
}
|
||||
sqlite3session S db main
|
||||
S attach sqlite_stat1
|
||||
execsql { ANALYZE }
|
||||
} {}
|
||||
do_changeset_test 3.6.2 S {
|
||||
{INSERT sqlite_stat1 0 XX. {} {t t2 b {} t 5}}
|
||||
{INSERT sqlite_stat1 0 XX. {} {t t1 b {} t 5}}
|
||||
}
|
||||
do_changeset_invert_test 3.6.3 S {
|
||||
{DELETE sqlite_stat1 0 XX. {t t2 b {} t 5} {}}
|
||||
{DELETE sqlite_stat1 0 XX. {t t1 b {} t 5} {}}
|
||||
}
|
||||
do_test 3.6.4 { S delete } {}
|
||||
|
||||
proc sql_changeset_concat {args} {
|
||||
foreach sql $args {
|
||||
sqlite3session S db main
|
||||
S attach sqlite_stat1
|
||||
execsql $sql
|
||||
set change [S changeset]
|
||||
S delete
|
||||
|
||||
if {[info vars ret]!=""} {
|
||||
set ret [sqlite3changeset_concat $ret $change]
|
||||
} else {
|
||||
set ret $change
|
||||
}
|
||||
}
|
||||
|
||||
changeset_to_list $ret
|
||||
}
|
||||
|
||||
proc do_scc_test {tn args} {
|
||||
uplevel [list \
|
||||
do_test $tn [concat sql_changeset_concat [lrange $args 0 end-1]] \
|
||||
[list {*}[ lindex $args end ]]
|
||||
]
|
||||
}
|
||||
|
||||
do_execsql_test 3.7.0 {
|
||||
DELETE FROM sqlite_stat1;
|
||||
}
|
||||
do_scc_test 3.7.1 {
|
||||
ANALYZE;
|
||||
} {
|
||||
INSERT INTO t2 VALUES(6,6,6);
|
||||
ANALYZE;
|
||||
} {
|
||||
{INSERT sqlite_stat1 0 XX. {} {t t1 b {} t 5}}
|
||||
{INSERT sqlite_stat1 0 XX. {} {t t2 b {} t 6}}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
catch { db2 close }
|
||||
reset_db
|
||||
forcedelete test.db2
|
||||
sqlite3 db2 test.db2
|
||||
|
||||
do_test 4.1.0 {
|
||||
do_common_sql {
|
||||
CREATE TABLE t1(a, b);
|
||||
CREATE INDEX i1 ON t1(a);
|
||||
CREATE INDEX i2 ON t1(b);
|
||||
INSERT INTO t1 VALUES(1,1), (2,2);
|
||||
ANALYZE;
|
||||
}
|
||||
execsql { DELETE FROM sqlite_stat1 }
|
||||
} {}
|
||||
|
||||
do_test 4.1.1 {
|
||||
execsql { INSERT INTO t1 VALUES(3,3); }
|
||||
set C [changeset_from_sql {ANALYZE}]
|
||||
set ::c [list]
|
||||
proc xConflict {args} {
|
||||
lappend ::c $args
|
||||
return "OMIT"
|
||||
}
|
||||
sqlite3changeset_apply db2 $C xConflict
|
||||
set ::c
|
||||
} [list {*}{
|
||||
{INSERT sqlite_stat1 CONFLICT {t t1 t i1 t {3 1}} {t t1 t i1 t {2 1}}}
|
||||
{INSERT sqlite_stat1 CONFLICT {t t1 t i2 t {3 1}} {t t1 t i2 t {2 1}}}
|
||||
}]
|
||||
|
||||
do_execsql_test -db db2 4.1.2 {
|
||||
SELECT * FROM sqlite_stat1 ORDER BY 1,2;
|
||||
} {t1 i1 {2 1} t1 i2 {2 1}}
|
||||
|
||||
do_test 4.1.3 {
|
||||
proc xConflict {args} {
|
||||
return "REPLACE"
|
||||
}
|
||||
sqlite3changeset_apply db2 $C xConflict
|
||||
execsql { SELECT * FROM sqlite_stat1 ORDER BY 1,2 } db2
|
||||
} {t1 i1 {3 1} t1 i2 {3 1}}
|
||||
|
||||
do_test 4.2.0 {
|
||||
do_common_sql {
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t3(x,y);
|
||||
INSERT INTO t3 VALUES('a','a');
|
||||
INSERT INTO t3 VALUES('b','b');
|
||||
ANALYZE;
|
||||
}
|
||||
execsql { DELETE FROM sqlite_stat1 }
|
||||
} {}
|
||||
do_test 4.2.1 {
|
||||
execsql { INSERT INTO t3 VALUES('c','c'); }
|
||||
set C [changeset_from_sql {ANALYZE}]
|
||||
set ::c [list]
|
||||
proc xConflict {args} {
|
||||
lappend ::c $args
|
||||
return "OMIT"
|
||||
}
|
||||
sqlite3changeset_apply db2 $C xConflict
|
||||
set ::c
|
||||
} [list {*}{
|
||||
{INSERT sqlite_stat1 CONFLICT {t t3 b {} t 3} {t t3 b {} t 2}}
|
||||
}]
|
||||
|
||||
db2 null null
|
||||
do_execsql_test -db db2 4.2.2 {
|
||||
SELECT * FROM sqlite_stat1 ORDER BY 1,2;
|
||||
} {t3 null 2}
|
||||
|
||||
do_test 4.2.3 {
|
||||
proc xConflict {args} {
|
||||
return "REPLACE"
|
||||
}
|
||||
sqlite3changeset_apply db2 $C xConflict
|
||||
execsql { SELECT * FROM sqlite_stat1 ORDER BY 1,2 } db2
|
||||
} {t3 null 3}
|
||||
|
||||
finish_test
|
||||
|
||||
+249
-56
@@ -46,6 +46,7 @@ struct sqlite3_session {
|
||||
int rc; /* Non-zero if an error has occurred */
|
||||
void *pFilterCtx; /* First argument to pass to xTableFilter */
|
||||
int (*xTableFilter)(void *pCtx, const char *zTab);
|
||||
sqlite3_value *pZeroBlob; /* Value containing X'' */
|
||||
sqlite3_session *pNext; /* Next session object on same db. */
|
||||
SessionTable *pTable; /* List of attached tables */
|
||||
SessionHook hook; /* APIs to grab new and old data with */
|
||||
@@ -113,6 +114,7 @@ struct SessionTable {
|
||||
SessionTable *pNext;
|
||||
char *zName; /* Local name of table */
|
||||
int nCol; /* Number of columns in table zName */
|
||||
int bStat1; /* True if this is sqlite_stat1 */
|
||||
const char **azCol; /* Column names */
|
||||
u8 *abPK; /* Array of primary key flags */
|
||||
int nEntry; /* Total number of entries in hash table */
|
||||
@@ -496,6 +498,7 @@ static int sessionPreupdateHash(
|
||||
h = sessionHashAppendBlob(h, n, z);
|
||||
}else{
|
||||
assert( eType==SQLITE_NULL );
|
||||
assert( pTab->bStat1==0 || i!=1 );
|
||||
*pbNullPK = 1;
|
||||
}
|
||||
}
|
||||
@@ -838,7 +841,6 @@ static int sessionPreupdateEqual(
|
||||
}
|
||||
if( memcmp(a, z, n) ) return 0;
|
||||
a += n;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -894,9 +896,7 @@ static int sessionGrowHash(int bPatchset, SessionTable *pTab){
|
||||
|
||||
/*
|
||||
** This function queries the database for the names of the columns of table
|
||||
** zThis, in schema zDb. It is expected that the table has nCol columns. If
|
||||
** not, SQLITE_SCHEMA is returned and none of the output variables are
|
||||
** populated.
|
||||
** zThis, in schema zDb.
|
||||
**
|
||||
** Otherwise, if they are not NULL, variable *pnCol is set to the number
|
||||
** of columns in the database table and variable *pzTab is set to point to a
|
||||
@@ -917,9 +917,7 @@ static int sessionGrowHash(int bPatchset, SessionTable *pTab){
|
||||
** *pabPK = {1, 0, 0, 1}
|
||||
**
|
||||
** All returned buffers are part of the same single allocation, which must
|
||||
** be freed using sqlite3_free() by the caller. If pazCol was not NULL, then
|
||||
** pointer *pazCol should be freed to release all memory. Otherwise, pointer
|
||||
** *pabPK. It is illegal for both pazCol and pabPK to be NULL.
|
||||
** be freed using sqlite3_free() by the caller
|
||||
*/
|
||||
static int sessionTableInfo(
|
||||
sqlite3 *db, /* Database connection */
|
||||
@@ -944,7 +942,23 @@ static int sessionTableInfo(
|
||||
assert( pazCol && pabPK );
|
||||
|
||||
nThis = sqlite3Strlen30(zThis);
|
||||
zPragma = sqlite3_mprintf("PRAGMA '%q'.table_info('%q')", zDb, zThis);
|
||||
if( nThis==12 && 0==sqlite3_stricmp("sqlite_stat1", zThis) ){
|
||||
rc = sqlite3_table_column_metadata(db, zDb, zThis, 0, 0, 0, 0, 0, 0);
|
||||
if( rc==SQLITE_OK ){
|
||||
/* For sqlite_stat1, pretend that (tbl,idx) is the PRIMARY KEY. */
|
||||
zPragma = sqlite3_mprintf(
|
||||
"SELECT 0, 'tbl', '', 0, '', 1 UNION ALL "
|
||||
"SELECT 1, 'idx', '', 0, '', 2 UNION ALL "
|
||||
"SELECT 2, 'stat', '', 0, '', 0"
|
||||
);
|
||||
}else if( rc==SQLITE_ERROR ){
|
||||
zPragma = sqlite3_mprintf("");
|
||||
}else{
|
||||
return rc;
|
||||
}
|
||||
}else{
|
||||
zPragma = sqlite3_mprintf("PRAGMA '%q'.table_info('%q')", zDb, zThis);
|
||||
}
|
||||
if( !zPragma ) return SQLITE_NOMEM;
|
||||
|
||||
rc = sqlite3_prepare_v2(db, zPragma, -1, &pStmt, 0);
|
||||
@@ -1036,11 +1050,55 @@ static int sessionInitTable(sqlite3_session *pSession, SessionTable *pTab){
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( 0==sqlite3_stricmp("sqlite_stat1", pTab->zName) ){
|
||||
pTab->bStat1 = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return (pSession->rc || pTab->abPK==0);
|
||||
}
|
||||
|
||||
/*
|
||||
** Versions of the four methods in object SessionHook for use with the
|
||||
** sqlite_stat1 table. The purpose of this is to substitute a zero-length
|
||||
** blob each time a NULL value is read from the "idx" column of the
|
||||
** sqlite_stat1 table.
|
||||
*/
|
||||
typedef struct SessionStat1Ctx SessionStat1Ctx;
|
||||
struct SessionStat1Ctx {
|
||||
SessionHook hook;
|
||||
sqlite3_session *pSession;
|
||||
};
|
||||
static int sessionStat1Old(void *pCtx, int iCol, sqlite3_value **ppVal){
|
||||
SessionStat1Ctx *p = (SessionStat1Ctx*)pCtx;
|
||||
sqlite3_value *pVal = 0;
|
||||
int rc = p->hook.xOld(p->hook.pCtx, iCol, &pVal);
|
||||
if( rc==SQLITE_OK && iCol==1 && sqlite3_value_type(pVal)==SQLITE_NULL ){
|
||||
pVal = p->pSession->pZeroBlob;
|
||||
}
|
||||
*ppVal = pVal;
|
||||
return rc;
|
||||
}
|
||||
static int sessionStat1New(void *pCtx, int iCol, sqlite3_value **ppVal){
|
||||
SessionStat1Ctx *p = (SessionStat1Ctx*)pCtx;
|
||||
sqlite3_value *pVal = 0;
|
||||
int rc = p->hook.xNew(p->hook.pCtx, iCol, &pVal);
|
||||
if( rc==SQLITE_OK && iCol==1 && sqlite3_value_type(pVal)==SQLITE_NULL ){
|
||||
pVal = p->pSession->pZeroBlob;
|
||||
}
|
||||
*ppVal = pVal;
|
||||
return rc;
|
||||
}
|
||||
static int sessionStat1Count(void *pCtx){
|
||||
SessionStat1Ctx *p = (SessionStat1Ctx*)pCtx;
|
||||
return p->hook.xCount(p->hook.pCtx);
|
||||
}
|
||||
static int sessionStat1Depth(void *pCtx){
|
||||
SessionStat1Ctx *p = (SessionStat1Ctx*)pCtx;
|
||||
return p->hook.xDepth(p->hook.pCtx);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** This function is only called from with a pre-update-hook reporting a
|
||||
** change on table pTab (attached to session pSession). The type of change
|
||||
@@ -1057,6 +1115,7 @@ static void sessionPreupdateOneChange(
|
||||
int iHash;
|
||||
int bNull = 0;
|
||||
int rc = SQLITE_OK;
|
||||
SessionStat1Ctx stat1 = {0};
|
||||
|
||||
if( pSession->rc ) return;
|
||||
|
||||
@@ -1076,6 +1135,25 @@ static void sessionPreupdateOneChange(
|
||||
return;
|
||||
}
|
||||
|
||||
if( pTab->bStat1 ){
|
||||
stat1.hook = pSession->hook;
|
||||
stat1.pSession = pSession;
|
||||
pSession->hook.pCtx = (void*)&stat1;
|
||||
pSession->hook.xNew = sessionStat1New;
|
||||
pSession->hook.xOld = sessionStat1Old;
|
||||
pSession->hook.xCount = sessionStat1Count;
|
||||
pSession->hook.xDepth = sessionStat1Depth;
|
||||
if( pSession->pZeroBlob==0 ){
|
||||
sqlite3_value *p = sqlite3ValueNew(0);
|
||||
if( p==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
goto error_out;
|
||||
}
|
||||
sqlite3ValueSetStr(p, 0, "", 0, SQLITE_STATIC);
|
||||
pSession->pZeroBlob = p;
|
||||
}
|
||||
}
|
||||
|
||||
/* Calculate the hash-key for this change. If the primary key of the row
|
||||
** includes a NULL value, exit early. Such changes are ignored by the
|
||||
** session module. */
|
||||
@@ -1165,6 +1243,9 @@ static void sessionPreupdateOneChange(
|
||||
|
||||
/* If an error has occurred, mark the session object as failed. */
|
||||
error_out:
|
||||
if( pTab->bStat1 ){
|
||||
pSession->hook = stat1.hook;
|
||||
}
|
||||
if( rc!=SQLITE_OK ){
|
||||
pSession->rc = rc;
|
||||
}
|
||||
@@ -1501,7 +1582,6 @@ int sqlite3session_diff(
|
||||
if( abPK[i] ) bHasPk = 1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
sqlite3_free((char*)azCol);
|
||||
if( bMismatch ){
|
||||
@@ -1627,6 +1707,7 @@ void sqlite3session_delete(sqlite3_session *pSession){
|
||||
}
|
||||
}
|
||||
sqlite3_mutex_leave(sqlite3_db_mutex(db));
|
||||
sqlite3ValueFree(pSession->pZeroBlob);
|
||||
|
||||
/* Delete all attached table objects. And the contents of their
|
||||
** associated hash-tables. */
|
||||
@@ -2094,28 +2175,41 @@ static int sessionSelectStmt(
|
||||
sqlite3_stmt **ppStmt /* OUT: Prepared SELECT statement */
|
||||
){
|
||||
int rc = SQLITE_OK;
|
||||
int i;
|
||||
const char *zSep = "";
|
||||
SessionBuffer buf = {0, 0, 0};
|
||||
char *zSql = 0;
|
||||
int nSql = -1;
|
||||
|
||||
sessionAppendStr(&buf, "SELECT * FROM ", &rc);
|
||||
sessionAppendIdent(&buf, zDb, &rc);
|
||||
sessionAppendStr(&buf, ".", &rc);
|
||||
sessionAppendIdent(&buf, zTab, &rc);
|
||||
sessionAppendStr(&buf, " WHERE ", &rc);
|
||||
for(i=0; i<nCol; i++){
|
||||
if( abPK[i] ){
|
||||
sessionAppendStr(&buf, zSep, &rc);
|
||||
sessionAppendIdent(&buf, azCol[i], &rc);
|
||||
sessionAppendStr(&buf, " = ?", &rc);
|
||||
sessionAppendInteger(&buf, i+1, &rc);
|
||||
zSep = " AND ";
|
||||
if( 0==sqlite3_stricmp("sqlite_stat1", zTab) ){
|
||||
zSql = sqlite3_mprintf(
|
||||
"SELECT tbl, ?2, stat FROM %Q.sqlite_stat1 WHERE tbl IS ?1 AND "
|
||||
"idx IS (CASE WHEN ?2=X'' THEN NULL ELSE ?2 END)", zDb
|
||||
);
|
||||
}else{
|
||||
int i;
|
||||
const char *zSep = "";
|
||||
SessionBuffer buf = {0, 0, 0};
|
||||
|
||||
sessionAppendStr(&buf, "SELECT * FROM ", &rc);
|
||||
sessionAppendIdent(&buf, zDb, &rc);
|
||||
sessionAppendStr(&buf, ".", &rc);
|
||||
sessionAppendIdent(&buf, zTab, &rc);
|
||||
sessionAppendStr(&buf, " WHERE ", &rc);
|
||||
for(i=0; i<nCol; i++){
|
||||
if( abPK[i] ){
|
||||
sessionAppendStr(&buf, zSep, &rc);
|
||||
sessionAppendIdent(&buf, azCol[i], &rc);
|
||||
sessionAppendStr(&buf, " IS ?", &rc);
|
||||
sessionAppendInteger(&buf, i+1, &rc);
|
||||
zSep = " AND ";
|
||||
}
|
||||
}
|
||||
zSql = (char*)buf.aBuf;
|
||||
nSql = buf.nBuf;
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3_prepare_v2(db, (char *)buf.aBuf, buf.nBuf, ppStmt, 0);
|
||||
rc = sqlite3_prepare_v2(db, zSql, nSql, ppStmt, 0);
|
||||
}
|
||||
sqlite3_free(buf.aBuf);
|
||||
sqlite3_free(zSql);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -2626,13 +2720,16 @@ static int sessionReadRecord(
|
||||
if( abPK && abPK[i]==0 ) continue;
|
||||
rc = sessionInputBuffer(pIn, 9);
|
||||
if( rc==SQLITE_OK ){
|
||||
eType = pIn->aData[pIn->iNext++];
|
||||
}
|
||||
|
||||
assert( apOut[i]==0 );
|
||||
if( eType ){
|
||||
apOut[i] = sqlite3ValueNew(0);
|
||||
if( !apOut[i] ) rc = SQLITE_NOMEM;
|
||||
if( pIn->iNext>=pIn->nData ){
|
||||
rc = SQLITE_CORRUPT_BKPT;
|
||||
}else{
|
||||
eType = pIn->aData[pIn->iNext++];
|
||||
assert( apOut[i]==0 );
|
||||
if( eType ){
|
||||
apOut[i] = sqlite3ValueNew(0);
|
||||
if( !apOut[i] ) rc = SQLITE_NOMEM;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
@@ -2642,10 +2739,14 @@ static int sessionReadRecord(
|
||||
pIn->iNext += sessionVarintGet(aVal, &nByte);
|
||||
rc = sessionInputBuffer(pIn, nByte);
|
||||
if( rc==SQLITE_OK ){
|
||||
u8 enc = (eType==SQLITE_TEXT ? SQLITE_UTF8 : 0);
|
||||
rc = sessionValueSetStr(apOut[i],&pIn->aData[pIn->iNext],nByte,enc);
|
||||
if( nByte<0 || nByte>pIn->nData-pIn->iNext ){
|
||||
rc = SQLITE_CORRUPT_BKPT;
|
||||
}else{
|
||||
u8 enc = (eType==SQLITE_TEXT ? SQLITE_UTF8 : 0);
|
||||
rc = sessionValueSetStr(apOut[i],&pIn->aData[pIn->iNext],nByte,enc);
|
||||
pIn->iNext += nByte;
|
||||
}
|
||||
}
|
||||
pIn->iNext += nByte;
|
||||
}
|
||||
if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){
|
||||
sqlite3_int64 v = sessionGetI64(aVal);
|
||||
@@ -2685,8 +2786,19 @@ static int sessionChangesetBufferTblhdr(SessionInput *pIn, int *pnByte){
|
||||
rc = sessionInputBuffer(pIn, 9);
|
||||
if( rc==SQLITE_OK ){
|
||||
nRead += sessionVarintGet(&pIn->aData[pIn->iNext + nRead], &nCol);
|
||||
rc = sessionInputBuffer(pIn, nRead+nCol+100);
|
||||
nRead += nCol;
|
||||
/* The hard upper limit for the number of columns in an SQLite
|
||||
** database table is, according to sqliteLimit.h, 32676. So
|
||||
** consider any table-header that purports to have more than 65536
|
||||
** columns to be corrupt. This is convenient because otherwise,
|
||||
** if the (nCol>65536) condition below were omitted, a sufficiently
|
||||
** large value for nCol may cause nRead to wrap around and become
|
||||
** negative. Leading to a crash. */
|
||||
if( nCol<0 || nCol>65536 ){
|
||||
rc = SQLITE_CORRUPT_BKPT;
|
||||
}else{
|
||||
rc = sessionInputBuffer(pIn, nRead+nCol+100);
|
||||
nRead += nCol;
|
||||
}
|
||||
}
|
||||
|
||||
while( rc==SQLITE_OK ){
|
||||
@@ -2763,11 +2875,15 @@ static int sessionChangesetReadTblhdr(sqlite3_changeset_iter *p){
|
||||
int nByte;
|
||||
int nVarint;
|
||||
nVarint = sessionVarintGet(&p->in.aData[p->in.iNext], &p->nCol);
|
||||
nCopy -= nVarint;
|
||||
p->in.iNext += nVarint;
|
||||
nByte = p->nCol * sizeof(sqlite3_value*) * 2 + nCopy;
|
||||
p->tblhdr.nBuf = 0;
|
||||
sessionBufferGrow(&p->tblhdr, nByte, &rc);
|
||||
if( p->nCol>0 ){
|
||||
nCopy -= nVarint;
|
||||
p->in.iNext += nVarint;
|
||||
nByte = p->nCol * sizeof(sqlite3_value*) * 2 + nCopy;
|
||||
p->tblhdr.nBuf = 0;
|
||||
sessionBufferGrow(&p->tblhdr, nByte, &rc);
|
||||
}else{
|
||||
rc = SQLITE_CORRUPT_BKPT;
|
||||
}
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
@@ -2845,6 +2961,13 @@ static int sessionChangesetNext(
|
||||
op = p->in.aData[p->in.iNext++];
|
||||
}
|
||||
|
||||
if( p->zTab==0 ){
|
||||
/* The first record in the changeset is not a table header. Must be a
|
||||
** corrupt changeset. */
|
||||
assert( p->in.iNext==1 );
|
||||
return (p->rc = SQLITE_CORRUPT_BKPT);
|
||||
}
|
||||
|
||||
p->op = op;
|
||||
p->bIndirect = p->in.aData[p->in.iNext++];
|
||||
if( p->op!=SQLITE_UPDATE && p->op!=SQLITE_DELETE && p->op!=SQLITE_INSERT ){
|
||||
@@ -2887,9 +3010,9 @@ static int sessionChangesetNext(
|
||||
** new.* to old.*, to accommodate the code that reads these arrays. */
|
||||
for(i=0; i<p->nCol; i++){
|
||||
assert( p->apValue[i]==0 );
|
||||
assert( p->abPK[i]==0 || p->apValue[i+p->nCol] );
|
||||
if( p->abPK[i] ){
|
||||
p->apValue[i] = p->apValue[i+p->nCol];
|
||||
if( p->apValue[i]==0 ) return (p->rc = SQLITE_CORRUPT_BKPT);
|
||||
p->apValue[i+p->nCol] = 0;
|
||||
}
|
||||
}
|
||||
@@ -3284,7 +3407,7 @@ struct SessionApplyCtx {
|
||||
int nCol; /* Size of azCol[] and abPK[] arrays */
|
||||
const char **azCol; /* Array of column names */
|
||||
u8 *abPK; /* Boolean array - true if column is in PK */
|
||||
|
||||
int bStat1; /* True if table is sqlite_stat1 */
|
||||
int bDeferConstraints; /* True to defer constraints */
|
||||
SessionBuffer constraints; /* Deferred constraints are stored here */
|
||||
};
|
||||
@@ -3454,6 +3577,7 @@ static int sessionUpdateRow(
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Formulate and prepare an SQL statement to query table zTab by primary
|
||||
** key. Assuming the following table structure:
|
||||
@@ -3515,6 +3639,47 @@ static int sessionInsertRow(
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int sessionPrepare(sqlite3 *db, sqlite3_stmt **pp, const char *zSql){
|
||||
return sqlite3_prepare_v2(db, zSql, -1, pp, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
** Prepare statements for applying changes to the sqlite_stat1 table.
|
||||
** These are similar to those created by sessionSelectRow(),
|
||||
** sessionInsertRow(), sessionUpdateRow() and sessionDeleteRow() for
|
||||
** other tables.
|
||||
*/
|
||||
static int sessionStat1Sql(sqlite3 *db, SessionApplyCtx *p){
|
||||
int rc = sessionSelectRow(db, "sqlite_stat1", p);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sessionPrepare(db, &p->pInsert,
|
||||
"INSERT INTO main.sqlite_stat1 VALUES(?1, "
|
||||
"CASE WHEN length(?2)=0 AND typeof(?2)='blob' THEN NULL ELSE ?2 END, "
|
||||
"?3)"
|
||||
);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sessionPrepare(db, &p->pUpdate,
|
||||
"UPDATE main.sqlite_stat1 SET "
|
||||
"tbl = CASE WHEN ?2 THEN ?3 ELSE tbl END, "
|
||||
"idx = CASE WHEN ?5 THEN ?6 ELSE idx END, "
|
||||
"stat = CASE WHEN ?8 THEN ?9 ELSE stat END "
|
||||
"WHERE tbl=?1 AND idx IS "
|
||||
"CASE WHEN length(?4)=0 AND typeof(?4)='blob' THEN NULL ELSE ?4 END "
|
||||
"AND (?10 OR ?8=0 OR stat IS ?7)"
|
||||
);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sessionPrepare(db, &p->pDelete,
|
||||
"DELETE FROM main.sqlite_stat1 WHERE tbl=?1 AND idx IS "
|
||||
"CASE WHEN length(?2)=0 AND typeof(?2)='blob' THEN NULL ELSE ?2 END "
|
||||
"AND (?4 OR stat IS ?3)"
|
||||
);
|
||||
}
|
||||
assert( rc==SQLITE_OK );
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** A wrapper around sqlite3_bind_value() that detects an extra problem.
|
||||
** See comments in the body of this function for details.
|
||||
@@ -3572,7 +3737,13 @@ static int sessionBindRow(
|
||||
if( !abPK || abPK[i] ){
|
||||
sqlite3_value *pVal;
|
||||
(void)xValue(pIter, i, &pVal);
|
||||
rc = sessionBindValue(pStmt, i+1, pVal);
|
||||
if( pVal==0 ){
|
||||
/* The value in the changeset was "undefined". This indicates a
|
||||
** corrupt changeset blob. */
|
||||
rc = SQLITE_CORRUPT_BKPT;
|
||||
}else{
|
||||
rc = sessionBindValue(pStmt, i+1, pVal);
|
||||
}
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
@@ -3845,11 +4016,25 @@ static int sessionApplyOneOp(
|
||||
|
||||
}else{
|
||||
assert( op==SQLITE_INSERT );
|
||||
rc = sessionBindRow(pIter, sqlite3changeset_new, nCol, 0, p->pInsert);
|
||||
if( rc!=SQLITE_OK ) return rc;
|
||||
if( p->bStat1 ){
|
||||
/* Check if there is a conflicting row. For sqlite_stat1, this needs
|
||||
** to be done using a SELECT, as there is no PRIMARY KEY in the
|
||||
** database schema to throw an exception if a duplicate is inserted. */
|
||||
rc = sessionSeekToRow(p->db, pIter, p->abPK, p->pSelect);
|
||||
if( rc==SQLITE_ROW ){
|
||||
rc = SQLITE_CONSTRAINT;
|
||||
sqlite3_reset(p->pSelect);
|
||||
}
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sessionBindRow(pIter, sqlite3changeset_new, nCol, 0, p->pInsert);
|
||||
if( rc!=SQLITE_OK ) return rc;
|
||||
|
||||
sqlite3_step(p->pInsert);
|
||||
rc = sqlite3_reset(p->pInsert);
|
||||
}
|
||||
|
||||
sqlite3_step(p->pInsert);
|
||||
rc = sqlite3_reset(p->pInsert);
|
||||
if( (rc&0xff)==SQLITE_CONSTRAINT ){
|
||||
rc = sessionConflictHandler(
|
||||
SQLITE_CHANGESET_CONFLICT, p, pIter, xConflict, pCtx, pbReplace
|
||||
@@ -4082,12 +4267,20 @@ static int sessionChangesetApply(
|
||||
}
|
||||
else{
|
||||
sApply.nCol = nCol;
|
||||
if((rc = sessionSelectRow(db, zTab, &sApply))
|
||||
|| (rc = sessionUpdateRow(db, zTab, &sApply))
|
||||
|| (rc = sessionDeleteRow(db, zTab, &sApply))
|
||||
|| (rc = sessionInsertRow(db, zTab, &sApply))
|
||||
){
|
||||
break;
|
||||
if( 0==sqlite3_stricmp(zTab, "sqlite_stat1") ){
|
||||
if( (rc = sessionStat1Sql(db, &sApply) ) ){
|
||||
break;
|
||||
}
|
||||
sApply.bStat1 = 1;
|
||||
}else{
|
||||
if((rc = sessionSelectRow(db, zTab, &sApply))
|
||||
|| (rc = sessionUpdateRow(db, zTab, &sApply))
|
||||
|| (rc = sessionDeleteRow(db, zTab, &sApply))
|
||||
|| (rc = sessionInsertRow(db, zTab, &sApply))
|
||||
){
|
||||
break;
|
||||
}
|
||||
sApply.bStat1 = 0;
|
||||
}
|
||||
}
|
||||
nTab = sqlite3Strlen30(zTab);
|
||||
|
||||
@@ -13,16 +13,23 @@ extern "C" {
|
||||
|
||||
/*
|
||||
** CAPI3REF: Session Object Handle
|
||||
**
|
||||
** An instance of this object is a [session] that can be used to
|
||||
** record changes to a database.
|
||||
*/
|
||||
typedef struct sqlite3_session sqlite3_session;
|
||||
|
||||
/*
|
||||
** CAPI3REF: Changeset Iterator Handle
|
||||
**
|
||||
** An instance of this object acts as a cursor for iterating
|
||||
** over the elements of a [changeset] or [patchset].
|
||||
*/
|
||||
typedef struct sqlite3_changeset_iter sqlite3_changeset_iter;
|
||||
|
||||
/*
|
||||
** CAPI3REF: Create A New Session Object
|
||||
** CONSTRUCTOR: sqlite3_session
|
||||
**
|
||||
** Create a new session object attached to database handle db. If successful,
|
||||
** a pointer to the new object is written to *ppSession and SQLITE_OK is
|
||||
@@ -59,6 +66,7 @@ int sqlite3session_create(
|
||||
|
||||
/*
|
||||
** CAPI3REF: Delete A Session Object
|
||||
** DESTRUCTOR: sqlite3_session
|
||||
**
|
||||
** Delete a session object previously allocated using
|
||||
** [sqlite3session_create()]. Once a session object has been deleted, the
|
||||
@@ -74,6 +82,7 @@ void sqlite3session_delete(sqlite3_session *pSession);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Enable Or Disable A Session Object
|
||||
** METHOD: sqlite3_session
|
||||
**
|
||||
** Enable or disable the recording of changes by a session object. When
|
||||
** enabled, a session object records changes made to the database. When
|
||||
@@ -93,6 +102,7 @@ int sqlite3session_enable(sqlite3_session *pSession, int bEnable);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Set Or Clear the Indirect Change Flag
|
||||
** METHOD: sqlite3_session
|
||||
**
|
||||
** Each change recorded by a session object is marked as either direct or
|
||||
** indirect. A change is marked as indirect if either:
|
||||
@@ -122,6 +132,7 @@ int sqlite3session_indirect(sqlite3_session *pSession, int bIndirect);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Attach A Table To A Session Object
|
||||
** METHOD: sqlite3_session
|
||||
**
|
||||
** If argument zTab is not NULL, then it is the name of a table to attach
|
||||
** to the session object passed as the first argument. All subsequent changes
|
||||
@@ -147,6 +158,35 @@ int sqlite3session_indirect(sqlite3_session *pSession, int bIndirect);
|
||||
**
|
||||
** SQLITE_OK is returned if the call completes without error. Or, if an error
|
||||
** occurs, an SQLite error code (e.g. SQLITE_NOMEM) is returned.
|
||||
**
|
||||
** <h3>Special sqlite_stat1 Handling</h3>
|
||||
**
|
||||
** As of SQLite version 3.22.0, the "sqlite_stat1" table is an exception to
|
||||
** some of the rules above. In SQLite, the schema of sqlite_stat1 is:
|
||||
** <pre>
|
||||
** CREATE TABLE sqlite_stat1(tbl,idx,stat)
|
||||
** </pre>
|
||||
**
|
||||
** Even though sqlite_stat1 does not have a PRIMARY KEY, changes are
|
||||
** recorded for it as if the PRIMARY KEY is (tbl,idx). Additionally, changes
|
||||
** are recorded for rows for which (idx IS NULL) is true. However, for such
|
||||
** rows a zero-length blob (SQL value X'') is stored in the changeset or
|
||||
** patchset instead of a NULL value. This allows such changesets to be
|
||||
** manipulated by legacy implementations of sqlite3changeset_invert(),
|
||||
** concat() and similar.
|
||||
**
|
||||
** The sqlite3changeset_apply() function automatically converts the
|
||||
** zero-length blob back to a NULL value when updating the sqlite_stat1
|
||||
** table. However, if the application calls sqlite3changeset_new(),
|
||||
** sqlite3changeset_old() or sqlite3changeset_conflict on a changeset
|
||||
** iterator directly (including on a changeset iterator passed to a
|
||||
** conflict-handler callback) then the X'' value is returned. The application
|
||||
** must translate X'' to NULL itself if required.
|
||||
**
|
||||
** Legacy (older than 3.22.0) versions of the sessions module cannot capture
|
||||
** changes made to the sqlite_stat1 table. Legacy versions of the
|
||||
** sqlite3changeset_apply() function silently ignore any modifications to the
|
||||
** sqlite_stat1 table that are part of a changeset or patchset.
|
||||
*/
|
||||
int sqlite3session_attach(
|
||||
sqlite3_session *pSession, /* Session object */
|
||||
@@ -155,6 +195,7 @@ int sqlite3session_attach(
|
||||
|
||||
/*
|
||||
** CAPI3REF: Set a table filter on a Session Object.
|
||||
** METHOD: sqlite3_session
|
||||
**
|
||||
** The second argument (xFilter) is the "filter callback". For changes to rows
|
||||
** in tables that are not attached to the Session object, the filter is called
|
||||
@@ -173,6 +214,7 @@ void sqlite3session_table_filter(
|
||||
|
||||
/*
|
||||
** CAPI3REF: Generate A Changeset From A Session Object
|
||||
** METHOD: sqlite3_session
|
||||
**
|
||||
** Obtain a changeset containing changes to the tables attached to the
|
||||
** session object passed as the first argument. If successful,
|
||||
@@ -282,7 +324,8 @@ int sqlite3session_changeset(
|
||||
);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Load The Difference Between Tables Into A Session
|
||||
** CAPI3REF: Load The Difference Between Tables Into A Session
|
||||
** METHOD: sqlite3_session
|
||||
**
|
||||
** If it is not already attached to the session object passed as the first
|
||||
** argument, this function attaches table zTbl in the same manner as the
|
||||
@@ -347,6 +390,7 @@ int sqlite3session_diff(
|
||||
|
||||
/*
|
||||
** CAPI3REF: Generate A Patchset From A Session Object
|
||||
** METHOD: sqlite3_session
|
||||
**
|
||||
** The differences between a patchset and a changeset are that:
|
||||
**
|
||||
@@ -398,6 +442,7 @@ int sqlite3session_isempty(sqlite3_session *pSession);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Create An Iterator To Traverse A Changeset
|
||||
** CONSTRUCTOR: sqlite3_changeset_iter
|
||||
**
|
||||
** Create an iterator used to iterate through the contents of a changeset.
|
||||
** If successful, *pp is set to point to the iterator handle and SQLITE_OK
|
||||
@@ -438,6 +483,7 @@ int sqlite3changeset_start(
|
||||
|
||||
/*
|
||||
** CAPI3REF: Advance A Changeset Iterator
|
||||
** METHOD: sqlite3_changeset_iter
|
||||
**
|
||||
** This function may only be used with iterators created by function
|
||||
** [sqlite3changeset_start()]. If it is called on an iterator passed to
|
||||
@@ -462,6 +508,7 @@ int sqlite3changeset_next(sqlite3_changeset_iter *pIter);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Obtain The Current Operation From A Changeset Iterator
|
||||
** METHOD: sqlite3_changeset_iter
|
||||
**
|
||||
** The pIter argument passed to this function may either be an iterator
|
||||
** passed to a conflict-handler by [sqlite3changeset_apply()], or an iterator
|
||||
@@ -496,6 +543,7 @@ int sqlite3changeset_op(
|
||||
|
||||
/*
|
||||
** CAPI3REF: Obtain The Primary Key Definition Of A Table
|
||||
** METHOD: sqlite3_changeset_iter
|
||||
**
|
||||
** For each modified table, a changeset includes the following:
|
||||
**
|
||||
@@ -527,6 +575,7 @@ int sqlite3changeset_pk(
|
||||
|
||||
/*
|
||||
** CAPI3REF: Obtain old.* Values From A Changeset Iterator
|
||||
** METHOD: sqlite3_changeset_iter
|
||||
**
|
||||
** The pIter argument passed to this function may either be an iterator
|
||||
** passed to a conflict-handler by [sqlite3changeset_apply()], or an iterator
|
||||
@@ -557,6 +606,7 @@ int sqlite3changeset_old(
|
||||
|
||||
/*
|
||||
** CAPI3REF: Obtain new.* Values From A Changeset Iterator
|
||||
** METHOD: sqlite3_changeset_iter
|
||||
**
|
||||
** The pIter argument passed to this function may either be an iterator
|
||||
** passed to a conflict-handler by [sqlite3changeset_apply()], or an iterator
|
||||
@@ -590,6 +640,7 @@ int sqlite3changeset_new(
|
||||
|
||||
/*
|
||||
** CAPI3REF: Obtain Conflicting Row Values From A Changeset Iterator
|
||||
** METHOD: sqlite3_changeset_iter
|
||||
**
|
||||
** This function should only be used with iterator objects passed to a
|
||||
** conflict-handler callback by [sqlite3changeset_apply()] with either
|
||||
@@ -617,6 +668,7 @@ int sqlite3changeset_conflict(
|
||||
|
||||
/*
|
||||
** CAPI3REF: Determine The Number Of Foreign Key Constraint Violations
|
||||
** METHOD: sqlite3_changeset_iter
|
||||
**
|
||||
** This function may only be called with an iterator passed to an
|
||||
** SQLITE_CHANGESET_FOREIGN_KEY conflict handler callback. In this case
|
||||
@@ -633,6 +685,7 @@ int sqlite3changeset_fk_conflicts(
|
||||
|
||||
/*
|
||||
** CAPI3REF: Finalize A Changeset Iterator
|
||||
** METHOD: sqlite3_changeset_iter
|
||||
**
|
||||
** This function is used to finalize an iterator allocated with
|
||||
** [sqlite3changeset_start()].
|
||||
@@ -649,6 +702,7 @@ int sqlite3changeset_fk_conflicts(
|
||||
** to that error is returned by this function. Otherwise, SQLITE_OK is
|
||||
** returned. This is to allow the following pattern (pseudo-code):
|
||||
**
|
||||
** <pre>
|
||||
** sqlite3changeset_start();
|
||||
** while( SQLITE_ROW==sqlite3changeset_next() ){
|
||||
** // Do something with change.
|
||||
@@ -657,6 +711,7 @@ int sqlite3changeset_fk_conflicts(
|
||||
** if( rc!=SQLITE_OK ){
|
||||
** // An error has occurred
|
||||
** }
|
||||
** </pre>
|
||||
*/
|
||||
int sqlite3changeset_finalize(sqlite3_changeset_iter *pIter);
|
||||
|
||||
@@ -704,6 +759,7 @@ int sqlite3changeset_invert(
|
||||
** sqlite3_changegroup object. Calling it produces similar results as the
|
||||
** following code fragment:
|
||||
**
|
||||
** <pre>
|
||||
** sqlite3_changegroup *pGrp;
|
||||
** rc = sqlite3_changegroup_new(&pGrp);
|
||||
** if( rc==SQLITE_OK ) rc = sqlite3changegroup_add(pGrp, nA, pA);
|
||||
@@ -714,6 +770,7 @@ int sqlite3changeset_invert(
|
||||
** *ppOut = 0;
|
||||
** *pnOut = 0;
|
||||
** }
|
||||
** </pre>
|
||||
**
|
||||
** Refer to the sqlite3_changegroup documentation below for details.
|
||||
*/
|
||||
@@ -729,11 +786,15 @@ int sqlite3changeset_concat(
|
||||
|
||||
/*
|
||||
** CAPI3REF: Changegroup Handle
|
||||
**
|
||||
** A changegroup is an object used to combine two or more
|
||||
** [changesets] or [patchsets]
|
||||
*/
|
||||
typedef struct sqlite3_changegroup sqlite3_changegroup;
|
||||
|
||||
/*
|
||||
** CAPI3REF: Create A New Changegroup Object
|
||||
** CONSTRUCTOR: sqlite3_changegroup
|
||||
**
|
||||
** An sqlite3_changegroup object is used to combine two or more changesets
|
||||
** (or patchsets) into a single changeset (or patchset). A single changegroup
|
||||
@@ -771,6 +832,7 @@ int sqlite3changegroup_new(sqlite3_changegroup **pp);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Add A Changeset To A Changegroup
|
||||
** METHOD: sqlite3_changegroup
|
||||
**
|
||||
** Add all changes within the changeset (or patchset) in buffer pData (size
|
||||
** nData bytes) to the changegroup.
|
||||
@@ -848,6 +910,7 @@ int sqlite3changegroup_add(sqlite3_changegroup*, int nData, void *pData);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Obtain A Composite Changeset From A Changegroup
|
||||
** METHOD: sqlite3_changegroup
|
||||
**
|
||||
** Obtain a buffer containing a changeset (or patchset) representing the
|
||||
** current contents of the changegroup. If the inputs to the changegroup
|
||||
@@ -878,6 +941,7 @@ int sqlite3changegroup_output(
|
||||
|
||||
/*
|
||||
** CAPI3REF: Delete A Changegroup Object
|
||||
** DESTRUCTOR: sqlite3_changegroup
|
||||
*/
|
||||
void sqlite3changegroup_delete(sqlite3_changegroup*);
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@ LIBOBJ+= vdbe.o parse.o \
|
||||
fts3_write.o fts5.o func.o global.o hash.o \
|
||||
icu.o insert.o json1.o legacy.o loadext.o \
|
||||
main.o malloc.o mem0.o mem1.o mem2.o mem3.o mem5.o \
|
||||
memjournal.o \
|
||||
memdb.o memjournal.o \
|
||||
mutex.o mutex_noop.o mutex_unix.o mutex_w32.o \
|
||||
notify.o opcodes.o os.o os_unix.o os_win.o \
|
||||
pager.o pcache.o pcache1.o pragma.o prepare.o printf.o \
|
||||
@@ -118,6 +118,7 @@ SRC = \
|
||||
$(TOP)/src/mem2.c \
|
||||
$(TOP)/src/mem3.c \
|
||||
$(TOP)/src/mem5.c \
|
||||
$(TOP)/src/memdb.c \
|
||||
$(TOP)/src/memjournal.c \
|
||||
$(TOP)/src/msvc.h \
|
||||
$(TOP)/src/mutex.c \
|
||||
@@ -361,6 +362,7 @@ TESTSRC += \
|
||||
$(TOP)/ext/misc/ieee754.c \
|
||||
$(TOP)/ext/misc/mmapwarm.c \
|
||||
$(TOP)/ext/misc/nextchar.c \
|
||||
$(TOP)/ext/misc/normalize.c \
|
||||
$(TOP)/ext/misc/percentile.c \
|
||||
$(TOP)/ext/misc/regexp.c \
|
||||
$(TOP)/ext/misc/remember.c \
|
||||
@@ -373,7 +375,7 @@ TESTSRC += \
|
||||
$(TOP)/ext/misc/zipfile.c \
|
||||
$(TOP)/ext/fts5/fts5_tcl.c \
|
||||
$(TOP)/ext/fts5/fts5_test_mi.c \
|
||||
$(TOP)/ext/fts5/fts5_test_tok.c
|
||||
$(TOP)/ext/fts5/fts5_test_tok.c
|
||||
|
||||
|
||||
#TESTSRC += $(TOP)/ext/fts2/fts2_tokenizer.c
|
||||
@@ -422,6 +424,7 @@ TESTSRC2 = \
|
||||
$(TOP)/ext/fts3/fts3_tokenizer.c \
|
||||
$(TOP)/ext/fts3/fts3_write.c \
|
||||
$(TOP)/ext/async/sqlite3async.c \
|
||||
$(TOP)/ext/misc/stmt.c \
|
||||
$(TOP)/ext/session/sqlite3session.c \
|
||||
$(TOP)/ext/session/test_session.c
|
||||
|
||||
@@ -517,6 +520,7 @@ SHELL_OPT += -DSQLITE_INTROSPECTION_PRAGMAS
|
||||
FUZZERSHELL_OPT = -DSQLITE_ENABLE_JSON1
|
||||
FUZZCHECK_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5
|
||||
FUZZCHECK_OPT += -DSQLITE_MAX_MEMORY=50000000
|
||||
FUZZCHECK_OPT += -DSQLITE_PRINTF_PRECISION_LIMIT=1000
|
||||
DBFUZZ_OPT =
|
||||
KV_OPT = -DSQLITE_THREADSAFE=0 -DSQLITE_DIRECT_OVERFLOW_READ
|
||||
ST_OPT = -DSQLITE_THREADSAFE=0
|
||||
@@ -571,6 +575,9 @@ ossshell$(EXE): $(TOP)/test/ossfuzz.c $(TOP)/test/ossshell.c sqlite3.c sqlite3.h
|
||||
-DSQLITE_ENABLE_MEMSYS5 $(FUZZCHECK_OPT) \
|
||||
$(TOP)/test/ossfuzz.c $(TOP)/test/ossshell.c sqlite3.c $(TLIBS) $(THREADLIB)
|
||||
|
||||
sessionfuzz$(EXE): $(TOP)/test/sessionfuzz.c sqlite3.c sqlite3.h
|
||||
$(TCC) -o sessionfuzz$(EXE) $(TOP)/test/sessionfuzz.c -lz $(TLIBS) $(THREADLIB)
|
||||
|
||||
mptester$(EXE): sqlite3.c $(TOP)/mptest/mptest.c
|
||||
$(TCCX) -o $@ -I. $(TOP)/mptest/mptest.c sqlite3.c \
|
||||
$(TLIBS) $(THREADLIB)
|
||||
@@ -891,14 +898,17 @@ fulltestonly: $(TESTPROGS) fuzztest
|
||||
queryplantest: testfixture$(EXE) sqlite3$(EXE)
|
||||
./testfixture$(EXE) $(TOP)/test/permutations.test queryplanner $(TESTOPTS)
|
||||
|
||||
fuzztest: fuzzcheck$(EXE) $(FUZZDATA)
|
||||
fuzztest: fuzzcheck$(EXE) $(FUZZDATA) sessionfuzz$(EXE) $(TOP)/test/sessionfuzz-data1.db
|
||||
./fuzzcheck$(EXE) $(FUZZDATA)
|
||||
./sessionfuzz run $(TOP)/test/sessionfuzz-data1.db
|
||||
|
||||
fastfuzztest: fuzzcheck$(EXE) $(FUZZDATA)
|
||||
fastfuzztest: fuzzcheck$(EXE) $(FUZZDATA) sessionfuzz$(EXE) $(TOP)/test/sessionfuzz-data1.db
|
||||
./fuzzcheck$(EXE) --limit-mem 100M $(FUZZDATA)
|
||||
./sessionfuzz run $(TOP)/test/sessionfuzz-data1.db
|
||||
|
||||
valgrindfuzz: fuzzcheck$(EXE) $(FUZZDATA)
|
||||
valgrindfuzz: fuzzcheck$(EXE) $(FUZZDATA) sessionfuzz$(EXE) $(TOP)/test/sessionfuzz-data1.db
|
||||
valgrind ./fuzzcheck$(EXE) --cell-size-check --limit-mem 10M --timeout 600 $(FUZZDATA)
|
||||
valgrind ./sessionfuzz run $(TOP)/test/sessionfuzz-data1.db
|
||||
|
||||
# The veryquick.test TCL tests.
|
||||
#
|
||||
@@ -1062,6 +1072,7 @@ clean:
|
||||
rm -f mptester mptester.exe
|
||||
rm -f fuzzershell fuzzershell.exe
|
||||
rm -f fuzzcheck fuzzcheck.exe
|
||||
rm -f sessionfuzz
|
||||
rm -f sqldiff sqldiff.exe
|
||||
rm -f fts5.* fts5parse.*
|
||||
rm -f lsm.h lsm1.c
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
C Add\sthe\ssqlite3_vtab_nochange()\smethod\swhich\svirtual\stable\simplementations\ncan\suse\sto\soptimize\sUPDATEs.
|
||||
D 2018-01-11T17:04:26.957
|
||||
C Fix\shandling\sof\s"UPDATE\sOR\sREPLACE"\sstatements\srun\son\szipfile\svirtual\stables.
|
||||
D 2018-03-20T13:26:01.034
|
||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||
F Makefile.in 38f84f301cbef443b2d269f67a74b8cc536469831f70df7c3e912acc04932cc2
|
||||
F Makefile.in 7016fc56c6b9bfe5daac4f34be8be38d8c0b5fab79ccbfb764d3b23bf1c6fff3
|
||||
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
|
||||
F Makefile.msc ede26e3fb675e0b3b07627640ce5917154a6ee7f8f2c97424eb5ab5f651cbd56
|
||||
F README.md eeae1e552f93ef72ef7c5b8f6647b368a001c28820ad1df179d3dae602bef681
|
||||
F VERSION 0c10cdfed866fdd2d80434f64f042c3330f1daaed12e54287beb104f04b3faaf
|
||||
F Makefile.msc bdcad21b027a56a73e54a1121cfb9edd0a35c0abfa53aa12c2f996006ff99960
|
||||
F README.md 1d5342ebda97420f114283e604e5fe99b0da939d63b76d492eabbaae23488276
|
||||
F VERSION cdf91ac446255ecf3d8f6d8c3ee40d64123235ae5b3cef29d344e61b45ec3759
|
||||
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
|
||||
F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2
|
||||
F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90
|
||||
F art/sqlite370.jpg d512473dae7e378a67e28ff96a34da7cb331def2
|
||||
F autoconf/INSTALL 83e4a25da9fd053c7b3665eaaaf7919707915903
|
||||
F autoconf/Makefile.am 66c0befa511f0d95ba229e180067cf0357a9ebf8b3201b06d683c5ba6220fb39
|
||||
F autoconf/Makefile.msc 2c50a59319af7da4eaca8c13e3240881b1bc245fd175845a055faab7d03d6e67
|
||||
F autoconf/Makefile.am 2c274948734e03c51790ff51468f91db8d570bcca864284d9c6d6e777264cd7e
|
||||
F autoconf/Makefile.msc 1223d1520e0b833041ad87b377fae61cc3e08d14c5aae4c1a9e36249225bd4e6
|
||||
F autoconf/README.first 6c4f34fe115ff55d4e8dbfa3cecf04a0188292f7
|
||||
F autoconf/README.txt 4f04b0819303aabaa35fff5f7b257fb0c1ef95f1
|
||||
F autoconf/configure.ac 8dd08ca564279fff091c9bfdd2599d8f992c9f1f70c5396de2126ad2bd1b3bed
|
||||
F autoconf/configure.ac 18fca06f884213be062dd5e07c5297079cc45893d9cd3f522ce426e715033e3d
|
||||
F autoconf/tea/Makefile.in b438a7020446c8a8156e8d97c8914a04833da6fd
|
||||
F autoconf/tea/README 3e9a3c060f29a44344ab50aec506f4db903fb873
|
||||
F autoconf/tea/aclocal.m4 52c47aac44ce0ddb1f918b6993e8beb8eee88f43
|
||||
@@ -32,7 +32,7 @@ F autoconf/tea/win/rules.vc c511f222b80064096b705dbeb97060ee1d6b6d63
|
||||
F config.guess 226d9a188c6196f3033ffc651cbc9dcee1a42977
|
||||
F config.h.in 6376abec766e9a0785178b1823b5a587e9f1ccbc
|
||||
F config.sub 9ebe4c3b3dab6431ece34f16828b594fb420da55
|
||||
F configure 9af547be0e0e1a8fca8553b82599b5a3be1528a3d78deb68cb49d3b611215cb7 x
|
||||
F configure 2c71f331b463e987567a2dd942f728534f1aa7a174551e08a7b31b328e9da4ff x
|
||||
F configure.ac d4529ebb26ae046269334f1dac65f2b1d6927c2efe22b2ec24dce24dfe4f83dd
|
||||
F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad
|
||||
F doc/lemon.html 278113807f49d12d04179a93fab92b5b917a08771152ca7949d34e928efa3941
|
||||
@@ -43,9 +43,9 @@ F ext/async/README.txt e12275968f6fde133a80e04387d0e839b0c51f91
|
||||
F ext/async/sqlite3async.c 0f3070cc3f5ede78f2b9361fb3b629ce200d7d74
|
||||
F ext/async/sqlite3async.h f489b080af7e72aec0e1ee6f1d98ab6cf2e4dcef
|
||||
F ext/expert/README.md b321c2762bb93c18ea102d5a5f7753a4b8bac646cb392b3b437f633caf2020c3
|
||||
F ext/expert/expert.c 4791c5e064aea81b2b829fa95228b22283380ee370ea88a1e580103b75516ebf
|
||||
F ext/expert/expert.c d548d603a4cc9e61f446cc179c120c6713511c413f82a4a32b1e1e69d3f086a4
|
||||
F ext/expert/expert1.test fd21496d8e52c817a7741f467f42b0502c0ac7e07dcdd1d6e15a3e8154ed4e41
|
||||
F ext/expert/sqlite3expert.c 55ea02e9fcc014f4252e8a8c78d2bddc6d7ef62f9cb54ee283a659516eabb711
|
||||
F ext/expert/sqlite3expert.c 1dfa561e64dc0f89d56b96e6afda87468c34b43604c2df50c47e3f4362778fb2
|
||||
F ext/expert/sqlite3expert.h af6354f8ee5c9e025024e63fec3bd640a802afcc3099a44d804752cf0791d811
|
||||
F ext/expert/test_expert.c d56c194b769bdc90cf829a14c9ecbc1edca9c850b837a4d0b13be14095c32a72
|
||||
F ext/fts1/README.txt 20ac73b006a70bcfd80069bdaf59214b6cf1db5e
|
||||
@@ -96,7 +96,7 @@ F ext/fts3/fts3_tokenizer.h 64c6ef6c5272c51ebe60fc607a896e84288fcbc3
|
||||
F ext/fts3/fts3_tokenizer1.c 5c98225a53705e5ee34824087478cf477bdb7004
|
||||
F ext/fts3/fts3_unicode.c 525a3bd9a7564603c5c061b7de55403a565307758a94600e8a2f6b00d1c40d9d
|
||||
F ext/fts3/fts3_unicode2.c cc04fc672bfd42b1e650398cb0bf71f64f9aae032cfe75bbcfe75b9cf966029c
|
||||
F ext/fts3/fts3_write.c a3f7bf869622d1d0aa66661ba71d88e6f9646d69a2c335f40a0addf25974db47
|
||||
F ext/fts3/fts3_write.c b583dede85eb0c3c3026f8d7ccb781ea4e845ae583754fecb2ca425b5907d87d
|
||||
F ext/fts3/fts3speed.tcl b54caf6a18d38174f1a6e84219950d85e98bb1e9
|
||||
F ext/fts3/mkfts3amal.tcl 252ecb7fe6467854f2aa237bf2c390b74e71f100
|
||||
F ext/fts3/tool/fts3cov.sh c331d006359456cf6f8f953e37f2b9c7d568f3863f00bb5f7eb87fea4ac01b73
|
||||
@@ -111,12 +111,12 @@ F ext/fts5/fts5Int.h eda28e3a0a5d87c412e8355fe35da875b04cb389908c8eb0d867ad662ad
|
||||
F ext/fts5/fts5_aux.c ca666a3bbe07c5a3bbe9fffaea19c935a1efaf337333e28bad7bdd1971ffd093
|
||||
F ext/fts5/fts5_buffer.c 1dd1ec0446b3acfc2d7d407eb894762a461613e2695273f48e449bfd13e973ff
|
||||
F ext/fts5/fts5_config.c 5af9c360e99669d29f06492c370892394aba0857
|
||||
F ext/fts5/fts5_expr.c 01048018d21524e2c302b063ff5c3cdcf546e03297215e577205d85b47499deb
|
||||
F ext/fts5/fts5_expr.c c23a2e4c14c401a147c4a730460e5b37057627bf4be95515ee281cd87f4d277c
|
||||
F ext/fts5/fts5_hash.c 32be400cf761868c9db33efe81a06eb19a17c5402ad477ee9efb51301546dd55
|
||||
F ext/fts5/fts5_index.c 5fe14375a29e8a7aa8f3e863babe180a19269206c254c8f47b216821d4ac1e15
|
||||
F ext/fts5/fts5_index.c 22b71d0e9e4b3ddd123a39ae27174e0012da2806f91b64087a68584f13f189de
|
||||
F ext/fts5/fts5_main.c 24868f88ab2a865defbba7a92eebeb726cc991eb092b71b5f5508f180c72605b
|
||||
F ext/fts5/fts5_storage.c fb5ef3c27073f67ade2e1bea08405f9e43f68f5f3676ed0ab7013bce5ba10be6
|
||||
F ext/fts5/fts5_tcl.c b470467be4c5cab2d8b026992c05d86cd2293e7d8c4a10ba56d5f4f707981097
|
||||
F ext/fts5/fts5_storage.c 4bec8a1b3905978b22a67bca5f4a3cfdb94af234cf51efb36f4f2d733d278634
|
||||
F ext/fts5/fts5_tcl.c 39bcbae507f594aad778172fa914cad0f585bf92fd3b078c686e249282db0d95
|
||||
F ext/fts5/fts5_test_mi.c 65864ba1e5c34a61d409c4c587e0bbe0466eb4f8f478d85dc42a92caad1338e6
|
||||
F ext/fts5/fts5_test_tok.c ffd657dd67e7fcdb31bf63fb60b6d867299a581d0f46e97086abacd66c2a9b26
|
||||
F ext/fts5/fts5_tokenize.c 2ce7b44183538ec46b7907726262ee43ffdd39a8
|
||||
@@ -126,7 +126,7 @@ F ext/fts5/fts5_vocab.c 1cd79854cb21543e66507b25b0578bc1b20aa6a1349b7feceb8e8fed
|
||||
F ext/fts5/fts5parse.y eb526940f892ade5693f22ffd6c4f2702543a9059942772526eac1fde256bb05
|
||||
F ext/fts5/mkportersteps.tcl 5acf962d2e0074f701620bb5308155fa1e4a63ba
|
||||
F ext/fts5/test/fts5_common.tcl b01c584144b5064f30e6c648145a2dd6bc440841
|
||||
F ext/fts5/test/fts5aa.test cba3fae6466446980caf1b9f5f26df77f95a999d35db7d932d6e82ae7ba0ede9
|
||||
F ext/fts5/test/fts5aa.test 6e2fdb0ee667c05f41921e7ec345cae874be651670900918e9ccc539514b9356
|
||||
F ext/fts5/test/fts5ab.test 9205c839332c908aaad2b01ab8670ece8b161e8f2ec8a9fabf18ca9385880bb7
|
||||
F ext/fts5/test/fts5ac.test a7aa7e1fefc6e1918aa4d3111d5c44a09177168e962c5fd2cca9620de8a7ed6d
|
||||
F ext/fts5/test/fts5ad.test e8cf959dfcd57c8e46d6f5f25665686f3b6627130a9a981371dafdf6482790de
|
||||
@@ -165,10 +165,10 @@ F ext/fts5/test/fts5fault2.test 69c8fdbef830cd0d450908d4504d5bb86609e255af99c421
|
||||
F ext/fts5/test/fts5fault3.test da2f9e3e56ff5740d68ebdd6877c97089e7ed28ddff28a0da87a6afea27e5522
|
||||
F ext/fts5/test/fts5fault4.test 1c1db5fcfe59401e7833146100f1d8de284a0a686fac31ddac9fb56c459f725b
|
||||
F ext/fts5/test/fts5fault5.test a336e4e11847de24c9497f80cce18e00bb3fab7fb11f97d04eb9af898900a762
|
||||
F ext/fts5/test/fts5fault6.test 8a3c61402e36960ba46a419e73121fcefdc9160e0c04b6f5318c7fb0e3180dbc
|
||||
F ext/fts5/test/fts5fault6.test a0fc0a8f99e4b16500c31dfc7e38e1defe0f1693ac47650517ac7b723b1956f8
|
||||
F ext/fts5/test/fts5fault7.test 0acbec416edb24b8881f154e99c31e9ccf73f539cfcd164090be139e9e97ed4c
|
||||
F ext/fts5/test/fts5fault8.test 318238659d35f82ad215ecb57ca4c87486ea85d45dbeedaee42f148ff5105ee2
|
||||
F ext/fts5/test/fts5fault9.test 0111b229388bdf251b91cfead68580227801dd30960a19aa8fe9021a1e73cb6d
|
||||
F ext/fts5/test/fts5fault9.test 098e6b894bbdf9b2192f994a30f4043673fb3f338b6b8ab1624c704422f39119
|
||||
F ext/fts5/test/fts5faultA.test be4487576bff8c22cee6597d1893b312f306504a8c6ccd3c53ca85af12290c8c
|
||||
F ext/fts5/test/fts5faultB.test e6d04f9ea7b21be1d89abb8df2cb4baf65b0453b744d5a805fcd3ef45ff86a7e
|
||||
F ext/fts5/test/fts5faultD.test cc5d1225556e356615e719c612e845d41bff7d5a
|
||||
@@ -268,32 +268,33 @@ F ext/lsm1/tool/mklsm1c.tcl f31561bbee5349f0a554d1ad7236ac1991fc09176626f529f607
|
||||
F ext/misc/README.md d6dd0fe1d8af77040216798a6a2b0c46c73054d2f0ea544fbbcdccf6f238c240
|
||||
F ext/misc/amatch.c 6db4607cb17c54b853a2d7c7c36046d004853f65b9b733e6f019d543d5dfae87
|
||||
F ext/misc/anycollseq.c 5ffdfde9829eeac52219136ad6aa7cd9a4edb3b15f4f2532de52f4a22525eddb
|
||||
F ext/misc/appendvfs.c 4c65f0b79686ae5a483134233d7fd912f0f2d4fd76023404f96f2290fff13b19
|
||||
F ext/misc/btreeinfo.c d7fd9a2fe2fa33ba28488e2fce703ebecc759219ea9e0bb3b254784866c0a676
|
||||
F ext/misc/appendvfs.c 3777f22ec1057dc4e5fd89f2fbddcc7a29fbeef1ad038c736c54411bb1967af7
|
||||
F ext/misc/btreeinfo.c 78c8c57d325185ccc04b7679e5b020e34a4d9c87453e6b7ac943d0a26cee3256
|
||||
F ext/misc/carray.c ed96c218ea940b85c9a274c4d9c59fe9491c299147a38a8bba537687bd6c6005
|
||||
F ext/misc/closure.c 0d2a038df8fbae7f19de42e7c7d71f2e4dc88704
|
||||
F ext/misc/completion.c 52c3f01523e3e387eb321b4739a89d1fe47cbe6025aa1f2d8d3685e9e365df0f
|
||||
F ext/misc/compress.c dd4f8a6d0baccff3c694757db5b430f3bbd821d8686d1fc24df55cf9f035b189
|
||||
F ext/misc/csv.c 1a009b93650732e22334edc92459c4630b9fa703397cbb3c8ca279921a36ca11
|
||||
F ext/misc/dbdump.c 3509fa6b8932d04e932d6b6b827b6a82ca362781b8e8f3c77336f416793e215e
|
||||
F ext/misc/dbdump.c 22018e00eb50e9ebf9067c92d4e7162dc5006a3efc4e0c19bc3829825a1043b0
|
||||
F ext/misc/eval.c f971962e92ebb8b0a4e6b62949463ee454d88fa2
|
||||
F ext/misc/fileio.c 1194228c96d6b7a374e93602e2ba1899b42d0fc4d4c5253962fb13e1c9ed1f77
|
||||
F ext/misc/fileio.c da441efc13c0fa96a41b168bb8aa1014b12d36f3a0d619a2b77b3bdf2a3ccf5e
|
||||
F ext/misc/fuzzer.c 7c64b8197bb77b7d64eff7cac7848870235d4c25
|
||||
F ext/misc/ieee754.c f190d0cc5182529acb15babd177781be1ac1718c
|
||||
F ext/misc/json1.c dbe086615b9546c156bf32b9378fc09383b58bd17513b866cfd24c1e15281984
|
||||
F ext/misc/memvfs.c ab36f49e02ebcdf85a1e08dc4d8599ea8f343e073ac9e0bca18a98b7e1ec9567
|
||||
F ext/misc/mmapwarm.c 70b618f2d0bde43fae288ad0b7498a629f2b6f61b50a27e06fae3cd23c83af29
|
||||
F ext/misc/nextchar.c 35c8b8baacb96d92abbb34a83a997b797075b342
|
||||
F ext/misc/normalize.c 19262ef3ef29d4de2f281b423326865c8916c63d0cb09f1dc98d24d5c1e8ba64
|
||||
F ext/misc/percentile.c 92699c8cd7d517ff610e6037e56506f8904dae2e
|
||||
F ext/misc/regexp.c a68d25c659bd2d893cd1215667bbf75ecb9dc7d4
|
||||
F ext/misc/remember.c add730f0f7e7436cd15ea3fd6a90fd83c3f706ab44169f7f048438b7d6baa69c
|
||||
F ext/misc/rot13.c 540a169cb0d74f15522a8930b0cccdcb37a4fd071d219a5a083a319fc6e8db77
|
||||
F ext/misc/scrub.c 1c5bfb8b0cd18b602fcb55755e84abf0023ac2fb
|
||||
F ext/misc/scrub.c db9fff56fed322ca587d73727c6021b11ae79ce3f31b389e1d82891d144f22ad
|
||||
F ext/misc/series.c f3c0dba5c5c749ce1782b53076108f87cf0b71041eb6023f727a9c50681da564
|
||||
F ext/misc/sha1.c 0b9e9b855354910d3ca467bf39099d570e73db56
|
||||
F ext/misc/shathree.c 9e960ba50483214c6a7a4b1517f8d8cef799e9db381195178c3fd3ad207e10c0
|
||||
F ext/misc/showauth.c 732578f0fe4ce42d577e1c86dc89dd14a006ab52
|
||||
F ext/misc/spellfix.c 41cf26c6b89fcaa8798ae10ae64d39c1f1d9d6995152e545bd491c13058b8fac
|
||||
F ext/misc/spellfix.c b3a644285cb008f3c10ed4cf04e17adcbc7d62c3911c79d786dfc91c177534f0
|
||||
F ext/misc/sqlar.c 57d5bc45cd5492208e451f697404be88f8612527d64c9d42f96b325b64983d74
|
||||
F ext/misc/stmt.c 6f16443abb3551e3f5813bb13ba19a30e7032830015b0f92fe0c0453045c0a11
|
||||
F ext/misc/totype.c 4a167594e791abeed95e0a8db028822b5e8fe512
|
||||
@@ -303,7 +304,8 @@ F ext/misc/vfsstat.c bf10ef0bc51e1ad6756629e1edb142f7a8db1178
|
||||
F ext/misc/vtablog.c 31d0d8f4406795679dcd3a67917c213d3a2a5fb3ea5de35f6e773491ed7e13c9
|
||||
F ext/misc/vtshim.c 1976e6dd68dd0d64508c91a6dfab8e75f8aaf6cd
|
||||
F ext/misc/wholenumber.c 784b12543d60702ebdd47da936e278aa03076212
|
||||
F ext/misc/zipfile.c cbf9dfaf94c25dfd835e79c1474fdc75517a45a37916dec66623b0937af10e51
|
||||
F ext/misc/zipfile.c 316c771140fe54c17729138f139c7d94b13674b375ccfbb1e6e30202d835e8c8
|
||||
F ext/misc/zorder.c b0ff58fa643afa1d846786d51ea8d5c4b6b35aa0254ab5a82617db92f3adda64
|
||||
F ext/rbu/rbu.c ea7d1b7eb44c123a2a619332e19fe5313500705c4a58aaa1887905c0d83ffc2e
|
||||
F ext/rbu/rbu1.test 43836fac8c7179a358eaf38a8a1ef3d6e6285842
|
||||
F ext/rbu/rbu10.test 1846519a438697f45e9dcb246908af81b551c29e1078d0304fae83f1fed7e9ee
|
||||
@@ -330,6 +332,7 @@ F ext/rbu/rbufault2.test 9a7f19edd6ea35c4c9f807d8a3db0a03a5670c06
|
||||
F ext/rbu/rbufault3.test 0913c1aeaee266d9c36c33179341a5a504aad7d423d1979cfec43c8346a29899
|
||||
F ext/rbu/rbufault4.test 34e70701cbec51571ffbd9fbf9d4e0f2ec495ca7
|
||||
F ext/rbu/rbufts.test a2bbd202c9321fba15fb4a62a90add7d70e07bd8404e1e598135adbfff8a0508
|
||||
F ext/rbu/rbumulti.test 2cf153ab3d5861ff26517dc6cbaec430787a59f1d50e8771fe7a7529a0551cf1
|
||||
F ext/rbu/rbuprogress.test 1849d4e0e50616edf5ce75ce7db86622e656b5cf
|
||||
F ext/rbu/rburesume.test 8acb77f4a422ff55acfcfc9cc15a5cb210b1de83
|
||||
F ext/rbu/rbusave.test 0f43b6686084f426ddd040b878426452fd2c2f48
|
||||
@@ -343,20 +346,20 @@ F ext/repair/README.md 92f5e8aae749a4dae14f02eea8e1bb42d4db2b6ce5e83dbcdd6b14469
|
||||
F ext/repair/checkfreelist.c 0dbae18c1b552f58d64f8969e4fb1e7f11930c60a8c2a9a8d50b7f15bdfd54bd
|
||||
F ext/repair/checkindex.c 7d28c01a2e012ac64257d230fc452b2cafb78311a91a343633d01d95220f66f3
|
||||
F ext/repair/sqlite3_checker.c.in 4a5a3af3f450fe503e5a2985e98516dc2a6b9ad247449e284c1cf140fc91720f
|
||||
F ext/repair/sqlite3_checker.tcl cc69e7fbc163f94da4a6400609be001543442d9f8f57a797d1eeb7b897585730
|
||||
F ext/repair/sqlite3_checker.tcl a9a2caa9660567257c177a91124d8c0dccdfa341e25c51e6da7f1fd9e601eafa
|
||||
F ext/repair/test/README.md 34b2f542cf5be7bffe479242b33ee3492cea30711e447cc4a1a86cb5915f419e
|
||||
F ext/repair/test/checkfreelist01.test 3e8aa6aeb4007680c94a8d07b41c339aa635cc78249442da72ff3f8297398a69
|
||||
F ext/repair/test/checkindex01.test 6945d0ffc0c1dc993b2ce88036b26e0f5d6fcc65da70fc9df27c2647bb358b0f
|
||||
F ext/repair/test/test.tcl 686d76d888dffd021f64260abf29a55c57b2cedfa7fc69150b42b1d6119aac3c
|
||||
F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761
|
||||
F ext/rtree/rtree.c 2111f685ae07988622c241f819b56fea60782f56e32f97e334473c59f6083481
|
||||
F ext/rtree/rtree.h 834dbcb82dc85b2481cde6a07cdadfddc99e9b9e
|
||||
F ext/rtree/rtree1.test 82a353747fcab1083d114b2ac84723dfefdbf86c1a6e1df57bf588c7d4285436
|
||||
F ext/rtree/rtree.c bc61010e978b5b8ae6dbb90274a2fbb5db5ff5e2880b5c6e8abd48eea77264db
|
||||
F ext/rtree/rtree.h 4a690463901cb5e6127cf05eb8e642f127012fd5003830dbc974eca5802d9412
|
||||
F ext/rtree/rtree1.test 47e2095bebea6813754fd7afa6a20e2b7b4ebcd5cb7dbcb6932b6c9f86bbf972
|
||||
F ext/rtree/rtree2.test 5f25b01acd03470067a2d52783b2eb0a50bf836803d4342d20ca39e541220fe2
|
||||
F ext/rtree/rtree3.test 2cafe8265d1ff28f206fce88d114f208349df482
|
||||
F ext/rtree/rtree4.test 67b021858ba4334c8d49b3449476942c2ce0e5ef7123538f2e9dd508ed03a12d
|
||||
F ext/rtree/rtree5.test 8aaa4bcdc42f718fe165572f5623e4732831aca95a2bc32482d33d4d2cf1325d
|
||||
F ext/rtree/rtree6.test 773a90db2dce6a8353dd0d5b64bca69b29761196
|
||||
F ext/rtree/rtree4.test 304de65d484540111b896827e4261815e5dca4ce28eeecd58be648cd73452c4b
|
||||
F ext/rtree/rtree5.test 49c9041d713d54560b315c2c7ef7207ee287eba1b20f8266968a06f2e55d3142
|
||||
F ext/rtree/rtree6.test 916a641d2beac01b9880871ff07612d56c1e466190a27c82ab36ffd58be03b9f
|
||||
F ext/rtree/rtree7.test c8fb2e555b128dd0f0bdb520c61380014f497f8a23c40f2e820acc9f9e4fdce5
|
||||
F ext/rtree/rtree8.test 649f5a37ec656028a4a32674b9b1183104285a7625a09d2a8f52a1cef72c93f2
|
||||
F ext/rtree/rtree9.test c646f12c8c1c68ef015c6c043d86a0c42488e2e68ed1bb1b0771a7ca246cbabf
|
||||
@@ -366,7 +369,7 @@ F ext/rtree/rtreeC.test d9d06dda1aee68b4dc227dfcc899f335f8b621e9d1920ee3d4e5dab8
|
||||
F ext/rtree/rtreeD.test fe46aa7f012e137bd58294409b16c0d43976c3bb92c8f710481e577c4a1100dc
|
||||
F ext/rtree/rtreeE.test e65d3fc625da1800b412fc8785817327d43ccfec5f5973912d8c9e471928caa9
|
||||
F ext/rtree/rtreeF.test 81ffa7ef51c4e4618d497a57328c265bf576990c7070633b623b23cd450ed331
|
||||
F ext/rtree/rtreeG.test fd3af1ca944a0bdb0cbb5455a4905c9f012e2fffcab6b791f07afa0dcbbcae0e
|
||||
F ext/rtree/rtreeG.test 1b9ca6e3effb48f4161edaa463ddeaa8fca4b2526d084f9cbf5dbe4e0184939c
|
||||
F ext/rtree/rtree_perf.tcl 6c18c1f23cd48e0f948930c98dfdd37dfccb5195
|
||||
F ext/rtree/rtree_util.tcl db734b4c5e75fed6acc56d9701f2235345acfdec750b5fc7b587936f5f6bceed
|
||||
F ext/rtree/rtreecheck.test 4d29103d1e16fcbf90135d1c637b833688492b063b2971dfb5dc6ba76555cfee
|
||||
@@ -378,7 +381,7 @@ F ext/session/changeset.c 4ccbaa4531944c24584bf6a61ba3a39c62b6267a
|
||||
F ext/session/session1.test 736d7ff178662f0b717c37f46531b84a5ce0210ccb0c4edf629c55dbcbbc3ea1
|
||||
F ext/session/session2.test 284de45abae4cc1082bc52012ee81521d5ac58e0
|
||||
F ext/session/session3.test ce9ce3dfa489473987f899e9f6a0f2db9bde3479
|
||||
F ext/session/session4.test 457b02bdc349eb01151e54de014df77abd3c08c8
|
||||
F ext/session/session4.test 3eea8058643e5adbd3293a5c553255c35e774ed90e7cbec09c9b010d176ad396
|
||||
F ext/session/session5.test 716bc6fafd625ce60dfa62ae128971628c1a1169
|
||||
F ext/session/session6.test 443789bc2fca12e4f7075cf692c60b8a2bea1a26
|
||||
F ext/session/session8.test 8e194b3f655d861ca36de5d4de53f702751bab3b
|
||||
@@ -386,19 +389,21 @@ F ext/session/session9.test 5409d90d8141881d08285ed1c2c0d8d10fb92069
|
||||
F ext/session/sessionA.test 1feeab0b8e03527f08f2f1defb442da25480138f
|
||||
F ext/session/sessionB.test 886252dcb7e692e62ef7e357456200912e367823
|
||||
F ext/session/sessionC.test 97556f5164ac29f2344b24bd7de6a3a35a95c390
|
||||
F ext/session/sessionD.test d4744c78334162851d2a2f285c7e603e31b49aa2
|
||||
F ext/session/sessionD.test d3617e29aa15c9413aee5286d99587633245d58d2ad28f3f331c822735418a22
|
||||
F ext/session/sessionE.test 0a616c4ad8fd2c05f23217ebb6212ef80b7fef30f5f086a6633a081f93e84637
|
||||
F ext/session/sessionF.test c2f178d4dfd723a5fd94a730ea2ccb44c669e3ce
|
||||
F ext/session/sessionG.test 01ef705096a9d3984eebdcca79807a211dee1b60
|
||||
F ext/session/sessionG.test 63f9a744341d670775af29e4f19c1ef09a4810798400f28cd76704803a2e56ff
|
||||
F ext/session/sessionH.test 332b60e4c2e0a680105e11936201cabe378216f307e2747803cea56fa7d9ebae
|
||||
F ext/session/session_common.tcl 7776eda579773113b30c7abfd4545c445228cb73
|
||||
F ext/session/session_speed_test.c edc1f96fd5e0e4b16eb03e2a73041013d59e8723
|
||||
F ext/session/sessionat.test feb7d22b3124882064b9d9df69f5484a9bb8c123dc9ddc6ffcd357521848139f
|
||||
F ext/session/sessionat.test efe88965e74ff1bc2af9c310b28358c02d420c1fb2705cc7a28f0c1cc142c3ec
|
||||
F ext/session/sessiondiff.test ad13dd65664bae26744e1f18eb3cbd5588349b7e9118851d8f9364248d67bcec
|
||||
F ext/session/sessionfault.test da273f2712b6411e85e71465a1733b8501dbf6f7
|
||||
F ext/session/sessionfault2.test 04aa0bc9aa70ea43d8de82c4f648db4de1e990b0
|
||||
F ext/session/sessionstat1.test 41cd97c2e48619a41cdf8ae749e1b25f34719de638689221aa43971be693bf4e
|
||||
F ext/session/sessionwor.test 2f3744236dc8b170a695b7d8ddc8c743c7e79fdc
|
||||
F ext/session/sqlite3session.c cc127222a9ea6f4eaa31281aa9da924f5244f6099be0ee526c950684fb3513a6
|
||||
F ext/session/sqlite3session.h cb4d860101ba6d3ac810f18684539b766d24d668fa2436cdde90d711af9464fb
|
||||
F ext/session/sqlite3session.c 9edfaaa74977ddecd7bbd94e8f844d9b0f6eec22d1d547e806361670db814c1e
|
||||
F ext/session/sqlite3session.h 2e1584b030fbd841cefdce15ba984871978d305f586da2d1972f6e1958fa10b1
|
||||
F ext/session/test_session.c eb0bd6c1ea791c1d66ee4ef94c16500dad936386
|
||||
F ext/userauth/sqlite3userauth.h 7f3ea8c4686db8e40b0a0e7a8e0b00fac13aa7a3
|
||||
F ext/userauth/user-auth.txt e6641021a9210364665fe625d067617d03f27b04
|
||||
@@ -406,7 +411,7 @@ F ext/userauth/userauth.c 3410be31283abba70255d71fd24734e017a4497f
|
||||
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
|
||||
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
|
||||
F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60
|
||||
F main.mk fc0edb268998a049ce70ee3dc056b2a96cc8aa4ef0c6da296700d7081d167627
|
||||
F main.mk 63668484c95454af7fc04a384da27ac556f27368d6d0c345e405e1677c66768f
|
||||
F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83
|
||||
F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
|
||||
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
|
||||
@@ -419,81 +424,82 @@ F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
|
||||
F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786
|
||||
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
|
||||
F src/alter.c cf7a8af45cb0ace672f47a1b29ab24092a9e8cd8d945a9974e3b5d925f548594
|
||||
F src/analyze.c 0d0ccf7520a201d8747ea2f02c92c26e26f801bc161f714f27b9f7630dde0421
|
||||
F src/attach.c 84c477e856b24c2b9a0983b438a707c0cf4d616cee7a425401d418e58afec24c
|
||||
F src/analyze.c 6b42e36a5dcc2703a771f2411bd5e99524bd62c7ecde209bb88dfb04c72f046e
|
||||
F src/attach.c f6f212c43dddba79dfcb723fb9470785f3ff55bde8953cd9d2546f3022070a41
|
||||
F src/auth.c 6277d63837357549fe14e723490d6dc1a38768d71c795c5eb5c0f8a99f918f73
|
||||
F src/backup.c faf17e60b43233c214aae6a8179d24503a61e83b
|
||||
F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33
|
||||
F src/btmutex.c 0e9ce2d56159b89b9bc8e197e023ee11e39ff8ca
|
||||
F src/btree.c 0a1f63b50ab1ac5d4b1637c30cb1ae123fbc162ec8cb6336ddb9491a0bc1e363
|
||||
F src/btree.c 18a53540aa35dbdf77f715ea928422a4ed9011dc16ea7b50f803fd1617fcc4f5
|
||||
F src/btree.h 0866c0a08255142ea0e754aabd211c843cab32045c978a592a43152405ed0c84
|
||||
F src/btreeInt.h 55b702efce17e5d1941865464227d3802cfc9c7c832fac81d4c94dced47a71fc
|
||||
F src/build.c 9f9647454f236cab097f266ae970f899b53c71cadab6756c47e2b2e81392c2a1
|
||||
F src/btreeInt.h 620ab4c7235f43572cf3ac2ac8723cbdf68073be4d29da24897c7b77dda5fd96
|
||||
F src/build.c 8b53aacc26944bb7fd9ab5ddeedecb4cc7c4b84df3a420cf6d2b8f772ad421df
|
||||
F src/callback.c fe677cb5f5abb02f7a772a62a98c2f516426081df68856e8f2d5f950929b966a
|
||||
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
|
||||
F src/ctime.c ff1be3eed7bdd75aaca61ca8dc848f7c9f850ef2fb9cb56f2734e922a098f9c0
|
||||
F src/date.c ebe1dc7c8a347117bb02570f1a931c62dd78f4a2b1b516f4837d45b7d6426957
|
||||
F src/dbpage.c 8db4c97f630e7d83f884ea75caf1ffd0988c160e9d530194d93721c80821e0f6
|
||||
F src/dbstat.c 7a4ba8518b6369ef3600c49cf9c918ad979acba610b2aebef1b656d649b96720
|
||||
F src/delete.c 74667ad914ac143731a444a1bacf29ceb18f6eded8a0dd17aafae80baa07f8bb
|
||||
F src/expr.c ad6e7a9c34a4bab9d10cc857d647ae7ce370a633b5c0bfa71f1c29b81ae364b8
|
||||
F src/delete.c 20c8788451dc737a967c87ea53ad43544d617f5b57d32ccce8bd52a0daf9e89b
|
||||
F src/expr.c 904f85e5f5fa232488cbb662fcf3306ae203728751468670fb9840a9b1886abc
|
||||
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
|
||||
F src/fkey.c d617daf66b5515e2b42c1405b2b4984c30ca50fb705ab164271a9bf66c69e331
|
||||
F src/func.c bd528d5ed68ce5cbf78a762e3b735fa75009f7197ff07fab07fd771f35ebaa1b
|
||||
F src/global.c ac3094f1dc59fbeb919aef7cc0cc827a8459d1fb1adb7972ef75bd9e0c10b75b
|
||||
F src/func.c 94f42cba2cc1c34aeaa441022ba0170ec3fec4bba54db4e0ded085c6dc0fdc51
|
||||
F src/global.c 01506976bd75e5e7b977207a6a05062e2dd0050012f8071be06bbea22ec6d69a
|
||||
F src/hash.c a12580e143f10301ed5166ea4964ae2853d3905a511d4e0c44497245c7ce1f7a
|
||||
F src/hash.h ab34c5c54a9e9de2e790b24349ba5aab3dbb4fd4
|
||||
F src/hwtime.h 747c1bbe9df21a92e9c50f3bbec1de841dc5e5da
|
||||
F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
|
||||
F src/insert.c 14686083cedc198540b15a79586cdd4be2acf6d5fa97627e355f817ab07e9fee
|
||||
F src/legacy.c 134ab3e3fae00a0f67a5187981d6935b24b337bcf0f4b3e5c9fa5763da95bf4e
|
||||
F src/loadext.c 55bcc3c741059a1056859e8adaf133aa179e22be12215c0936b2f354ef71209b
|
||||
F src/main.c 26918d50dd4a61b8f6f210320a522f46b5e7e592335b6aa664ab15b80b7c239b
|
||||
F src/loadext.c f6e4e416a736369f9e80eba609f0acda97148a8b0453784d670c78d3eed2f302
|
||||
F src/main.c c1e97e4c6fffff1fb1a6f1c48807386819af78657b4ae4acfd6d6d17353b8277
|
||||
F src/malloc.c 07295435093ce354c6d9063ac05a2eeae28bd251d2e63c48b3d67c12c76f7e18
|
||||
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
|
||||
F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de
|
||||
F src/mem2.c f1940d9e91948dd6a908fbb9ce3835c36b5d83c3
|
||||
F src/mem3.c 8768ac94694f31ffaf8b4d0ea5dc08af7010a35a
|
||||
F src/mem5.c 9bf955937b07f8c32541c8a9991f33ce3173d944
|
||||
F src/memdb.c 2bcebf99f77270e4b30ee5fad749347a6296db1662b3a196593e5410780aea85
|
||||
F src/memjournal.c 6f3d36a0a8f72f48f6c3c722f04301ac64f2515435fa42924293e46fc7994661
|
||||
F src/msvc.h 4942752b6a253116baaa8de75256c51a459a5e81
|
||||
F src/mutex.c b021263554c8a3995e9d53193b8194b96d1ed28e06c3b532dd7f7d29cf0c7d53
|
||||
F src/mutex.h 779d588e3b7756ec3ecf7d78cde1d84aba414f85
|
||||
F src/mutex_noop.c 9d4309c075ba9cc7249e19412d3d62f7f94839c4
|
||||
F src/mutex_unix.c 27bb6cc49485ee46711a6580ab7b3f1402211d23
|
||||
F src/mutex_w32.c a898fa969823b100c0f5fdc57e54c9a1e419ab4d
|
||||
F src/mutex_unix.c aaf9ebc3f89df28483c52208497a99a02cc3650011422fc9d4c57e4392f7fe58
|
||||
F src/mutex_w32.c 7670d770c94bbfe8289bec9d7f1394c5a00a57c37f892aab6b6612d085255235
|
||||
F src/notify.c 9711a7575036f0d3040ba61bc6e217f13a9888e7
|
||||
F src/os.c 22d31db3ca5a96a408fbf1ceeaaebcaf64c87024d2ff9fe1cf2ddbec3e75c104
|
||||
F src/os.h 48388821692e87da174ea198bf96b1b2d9d83be5dfc908f673ee21fafbe0d432
|
||||
F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85
|
||||
F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586
|
||||
F src/os_unix.c ecdffdc7fc25c07e42908be7c5ea30456fee6263e0d54cdf204557945b445da2
|
||||
F src/os_win.c 0a4afa35cc8e812000df3ea2f64b476131b39e29e75d8007d0504726e4761de4
|
||||
F src/os_unix.c 928586cbde31890538854f1657463392d63b2d7794f577774573ae53ec283d7b
|
||||
F src/os_win.c eb03c6d52f893bcd7fdd4c6006674c13c1b5e49543fec98d605201af2997171c
|
||||
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
|
||||
F src/pager.c 9b9cb4e06c03d43d62480a7a685a012d645fcf3a39e7767ccb505fb41ee083ec
|
||||
F src/pager.c 3e3b659b6b3f40b5a5efef6b8890ced490c397a81d96feb5266fde1f7362e608
|
||||
F src/pager.h 581698f2177e8bd4008fe4760898ce20b6133d1df22139b9101b5155f900df7a
|
||||
F src/parse.y 4e750e1b261ff9f1d0b6b5d40a829c66d691899f48953fde839d8b52d41aa148
|
||||
F src/pcache.c 7ae91a4557a43d77d449accbfdc68846e6516f8e2eda46e8bbe4536fb669b201
|
||||
F src/parse.y 3be4b2b5e33ef7dab3128b765898ee786fc6cd698a7f053f756a68f2f238f0aa
|
||||
F src/pcache.c 135ef0bc6fb2e3b7178d49ab5c9176254c8a691832c1bceb1156b2fbdd0869bd
|
||||
F src/pcache.h 072f94d29281cffd99e46c1539849f248c4b56ae7684c1f36626797fee375170
|
||||
F src/pcache1.c 716975564c15eb6679e97f734cec1bfd6c16ac3d4010f05f1f8e509fc7d19880
|
||||
F src/pragma.c bea56df3ae0637768c0da4fbbb8f2492f780980d95000034a105ff291bf7ca69
|
||||
F src/pragma.h bb83728944b42f6d409c77f5838a8edbdb0fe83046c5496ffc9602b40340a324
|
||||
F src/prepare.c 259f4e7960c47082c9653f3d5f0c294abd68bb9c3aab86de7630700cba1c20fb
|
||||
F src/printf.c 9506b4b96e59c0467047155f09015750cb2878aeda3d39e5610c1192ddc3c41c
|
||||
F src/prepare.c b086fea6a1952db88beca31fdd621201ee5e4ce3f02905248cc3035a8174aa89
|
||||
F src/printf.c d3b7844ddeb11fbbdd38dd84d09c9c1ac171d21fb038473c3aa97981201cc660
|
||||
F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
|
||||
F src/resolve.c bbee7e31d369a18a2f4836644769882e9c5d40ef4a3af911db06410b65cb3730
|
||||
F src/resolve.c 66c73fcb7719b8ff0e841b58338f13604ff3e2b50a723f9b8f383595735262f6
|
||||
F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac
|
||||
F src/select.c 8b22abe193e4d8243befa2038e4ae2405802fed1c446e5e502d11f652e09ba74
|
||||
F src/shell.c.in b87abffd0db09203ad8a133d56fe8f154ace5ec0a14197a153fb7d80b1438c01
|
||||
F src/sqlite.h.in f83e63a48fb31fefc69c83bbe8700b4b44acdd64e440219087b0f14e35eeb8d4
|
||||
F src/select.c f02352ac5cbb6fad3804add825743b924cfb6c742ba2e8666d726828a9985d73
|
||||
F src/shell.c.in 9b7e7ac1ccdbc045e285e745ff6d21dbec6ce91330f2bdd5db50d5c39f40679e
|
||||
F src/sqlite.h.in 2619d00bccc0454e875bce5e90b1dc986f87975c267dd7bbbe251f1be297d2f3
|
||||
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
|
||||
F src/sqlite3ext.h c02d628cca67f3889c689d82d25c3eb45e2c155db08e4c6089b5840d64687d34
|
||||
F src/sqliteInt.h fd8702c65994d7de3e2d8f7d85d958731da1ed29476571fdfa2290fd8ec0bf80
|
||||
F src/sqlite3ext.h 83a3c4ce93d650bedfd1aa558cb85a516bd6d094445ee989740827d0d944368d
|
||||
F src/sqliteInt.h 2ef60a6d9a50e6eef224e9eae71b29a9fb91c301e882d9fbbb77afd50b6cf815
|
||||
F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b
|
||||
F src/status.c 9737ed017279a9e0c5da748701c3c7bf1e8ae0dae459aad20dd64fcff97a7e35
|
||||
F src/status.c 46e7aec11f79dad50965a5ca5fa9de009f7d6bde08be2156f1538a0a296d4d0e
|
||||
F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34
|
||||
F src/tclsqlite.c 1833388c01e3b77f4c712185ee7250b9423ee0981ce6ae7e401e47db0319a696
|
||||
F src/test1.c b52f9e7fe62016d357c3266fcfa0793cc1883d3cb2b11dfa39fcba2e70b0305c
|
||||
F src/tclsqlite.c 916a92de77ec5cbe27818ca194d8cf0c58aa7ad5b87527098f6aa5a6068800ce
|
||||
F src/test1.c 1ab7cbbb6693e08364c1a9241e2aee17f8c4925e4cc52396be77ae6845a05828
|
||||
F src/test2.c 3efb99ab7f1fc8d154933e02ae1378bac9637da5
|
||||
F src/test3.c b8434949dfb8aff8dfa082c8b592109e77844c2135ed3c492113839b6956255b
|
||||
F src/test4.c 18ec393bb4d0ad1de729f0b94da7267270f3d8e6
|
||||
@@ -508,7 +514,7 @@ F src/test_backup.c bf5da90c9926df0a4b941f2d92825a01bbe090a0
|
||||
F src/test_bestindex.c 78809f11026f18a93fcfd798d9479cba37e1201c830260bf1edc674b2fa9b857
|
||||
F src/test_blob.c ae4a0620b478548afb67963095a7417cd06a4ec0a56adb453542203bfdcb31ce
|
||||
F src/test_btree.c 8b2dc8b8848cf3a4db93f11578f075e82252a274
|
||||
F src/test_config.c cc8a1d44648d9392a14f4ecfc841d027daaf61f952b9f70792edf11373aaa3dd
|
||||
F src/test_config.c 097c6189803886a1fb26ec37d8bc62b90512cb53ab79a1fb6d35196c1ec42ded
|
||||
F src/test_delete.c e2fe07646dff6300b48d49b2fee2fe192ed389e834dd635e3b3bac0ce0bf9f8f
|
||||
F src/test_demovfs.c a0c3bdd45ed044115c2c9f7779e56eafff18741e
|
||||
F src/test_devsym.c 1960abbb234b97e9b920f07e99503fc04b443f62bbc3c6ff2c2cea2133e3b8a2
|
||||
@@ -520,7 +526,7 @@ F src/test_intarray.c 988fc61cb0ff539f4172c0d95f15287c92516f64
|
||||
F src/test_intarray.h f3b7672f5d1056eac563c0d6ea8480a660b1475c
|
||||
F src/test_journal.c 619f2aa10e0d7a5f87c0f06825bc61dfce1c6b9c7f3ad990fb13de6c3b8874a3
|
||||
F src/test_loadext.c 337056bae59f80b9eb00ba82088b39d0f4fe6dfd
|
||||
F src/test_malloc.c 4f06a805de86be5216a127b3777ca2d5a1ff99d1a9238374ce136a47411be36c
|
||||
F src/test_malloc.c 5201422e2403e66a7a9c2b7d8df806acd8d2a0429822adb7e932f324e7b5b3c6
|
||||
F src/test_md5.c 7268e1e8c399d4a5e181b64ac20e1e6f3bc4dd9fc87abac02db145a3d951fa8c
|
||||
F src/test_multiplex.c e054459f7633f3ff8ce1245da724f9a8be189e4e
|
||||
F src/test_multiplex.h 5436d03f2d0501d04f3ed50a75819e190495b635
|
||||
@@ -542,34 +548,34 @@ F src/test_thread.c 911d15fb14e19c0c542bdc8aabf981c2f10a4858
|
||||
F src/test_vfs.c f0186261a24de2671d080bcd8050732f0cb64f6e
|
||||
F src/test_vfstrace.c bab9594adc976cbe696ff3970728830b4c5ed698
|
||||
F src/test_windirent.c a895e2c068a06644eef91a7f0a32182445a893b9a0f33d0cdb4283dca2486ac1
|
||||
F src/test_windirent.h 8782864172ba5ae52c5c313c70faeadb324ff74de9c3dcc6b56a557dccaa1de6
|
||||
F src/test_windirent.h 90dfbe95442c9762357fe128dc7ae3dc199d006de93eb33ba3972e0a90484215
|
||||
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
|
||||
F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
|
||||
F src/tokenize.c 5b0c661a85f783d35b9883830736eeb63be4aefc4f6b7d9cd081d48782c041e2
|
||||
F src/treeview.c eae35972ff44f67064de2eaf35f04afe94e7aea3271a8b3bcebb3f954880fec3
|
||||
F src/treeview.c e0d62678314abf0e1e6d09ea405f4de3f404a17b4641c2169c304b5edf509320
|
||||
F src/trigger.c a34539c69433276d37b0da9a89c117726ff2d292c0902895af1f393a983cd3a1
|
||||
F src/update.c 8bd52c38d6d426925be4488ee106db26d9ee344406315671ed246ddace8d6091
|
||||
F src/update.c a90a32ffc0100265b0693dbbdbe490756447af181f5ea2c138cce515b08c8795
|
||||
F src/utf.c 810fbfebe12359f10bc2a011520a6e10879ab2a163bcb26c74768eab82ea62a5
|
||||
F src/util.c 7315e97a8dc2c8e19ca64196c652cf0a65d13fd0a211b2cec082062372dc6261
|
||||
F src/vacuum.c 90839322fd5f00df9617eb21b68beda9b6e2a2937576b0d65985e4aeb1c53739
|
||||
F src/vdbe.c 4d0666741d884dfaceb6ac5bbededbd947068e4b742163898feea84a027dace6
|
||||
F src/vdbe.h d50cadf12bcf9fb99117ef392ce1ea283aa429270481426b6e8b0280c101fd97
|
||||
F src/vdbeInt.h a0969c14950bcc61b2dfa19c6f62b42c5012013fcda342ca927a192ed37e6592
|
||||
F src/vdbeapi.c f519346f6db99a1eb3f85ca3ae8aede9ff9c4d90fec809dae7cb946786b2e270
|
||||
F src/vdbeaux.c 7ae48b180e5dd5d282e6752d155f1ab7929196d8e6577b82742044188152ca85
|
||||
F src/util.c d9eb0a6c4aae1b00a7369eadd7ca0bbe946cb4c953b6751aa20d357c2f482157
|
||||
F src/vacuum.c 762ee9bbf8733d87d8cd06f58d950e881982e416f8c767334a40ffd341b6bff5
|
||||
F src/vdbe.c 88d8e0797bf49624d056014f34f302a7370cc119915cc0ece8f2b7bf5e7c30fb
|
||||
F src/vdbe.h 134beb7a12a6213c00eba58febaede33447cc4441bc568a0d9c144b33fc3720a
|
||||
F src/vdbeInt.h 95f7adfdc5c8f1353321f55a6c5ec00a90877e3b85af5159e393afb41ff54110
|
||||
F src/vdbeapi.c 29d2baf9c1233131ec467d7bed1b7c8a03c27579048d768c4b04acf427838858
|
||||
F src/vdbeaux.c 2756ac68ac259c416554100598fc291870063288cd7e1af22847f57b3e130e56
|
||||
F src/vdbeblob.c f5c70f973ea3a9e915d1693278a5f890dc78594300cf4d54e64f2b0917c94191
|
||||
F src/vdbemem.c 8478f7fb1948bf8fdeec7c2cb59ea58155c31258b9cd43c56d485e03ed40bd07
|
||||
F src/vdbemem.c 414e28d3a7e2a8bee2bb247de115dcbc68e3cbac284d5862d077002f7a93bce1
|
||||
F src/vdbesort.c 731a09e5cb9e96b70c394c1b7cf3860fbe84acca7682e178615eb941a3a0ef2f
|
||||
F src/vdbetrace.c 48e11ebe040c6b41d146abed2602e3d00d621d7ebe4eb29b0a0f1617fd3c2f6c
|
||||
F src/vtab.c 0e4885495172e1bdf54b12cce23b395ac74ef5729031f15e1bc1e3e6b360ed1a
|
||||
F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
|
||||
F src/wal.c 5a3f464edd64596f601683ed321d12e6fd93c5fb9afdfb3653d6ffd0fee9c48f
|
||||
F src/wal.c aa9cffc7a2bad6b826a86c8562dd4978398720ed41cb8ee7aa9d054eb8b456a0
|
||||
F src/wal.h 8de5d2d3de0956d6f6cb48c83a4012d5f227b8fe940f3a349a4b7e85ebcb492a
|
||||
F src/walker.c da987a20d40145c0a03c07d8fefcb2ed363becc7680d0500d9c79915591f5b1f
|
||||
F src/where.c 36b92103f726609cc3dbe07c619426bd6886bede455de56ccff54c8e567f5582
|
||||
F src/where.c 7cae47e813393d70c6d327fdf000fcb30f76b1b0b5a5b52ff6402e0c658de32c
|
||||
F src/whereInt.h 82c04c5075308abbac59180c8bad5ecb45b07453981f60a53f3c7dee21e1e971
|
||||
F src/wherecode.c af1e79154aaa88cd802d6f2e5b945f67eaca7c958d1525fbf8ee19d5bd7b9020
|
||||
F src/whereexpr.c 427ea8e96ec24f2a7814c67b8024ad664a9c7656264c4566c34743cb23186e46
|
||||
F src/wherecode.c e1aaadd8fec650037cfbf27d1b3470338fb3b58fec34d11082df16fe9a08fbd7
|
||||
F src/whereexpr.c 53532be687e12f3cd314f1e204cd4fbdac7ad250e918a182b048121e16e828ae
|
||||
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
||||
F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd
|
||||
F test/affinity3.test 6a101af2fc945ce2912f6fe54dd646018551710d
|
||||
@@ -669,7 +675,7 @@ F test/capi3b.test efb2b9cfd127efa84433cd7a2d72ce0454ae0dc4
|
||||
F test/capi3c.test 7ebed1d8fa2f3190149d556fe8cff5a006be62af437c5c4640db614470126098
|
||||
F test/capi3d.test 485048dc5cd07bc68011e4917ad035ad6047ab82
|
||||
F test/capi3e.test 3d49c01ef2a1a55f41d73cba2b23b5059ec460fe
|
||||
F test/cast.test 4c275cbdc8202d6f9c54a3596701719868ac7dc3
|
||||
F test/cast.test 5ceb920718d280b61163500a7d29e0e0a86458b1cbd92d96f962c9d970aa3857
|
||||
F test/cffault.test 9d6b20606afe712374952eec4f8fd74b1a8097ef
|
||||
F test/check.test 33a698e8c63613449d85d624a38ef669bf20331daabebe3891c9405dd6df463a
|
||||
F test/close.test 799ea4599d2f5704b0a30f477d17c2c760d8523fa5d0c8be4a7df2a8cad787d8
|
||||
@@ -722,7 +728,7 @@ F test/crash4.test fe2821baf37168dc59dd733dcf7dba2a401487bc
|
||||
F test/crash5.test 05dd3aa9dbb751a22d5cdaf22a9c49b6667aa219
|
||||
F test/crash6.test 4c56f1e40d0291e1110790a99807aa875b1647ba
|
||||
F test/crash7.test 1a194c4900a255258cf94b7fcbfd29536db572df
|
||||
F test/crash8.test a63907617d8e74fb54b4bff23eca8a4435625245
|
||||
F test/crash8.test 64366e459c28dd62edfb7ad87253a409c7533b92d16fcc479a6a8131bdcc3100
|
||||
F test/crashM.test d95f59046fa749b0d0822edf18a717788c8f318d
|
||||
F test/crashtest1.c 09c1c7d728ccf4feb9e481671e29dda5669bbcc2
|
||||
F test/createtab.test b5de160630b209c4b8925bdcbbaf48cc90b67fe8
|
||||
@@ -735,14 +741,14 @@ F test/date.test 9b73bbeb1b82d9c1f44dec5cf563bf7da58d2373
|
||||
F test/date2.test 74c234bece1b016e94dd4ef9c8cc7a199a8806c0e2291cab7ba64bace6350b10
|
||||
F test/dbfuzz.c 73047c920d6210e5912c87cdffd9a1c281d4252e
|
||||
F test/dbpage.test dbf50a4d361f9e45a979432c727506065113124478a7d2db12074fa655e65d6c
|
||||
F test/dbstatus.test 73149851b3aff14fc6db478e58f9083a66422cf5
|
||||
F test/dbstatus2.test e93ab03bfae6d62d4d935f20de928c19ca0ed0ab
|
||||
F test/dbstatus.test c15fa97f743dac7ce996814c84b56317e138895ee15ce27f15b608aa6924c90a
|
||||
F test/dbstatus2.test f5fe0afed3fa45e57cfa70d1147606c20d2ba23feac78e9a172f2fe8ab5b78ef
|
||||
F test/default.test 0cb49b1c315a0d81c81d775e407f66906a2a604d
|
||||
F test/delete.test acc38fca8ee4851467705b1c2cfea64cd26667e5
|
||||
F test/delete2.test 3a03f2cca1f9a67ec469915cb8babd6485db43fa
|
||||
F test/delete3.test 555e84a00a99230b7d049d477a324a631126a6ab
|
||||
F test/delete4.test 21d2113217eeaacac2d99defe14fe6611615ae86
|
||||
F test/delete_db.test c70a43629dd4d3e1dd03fdaf7a22153af6a69d92
|
||||
F test/delete_db.test 096d828493c7907f9ea11a7098ea6a0f73edba89406487d5d6cc2228dc4ab8b0
|
||||
F test/descidx1.test 6d03b44c8538fe0eb4924e19fba10cdd8f3c9240
|
||||
F test/descidx2.test 9f1a0c83fd57f8667c82310ca21b30a350888b5d
|
||||
F test/descidx3.test 09ddbe3f5295f482d2f8b687cf6db8bad7acd9a2
|
||||
@@ -783,14 +789,14 @@ F test/enc4.test c8f1ce3618508fd0909945beb8b8831feef2c020
|
||||
F test/eqp.test 3fe051af50921284189d1970eb653f9fcf5117d2
|
||||
F test/errmsg.test eae9f091eb39ce7e20305de45d8e5d115b68fa856fba4ea6757b6ca3705ff7f9
|
||||
F test/eval.test a64c9105d6ff163df7cf09d6ac29cdad5922078c
|
||||
F test/exclusive.test 9a57bd66e39144b888ca75c309914fcdefb4e3f9
|
||||
F test/exclusive.test 1206b87e192497d78c7f35552e86a9d05421498da300fb1cce5ca5351ccde3c3
|
||||
F test/exclusive2.test 984090e8e9d1b331d2e8111daf6e5d61dda0bef7
|
||||
F test/exec.test e949714dc127eaa5ecc7d723efec1ec27118fdd7
|
||||
F test/exists.test 79a75323c78f02bbe9c251ea502a092f9ef63dac
|
||||
F test/expr.test 66a2c9ac34f74f036faa4092f5402c7d3162fc93
|
||||
F test/expr.test 7cb55e80aeb41d65fec968c08212505123063fea60bdc355d764d747670e9eea
|
||||
F test/extension01.test 00d13cec817f331a687a243e0e5a2d87b0e358c9
|
||||
F test/extraquick.test cb254400bd42bfb777ff675356aabf3287978f79
|
||||
F test/fallocate.test 87b5e43c872b7e69cd80b7b8813eb102b571a75d45dda24e38b65537bcc85733
|
||||
F test/fallocate.test 07416bd593a116d5893cb244f45a94d5c6fe030561df3bd972e6135f8106e509
|
||||
F test/filectrl.test 6e871c2d35dead1d9a88e176e8d2ca094fec6bb3
|
||||
F test/filefmt.test f393e80c4b8d493b7a7f8f3809a8425bbf4292af1f5140f01cb1427798a2bbd4
|
||||
F test/fkey1.test d11dbb8a93ead9b5c46ae5d02da016d61245d47662fb2d844c99214f6163f768
|
||||
@@ -841,7 +847,7 @@ F test/fts2r.test b154c30b63061d8725e320fba1a39e2201cadd5e
|
||||
F test/fts2token.test d8070b241a15ff13592a9ae4a8b7c171af6f445a
|
||||
F test/fts3.test 672a040ea57036fb4b6fdc09027c18d7d24ab654
|
||||
F test/fts3_common.tcl 99cf6659b87c0f74f55963c2aea03b3a7d66ceb0
|
||||
F test/fts3aa.test 39b65c11913d277c91d7426c62cfc1d147d1b4e9a48fecd9e38f60d0b5a5f505
|
||||
F test/fts3aa.test f267fcd6aca30fc70b81e5d82b68b34b38f581896020b57ed49e9777c7ebd85f
|
||||
F test/fts3ab.test 7f6cf260ae80dda064023df8e8e503e9a412b91f
|
||||
F test/fts3ac.test 636ed7486043055d4f126a0e385f2d5a82ebbf63
|
||||
F test/fts3ad.test e40570cb6f74f059129ad48bcef3d7cbc20dda49
|
||||
@@ -891,7 +897,7 @@ F test/fts3offsets.test b85fd382abdc78ebce721d8117bd552dfb75094c
|
||||
F test/fts3prefix.test fa794eaab0bdae466494947b0b153d7844478ab2
|
||||
F test/fts3prefix2.test e1f0a822ca661dced7f12ce392e14eaf65609dce
|
||||
F test/fts3query.test f33eb71a1fe1084ea585eeb7ee76b390729f5170
|
||||
F test/fts3rank.test e4d2e16a28c98cae95001a75e2b4b05b19b051ffd6aaab15491c5e0595127b9b
|
||||
F test/fts3rank.test cd99bc83a3c923c8d52afd90d86979cf05fc41849f892faeac3988055ef37b99
|
||||
F test/fts3rnd.test 1320d8826a845e38a96e769562bf83d7a92a15d0
|
||||
F test/fts3shared.test 57e26a801f21027b7530da77db54286a6fe4997e
|
||||
F test/fts3snippet.test 01a4231816e03a0660ae53ba2404fe69012fe0db
|
||||
@@ -913,23 +919,23 @@ F test/fts4merge2.test 5faa558d1b672f82b847d2a337465fa745e46891
|
||||
F test/fts4merge3.test 8d9ccb4a3d41c4c617a149d6c4b13ad02de797d0
|
||||
F test/fts4merge4.test d895b1057a7798b67e03455d0fa50e9ea836c47b
|
||||
F test/fts4noti.test 5553d7bb2e20bf4a06b23e849352efc022ce6309
|
||||
F test/fts4onepass.test 7319d61a2ed1325fc54afd0c060a0513b462303a
|
||||
F test/fts4onepass.test d69ddc4ee3415e40b0c5d1d0408488a87614d4f63ba9c44f3e52db541d6b7cc7
|
||||
F test/fts4opt.test fd6a11684b965e1999564ae763797b7fb9e34c96
|
||||
F test/fts4unicode.test ceca76422abc251818cb25dabe33d3c3970da5f7c90e1540f190824e6b3a7c95
|
||||
F test/full.test 6b3c8fb43c6beab6b95438c1675374b95fab245d
|
||||
F test/func.test ae97561957aba6ca9e3a7b8a13aac41830d701ef
|
||||
F test/func.test 09dda479bcfc568f99f3070413e9672a8eeedc1be9c5d819bf55d4788c2583b7
|
||||
F test/func2.test 772d66227e4e6684b86053302e2d74a2500e1e0f
|
||||
F test/func3.test d202a7606d23f90988a664e88e268aed1087c11c
|
||||
F test/func4.test 6beacdfcb0e18c358e6c2dcacf1b65d1fa80955f
|
||||
F test/func5.test cdd224400bc3e48d891827cc913a57051a426fa4
|
||||
F test/func6.test a4281c8fcd42b56f7a60f28e8e4d444e8b2256f9e82658b7ab87699f8318f564
|
||||
F test/func6.test 90e42b64c4f9fb6f04f44cb8a1da586c8542502e926b19c76504fe74ff2a9b7c
|
||||
F test/fuzz-oss1.test e58330d01cbbd8215ee636b17a03fe220b37dbfa
|
||||
F test/fuzz.test 96083052bf5765e4518c1ba686ce2bab785670d1
|
||||
F test/fuzz2.test 76dc35b32b6d6f965259508508abce75a6c4d7e1
|
||||
F test/fuzz3.test 9c813e6613b837cb7a277b0383cd66bfa07042b4cf0317157c35852f30043c31
|
||||
F test/fuzz_common.tcl a87dfbb88c2a6b08a38e9a070dabd129e617b45b
|
||||
F test/fuzz_malloc.test 328f70aaca63adf29b4c6f06505ed0cf57ca7c26
|
||||
F test/fuzzcheck.c 2152602232c96d9c790eff3013e1369ce59de3203fa0b75bc613531448454e61
|
||||
F test/fuzzcheck.c 5eb86c6ac96833ee622f45bf47e8045999c1b4b10d05e4eb809894a4b39f2f84
|
||||
F test/fuzzdata1.db 7ee3227bad0e7ccdeb08a9e6822916777073c664
|
||||
F test/fuzzdata2.db f03a420d3b822cc82e4f894ca957618fbe9c4973
|
||||
F test/fuzzdata3.db c6586d3e3cef0fbc18108f9bb649aa77bfc38aba
|
||||
@@ -943,7 +949,7 @@ F test/genesis.tcl 1e2e2e8e5cc4058549a154ff1892fe5c9de19f98
|
||||
F test/having.test e4098a4b8962f9596035c3b87a8928a10648acc509f1bb8d6f96413bbf79a1b3
|
||||
F test/hexlit.test 4a6a5f46e3c65c4bf1fa06f5dd5a9507a5627751
|
||||
F test/hidden.test 23c1393a79e846d68fd902d72c85d5e5dcf98711
|
||||
F test/hook.test dbc0b87756e1e20e7497b56889c9e9cd2f8cc2b5
|
||||
F test/hook.test 1604b3b2f5931430087540404555c1b6be3618600b81558657c66b533ed70b13
|
||||
F test/hook2.test b9ff3b8c6519fb67f33192f1afe86e7782ee4ac8
|
||||
F test/icu.test 41aa8847745a879b897a7febea0f8f9efc8e67fe8bf680589b6e07c7b0a1569a
|
||||
F test/ieee754.test 806fc0ce7f305f57e3331eaceeddcfec9339e607
|
||||
@@ -974,7 +980,7 @@ F test/index7.test 7feababe16f2091b229c22aff2bcc1d4d6b9d2bb
|
||||
F test/index8.test bc2e3db70e8e62459aaa1bd7e4a9b39664f8f9d7
|
||||
F test/index9.test 0aa3e509dddf81f93380396e40e9bb386904c1054924ba8fa9bcdfe85a8e7721
|
||||
F test/indexedby.test faa585e315e868f09bce0eb39c41d6134649b13d2801638294d3ae616edf1609
|
||||
F test/indexexpr1.test ace1ad489adc25325ad298434f13b1a515b36bf5dca9fe2a4b66cdf17aea3fa0
|
||||
F test/indexexpr1.test 635261197bcdc19b9b2c59bbfa7227d525c00e9587faddb2d293c44d287ce60e
|
||||
F test/indexexpr2.test 13247bac49143196556eb3f65e97ef301bd3e993f4511558b5db322ddc370ea6
|
||||
F test/indexfault.test 31d4ab9a7d2f6e9616933eb079722362a883eb1d
|
||||
F test/init.test 15c823093fdabbf7b531fe22cf037134d09587a7
|
||||
@@ -990,30 +996,31 @@ F test/interrupt.test 16ea879ec728cb76414c148c5f24afd5d1f91054
|
||||
F test/interrupt2.test e4408ca770a6feafbadb0801e54a0dcd1a8d108d
|
||||
F test/intpkey.test ac71107a49a06492b69b82aafaf225400598d3c8
|
||||
F test/io.test f95bca1783b01ea7761671560d023360d2dfa4cc
|
||||
F test/ioerr.test 2a24bd6ed5a8b062e64bfe1f6cf94fb25e92210d
|
||||
F test/ioerr.test 470fcc78e9cd352d162baf782fe301ea807d764241f58a48fc58109c2dfcdb6b
|
||||
F test/ioerr2.test 2593563599e2cc6b6b4fcf5878b177bdd5d8df26
|
||||
F test/ioerr3.test d3cec5e1a11ad6d27527d0d38573fbff14c71bdd
|
||||
F test/ioerr4.test f130fe9e71008577b342b8874d52984bd04ede2c
|
||||
F test/ioerr5.test 2edfa4fb0f896f733071303b42224df8bedd9da4
|
||||
F test/ioerr6.test a395a6ab144b26a9e3e21059a1ab6a7149cca65b
|
||||
F test/istrue.test 2d89873d72248b7a0ef7b5457120100cce75a19181bcf4b30e90a3f96a5c5558
|
||||
F test/join.test 442c462eea85cf065d70a663c626b780a95af6e11585d909bb63b87598afe678
|
||||
F test/join2.test 1a0c26399910b015d9f8f95b884e9a079fd2cfdccd65f7b1603846508cae0dc6
|
||||
F test/join2.test f1b5ba94ba70a791df2d99e61adcebf62edacad1eca57881c97eb3e2ca718595
|
||||
F test/join3.test 6f0c774ff1ba0489e6c88a3e77b9d3528fb4fda0
|
||||
F test/join4.test 1a352e4e267114444c29266ce79e941af5885916
|
||||
F test/join5.test bc98ea4b4e5003f5b1453701ebb8cd7d1c01a550
|
||||
F test/join6.test cfe6503791ceb0cbb509966740286ec423cbf10b
|
||||
F test/journal1.test 69abc726c51b4a0409189f9a85191205297c0577
|
||||
F test/journal1.test c7b768041b7f494471531e17abc2f4f5ebf9e5096984f43ed17c4eb80ba34497
|
||||
F test/journal2.test 9dac6b4ba0ca79c3b21446bbae993a462c2397c4
|
||||
F test/journal3.test ff8af941f9e06161d3db1b46bb9f965ff0e7f307
|
||||
F test/jrnlmode.test 7864d59cf7f6e552b9b99ba0f38acd167edc10fa
|
||||
F test/jrnlmode2.test 81610545a4e6ed239ea8fa661891893385e23a1d
|
||||
F test/journal3.test c9c29883f5bf535ae82ae21c472df6263806a22e467b6db7cd0d6d545305b4f6
|
||||
F test/jrnlmode.test a6693f2bed4541a21e703aaa37bb3e10de154130645952933b82b2dec0a8b539
|
||||
F test/jrnlmode2.test 8759a1d4657c064637f8b079592651530db738419e1d649c6df7048cd724363d
|
||||
F test/jrnlmode3.test 556b447a05be0e0963f4311e95ab1632b11c9eaa
|
||||
F test/json101.test d7cdf3e6731d41e0c4bde1c88806abd17f1f478486a1409933c1d8eac9120095
|
||||
F test/json101.test 24e97954e3bd6404f3715888c7f8f835e36e19c7ae6513b5d9ab2d381498962d
|
||||
F test/json102.test eeb54efa221e50b74a2d6fb9259963b48d7414dca3ce2fdfdeed45cb28487bc1
|
||||
F test/json103.test c5f6b85e69de05f6b3195f9f9d5ce9cd179099a0
|
||||
F test/json104.test 877d5845f6303899b7889ea5dd1bea99076e3100574d5c536082245c5805dcaa
|
||||
F test/keyword1.test 37ef6bba5d2ed5b07ecdd6810571de2956599dff
|
||||
F test/kvtest.c fcb38ffe3db028a3138b4818fc098359c80dc51a0d1278a91c99c554cc1abb92
|
||||
F test/kvtest.c 23452e653e6b0254dc2fd1d242d4c7c65644504de8951d7d60f7e4291c52c231
|
||||
F test/lastinsert.test 42e948fd6442f07d60acbd15d33fb86473e0ef63
|
||||
F test/laststmtchanges.test ae613f53819206b3222771828d024154d51db200
|
||||
F test/like.test 11cfd7d4ef8625389df9efc46735ff0b0b41d5e62047ef0f3bc24c380d28a7a6
|
||||
@@ -1026,7 +1033,7 @@ F test/loadext2.test 0408380b57adca04004247179837a18e866a74f7
|
||||
F test/lock.test be4fe08118fb988fed741f429b7dd5d65e1c90db
|
||||
F test/lock2.test 5242d8ac4e2d59c403aebff606af449b455aceff
|
||||
F test/lock3.test f271375930711ae044080f4fe6d6eda930870d00
|
||||
F test/lock4.test e175ae13865bc87680607563bafba21f31a26f12
|
||||
F test/lock4.test 27143363eda1622f03c133efc8db808fc331afd973486cb571ea71cd717d37b8
|
||||
F test/lock5.test c6c5e0ebcb21c61a572870cc86c0cb9f14cede38
|
||||
F test/lock6.test ad5b387a3a8096afd3c68a55b9535056431b0cf5
|
||||
F test/lock7.test 49f1eaff1cdc491cc5dee3669f3c671d9f172431
|
||||
@@ -1034,8 +1041,8 @@ F test/lock_common.tcl 7ffb45accf6ee91c736df9bafe0806a44358f035
|
||||
F test/lookaside.test b17c99ae3aef96a8c9fa6f6be33cc75b93d657cb791d3827302b6835b71941f7
|
||||
F test/main.test 6bbb3999fd461eb8fb335cbab97409a3d7f91bbb8da60635e8be3e4a04a77772
|
||||
F test/make-where7.tcl 05c16b5d4f5d6512881dfec560cb793915932ef9
|
||||
F test/malloc.test 21c213365f2cca95ab2d7dc078dc8525f96065f8
|
||||
F test/malloc3.test e3b32c724b5a124b57cb0ed177f675249ad0c66a
|
||||
F test/malloc.test 18dd1c4188c81ca79cf123527c71b19ee0c31feb9947fdffb0dc6ceb1436816a
|
||||
F test/malloc3.test 6e88bae6312854a4adb4ecc2a6a5ea8c59b4db778b724ba718e1c43fc8c3c136
|
||||
F test/malloc4.test 957337613002b7058a85116493a262f679f3a261
|
||||
F test/malloc5.test f6eb6eca07a4c75f2897bf43a404689b6295bb95ab2e07d4b52eda743f925a27
|
||||
F test/malloc6.test 2f039d9821927eacae43e1831f815e157659a151
|
||||
@@ -1060,6 +1067,7 @@ F test/malloc_common.tcl aac62499b76be719fac31e7a3e54a7fd53272e7f
|
||||
F test/manydb.test 28385ae2087967aa05c38624cec7d96ec74feb3e
|
||||
F test/mem5.test c6460fba403c5703141348cd90de1c294188c68f
|
||||
F test/memdb.test c1f2a343ad14398d5d6debda6ea33e80d0dafcc7
|
||||
F test/memdb1.test fbe47f36c12725ebdd2760f846371e6eb09f403bd7236fbdddb21aa6e3c652b4
|
||||
F test/memleak.test 10b9c6c57e19fc68c32941495e9ba1c50123f6e2
|
||||
F test/memsubsys1.test 9e7555a22173b8f1c96c281ce289b338fcba2abe8b157f8798ca195bbf1d347e
|
||||
F test/memsubsys2.test 3e4a8d0c05fd3e5fa92017c64666730a520c7e08
|
||||
@@ -1073,7 +1081,7 @@ F test/misc3.test cf3dda47d5dda3e53fc5804a100d3c82be736c9d
|
||||
F test/misc4.test 0d8be3466adf123a7791a66ba2bc8e8d229e87f3
|
||||
F test/misc5.test 60e1fc758a93cacd19eb2fafcd1d40d150a05047546c7a92389c98047d621901
|
||||
F test/misc6.test 953cc693924d88e6117aeba16f46f0bf5abede91
|
||||
F test/misc7.test 859894e3192257ce2fc4063b5438b220e352286974b387e485050f0ad1f665d6
|
||||
F test/misc7.test 567e223b6497da2226a0340befaf2d663c91ad57a48aede21a35a984a2882d41
|
||||
F test/misc8.test ba03aaa08f02d62fbb8d3b2f5595c1b33aa9bbc5
|
||||
F test/misuse.test 9e7f78402005e833af71dcab32d048003869eca5abcaccc985d4f8dc1d86bcc7
|
||||
F test/mjournal.test 9d86e697dcbc5da2c4e8caba9b176b5765fe65e80c88c278b8c09a917e436795
|
||||
@@ -1090,12 +1098,13 @@ F test/multiplex4.test e8ae4c4bd70606a5727743241f13b5701990abe4
|
||||
F test/mutex1.test ea2cc74d97f077b9e74c84cbd024f14d79a8126f
|
||||
F test/mutex2.test bfeaeac2e73095b2ac32285d2756e3a65e681660
|
||||
F test/nan.test 437d40e6d0778b050d7750726c0cbd2c9936b81962926e8f8c48ca698f00f4d1
|
||||
F test/nockpt.test 9a436a7213ba5ef7a32304998d386d3ea3f76c9d
|
||||
F test/nockpt.test 8c43b25af63b0bd620cf1b003529e37b6f1dc53bd22690e96a1bd73f78dde53a
|
||||
F test/nolock.test f196cf8b8fbea4e2ca345140a2b3f3b0da45c76e
|
||||
F test/normalize.test 501630ab49b0b26b65c74124bf03e3374c1b57fa97aae750f84803609141d167
|
||||
F test/notify1.test 669b2b743618efdc18ca4b02f45423d5d2304abf
|
||||
F test/notify2.test 2ecabaa1305083856b7c39cf32816b612740c161
|
||||
F test/notify3.test 10ff25cde502e72a92053a2f215d64bece4ef934
|
||||
F test/notnull.test f8fcf58669ddba79274daa2770d61dfad8274f62
|
||||
F test/notnull.test b6999231221df3534827e45e2005dd7a815fdd5f2c2e1afb9be21ead410816f8
|
||||
F test/null.test 0dcce4f04284ec66108c503327ad6d224c0752b3
|
||||
F test/numcast.test 5d126f7f581432e86a90d1e35cac625164aec4a1
|
||||
F test/numindex1.test 20a5450d4b056e48cd5db30e659f13347a099823
|
||||
@@ -1111,14 +1120,14 @@ F test/orderby7.test 3d1383d52ade5b9eb3a173b3147fdd296f0202da
|
||||
F test/orderby8.test 23ef1a5d72bd3adcc2f65561c654295d1b8047bd
|
||||
F test/orderby9.test 87fb9548debcc2cd141c5299002dd94672fa76a3
|
||||
F test/oserror.test b32dc34f2363ef18532e3a0a7358e3e7e321974f
|
||||
F test/ossfuzz.c 7f5cc87a0280a5854c1bfa7d5c4d07d34731f08ec34dc9c916aa35ed292b1468
|
||||
F test/ossshell.c 296ab63067841bd1b1e97b46a0b2af48ee7f69d50d1a723008bee12dd7122622
|
||||
F test/ossfuzz.c c4c4547e2c92ac52f10038b073a03248251a23c1c559728f63a18aeca0e79f03
|
||||
F test/ossshell.c f125c5bd16e537a2549aa579b328dd1c59905e7ab1338dfc210e755bb7b69f17
|
||||
F test/ovfl.test 199c482696defceacee8c8e0e0ef36da62726b2f
|
||||
F test/pager1.test 8149b2a8986fee667ab6a8171ab310be19e77ae215bebad0e90c857b0df1935c
|
||||
F test/pager1.test f596d3bd53ce96e1d87d44d223d2ae6c8867dd782c425e5eb28b5721fa6aaa97
|
||||
F test/pager2.test 67b8f40ae98112bcdba1f2b2d03ea83266418c71
|
||||
F test/pager3.test 3856d9c80839be0668efee1b74811b1b7f7fc95f
|
||||
F test/pager3.test 4e9a83d6ca0838d7c602c9eb93d1357562d9059c1e02ffb138a8271020838370
|
||||
F test/pager4.test a122e9e6925d5b23b31e3dfef8c6a44bbf19590e
|
||||
F test/pagerfault.test 263c5442c06caf0b9b9e3fe42acdeb11f254dcebe533f69f401aaef9111eaf20
|
||||
F test/pagerfault.test 63c5da625562c66345ab4528790327ca63db2f6f9cbae2aba8cb7c51de3d1628
|
||||
F test/pagerfault2.test caf4c7facb914fd3b03a17b31ae2b180c8d6ca1f
|
||||
F test/pagerfault3.test 1003fcda009bf48a8e22a516e193b6ef0dd1bbd8
|
||||
F test/pageropt.test 84e4cc5cbca285357f7906e99b21be4f2bf5abc0
|
||||
@@ -1135,7 +1144,7 @@ F test/pragma4.test 3046501bee2f652dc2a4f9c87781e2741361d6864439c8381aba6c3b774b
|
||||
F test/pragma5.test 824ce6ced5d6b7ec71abe37fc6005ff836fe39d638273dc5192b39864b9ee983
|
||||
F test/pragmafault.test 275edaf3161771d37de60e5c2b412627ac94cef11739236bec12ed1258b240f8
|
||||
F test/printf.test b3ff34e73d59124140eaf89f7672e21bc2ca5fcc
|
||||
F test/printf2.test 9e6db85f81c63f2367c34a9d7db384088bd374ad
|
||||
F test/printf2.test 30b5dd0b4b992dc5626496846ecce17ff592cacbcb11c3e589f3ac4d7e129dae
|
||||
F test/progress.test ebab27f670bd0d4eb9d20d49cef96e68141d92fb
|
||||
F test/ptrchng.test ef1aa72d6cf35a2bbd0869a649b744e9d84977fc
|
||||
F test/pushdown.test 5e72c51c5e33253ed639ccee1e01ce62d62b6eee5ca893cd82334e4ee7b1d7fc
|
||||
@@ -1154,13 +1163,13 @@ F test/regexp2.test 40e894223b3d6672655481493f1be12012f2b33c
|
||||
F test/reindex.test 44edd3966b474468b823d481eafef0c305022254
|
||||
F test/releasetest.tcl 6aaa853f7a7bbdc458d4cb42c0425228729b0f3e5769e9b41088c08eee999a49 x
|
||||
F test/resolver01.test f4022acafda7f4d40eca94dbf16bc5fc4ac30ceb
|
||||
F test/rollback.test f580934279800d480a19176c6b44909df31ce7ad45267ea475a541daa522f3d3
|
||||
F test/rollback.test 06680159bc6746d0f26276e339e3ae2f951c64812468308838e0a3362d911eaa
|
||||
F test/rollback2.test 8435d6ff0f13f51d2a4181c232e706005fa90fc5
|
||||
F test/rollbackfault.test 0e646aeab8840c399cfbfa43daab46fd609cf04a
|
||||
F test/rowallock.test 3f88ec6819489d0b2341c7a7528ae17c053ab7cc
|
||||
F test/rowhash.test 0bc1d31415e4575d10cacf31e1a66b5cc0f8be81
|
||||
F test/rowid.test 5b7509f384f4f6fae1af3c8c104c8ca299fea18d
|
||||
F test/rowvalue.test 44f3492f415cc9f374e8388a5eb61503eaca5230
|
||||
F test/rowvalue.test 32861d6a933ded868035f2ec79aeb993a2a46eb7a6d282ae13415a4c2e369463
|
||||
F test/rowvalue2.test 060d238b7e5639a7c5630cb5e63e311b44efef2b
|
||||
F test/rowvalue3.test 3068f508753af69884b12125995f023da0dbb256
|
||||
F test/rowvalue4.test 4b556d7de161a0dd8cff095c336e913986398bea
|
||||
@@ -1203,9 +1212,11 @@ F test/selectC.test e25243f8ca503e06f252eb0218976d07cfeceac3
|
||||
F test/selectD.test b0f02a04ef7737decb24e08be2c39b9664b43394
|
||||
F test/selectE.test a8730ca330fcf40ace158f134f4fe0eb00c7edbf
|
||||
F test/selectF.test 21c94e6438f76537b72532fa9fd4710cdd455fc3
|
||||
F test/selectG.test e8600e379589e85e9fefd2fe4d44a4cdd63f6982
|
||||
F test/selectG.test 089f7d3d7e6db91566f00b036cb353107a2cca6220eb1cb264085a836dae8840
|
||||
F test/server1.test 46803bd3fe8b99b30dbc5ff38ffc756f5c13a118
|
||||
F test/session.test 78fa2365e93d3663a6e933f86e7afc395adf18be
|
||||
F test/sessionfuzz-data1.db 1f8d5def831f19b1c74571037f0d53a588ea49a6c4ca2a028fc0c27ef896dbcb
|
||||
F test/sessionfuzz.c b0fcdcf757451957e17396a3af5171f1fdf9b2babc81da9fa35675df46c4729a
|
||||
F test/shared.test 1da9dbad400cee0d93f252ccf76e1ae007a63746
|
||||
F test/shared2.test 03eb4a8d372e290107d34b6ce1809919a698e879
|
||||
F test/shared3.test ab693f9b6e156b8bfb2a0ad94f29fe69602a5d38
|
||||
@@ -1214,7 +1225,7 @@ F test/shared6.test 866bb4982c45ce216c61ded5e8fde4e7e2f3ffa9
|
||||
F test/shared7.test a81e99f83e6c51b02ac99c96fb3a2a7b5978c956
|
||||
F test/shared8.test 00a07bf5e1337ecf72e94542bdefdc330d7a2538
|
||||
F test/shared9.test 5f2a8f79b4d6c7d107a01ffa1ed05ae7e6333e21
|
||||
F test/sharedA.test 0cdf1a76dfa00e6beee66af5b534b1e8df2720f5
|
||||
F test/sharedA.test 49d87ec54ab640fbbc3786ee3c01de94aaa482a3a9f834ad3fe92770eb69e281
|
||||
F test/sharedB.test 16cc7178e20965d75278f410943109b77b2e645e
|
||||
F test/shared_err.test 32634e404a3317eeb94abc7a099c556a346fdb8fb3858dbe222a4cbb8926a939
|
||||
F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304
|
||||
@@ -1225,7 +1236,7 @@ F test/shell4.test 89ad573879a745974ff2df20ff97c5d6ffffbd5d
|
||||
F test/shell5.test 23939a4c51f0421330ea61dbd3c74f9c215f5f8d3d1a94846da6ffc777a35458
|
||||
F test/shell6.test 1ceb51b2678c472ba6cf1e5da96679ce8347889fe2c3bf93a0e0fa73f00b00d3
|
||||
F test/shell7.test 115132f66d0463417f408562cc2cf534f6bbc6d83a6d50f0072a9eb171bae97f
|
||||
F test/shell8.test c836470ccde867e1f438a7acad7560805cc04f9dbab84cb55d92925942b76247
|
||||
F test/shell8.test 96be02ea0c21f05b24c1883d7b711a1fa8525a68ab7b636aacf6057876941013
|
||||
F test/shortread1.test bb591ef20f0fd9ed26d0d12e80eee6d7ac8897a3
|
||||
F test/show_speedtest1_rtree.tcl 32e6c5f073d7426148a6936a0408f4b5b169aba5
|
||||
F test/shrink.test 1b4330b1fd9e818c04726d45cb28db73087535ce
|
||||
@@ -1254,17 +1265,18 @@ F test/speed2.test 53177056baf6556dcbdcf032bbdfc41c1aa74ded
|
||||
F test/speed3.test 694affeb9100526007436334cf7d08f3d74b85ef
|
||||
F test/speed4.test abc0ad3399dcf9703abed2fff8705e4f8e416715
|
||||
F test/speed4p.explain 6b5f104ebeb34a038b2f714150f51d01143e59aa
|
||||
F test/speed4p.test 0e51908951677de5a969b723e03a27a1c45db38b
|
||||
F test/speed4p.test 377a0c48e5a92e0b11c1c5ebb1bc9d83a7312c922bc0cb05970ef5d6a96d1f0c
|
||||
F test/speedtest1.c a5faf4cbe5769eee4b721b3875cb3f12520a9b99d9026b1063b47c39603375b8
|
||||
F test/spellfix.test f9c1f431e2c096c8775fec032952320c0e4700db
|
||||
F test/spellfix.test 951a6405d49d1a23d6b78027d3877b4a33eeb8221dcab5704b499755bb4f552e
|
||||
F test/spellfix2.test dfc8f519a3fc204cb2dfa8b4f29821ae90f6f8c3
|
||||
F test/spellfix3.test 0f9efaaa502a0e0a09848028518a6fb096c8ad33
|
||||
F test/spellfix4.test 51c7c26514ade169855c66bcf130bd5acfb4d7fd090cc624645ab275ae6a41fb
|
||||
F test/sqldiff1.test 28cd737cf1b0078b1ec1bbf425e674c47785835e
|
||||
F test/sqllimits1.test a74ee2a3740b9f9c2437c246d8fb77354862a142
|
||||
F test/sqllog.test 6af6cb0b09f4e44e1917e06ce85be7670302517a
|
||||
F test/stat.test f8f1279ffffabe6df825723af18cc6e0ae70a893
|
||||
F test/statfault.test f525a7bf633e50afd027700e9a486090684b1ac1
|
||||
F test/stmt.test 64844332db69cf1a735fcb3e11548557fc95392f
|
||||
F test/stmt.test 54ed2cc0764bf3e48a058331813c3dbd19fc1d0827c3d8369914a5d8f564ec75
|
||||
F test/stmtvtab1.test 6873dfb24f8e79cbb5b799b95c2e4349060eb7a3b811982749a84b359468e2d5
|
||||
F test/subjournal.test 8d4e2572c0ee9a15549f0d8e40863161295107e52f07a3e8012a2e1fdd093c49
|
||||
F test/subquery.test d7268d193dd33d5505df965399d3a594e76ae13f
|
||||
@@ -1277,25 +1289,25 @@ F test/swarmvtab.test 9a3fd5ab3e9b3c976ad1b3d7646aab725114f2ac26b59395d0778b33ba
|
||||
F test/swarmvtab2.test c948cb2fdfc5b01d85e8f6d6504854202dc1a0782ab2a0ed61538f27cbd0aa5c
|
||||
F test/swarmvtab3.test 6cb664669630fcec4102a09333e52068734858fd2761eee3b0465c14cdbcee29
|
||||
F test/swarmvtabfault.test 00aec54665909490f5c383f3cae3b5d18bd97c12490b429ff8752a3027acfa42
|
||||
F test/symlink.test c9ebe7330d228249e447038276bfc8a7b22f4849
|
||||
F test/sync.test 2f84bdbc2b2df1fcb0220575b4b9f8cea94b7529
|
||||
F test/sync2.test 6be8ed007fa063b147773c1982b5bdba97a32badc536bdc6077eff5cf8710ece
|
||||
F test/symlink.test 0d816670325536b8973ec08d32b45136baddb80bd45fd178e0ce7a9e8153f3e7
|
||||
F test/sync.test 89539f4973c010eda5638407e71ca7fddbcd8e0594f4c9980229f804d4333092
|
||||
F test/sync2.test 8f9f7d4f6d5be8ca8941a8dadcc4299e558cb6a1ff653a9469146c7a76ef2039
|
||||
F test/syscall.test a39d9a36f852ae6e4800f861bc2f2e83f68bbc2112d9399931ecfadeabd2d69d
|
||||
F test/sysfault.test c9f2b0d8d677558f74de750c75e12a5454719d04
|
||||
F test/tabfunc01.test c47171c36b3d411df2bd49719dcaa5d034f8d277477fd41d253940723b969a51
|
||||
F test/table.test b708f3e5fa2542fa51dfab21fc07b36ea445cb2f
|
||||
F test/tableapi.test 2674633fa95d80da917571ebdd759a14d9819126
|
||||
F test/tableopts.test dba698ba97251017b7c80d738c198d39ab747930
|
||||
F test/tclsqlite.test c3d7ac9449634b9f17fd048a3c0212e88a7448be810a9c5bd051acc1ffa00d2f
|
||||
F test/tempdb.test bd92eba8f20e16a9136e434e20b280794de3cdb6
|
||||
F test/tclsqlite.test 5337e8890b96dad1ee541b15fbeec32e6bac2fe7fa096f91089057385aadba9b
|
||||
F test/tempdb.test 4cdaa23ddd8acb4d79cbb1b68ccdfd09b0537aaba909ca69a876157c2a2cbd08
|
||||
F test/tempdb2.test 27e41ed540b2f9b056c2e77e9bddc1b875358507
|
||||
F test/tempfault.test 0c0d349c9a99bf5f374655742577f8712c647900
|
||||
F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30
|
||||
F test/temptable2.test cd396beb41117a5302fff61767c35fa4270a0d5e
|
||||
F test/temptable3.test d11a0974e52b347e45ee54ef1923c91ed91e4637
|
||||
F test/temptrigger.test 38f0ca479b1822d3117069e014daabcaacefffcc
|
||||
F test/tester.tcl 3ed81b9e1d9718a8d9603596c8a877793d054294053c4277a3d3897eabab3866
|
||||
F test/thread001.test 9f22fd3525a307ff42a326b6bc7b0465be1745a5
|
||||
F test/tester.tcl 94901a4625d9a2229666dd5c44120ddf7f0fb639470710ef74a4cefc7b039e07
|
||||
F test/thread001.test b61a29dd87cf669f5f6ac96124a7c97d71b0c80d9012746072055877055cf9ef
|
||||
F test/thread002.test e630504f8a06c00bf8bbe68528774dd96aeb2e58
|
||||
F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7
|
||||
F test/thread004.test f51dfc3936184aaf73ee85f315224baad272a87f
|
||||
@@ -1414,7 +1426,7 @@ F test/tkt3357.test 77c37c6482b526fe89941ce951c22d011f5922ed
|
||||
F test/tkt3419.test 1bbf36d7ea03b638c15804251287c2391f5c1f6b
|
||||
F test/tkt3424.test 61f831bd2b071bd128fa5d00fbda57e656ca5812
|
||||
F test/tkt3442.test 53840ec5325bb94544792aad4c20476f81dc26b1
|
||||
F test/tkt3457.test 44e980fe5334753dcc27b94fa4deabc485a92f74
|
||||
F test/tkt3457.test 5651e2cbb94645b677ec663160b9e192b87b7d365aecdfb24e19f749575a6fc2
|
||||
F test/tkt3461.test 228ea328a5a21e8663f80ee3d212a6ad92549a19
|
||||
F test/tkt3493.test 1686cbde85f8721fc1bdc0ee72f2ef2f63139218
|
||||
F test/tkt3508.test d75704db9501625c7f7deec119fcaf1696aefb7d
|
||||
@@ -1452,7 +1464,7 @@ F test/tokenize.test ce430a7aed48fc98301611429595883fdfcab5d7
|
||||
F test/tpch01.test 04adbf8d8300fa60a222f28d901abd76e7be6dd4
|
||||
F test/trace.test a659a9862957f4789e37a92b3bf6d2caf5c86b02cdeefc41e850ae53acf6992a
|
||||
F test/trace2.test f5cb67ad3bc09e0c58e8cca78dfd0b5639259983
|
||||
F test/trace3.test 56ab944fddacf628b118cc298503fc45c2e50ab0
|
||||
F test/trace3.test 1dff966888773ff1bfea01c080caf15417892b3f998408fe920c4791f7337144
|
||||
F test/trans.test 6e1b4c6a42dba31bd65f8fa5e61a2708e08ddde6
|
||||
F test/trans2.test 62bd045bfc7a1c14c5ba83ba64d21ade31583f76
|
||||
F test/trans3.test 91a100e5412b488e22a655fe423a14c26403ab94
|
||||
@@ -1488,7 +1500,7 @@ F test/unique2.test 3674e9f2a3f1fbbfd4772ac74b7a97090d0f77d2
|
||||
F test/unixexcl.test d936ba2b06794018e136418addd59a2354eeae97
|
||||
F test/unordered.test ca7adce0419e4ca0c50f039885e76ed2c531eda8
|
||||
F test/update.test 6c68446b8a0a33d522a7c72b320934596a2d7d32
|
||||
F test/update2.test fffc92e72ae568fe048588762e650cd8ccbd8c8b6e4fe9099231766bfe4b51de
|
||||
F test/update2.test 5e67667e1c54017d964e626db765cf8bedcf87483c184f4c575bdb8c1dd2313e
|
||||
F test/uri.test 3481026f00ade6dfe8adb7acb6e1e47b04369568
|
||||
F test/uri2.test 9d3ba7a53ee167572d53a298ee4a5d38ec4a8fb7
|
||||
F test/userauth01.test e740a2697a7b40d7c5003a7d7edaee16acd349a9
|
||||
@@ -1497,7 +1509,7 @@ F test/vacuum.test ce91c39f7f91a4273bf620efad21086b5aa6ef1d
|
||||
F test/vacuum2.test aa048abee196c16c9ba308465494009057b79f9b
|
||||
F test/vacuum3.test 77ecdd54592b45a0bcb133339f99f1ae0ae94d0d
|
||||
F test/vacuum4.test 7ea76b769fffeb41f925303b04cbcf5a5bbeabe55e4c60ae754ff24eeeb7c010
|
||||
F test/vacuum5.test c87234e8ca4107f349da4edbeda3e4ea5adc93f3
|
||||
F test/vacuum5.test 263b144d537e92ad8e9ca8a73cc6e1583f41cfd0dda9432b87f7806174a2f48c
|
||||
F test/vacuummem.test 7b42abb3208bd82dd23a7536588396f295a314f2
|
||||
F test/varint.test bbce22cda8fc4d135bcc2b589574be8410614e62
|
||||
F test/veryquick.test 57ab846bacf7b90cf4e9a672721ea5c5b669b661
|
||||
@@ -1524,7 +1536,7 @@ F test/vtab_alter.test 736e66fb5ec7b4fee58229aa3ada2f27ec58bc58c00edae4836890c37
|
||||
F test/vtab_err.test 0d4d8eb4def1d053ac7c5050df3024fd47a3fbd8
|
||||
F test/vtab_shared.test 5253bff2355a9a3f014c15337da7e177ab0ef8ad
|
||||
F test/wal.test 613efec03e517e1775d86b993a54877d2e29a477
|
||||
F test/wal2.test 2d81ffe2a02d9e5c7447b266f7153716cfcba7aecda5ed832db4544617399e29
|
||||
F test/wal2.test 155b9efa999bdb38ce1cd729b9a4fcdbffd6b88be27f039bad1d2929d287d918
|
||||
F test/wal3.test 2a93004bc0fb2b5c29888964024695bade278ab2
|
||||
F test/wal4.test 4744e155cd6299c6bd99d3eab1c82f77db9cdb3c
|
||||
F test/wal5.test 9c11da7aeccd83a46d79a556ad11a18d3cb15aa9
|
||||
@@ -1542,19 +1554,19 @@ F test/walcrash.test 21038858cc552077b0522f50b0fa87e38139306a
|
||||
F test/walcrash2.test a0edab4e5390f03b99a790de89aad15d6ec70b36
|
||||
F test/walcrash3.test e426aa58122d20f2b9fbe9a507f9eb8cab85b8af
|
||||
F test/walcrash4.test e7b6e7639a950a0cca8e210e248c8dad4d63bf20
|
||||
F test/walfault.test 1f8389f7709877e9b4cc679033d71d6fe529056b
|
||||
F test/walfault.test 09b8ad7e52d2f54bce50e31aa7ea51412bb9f70ac13c74e669ddcd8b48b0d98d
|
||||
F test/walhook.test ed00a40ba7255da22d6b66433ab61fab16a63483
|
||||
F test/walmode.test 4022fe03ae6e830583672caa101f046438a0473c
|
||||
F test/walmode.test cd6e7cff618eaaa5910ce57c3657aa50110397f86213886a2400afb9bfec7b7b
|
||||
F test/walnoshm.test 84ca10c544632a756467336b7c3b864d493ee496
|
||||
F test/waloverwrite.test dad2f26567f1b45174e54fbf9a8dc1cb876a7f03
|
||||
F test/walpersist.test 8c6b7e3ec1ba91b5e4dc4e0921d6d3f87cd356a6
|
||||
F test/walprotocol.test a112aba0b79e3adeaa485fed09484b32c654e97df58e454aa8489ac2cd57bf84
|
||||
F test/walro.test cb438d05ba0d191f10b688e39c4f0cd5b71569a1d1f4440e5bdf3c6880e08c20
|
||||
F test/walro2.test 5cd57d192ee334c3894330303b5f8cb6789fef49b2c83ad1b50b9b132d0f7ae1
|
||||
F test/walro2.test 0e79dd15cbdb4f482c01ea248373669c732414a726b357d04846a816afafb768
|
||||
F test/walrofault.test c70cb6e308c443867701856cce92ad8288cd99488fa52afab77cca6cfd51af68
|
||||
F test/walshared.test 0befc811dcf0b287efae21612304d15576e35417
|
||||
F test/walslow.test c05c68d4dc2700a982f89133ce103a1a84cc285f
|
||||
F test/walthread.test de8dbaf6d9e41481c460ba31ca61e163d7348f8e
|
||||
F test/walthread.test 14b20fcfa6ae152f5d8e12f5dc8a8a724b7ef189f5d8ef1e2ceab79f2af51747
|
||||
F test/where.test f0c325563acde44f2c4ea6ba348e9e29f7121757
|
||||
F test/where2.test 478d2170637b9211f593120648858593bf2445a1
|
||||
F test/where3.test 54cdeb02157acc979de41530b804ae7b09552bf1
|
||||
@@ -1569,7 +1581,7 @@ F test/whereB.test 0def95db3bdec220a731c7e4bec5930327c1d8c5
|
||||
F test/whereC.test cae295158703cb3fc23bf1a108a9ab730efff0f6
|
||||
F test/whereD.test 711d4df58d6d4fb9b3f5ce040b818564198be002
|
||||
F test/whereE.test b3a055eef928c992b0a33198a7b8dc10eea5ad2f
|
||||
F test/whereF.test d44b58338fe5ddd7286023e9bedb255aa264a6c4d2168b49591b167371c675c7
|
||||
F test/whereF.test 3d9412b1199d3e2bed34fcb76b4c48d0bf4df95d27e3f8dd27b6f8b4716d0d89
|
||||
F test/whereG.test dde4c52a97385a55be6a7cd46be8373f0cf35501
|
||||
F test/whereH.test e4b07f7a3c2f5d31195cd33710054c78667573b2
|
||||
F test/whereI.test eab5b226bbc344ac70d7dc09b963a064860ae6d7
|
||||
@@ -1587,6 +1599,7 @@ F test/win32nolock.test ac4f08811a562e45a5755e661f45ca85892bdbbc
|
||||
F test/with1.test ca08e291249a810a2ec9b72ceef5575e07d5925b360fcf6652ae6fe06ac4dced
|
||||
F test/with2.test e0030e2f0267a910d6c0e4f46f2dfe941c1cc0d4f659ba69b3597728e7e8f1ab
|
||||
F test/with3.test e71604a0e53cba82bc04c703987cb1d6751ec0b6
|
||||
F test/with4.test 257be66c0c67fee1defbbac0f685c3465e2cad037f21ce65f23f86084f198205
|
||||
F test/withM.test 693b61765f2b387b5e3e24a4536e2e82de15ff64
|
||||
F test/without_rowid1.test 06b7215130882d6a072233820dd364c874c4fd69221e8fc756ec471009192874
|
||||
F test/without_rowid2.test af260339f79d13cb220288b67cd287fbcf81ad99
|
||||
@@ -1597,12 +1610,14 @@ F test/without_rowid6.test 1f99644e6508447fb050f73697350c7ceca3392e
|
||||
F test/wordcount.c cb589cec469a1d90add05b1f8cee75c7210338d87a5afd65260ed5c0f4bbf8ac
|
||||
F test/writecrash.test f1da7f7adfe8d7f09ea79b42e5ca6dcc41102f27f8e334ad71539501ddd910cc
|
||||
F test/zeroblob.test 3857870fe681b8185654414a9bccfde80b62a0fa
|
||||
F test/zerodamage.test e59a56443d6298ecf7435f618f0b27654f0c849e
|
||||
F test/zipfile.test e7132ca60031ca5d1df684cf644952bb3f253de3671a5b502780c5de3126a453
|
||||
F test/zerodamage.test 9c41628db7e8d9e8a0181e59ea5f189df311a9f6ce99cc376dc461f66db6f8dc
|
||||
F test/zipfile.test 2a923f6ead6a0f9b61d936881f3ee2aeaabe15fc65c196456f58ea9b4b450f9b
|
||||
F test/zipfile2.test fc2f08d5ec19c18c83289fbed32e378dc5116519972166e57a244da7bf2e5805
|
||||
F test/zipfilefault.test 44d4d7a7f7cca7521d569d7f71026b241d65a6b1757aa409c1a168827edbbc2c
|
||||
F tool/GetFile.cs a15e08acb5dd7539b75ba23501581d7c2b462cb5
|
||||
F tool/GetTclKit.bat 8995df40c4209808b31f24de0b58f90930239a234f7591e3675d45bfbb990c5d
|
||||
F tool/Replace.cs 02c67258801c2fb5f63231e0ac0f220b4b36ba91
|
||||
F tool/addopcodes.tcl 7181c041d495e3f26acc36d15c86923ed722285f9015f017f41a3efdb9a0dab4
|
||||
F tool/addopcodes.tcl 0288d5b26b9b35f4cb5affb76eec63f1dfce117bbc2020066708069ef60b86ff
|
||||
F tool/build-all-msvc.bat c12328d06c45fec8baada5949e3d5af54bf8c887 x
|
||||
F tool/build-shell.sh 950f47c6174f1eea171319438b93ba67ff5bf367
|
||||
F tool/cg_anno.tcl f95b0006c52cf7f0496b506343415b6ee3cdcdd3 x
|
||||
@@ -1617,7 +1632,7 @@ F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5
|
||||
F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce
|
||||
F tool/kvtest-speed.sh 4761a9c4b3530907562314d7757995787f7aef8f
|
||||
F tool/lemon.c 7f7735326ca9c3b48327b241063cee52d35d44e20ebe1b3624a81658052a4d39
|
||||
F tool/lempar.c dddd4f592b8bad36aec4500d456c5db5fe42fefc4ee384913880439d8917f87a
|
||||
F tool/lempar.c 468a155e8729cfbccfe1d85bf60d064f1dab76167a51149ec5c7928a2de63953
|
||||
F tool/libvers.c caafc3b689638a1d88d44bc5f526c2278760d9b9
|
||||
F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862
|
||||
F tool/logest.c 11346aa019e2e77a00902aa7d0cabd27bd2e8cca
|
||||
@@ -1629,13 +1644,13 @@ F tool/mkkeywordhash.c 2e852ac0dfdc5af18886dc1ce7e9676d11714ae3df0a282dc7d90b3a0
|
||||
F tool/mkmsvcmin.tcl 8baf26690b80d861d0ac341b29880eec6ade39e4f11fe690271ded9cb90563a3
|
||||
F tool/mkopcodec.tcl d1b6362bd3aa80d5520d4d6f3765badf01f6c43c
|
||||
F tool/mkopcodeh.tcl 4ee2a30ccbd900dc4d5cdb61bdab87cd2166cd2affcc78c9cc0b8d22a65b2eee
|
||||
F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e
|
||||
F tool/mkopts.tcl 680f785fdb09729fd9ac50632413da4eadbdf9071535e3f26d03795828ab07fa
|
||||
F tool/mkpragmatab.tcl 2144bc8550a6471a029db262a132d2df4b9e0db61b90398bf64f5b7b3f8d92cd
|
||||
F tool/mkshellc.tcl 1f45770aea226ac093a9c72f718efbb88a2a2833409ec2e1c4cecae4202626f5
|
||||
F tool/mksourceid.c d458f9004c837bee87a6382228ac20d3eae3c49ea3b0a5aace936f8b60748d3b
|
||||
F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97
|
||||
F tool/mksqlite3c-noext.tcl fef88397668ae83166735c41af99d79f56afaabb
|
||||
F tool/mksqlite3c.tcl 1fb69d39166f52d802a70ec37d99bca51d011c8ab30be27bc495be493196ae41
|
||||
F tool/mksqlite3c.tcl a03cee30de81a2e67b93e5c659f24113a003677c557daeb008205c8e6d4345d6
|
||||
F tool/mksqlite3h.tcl f92f994d9709aeb9e2b6e6f9fc8b069d2f55202c8e23f453edc44390a25982dc
|
||||
F tool/mksqlite3internalh.tcl eb994013e833359137eb53a55acdad0b5ae1049b
|
||||
F tool/mkvsix.tcl b9e0777a213c23156b6542842c238479e496ebf5
|
||||
@@ -1655,7 +1670,7 @@ F tool/showstat4.c 0682ebea7abf4d3657f53c4a243f2e7eab48eab344ed36a94bb75dcd19a5c
|
||||
F tool/showwal.c ad9d768f96ca6199ad3a8c9562d679680bd032dd01204ea3e5ea6fb931d81847
|
||||
F tool/soak1.tcl 8d407956e1a45b485a8e072470a3e629a27037fe
|
||||
F tool/spaceanal.tcl 4bfd19aad7eb3ce0372ef0255f58035e0bba4ff5e9acfd763a10c6fb365c8dec
|
||||
F tool/speed-check.sh 9ae425da8819e54e780cf494fc6d8175dfb16e109ae3214a45a5c9bb2b74e2c4
|
||||
F tool/speed-check.sh 4ff9b095cf1a7643f0264e7fb7d23f0b12b7cce587a9de315877c378e90eeaf4
|
||||
F tool/speedtest.tcl 06c76698485ccf597b9e7dbb1ac70706eb873355
|
||||
F tool/speedtest16.c ecb6542862151c3e6509bbc00509b234562ae81e
|
||||
F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
|
||||
@@ -1697,10 +1712,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||
P 4f68bed3b9a63a349a2a2d7f26609491577e9717034ad86af404cf9eed9d6aaf
|
||||
R ca3c0ce043db4afb0303f36904592ef8
|
||||
T *branch * sqlite3_vtab_nochange
|
||||
T *sym-sqlite3_vtab_nochange *
|
||||
T -sym-trunk *
|
||||
U drh
|
||||
Z 5a280540fff60985c8c72fc104fac16d
|
||||
P 7834cf6c28c63f6ca0e29a508c0f6e3ec9c5c48715344c2db99a9866e92ef205
|
||||
R 0676d2c36dd5dc602d3c6343c630c1e9
|
||||
U dan
|
||||
Z 67bd751f2f713e6278cdb7ebdf4ff3a3
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
d444b1ff39f0a1673a977b8047e1e14a49d461c9934be080d27c2392a830c1c0
|
||||
9a5ef341de2bd2fc4657a510f48159f7876f58d340b457b4272a71d389f88da3
|
||||
@@ -234,6 +234,10 @@ static void openStatTable(
|
||||
"DELETE FROM %Q.%s WHERE %s=%Q",
|
||||
pDb->zDbSName, zTab, zWhereType, zWhere
|
||||
);
|
||||
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
|
||||
}else if( db->xPreUpdateCallback ){
|
||||
sqlite3NestedParse(pParse, "DELETE FROM %Q.%s", pDb->zDbSName, zTab);
|
||||
#endif
|
||||
}else{
|
||||
/* The sqlite_stat[134] table already exists. Delete all rows. */
|
||||
sqlite3VdbeAddOp2(v, OP_Clear, aRoot[i], iDb);
|
||||
@@ -998,6 +1002,9 @@ static void analyzeOneTable(
|
||||
int regIdxname = iMem++; /* Register containing index name */
|
||||
int regStat1 = iMem++; /* Value for the stat column of sqlite_stat1 */
|
||||
int regPrev = iMem; /* MUST BE LAST (see below) */
|
||||
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
|
||||
Table *pStat1 = 0;
|
||||
#endif
|
||||
|
||||
pParse->nMem = MAX(pParse->nMem, iMem);
|
||||
v = sqlite3GetVdbe(pParse);
|
||||
@@ -1023,6 +1030,18 @@ static void analyzeOneTable(
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
|
||||
if( db->xPreUpdateCallback ){
|
||||
pStat1 = (Table*)sqlite3DbMallocZero(db, sizeof(Table) + 13);
|
||||
if( pStat1==0 ) return;
|
||||
pStat1->zName = (char*)&pStat1[1];
|
||||
memcpy(pStat1->zName, "sqlite_stat1", 13);
|
||||
pStat1->nCol = 3;
|
||||
pStat1->iPKey = -1;
|
||||
sqlite3VdbeAddOp4(pParse->pVdbe, OP_Noop, 0, 0, 0,(char*)pStat1,P4_DYNBLOB);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Establish a read-lock on the table at the shared-cache level.
|
||||
** Open a read-only cursor on the table. Also allocate a cursor number
|
||||
** to use for scanning indexes (iIdxCur). No index cursor is opened at
|
||||
@@ -1224,6 +1243,9 @@ static void analyzeOneTable(
|
||||
sqlite3VdbeAddOp4(v, OP_MakeRecord, regTabname, 3, regTemp, "BBB", 0);
|
||||
sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur, regNewRowid);
|
||||
sqlite3VdbeAddOp3(v, OP_Insert, iStatCur, regTemp, regNewRowid);
|
||||
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
|
||||
sqlite3VdbeChangeP4(v, -1, (char*)pStat1, P4_TABLE);
|
||||
#endif
|
||||
sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
|
||||
|
||||
/* Add the entries to the stat3 or stat4 table. */
|
||||
@@ -1287,6 +1309,9 @@ static void analyzeOneTable(
|
||||
sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur, regNewRowid);
|
||||
sqlite3VdbeAddOp3(v, OP_Insert, iStatCur, regTemp, regNewRowid);
|
||||
sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
|
||||
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
|
||||
sqlite3VdbeChangeP4(v, -1, (char*)pStat1, P4_TABLE);
|
||||
#endif
|
||||
sqlite3VdbeJumpHere(v, jZeroRows);
|
||||
}
|
||||
}
|
||||
|
||||
+105
-69
@@ -55,6 +55,10 @@ static int resolveAttachExpr(NameContext *pName, Expr *pExpr)
|
||||
**
|
||||
** If the optional "KEY z" syntax is omitted, an SQL NULL is passed as the
|
||||
** third argument.
|
||||
**
|
||||
** If the db->init.reopenMemdb flags is set, then instead of attaching a
|
||||
** new database, close the database on db->init.iDb and reopen it as an
|
||||
** empty MemDB.
|
||||
*/
|
||||
static void attachFunc(
|
||||
sqlite3_context *context,
|
||||
@@ -75,65 +79,85 @@ static void attachFunc(
|
||||
sqlite3_vfs *pVfs;
|
||||
|
||||
UNUSED_PARAMETER(NotUsed);
|
||||
|
||||
zFile = (const char *)sqlite3_value_text(argv[0]);
|
||||
zName = (const char *)sqlite3_value_text(argv[1]);
|
||||
if( zFile==0 ) zFile = "";
|
||||
if( zName==0 ) zName = "";
|
||||
|
||||
/* Check for the following errors:
|
||||
**
|
||||
** * Too many attached databases,
|
||||
** * Transaction currently open
|
||||
** * Specified database name already being used.
|
||||
*/
|
||||
if( db->nDb>=db->aLimit[SQLITE_LIMIT_ATTACHED]+2 ){
|
||||
zErrDyn = sqlite3MPrintf(db, "too many attached databases - max %d",
|
||||
db->aLimit[SQLITE_LIMIT_ATTACHED]
|
||||
);
|
||||
goto attach_error;
|
||||
}
|
||||
for(i=0; i<db->nDb; i++){
|
||||
char *z = db->aDb[i].zDbSName;
|
||||
assert( z && zName );
|
||||
if( sqlite3StrICmp(z, zName)==0 ){
|
||||
zErrDyn = sqlite3MPrintf(db, "database %s is already in use", zName);
|
||||
#ifdef SQLITE_ENABLE_DESERIALIZE
|
||||
# define REOPEN_AS_MEMDB(db) (db->init.reopenMemdb)
|
||||
#else
|
||||
# define REOPEN_AS_MEMDB(db) (0)
|
||||
#endif
|
||||
|
||||
if( REOPEN_AS_MEMDB(db) ){
|
||||
/* This is not a real ATTACH. Instead, this routine is being called
|
||||
** from sqlite3_deserialize() to close database db->init.iDb and
|
||||
** reopen it as a MemDB */
|
||||
pVfs = sqlite3_vfs_find("memdb");
|
||||
if( pVfs==0 ) return;
|
||||
pNew = &db->aDb[db->init.iDb];
|
||||
if( pNew->pBt ) sqlite3BtreeClose(pNew->pBt);
|
||||
pNew->pBt = 0;
|
||||
pNew->pSchema = 0;
|
||||
rc = sqlite3BtreeOpen(pVfs, "x", db, &pNew->pBt, 0, SQLITE_OPEN_MAIN_DB);
|
||||
}else{
|
||||
/* This is a real ATTACH
|
||||
**
|
||||
** Check for the following errors:
|
||||
**
|
||||
** * Too many attached databases,
|
||||
** * Transaction currently open
|
||||
** * Specified database name already being used.
|
||||
*/
|
||||
if( db->nDb>=db->aLimit[SQLITE_LIMIT_ATTACHED]+2 ){
|
||||
zErrDyn = sqlite3MPrintf(db, "too many attached databases - max %d",
|
||||
db->aLimit[SQLITE_LIMIT_ATTACHED]
|
||||
);
|
||||
goto attach_error;
|
||||
}
|
||||
for(i=0; i<db->nDb; i++){
|
||||
char *z = db->aDb[i].zDbSName;
|
||||
assert( z && zName );
|
||||
if( sqlite3StrICmp(z, zName)==0 ){
|
||||
zErrDyn = sqlite3MPrintf(db, "database %s is already in use", zName);
|
||||
goto attach_error;
|
||||
}
|
||||
}
|
||||
|
||||
/* Allocate the new entry in the db->aDb[] array and initialize the schema
|
||||
** hash tables.
|
||||
*/
|
||||
if( db->aDb==db->aDbStatic ){
|
||||
aNew = sqlite3DbMallocRawNN(db, sizeof(db->aDb[0])*3 );
|
||||
if( aNew==0 ) return;
|
||||
memcpy(aNew, db->aDb, sizeof(db->aDb[0])*2);
|
||||
}else{
|
||||
aNew = sqlite3DbRealloc(db, db->aDb, sizeof(db->aDb[0])*(db->nDb+1) );
|
||||
if( aNew==0 ) return;
|
||||
}
|
||||
db->aDb = aNew;
|
||||
pNew = &db->aDb[db->nDb];
|
||||
memset(pNew, 0, sizeof(*pNew));
|
||||
|
||||
/* Open the database file. If the btree is successfully opened, use
|
||||
** it to obtain the database schema. At this point the schema may
|
||||
** or may not be initialized.
|
||||
*/
|
||||
flags = db->openFlags;
|
||||
rc = sqlite3ParseUri(db->pVfs->zName, zFile, &flags, &pVfs, &zPath, &zErr);
|
||||
if( rc!=SQLITE_OK ){
|
||||
if( rc==SQLITE_NOMEM ) sqlite3OomFault(db);
|
||||
sqlite3_result_error(context, zErr, -1);
|
||||
sqlite3_free(zErr);
|
||||
return;
|
||||
}
|
||||
assert( pVfs );
|
||||
flags |= SQLITE_OPEN_MAIN_DB;
|
||||
rc = sqlite3BtreeOpen(pVfs, zPath, db, &pNew->pBt, 0, flags);
|
||||
sqlite3_free( zPath );
|
||||
db->nDb++;
|
||||
}
|
||||
|
||||
/* Allocate the new entry in the db->aDb[] array and initialize the schema
|
||||
** hash tables.
|
||||
*/
|
||||
if( db->aDb==db->aDbStatic ){
|
||||
aNew = sqlite3DbMallocRawNN(db, sizeof(db->aDb[0])*3 );
|
||||
if( aNew==0 ) return;
|
||||
memcpy(aNew, db->aDb, sizeof(db->aDb[0])*2);
|
||||
}else{
|
||||
aNew = sqlite3DbRealloc(db, db->aDb, sizeof(db->aDb[0])*(db->nDb+1) );
|
||||
if( aNew==0 ) return;
|
||||
}
|
||||
db->aDb = aNew;
|
||||
pNew = &db->aDb[db->nDb];
|
||||
memset(pNew, 0, sizeof(*pNew));
|
||||
|
||||
/* Open the database file. If the btree is successfully opened, use
|
||||
** it to obtain the database schema. At this point the schema may
|
||||
** or may not be initialized.
|
||||
*/
|
||||
flags = db->openFlags;
|
||||
rc = sqlite3ParseUri(db->pVfs->zName, zFile, &flags, &pVfs, &zPath, &zErr);
|
||||
if( rc!=SQLITE_OK ){
|
||||
if( rc==SQLITE_NOMEM ) sqlite3OomFault(db);
|
||||
sqlite3_result_error(context, zErr, -1);
|
||||
sqlite3_free(zErr);
|
||||
return;
|
||||
}
|
||||
assert( pVfs );
|
||||
flags |= SQLITE_OPEN_MAIN_DB;
|
||||
rc = sqlite3BtreeOpen(pVfs, zPath, db, &pNew->pBt, 0, flags);
|
||||
sqlite3_free( zPath );
|
||||
db->nDb++;
|
||||
db->skipBtreeMutex = 0;
|
||||
if( rc==SQLITE_CONSTRAINT ){
|
||||
rc = SQLITE_ERROR;
|
||||
@@ -160,7 +184,7 @@ static void attachFunc(
|
||||
sqlite3BtreeLeave(pNew->pBt);
|
||||
}
|
||||
pNew->safety_level = SQLITE_DEFAULT_SYNCHRONOUS+1;
|
||||
pNew->zDbSName = sqlite3DbStrDup(db, zName);
|
||||
if( !REOPEN_AS_MEMDB(db) ) pNew->zDbSName = sqlite3DbStrDup(db, zName);
|
||||
if( rc==SQLITE_OK && pNew->zDbSName==0 ){
|
||||
rc = SQLITE_NOMEM_BKPT;
|
||||
}
|
||||
@@ -200,13 +224,15 @@ static void attachFunc(
|
||||
|
||||
/* If the file was opened successfully, read the schema for the new database.
|
||||
** If this fails, or if opening the file failed, then close the file and
|
||||
** remove the entry from the db->aDb[] array. i.e. put everything back the way
|
||||
** we found it.
|
||||
** remove the entry from the db->aDb[] array. i.e. put everything back the
|
||||
** way we found it.
|
||||
*/
|
||||
if( rc==SQLITE_OK ){
|
||||
sqlite3BtreeEnterAll(db);
|
||||
db->init.iDb = 0;
|
||||
rc = sqlite3Init(db, &zErrDyn);
|
||||
sqlite3BtreeLeaveAll(db);
|
||||
assert( zErrDyn==0 || rc!=SQLITE_OK );
|
||||
}
|
||||
#ifdef SQLITE_USER_AUTHENTICATION
|
||||
if( rc==SQLITE_OK ){
|
||||
@@ -218,21 +244,23 @@ static void attachFunc(
|
||||
}
|
||||
#endif
|
||||
if( rc ){
|
||||
int iDb = db->nDb - 1;
|
||||
assert( iDb>=2 );
|
||||
if( db->aDb[iDb].pBt ){
|
||||
sqlite3BtreeClose(db->aDb[iDb].pBt);
|
||||
db->aDb[iDb].pBt = 0;
|
||||
db->aDb[iDb].pSchema = 0;
|
||||
}
|
||||
sqlite3ResetAllSchemasOfConnection(db);
|
||||
db->nDb = iDb;
|
||||
if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){
|
||||
sqlite3OomFault(db);
|
||||
sqlite3DbFree(db, zErrDyn);
|
||||
zErrDyn = sqlite3MPrintf(db, "out of memory");
|
||||
}else if( zErrDyn==0 ){
|
||||
zErrDyn = sqlite3MPrintf(db, "unable to open database: %s", zFile);
|
||||
if( !REOPEN_AS_MEMDB(db) ){
|
||||
int iDb = db->nDb - 1;
|
||||
assert( iDb>=2 );
|
||||
if( db->aDb[iDb].pBt ){
|
||||
sqlite3BtreeClose(db->aDb[iDb].pBt);
|
||||
db->aDb[iDb].pBt = 0;
|
||||
db->aDb[iDb].pSchema = 0;
|
||||
}
|
||||
sqlite3ResetAllSchemasOfConnection(db);
|
||||
db->nDb = iDb;
|
||||
if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){
|
||||
sqlite3OomFault(db);
|
||||
sqlite3DbFree(db, zErrDyn);
|
||||
zErrDyn = sqlite3MPrintf(db, "out of memory");
|
||||
}else if( zErrDyn==0 ){
|
||||
zErrDyn = sqlite3MPrintf(db, "unable to open database: %s", zFile);
|
||||
}
|
||||
}
|
||||
goto attach_error;
|
||||
}
|
||||
@@ -504,6 +532,14 @@ int sqlite3FixSelect(
|
||||
if( sqlite3FixExpr(pFix, pSelect->pLimit) ){
|
||||
return 1;
|
||||
}
|
||||
if( pSelect->pWith ){
|
||||
int i;
|
||||
for(i=0; i<pSelect->pWith->nCte; i++){
|
||||
if( sqlite3FixSelect(pFix, pSelect->pWith->a[i].pSelect) ){
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
pSelect = pSelect->pPrior;
|
||||
}
|
||||
return 0;
|
||||
|
||||
+20
-9
@@ -123,9 +123,12 @@ int sqlite3_enable_shared_cache(int enable){
|
||||
*/
|
||||
#ifdef SQLITE_DEBUG
|
||||
int corruptPageError(int lineno, MemPage *p){
|
||||
char *zMsg = sqlite3_mprintf("database corruption page %d of %s",
|
||||
char *zMsg;
|
||||
sqlite3BeginBenignMalloc();
|
||||
zMsg = sqlite3_mprintf("database corruption page %d of %s",
|
||||
(int)p->pgno, sqlite3PagerFilename(p->pBt->pPager, 0)
|
||||
);
|
||||
sqlite3EndBenignMalloc();
|
||||
if( zMsg ){
|
||||
sqlite3ReportError(SQLITE_CORRUPT, lineno, zMsg);
|
||||
}
|
||||
@@ -4342,7 +4345,7 @@ int sqlite3BtreeCursorSize(void){
|
||||
** of run-time by skipping the initialization of those elements.
|
||||
*/
|
||||
void sqlite3BtreeCursorZero(BtCursor *p){
|
||||
memset(p, 0, offsetof(BtCursor, iPage));
|
||||
memset(p, 0, offsetof(BtCursor, BTCURSOR_FIRST_UNINIT));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -4385,11 +4388,19 @@ int sqlite3BtreeCloseCursor(BtCursor *pCur){
|
||||
** Using this cache reduces the number of calls to btreeParseCell().
|
||||
*/
|
||||
#ifndef NDEBUG
|
||||
static int cellInfoEqual(CellInfo *a, CellInfo *b){
|
||||
if( a->nKey!=b->nKey ) return 0;
|
||||
if( a->pPayload!=b->pPayload ) return 0;
|
||||
if( a->nPayload!=b->nPayload ) return 0;
|
||||
if( a->nLocal!=b->nLocal ) return 0;
|
||||
if( a->nSize!=b->nSize ) return 0;
|
||||
return 1;
|
||||
}
|
||||
static void assertCellInfo(BtCursor *pCur){
|
||||
CellInfo info;
|
||||
memset(&info, 0, sizeof(info));
|
||||
btreeParseCell(pCur->pPage, pCur->ix, &info);
|
||||
assert( CORRUPT_DB || memcmp(&info, &pCur->info, sizeof(info))==0 );
|
||||
assert( CORRUPT_DB || cellInfoEqual(&info, &pCur->info) );
|
||||
}
|
||||
#else
|
||||
#define assertCellInfo(x)
|
||||
@@ -4665,14 +4676,15 @@ static int accessPayload(
|
||||
*/
|
||||
if( (pCur->curFlags & BTCF_ValidOvfl)==0 ){
|
||||
int nOvfl = (pCur->info.nPayload-pCur->info.nLocal+ovflSize-1)/ovflSize;
|
||||
if( nOvfl>pCur->nOvflAlloc ){
|
||||
if( pCur->aOverflow==0
|
||||
|| nOvfl*(int)sizeof(Pgno) > sqlite3MallocSize(pCur->aOverflow)
|
||||
){
|
||||
Pgno *aNew = (Pgno*)sqlite3Realloc(
|
||||
pCur->aOverflow, nOvfl*2*sizeof(Pgno)
|
||||
);
|
||||
if( aNew==0 ){
|
||||
return SQLITE_NOMEM_BKPT;
|
||||
}else{
|
||||
pCur->nOvflAlloc = nOvfl*2;
|
||||
pCur->aOverflow = aNew;
|
||||
}
|
||||
}
|
||||
@@ -6186,9 +6198,8 @@ static void freePage(MemPage *pPage, int *pRC){
|
||||
}
|
||||
|
||||
/*
|
||||
** Free any overflow pages associated with the given Cell. Write the
|
||||
** local Cell size (the number of bytes on the original page, omitting
|
||||
** overflow) into *pnSize.
|
||||
** Free any overflow pages associated with the given Cell. Store
|
||||
** size information about the cell in pInfo.
|
||||
*/
|
||||
static int clearCell(
|
||||
MemPage *pPage, /* The page that contains the Cell */
|
||||
@@ -7392,7 +7403,7 @@ static int balance_nonroot(
|
||||
}
|
||||
|
||||
/* Load b.apCell[] with pointers to all cells in pOld. If pOld
|
||||
** constains overflow cells, include them in the b.apCell[] array
|
||||
** contains overflow cells, include them in the b.apCell[] array
|
||||
** in the correct spot.
|
||||
**
|
||||
** Note that when there are multiple overflow cells, it is always the
|
||||
|
||||
+11
-11
@@ -503,20 +503,20 @@ struct BtCursor {
|
||||
u8 curFlags; /* zero or more BTCF_* flags defined below */
|
||||
u8 curPagerFlags; /* Flags to send to sqlite3PagerGet() */
|
||||
u8 hints; /* As configured by CursorSetHints() */
|
||||
int nOvflAlloc; /* Allocated size of aOverflow[] array */
|
||||
Btree *pBtree; /* The Btree to which this cursor belongs */
|
||||
BtShared *pBt; /* The BtShared this cursor points to */
|
||||
BtCursor *pNext; /* Forms a linked list of all cursors */
|
||||
Pgno *aOverflow; /* Cache of overflow page locations */
|
||||
CellInfo info; /* A parse of the cell we are pointing at */
|
||||
i64 nKey; /* Size of pKey, or last integer key */
|
||||
void *pKey; /* Saved key that was cursor last known position */
|
||||
Pgno pgnoRoot; /* The root page of this tree */
|
||||
int skipNext; /* Prev() is noop if negative. Next() is noop if positive.
|
||||
** Error code if eState==CURSOR_FAULT */
|
||||
Btree *pBtree; /* The Btree to which this cursor belongs */
|
||||
Pgno *aOverflow; /* Cache of overflow page locations */
|
||||
void *pKey; /* Saved key that was cursor last known position */
|
||||
/* All fields above are zeroed when the cursor is allocated. See
|
||||
** sqlite3BtreeCursorZero(). Fields that follow must be manually
|
||||
** initialized. */
|
||||
#define BTCURSOR_FIRST_UNINIT pBt /* Name of first uninitialized field */
|
||||
BtShared *pBt; /* The BtShared this cursor points to */
|
||||
BtCursor *pNext; /* Forms a linked list of all cursors */
|
||||
CellInfo info; /* A parse of the cell we are pointing at */
|
||||
i64 nKey; /* Size of pKey, or last integer key */
|
||||
Pgno pgnoRoot; /* The root page of this tree */
|
||||
i8 iPage; /* Index of current page in apPage */
|
||||
u8 curIntKey; /* Value of apPage[0]->intKey */
|
||||
u16 ix; /* Current index for apPage[iPage] */
|
||||
@@ -566,8 +566,8 @@ struct BtCursor {
|
||||
** Do nothing else with this cursor. Any attempt to use the cursor
|
||||
** should return the error code stored in BtCursor.skipNext
|
||||
*/
|
||||
#define CURSOR_INVALID 0
|
||||
#define CURSOR_VALID 1
|
||||
#define CURSOR_VALID 0
|
||||
#define CURSOR_INVALID 1
|
||||
#define CURSOR_SKIPNEXT 2
|
||||
#define CURSOR_REQUIRESEEK 3
|
||||
#define CURSOR_FAULT 4
|
||||
|
||||
+22
-4
@@ -1118,10 +1118,24 @@ void sqlite3AddColumn(Parse *pParse, Token *pName, Token *pType){
|
||||
*/
|
||||
void sqlite3AddNotNull(Parse *pParse, int onError){
|
||||
Table *p;
|
||||
Column *pCol;
|
||||
p = pParse->pNewTable;
|
||||
if( p==0 || NEVER(p->nCol<1) ) return;
|
||||
p->aCol[p->nCol-1].notNull = (u8)onError;
|
||||
pCol = &p->aCol[p->nCol-1];
|
||||
pCol->notNull = (u8)onError;
|
||||
p->tabFlags |= TF_HasNotNull;
|
||||
|
||||
/* Set the uniqNotNull flag on any UNIQUE or PK indexes already created
|
||||
** on this column. */
|
||||
if( pCol->colFlags & COLFLAG_UNIQUE ){
|
||||
Index *pIdx;
|
||||
for(pIdx=p->pIndex; pIdx; pIdx=pIdx->pNext){
|
||||
assert( pIdx->nKeyCol==1 && pIdx->onError!=OE_None );
|
||||
if( pIdx->aiColumn[0]==p->nCol-1 ){
|
||||
pIdx->uniqNotNull = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1856,8 +1870,6 @@ void sqlite3EndTable(
|
||||
p = pParse->pNewTable;
|
||||
if( p==0 ) return;
|
||||
|
||||
assert( !db->init.busy || !pSelect );
|
||||
|
||||
/* If the db->init.busy is 1 it means we are reading the SQL off the
|
||||
** "sqlite_master" or "sqlite_temp_master" table on the disk.
|
||||
** So do not write to the disk again. Extract the root page number
|
||||
@@ -1868,6 +1880,10 @@ void sqlite3EndTable(
|
||||
** table itself. So mark it read-only.
|
||||
*/
|
||||
if( db->init.busy ){
|
||||
if( pSelect ){
|
||||
sqlite3ErrorMsg(pParse, "");
|
||||
return;
|
||||
}
|
||||
p->tnum = db->init.newTnum;
|
||||
if( p->tnum==1 ) p->tabFlags |= TF_Readonly;
|
||||
}
|
||||
@@ -3085,7 +3101,9 @@ void sqlite3CreateIndex(
|
||||
*/
|
||||
if( pList==0 ){
|
||||
Token prevCol;
|
||||
sqlite3TokenInit(&prevCol, pTab->aCol[pTab->nCol-1].zName);
|
||||
Column *pCol = &pTab->aCol[pTab->nCol-1];
|
||||
pCol->colFlags |= COLFLAG_UNIQUE;
|
||||
sqlite3TokenInit(&prevCol, pCol->zName);
|
||||
pList = sqlite3ExprListAppend(pParse, 0,
|
||||
sqlite3ExprAlloc(db, TK_ID, &prevCol, 0));
|
||||
if( pList==0 ) goto exit_create_index;
|
||||
|
||||
+1
-1
@@ -760,7 +760,7 @@ void sqlite3GenerateRowDelete(
|
||||
u8 p5 = 0;
|
||||
sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur,0,iIdxNoSeek);
|
||||
sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, (count?OPFLAG_NCHANGE:0));
|
||||
if( pParse->nested==0 ){
|
||||
if( pParse->nested==0 || 0==sqlite3_stricmp(pTab->zName, "sqlite_stat1") ){
|
||||
sqlite3VdbeAppendP4(v, (char*)pTab, P4_TABLE);
|
||||
}
|
||||
if( eMode!=ONEPASS_OFF ){
|
||||
|
||||
+90
-4
@@ -658,15 +658,15 @@ static void heightOfExprList(ExprList *p, int *pnHeight){
|
||||
}
|
||||
}
|
||||
}
|
||||
static void heightOfSelect(Select *p, int *pnHeight){
|
||||
if( p ){
|
||||
static void heightOfSelect(Select *pSelect, int *pnHeight){
|
||||
Select *p;
|
||||
for(p=pSelect; p; p=p->pPrior){
|
||||
heightOfExpr(p->pWhere, pnHeight);
|
||||
heightOfExpr(p->pHaving, pnHeight);
|
||||
heightOfExpr(p->pLimit, pnHeight);
|
||||
heightOfExprList(p->pEList, pnHeight);
|
||||
heightOfExprList(p->pGroupBy, pnHeight);
|
||||
heightOfExprList(p->pOrderBy, pnHeight);
|
||||
heightOfSelect(p->pPrior, pnHeight);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1732,6 +1732,34 @@ int sqlite3SelectWalkFail(Walker *pWalker, Select *NotUsed){
|
||||
return WRC_Abort;
|
||||
}
|
||||
|
||||
/*
|
||||
** If the input expression is an ID with the name "true" or "false"
|
||||
** then convert it into an TK_TRUEFALSE term. Return non-zero if
|
||||
** the conversion happened, and zero if the expression is unaltered.
|
||||
*/
|
||||
int sqlite3ExprIdToTrueFalse(Expr *pExpr){
|
||||
assert( pExpr->op==TK_ID || pExpr->op==TK_STRING );
|
||||
if( sqlite3StrICmp(pExpr->u.zToken, "true")==0
|
||||
|| sqlite3StrICmp(pExpr->u.zToken, "false")==0
|
||||
){
|
||||
pExpr->op = TK_TRUEFALSE;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** The argument must be a TK_TRUEFALSE Expr node. Return 1 if it is TRUE
|
||||
** and 0 if it is FALSE.
|
||||
*/
|
||||
int sqlite3ExprTruthValue(const Expr *pExpr){
|
||||
assert( pExpr->op==TK_TRUEFALSE );
|
||||
assert( sqlite3StrICmp(pExpr->u.zToken,"true")==0
|
||||
|| sqlite3StrICmp(pExpr->u.zToken,"false")==0 );
|
||||
return pExpr->u.zToken[4]==0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** These routines are Walker callbacks used to check expressions to
|
||||
** see if they are "constant" for some definition of constant. The
|
||||
@@ -1779,6 +1807,12 @@ static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){
|
||||
return WRC_Abort;
|
||||
}
|
||||
case TK_ID:
|
||||
/* Convert "true" or "false" in a DEFAULT clause into the
|
||||
** appropriate TK_TRUEFALSE operator */
|
||||
if( sqlite3ExprIdToTrueFalse(pExpr) ){
|
||||
return WRC_Prune;
|
||||
}
|
||||
/* Fall thru */
|
||||
case TK_COLUMN:
|
||||
case TK_AGG_FUNCTION:
|
||||
case TK_AGG_COLUMN:
|
||||
@@ -2764,7 +2798,6 @@ int sqlite3CodeSubselect(
|
||||
pSel->pLimit = sqlite3PExpr(pParse, TK_LIMIT, pLimit, 0);
|
||||
}
|
||||
pSel->iLimit = 0;
|
||||
pSel->selFlags &= ~SF_MultiValue;
|
||||
if( sqlite3Select(pParse, pSel, &dest) ){
|
||||
return 0;
|
||||
}
|
||||
@@ -3544,6 +3577,10 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
||||
codeInteger(pParse, pExpr, 0, target);
|
||||
return target;
|
||||
}
|
||||
case TK_TRUEFALSE: {
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, sqlite3ExprTruthValue(pExpr), target);
|
||||
return target;
|
||||
}
|
||||
#ifndef SQLITE_OMIT_FLOATING_POINT
|
||||
case TK_FLOAT: {
|
||||
assert( !ExprHasProperty(pExpr, EP_IntValue) );
|
||||
@@ -3699,6 +3736,18 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
||||
sqlite3VdbeAddOp2(v, op, r1, inReg);
|
||||
break;
|
||||
}
|
||||
case TK_TRUTH: {
|
||||
int isTrue; /* IS TRUE or IS NOT TRUE */
|
||||
int bNormal; /* IS TRUE or IS FALSE */
|
||||
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1);
|
||||
testcase( regFree1==0 );
|
||||
isTrue = sqlite3ExprTruthValue(pExpr->pRight);
|
||||
bNormal = pExpr->op2==TK_IS;
|
||||
testcase( isTrue && bNormal);
|
||||
testcase( !isTrue && bNormal);
|
||||
sqlite3VdbeAddOp4Int(v, OP_IsTrue, r1, inReg, !isTrue, isTrue ^ bNormal);
|
||||
break;
|
||||
}
|
||||
case TK_ISNULL:
|
||||
case TK_NOTNULL: {
|
||||
int addr;
|
||||
@@ -4474,6 +4523,23 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
|
||||
sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull);
|
||||
break;
|
||||
}
|
||||
case TK_TRUTH: {
|
||||
int isNot; /* IS NOT TRUE or IS NOT FALSE */
|
||||
int isTrue; /* IS TRUE or IS NOT TRUE */
|
||||
testcase( jumpIfNull==0 );
|
||||
isNot = pExpr->op2==TK_ISNOT;
|
||||
isTrue = sqlite3ExprTruthValue(pExpr->pRight);
|
||||
testcase( isTrue && isNot );
|
||||
testcase( !isTrue && isNot );
|
||||
if( isTrue ^ isNot ){
|
||||
sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest,
|
||||
isNot ? SQLITE_JUMPIFNULL : 0);
|
||||
}else{
|
||||
sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest,
|
||||
isNot ? SQLITE_JUMPIFNULL : 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TK_IS:
|
||||
case TK_ISNOT:
|
||||
testcase( op==TK_IS );
|
||||
@@ -4628,6 +4694,26 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
|
||||
sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull);
|
||||
break;
|
||||
}
|
||||
case TK_TRUTH: {
|
||||
int isNot; /* IS NOT TRUE or IS NOT FALSE */
|
||||
int isTrue; /* IS TRUE or IS NOT TRUE */
|
||||
testcase( jumpIfNull==0 );
|
||||
isNot = pExpr->op2==TK_ISNOT;
|
||||
isTrue = sqlite3ExprTruthValue(pExpr->pRight);
|
||||
testcase( isTrue && isNot );
|
||||
testcase( !isTrue && isNot );
|
||||
if( isTrue ^ isNot ){
|
||||
/* IS TRUE and IS NOT FALSE */
|
||||
sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest,
|
||||
isNot ? 0 : SQLITE_JUMPIFNULL);
|
||||
|
||||
}else{
|
||||
/* IS FALSE and IS NOT TRUE */
|
||||
sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest,
|
||||
isNot ? 0 : SQLITE_JUMPIFNULL);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TK_IS:
|
||||
case TK_ISNOT:
|
||||
testcase( pExpr->op==TK_IS );
|
||||
|
||||
+37
-24
@@ -35,6 +35,8 @@ static CollSeq *sqlite3GetFuncCollSeq(sqlite3_context *context){
|
||||
** iteration of the aggregate loop.
|
||||
*/
|
||||
static void sqlite3SkipAccumulatorLoad(sqlite3_context *context){
|
||||
assert( context->isError<=0 );
|
||||
context->isError = -1;
|
||||
context->skipFlag = 1;
|
||||
}
|
||||
|
||||
@@ -101,8 +103,6 @@ static void lengthFunc(
|
||||
int argc,
|
||||
sqlite3_value **argv
|
||||
){
|
||||
int len;
|
||||
|
||||
assert( argc==1 );
|
||||
UNUSED_PARAMETER(argc);
|
||||
switch( sqlite3_value_type(argv[0]) ){
|
||||
@@ -114,13 +114,17 @@ static void lengthFunc(
|
||||
}
|
||||
case SQLITE_TEXT: {
|
||||
const unsigned char *z = sqlite3_value_text(argv[0]);
|
||||
const unsigned char *z0;
|
||||
unsigned char c;
|
||||
if( z==0 ) return;
|
||||
len = 0;
|
||||
while( *z ){
|
||||
len++;
|
||||
SQLITE_SKIP_UTF8(z);
|
||||
z0 = z;
|
||||
while( (c = *z)!=0 ){
|
||||
z++;
|
||||
if( c>=0xc0 ){
|
||||
while( (*z & 0xc0)==0x80 ){ z++; z0++; }
|
||||
}
|
||||
}
|
||||
sqlite3_result_int(context, len);
|
||||
sqlite3_result_int(context, (int)(z-z0));
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
@@ -1195,6 +1199,8 @@ static void replaceFunc(
|
||||
i64 nOut; /* Maximum size of zOut */
|
||||
int loopLimit; /* Last zStr[] that might match zPattern[] */
|
||||
int i, j; /* Loop counters */
|
||||
unsigned cntExpand; /* Number zOut expansions */
|
||||
sqlite3 *db = sqlite3_context_db_handle(context);
|
||||
|
||||
assert( argc==3 );
|
||||
UNUSED_PARAMETER(argc);
|
||||
@@ -1226,33 +1232,40 @@ static void replaceFunc(
|
||||
return;
|
||||
}
|
||||
loopLimit = nStr - nPattern;
|
||||
cntExpand = 0;
|
||||
for(i=j=0; i<=loopLimit; i++){
|
||||
if( zStr[i]!=zPattern[0] || memcmp(&zStr[i], zPattern, nPattern) ){
|
||||
zOut[j++] = zStr[i];
|
||||
}else{
|
||||
u8 *zOld;
|
||||
sqlite3 *db = sqlite3_context_db_handle(context);
|
||||
nOut += nRep - nPattern;
|
||||
testcase( nOut-1==db->aLimit[SQLITE_LIMIT_LENGTH] );
|
||||
testcase( nOut-2==db->aLimit[SQLITE_LIMIT_LENGTH] );
|
||||
if( nOut-1>db->aLimit[SQLITE_LIMIT_LENGTH] ){
|
||||
sqlite3_result_error_toobig(context);
|
||||
sqlite3_free(zOut);
|
||||
return;
|
||||
}
|
||||
zOld = zOut;
|
||||
zOut = sqlite3_realloc64(zOut, (int)nOut);
|
||||
if( zOut==0 ){
|
||||
sqlite3_result_error_nomem(context);
|
||||
sqlite3_free(zOld);
|
||||
return;
|
||||
if( nRep>nPattern ){
|
||||
nOut += nRep - nPattern;
|
||||
testcase( nOut-1==db->aLimit[SQLITE_LIMIT_LENGTH] );
|
||||
testcase( nOut-2==db->aLimit[SQLITE_LIMIT_LENGTH] );
|
||||
if( nOut-1>db->aLimit[SQLITE_LIMIT_LENGTH] ){
|
||||
sqlite3_result_error_toobig(context);
|
||||
sqlite3_free(zOut);
|
||||
return;
|
||||
}
|
||||
cntExpand++;
|
||||
if( (cntExpand&(cntExpand-1))==0 ){
|
||||
/* Grow the size of the output buffer only on substitutions
|
||||
** whose index is a power of two: 1, 2, 4, 8, 16, 32, ... */
|
||||
u8 *zOld;
|
||||
zOld = zOut;
|
||||
zOut = sqlite3_realloc64(zOut, (int)nOut + (nOut - nStr - 1));
|
||||
if( zOut==0 ){
|
||||
sqlite3_result_error_nomem(context);
|
||||
sqlite3_free(zOld);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
memcpy(&zOut[j], zRep, nRep);
|
||||
j += nRep;
|
||||
i += nPattern-1;
|
||||
}
|
||||
}
|
||||
assert( j+nStr-i+1==nOut );
|
||||
assert( j+nStr-i+1<=nOut );
|
||||
memcpy(&zOut[j], &zStr[i], nStr-i);
|
||||
j += nStr - i;
|
||||
assert( j<=nOut );
|
||||
|
||||
@@ -258,6 +258,13 @@ const Token sqlite3IntTokens[] = {
|
||||
{ "1", 1 }
|
||||
};
|
||||
|
||||
#ifdef VDBE_PROFILE
|
||||
/*
|
||||
** The following performance counter can be used in place of
|
||||
** sqlite3Hwtime() for profiling. This is a no-op on standard builds.
|
||||
*/
|
||||
sqlite3_uint64 sqlite3NProfileCnt = 0;
|
||||
#endif
|
||||
|
||||
/*
|
||||
** The value of the "pending" byte must be 0x40000000 (1 byte past the
|
||||
|
||||
+5
-1
@@ -430,7 +430,11 @@ static const sqlite3_api_routines sqlite3Apis = {
|
||||
sqlite3_prepare16_v3,
|
||||
sqlite3_bind_pointer,
|
||||
sqlite3_result_pointer,
|
||||
sqlite3_value_pointer
|
||||
sqlite3_value_pointer,
|
||||
/* Version 3.22.0 and later */
|
||||
sqlite3_vtab_nochange,
|
||||
sqlite3_value_nochange,
|
||||
sqlite3_vtab_collation
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
+16
-1
@@ -239,6 +239,11 @@ int sqlite3_initialize(void){
|
||||
sqlite3GlobalConfig.isPCacheInit = 1;
|
||||
rc = sqlite3OsInit();
|
||||
}
|
||||
#ifdef SQLITE_ENABLE_DESERIALIZE
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3MemdbInit();
|
||||
}
|
||||
#endif
|
||||
if( rc==SQLITE_OK ){
|
||||
sqlite3PCacheBufferSetup( sqlite3GlobalConfig.pPage,
|
||||
sqlite3GlobalConfig.szPage, sqlite3GlobalConfig.nPage);
|
||||
@@ -271,7 +276,7 @@ int sqlite3_initialize(void){
|
||||
#ifndef NDEBUG
|
||||
#ifndef SQLITE_OMIT_FLOATING_POINT
|
||||
/* This section of code's only "output" is via assert() statements. */
|
||||
if ( rc==SQLITE_OK ){
|
||||
if( rc==SQLITE_OK ){
|
||||
u64 x = (((u64)1)<<63)-1;
|
||||
double y;
|
||||
assert(sizeof(x)==8);
|
||||
@@ -1438,6 +1443,8 @@ const char *sqlite3ErrStr(int rc){
|
||||
/* SQLITE_FORMAT */ 0,
|
||||
/* SQLITE_RANGE */ "column index out of range",
|
||||
/* SQLITE_NOTADB */ "file is not a database",
|
||||
/* SQLITE_NOTICE */ "notification message",
|
||||
/* SQLITE_WARNING */ "warning message",
|
||||
};
|
||||
const char *zErr = "unknown error";
|
||||
switch( rc ){
|
||||
@@ -1445,6 +1452,14 @@ const char *sqlite3ErrStr(int rc){
|
||||
zErr = "abort due to ROLLBACK";
|
||||
break;
|
||||
}
|
||||
case SQLITE_ROW: {
|
||||
zErr = "another row available";
|
||||
break;
|
||||
}
|
||||
case SQLITE_DONE: {
|
||||
zErr = "no more rows available";
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
rc &= 0xff;
|
||||
if( ALWAYS(rc>=0) && rc<ArraySize(aMsg) && aMsg[rc]!=0 ){
|
||||
|
||||
+589
@@ -0,0 +1,589 @@
|
||||
/*
|
||||
** 2016-09-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 implements in-memory VFS. A database is held as a contiguous
|
||||
** block of memory.
|
||||
**
|
||||
** This file also implements interface sqlite3_serialize() and
|
||||
** sqlite3_deserialize().
|
||||
*/
|
||||
#ifdef SQLITE_ENABLE_DESERIALIZE
|
||||
#include "sqliteInt.h"
|
||||
|
||||
/*
|
||||
** Forward declaration of objects used by this utility
|
||||
*/
|
||||
typedef struct sqlite3_vfs MemVfs;
|
||||
typedef struct MemFile MemFile;
|
||||
|
||||
/* Access to a lower-level VFS that (might) implement dynamic loading,
|
||||
** access to randomness, etc.
|
||||
*/
|
||||
#define ORIGVFS(p) ((sqlite3_vfs*)((p)->pAppData))
|
||||
|
||||
/* An open file */
|
||||
struct MemFile {
|
||||
sqlite3_file base; /* IO methods */
|
||||
sqlite3_int64 sz; /* Size of the file */
|
||||
sqlite3_int64 szMax; /* Space allocated to aData */
|
||||
unsigned char *aData; /* content of the file */
|
||||
int nMmap; /* Number of memory mapped pages */
|
||||
unsigned mFlags; /* Flags */
|
||||
int eLock; /* Most recent lock against this file */
|
||||
};
|
||||
|
||||
/*
|
||||
** Methods for MemFile
|
||||
*/
|
||||
static int memdbClose(sqlite3_file*);
|
||||
static int memdbRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
|
||||
static int memdbWrite(sqlite3_file*,const void*,int iAmt, sqlite3_int64 iOfst);
|
||||
static int memdbTruncate(sqlite3_file*, sqlite3_int64 size);
|
||||
static int memdbSync(sqlite3_file*, int flags);
|
||||
static int memdbFileSize(sqlite3_file*, sqlite3_int64 *pSize);
|
||||
static int memdbLock(sqlite3_file*, int);
|
||||
/* static int memdbCheckReservedLock(sqlite3_file*, int *pResOut);// not used */
|
||||
static int memdbFileControl(sqlite3_file*, int op, void *pArg);
|
||||
/* static int memdbSectorSize(sqlite3_file*); // not used */
|
||||
static int memdbDeviceCharacteristics(sqlite3_file*);
|
||||
static int memdbFetch(sqlite3_file*, sqlite3_int64 iOfst, int iAmt, void **pp);
|
||||
static int memdbUnfetch(sqlite3_file*, sqlite3_int64 iOfst, void *p);
|
||||
|
||||
/*
|
||||
** Methods for MemVfs
|
||||
*/
|
||||
static int memdbOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *);
|
||||
/* static int memdbDelete(sqlite3_vfs*, const char *zName, int syncDir); */
|
||||
static int memdbAccess(sqlite3_vfs*, const char *zName, int flags, int *);
|
||||
static int memdbFullPathname(sqlite3_vfs*, const char *zName, int, char *zOut);
|
||||
static void *memdbDlOpen(sqlite3_vfs*, const char *zFilename);
|
||||
static void memdbDlError(sqlite3_vfs*, int nByte, char *zErrMsg);
|
||||
static void (*memdbDlSym(sqlite3_vfs *pVfs, void *p, const char*zSym))(void);
|
||||
static void memdbDlClose(sqlite3_vfs*, void*);
|
||||
static int memdbRandomness(sqlite3_vfs*, int nByte, char *zOut);
|
||||
static int memdbSleep(sqlite3_vfs*, int microseconds);
|
||||
/* static int memdbCurrentTime(sqlite3_vfs*, double*); */
|
||||
static int memdbGetLastError(sqlite3_vfs*, int, char *);
|
||||
static int memdbCurrentTimeInt64(sqlite3_vfs*, sqlite3_int64*);
|
||||
|
||||
static sqlite3_vfs memdb_vfs = {
|
||||
2, /* iVersion */
|
||||
0, /* szOsFile (set when registered) */
|
||||
1024, /* mxPathname */
|
||||
0, /* pNext */
|
||||
"memdb", /* zName */
|
||||
0, /* pAppData (set when registered) */
|
||||
memdbOpen, /* xOpen */
|
||||
0, /* memdbDelete, */ /* xDelete */
|
||||
memdbAccess, /* xAccess */
|
||||
memdbFullPathname, /* xFullPathname */
|
||||
memdbDlOpen, /* xDlOpen */
|
||||
memdbDlError, /* xDlError */
|
||||
memdbDlSym, /* xDlSym */
|
||||
memdbDlClose, /* xDlClose */
|
||||
memdbRandomness, /* xRandomness */
|
||||
memdbSleep, /* xSleep */
|
||||
0, /* memdbCurrentTime, */ /* xCurrentTime */
|
||||
memdbGetLastError, /* xGetLastError */
|
||||
memdbCurrentTimeInt64 /* xCurrentTimeInt64 */
|
||||
};
|
||||
|
||||
static const sqlite3_io_methods memdb_io_methods = {
|
||||
3, /* iVersion */
|
||||
memdbClose, /* xClose */
|
||||
memdbRead, /* xRead */
|
||||
memdbWrite, /* xWrite */
|
||||
memdbTruncate, /* xTruncate */
|
||||
memdbSync, /* xSync */
|
||||
memdbFileSize, /* xFileSize */
|
||||
memdbLock, /* xLock */
|
||||
memdbLock, /* xUnlock - same as xLock in this case */
|
||||
0, /* memdbCheckReservedLock, */ /* xCheckReservedLock */
|
||||
memdbFileControl, /* xFileControl */
|
||||
0, /* memdbSectorSize,*/ /* xSectorSize */
|
||||
memdbDeviceCharacteristics, /* xDeviceCharacteristics */
|
||||
0, /* xShmMap */
|
||||
0, /* xShmLock */
|
||||
0, /* xShmBarrier */
|
||||
0, /* xShmUnmap */
|
||||
memdbFetch, /* xFetch */
|
||||
memdbUnfetch /* xUnfetch */
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** Close an memdb-file.
|
||||
**
|
||||
** The pData pointer is owned by the application, so there is nothing
|
||||
** to free.
|
||||
*/
|
||||
static int memdbClose(sqlite3_file *pFile){
|
||||
MemFile *p = (MemFile *)pFile;
|
||||
if( p->mFlags & SQLITE_DESERIALIZE_FREEONCLOSE ) sqlite3_free(p->aData);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Read data from an memdb-file.
|
||||
*/
|
||||
static int memdbRead(
|
||||
sqlite3_file *pFile,
|
||||
void *zBuf,
|
||||
int iAmt,
|
||||
sqlite_int64 iOfst
|
||||
){
|
||||
MemFile *p = (MemFile *)pFile;
|
||||
if( iOfst+iAmt>p->sz ){
|
||||
memset(zBuf, 0, iAmt);
|
||||
if( iOfst<p->sz ) memcpy(zBuf, p->aData+iOfst, p->sz - iOfst);
|
||||
return SQLITE_IOERR_SHORT_READ;
|
||||
}
|
||||
memcpy(zBuf, p->aData+iOfst, iAmt);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Try to enlarge the memory allocation to hold at least sz bytes
|
||||
*/
|
||||
static int memdbEnlarge(MemFile *p, sqlite3_int64 newSz){
|
||||
unsigned char *pNew;
|
||||
if( (p->mFlags & SQLITE_DESERIALIZE_RESIZEABLE)==0 || p->nMmap>0 ){
|
||||
return SQLITE_FULL;
|
||||
}
|
||||
pNew = sqlite3_realloc64(p->aData, newSz);
|
||||
if( pNew==0 ) return SQLITE_NOMEM;
|
||||
p->aData = pNew;
|
||||
p->szMax = newSz;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Write data to an memdb-file.
|
||||
*/
|
||||
static int memdbWrite(
|
||||
sqlite3_file *pFile,
|
||||
const void *z,
|
||||
int iAmt,
|
||||
sqlite_int64 iOfst
|
||||
){
|
||||
MemFile *p = (MemFile *)pFile;
|
||||
if( iOfst+iAmt>p->sz ){
|
||||
int rc;
|
||||
if( iOfst+iAmt>p->szMax
|
||||
&& (rc = memdbEnlarge(p, (iOfst+iAmt)*2))!=SQLITE_OK
|
||||
){
|
||||
return rc;
|
||||
}
|
||||
if( iOfst>p->sz ) memset(p->aData+p->sz, 0, iOfst-p->sz);
|
||||
p->sz = iOfst+iAmt;
|
||||
}
|
||||
memcpy(p->aData+iOfst, z, iAmt);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Truncate an memdb-file.
|
||||
**
|
||||
** In rollback mode (which is always the case for memdb, as it does not
|
||||
** support WAL mode) the truncate() method is only used to reduce
|
||||
** the size of a file, never to increase the size.
|
||||
*/
|
||||
static int memdbTruncate(sqlite3_file *pFile, sqlite_int64 size){
|
||||
MemFile *p = (MemFile *)pFile;
|
||||
if( NEVER(size>p->sz) ) return SQLITE_FULL;
|
||||
p->sz = size;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Sync an memdb-file.
|
||||
*/
|
||||
static int memdbSync(sqlite3_file *pFile, int flags){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return the current file-size of an memdb-file.
|
||||
*/
|
||||
static int memdbFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
|
||||
MemFile *p = (MemFile *)pFile;
|
||||
*pSize = p->sz;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Lock an memdb-file.
|
||||
*/
|
||||
static int memdbLock(sqlite3_file *pFile, int eLock){
|
||||
MemFile *p = (MemFile *)pFile;
|
||||
p->eLock = eLock;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
#if 0 /* Never used because memdbAccess() always returns false */
|
||||
/*
|
||||
** Check if another file-handle holds a RESERVED lock on an memdb-file.
|
||||
*/
|
||||
static int memdbCheckReservedLock(sqlite3_file *pFile, int *pResOut){
|
||||
*pResOut = 0;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** File control method. For custom operations on an memdb-file.
|
||||
*/
|
||||
static int memdbFileControl(sqlite3_file *pFile, int op, void *pArg){
|
||||
MemFile *p = (MemFile *)pFile;
|
||||
int rc = SQLITE_NOTFOUND;
|
||||
if( op==SQLITE_FCNTL_VFSNAME ){
|
||||
*(char**)pArg = sqlite3_mprintf("memdb(%p,%lld)", p->aData, p->sz);
|
||||
rc = SQLITE_OK;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
#if 0 /* Not used because of SQLITE_IOCAP_POWERSAFE_OVERWRITE */
|
||||
/*
|
||||
** Return the sector-size in bytes for an memdb-file.
|
||||
*/
|
||||
static int memdbSectorSize(sqlite3_file *pFile){
|
||||
return 1024;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Return the device characteristic flags supported by an memdb-file.
|
||||
*/
|
||||
static int memdbDeviceCharacteristics(sqlite3_file *pFile){
|
||||
return SQLITE_IOCAP_ATOMIC |
|
||||
SQLITE_IOCAP_POWERSAFE_OVERWRITE |
|
||||
SQLITE_IOCAP_SAFE_APPEND |
|
||||
SQLITE_IOCAP_SEQUENTIAL;
|
||||
}
|
||||
|
||||
/* Fetch a page of a memory-mapped file */
|
||||
static int memdbFetch(
|
||||
sqlite3_file *pFile,
|
||||
sqlite3_int64 iOfst,
|
||||
int iAmt,
|
||||
void **pp
|
||||
){
|
||||
MemFile *p = (MemFile *)pFile;
|
||||
p->nMmap++;
|
||||
*pp = (void*)(p->aData + iOfst);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/* Release a memory-mapped page */
|
||||
static int memdbUnfetch(sqlite3_file *pFile, sqlite3_int64 iOfst, void *pPage){
|
||||
MemFile *p = (MemFile *)pFile;
|
||||
p->nMmap--;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Open an mem file handle.
|
||||
*/
|
||||
static int memdbOpen(
|
||||
sqlite3_vfs *pVfs,
|
||||
const char *zName,
|
||||
sqlite3_file *pFile,
|
||||
int flags,
|
||||
int *pOutFlags
|
||||
){
|
||||
MemFile *p = (MemFile*)pFile;
|
||||
if( (flags & SQLITE_OPEN_MAIN_DB)==0 ){
|
||||
return ORIGVFS(pVfs)->xOpen(ORIGVFS(pVfs), zName, pFile, flags, pOutFlags);
|
||||
}
|
||||
memset(p, 0, sizeof(*p));
|
||||
p->mFlags = SQLITE_DESERIALIZE_RESIZEABLE | SQLITE_DESERIALIZE_FREEONCLOSE;
|
||||
assert( pOutFlags!=0 ); /* True because flags==SQLITE_OPEN_MAIN_DB */
|
||||
*pOutFlags = flags | SQLITE_OPEN_MEMORY;
|
||||
p->base.pMethods = &memdb_io_methods;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
#if 0 /* Only used to delete rollback journals, master journals, and WAL
|
||||
** files, none of which exist in memdb. So this routine is never used */
|
||||
/*
|
||||
** Delete the file located at zPath. If the dirSync argument is true,
|
||||
** ensure the file-system modifications are synced to disk before
|
||||
** returning.
|
||||
*/
|
||||
static int memdbDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
|
||||
return SQLITE_IOERR_DELETE;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Test for access permissions. Return true if the requested permission
|
||||
** is available, or false otherwise.
|
||||
**
|
||||
** With memdb, no files ever exist on disk. So always return false.
|
||||
*/
|
||||
static int memdbAccess(
|
||||
sqlite3_vfs *pVfs,
|
||||
const char *zPath,
|
||||
int flags,
|
||||
int *pResOut
|
||||
){
|
||||
*pResOut = 0;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Populate buffer zOut with the full canonical pathname corresponding
|
||||
** to the pathname in zPath. zOut is guaranteed to point to a buffer
|
||||
** of at least (INST_MAX_PATHNAME+1) bytes.
|
||||
*/
|
||||
static int memdbFullPathname(
|
||||
sqlite3_vfs *pVfs,
|
||||
const char *zPath,
|
||||
int nOut,
|
||||
char *zOut
|
||||
){
|
||||
sqlite3_snprintf(nOut, zOut, "%s", zPath);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Open the dynamic library located at zPath and return a handle.
|
||||
*/
|
||||
static void *memdbDlOpen(sqlite3_vfs *pVfs, const char *zPath){
|
||||
return ORIGVFS(pVfs)->xDlOpen(ORIGVFS(pVfs), zPath);
|
||||
}
|
||||
|
||||
/*
|
||||
** Populate the buffer zErrMsg (size nByte bytes) with a human readable
|
||||
** utf-8 string describing the most recent error encountered associated
|
||||
** with dynamic libraries.
|
||||
*/
|
||||
static void memdbDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){
|
||||
ORIGVFS(pVfs)->xDlError(ORIGVFS(pVfs), nByte, zErrMsg);
|
||||
}
|
||||
|
||||
/*
|
||||
** Return a pointer to the symbol zSymbol in the dynamic library pHandle.
|
||||
*/
|
||||
static void (*memdbDlSym(sqlite3_vfs *pVfs, void *p, const char *zSym))(void){
|
||||
return ORIGVFS(pVfs)->xDlSym(ORIGVFS(pVfs), p, zSym);
|
||||
}
|
||||
|
||||
/*
|
||||
** Close the dynamic library handle pHandle.
|
||||
*/
|
||||
static void memdbDlClose(sqlite3_vfs *pVfs, void *pHandle){
|
||||
ORIGVFS(pVfs)->xDlClose(ORIGVFS(pVfs), pHandle);
|
||||
}
|
||||
|
||||
/*
|
||||
** Populate the buffer pointed to by zBufOut with nByte bytes of
|
||||
** random data.
|
||||
*/
|
||||
static int memdbRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
|
||||
return ORIGVFS(pVfs)->xRandomness(ORIGVFS(pVfs), nByte, zBufOut);
|
||||
}
|
||||
|
||||
/*
|
||||
** Sleep for nMicro microseconds. Return the number of microseconds
|
||||
** actually slept.
|
||||
*/
|
||||
static int memdbSleep(sqlite3_vfs *pVfs, int nMicro){
|
||||
return ORIGVFS(pVfs)->xSleep(ORIGVFS(pVfs), nMicro);
|
||||
}
|
||||
|
||||
#if 0 /* Never used. Modern cores only call xCurrentTimeInt64() */
|
||||
/*
|
||||
** Return the current time as a Julian Day number in *pTimeOut.
|
||||
*/
|
||||
static int memdbCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
|
||||
return ORIGVFS(pVfs)->xCurrentTime(ORIGVFS(pVfs), pTimeOut);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int memdbGetLastError(sqlite3_vfs *pVfs, int a, char *b){
|
||||
return ORIGVFS(pVfs)->xGetLastError(ORIGVFS(pVfs), a, b);
|
||||
}
|
||||
static int memdbCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *p){
|
||||
return ORIGVFS(pVfs)->xCurrentTimeInt64(ORIGVFS(pVfs), p);
|
||||
}
|
||||
|
||||
/*
|
||||
** Translate a database connection pointer and schema name into a
|
||||
** MemFile pointer.
|
||||
*/
|
||||
static MemFile *memdbFromDbSchema(sqlite3 *db, const char *zSchema){
|
||||
MemFile *p = 0;
|
||||
int rc = sqlite3_file_control(db, zSchema, SQLITE_FCNTL_FILE_POINTER, &p);
|
||||
if( rc ) return 0;
|
||||
if( p->base.pMethods!=&memdb_io_methods ) return 0;
|
||||
return p;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return the serialization of a database
|
||||
*/
|
||||
unsigned char *sqlite3_serialize(
|
||||
sqlite3 *db, /* The database connection */
|
||||
const char *zSchema, /* Which database within the connection */
|
||||
sqlite3_int64 *piSize, /* Write size here, if not NULL */
|
||||
unsigned int mFlags /* Maybe SQLITE_SERIALIZE_NOCOPY */
|
||||
){
|
||||
MemFile *p;
|
||||
int iDb;
|
||||
Btree *pBt;
|
||||
sqlite3_int64 sz;
|
||||
int szPage = 0;
|
||||
sqlite3_stmt *pStmt = 0;
|
||||
unsigned char *pOut;
|
||||
char *zSql;
|
||||
int rc;
|
||||
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( !sqlite3SafetyCheckOk(db) ){
|
||||
(void)SQLITE_MISUSE_BKPT;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
if( zSchema==0 ) zSchema = db->aDb[0].zDbSName;
|
||||
p = memdbFromDbSchema(db, zSchema);
|
||||
iDb = sqlite3FindDbName(db, zSchema);
|
||||
if( piSize ) *piSize = -1;
|
||||
if( iDb<0 ) return 0;
|
||||
if( p ){
|
||||
if( piSize ) *piSize = p->sz;
|
||||
if( mFlags & SQLITE_SERIALIZE_NOCOPY ){
|
||||
pOut = p->aData;
|
||||
}else{
|
||||
pOut = sqlite3_malloc64( p->sz );
|
||||
if( pOut ) memcpy(pOut, p->aData, p->sz);
|
||||
}
|
||||
return pOut;
|
||||
}
|
||||
pBt = db->aDb[iDb].pBt;
|
||||
if( pBt==0 ) return 0;
|
||||
szPage = sqlite3BtreeGetPageSize(pBt);
|
||||
zSql = sqlite3_mprintf("PRAGMA \"%w\".page_count", zSchema);
|
||||
rc = zSql ? sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0) : SQLITE_NOMEM;
|
||||
sqlite3_free(zSql);
|
||||
if( rc ) return 0;
|
||||
rc = sqlite3_step(pStmt);
|
||||
if( rc!=SQLITE_ROW ){
|
||||
pOut = 0;
|
||||
}else{
|
||||
sz = sqlite3_column_int64(pStmt, 0)*szPage;
|
||||
if( piSize ) *piSize = sz;
|
||||
if( mFlags & SQLITE_SERIALIZE_NOCOPY ){
|
||||
pOut = 0;
|
||||
}else{
|
||||
pOut = sqlite3_malloc64( sz );
|
||||
if( pOut ){
|
||||
int nPage = sqlite3_column_int(pStmt, 0);
|
||||
Pager *pPager = sqlite3BtreePager(pBt);
|
||||
int pgno;
|
||||
for(pgno=1; pgno<=nPage; pgno++){
|
||||
DbPage *pPage = 0;
|
||||
unsigned char *pTo = pOut + szPage*(sqlite3_int64)(pgno-1);
|
||||
rc = sqlite3PagerGet(pPager, pgno, (DbPage**)&pPage, 0);
|
||||
if( rc==SQLITE_OK ){
|
||||
memcpy(pTo, sqlite3PagerGetData(pPage), szPage);
|
||||
}else{
|
||||
memset(pTo, 0, szPage);
|
||||
}
|
||||
sqlite3PagerUnref(pPage);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
sqlite3_finalize(pStmt);
|
||||
return pOut;
|
||||
}
|
||||
|
||||
/* Convert zSchema to a MemDB and initialize its content.
|
||||
*/
|
||||
int sqlite3_deserialize(
|
||||
sqlite3 *db, /* The database connection */
|
||||
const char *zSchema, /* Which DB to reopen with the deserialization */
|
||||
unsigned char *pData, /* The serialized database content */
|
||||
sqlite3_int64 szDb, /* Number bytes in the deserialization */
|
||||
sqlite3_int64 szBuf, /* Total size of buffer pData[] */
|
||||
unsigned mFlags /* Zero or more SQLITE_DESERIALIZE_* flags */
|
||||
){
|
||||
MemFile *p;
|
||||
char *zSql;
|
||||
sqlite3_stmt *pStmt = 0;
|
||||
int rc;
|
||||
int iDb;
|
||||
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( !sqlite3SafetyCheckOk(db) ){
|
||||
return SQLITE_MISUSE_BKPT;
|
||||
}
|
||||
if( szDb<0 ) return SQLITE_MISUSE_BKPT;
|
||||
if( szBuf<0 ) return SQLITE_MISUSE_BKPT;
|
||||
#endif
|
||||
|
||||
sqlite3_mutex_enter(db->mutex);
|
||||
if( zSchema==0 ) zSchema = db->aDb[0].zDbSName;
|
||||
iDb = sqlite3FindDbName(db, zSchema);
|
||||
if( iDb<0 ){
|
||||
rc = SQLITE_ERROR;
|
||||
goto end_deserialize;
|
||||
}
|
||||
zSql = sqlite3_mprintf("ATTACH x AS %Q", zSchema);
|
||||
rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
|
||||
sqlite3_free(zSql);
|
||||
if( rc ) goto end_deserialize;
|
||||
db->init.iDb = (u8)iDb;
|
||||
db->init.reopenMemdb = 1;
|
||||
rc = sqlite3_step(pStmt);
|
||||
db->init.reopenMemdb = 0;
|
||||
if( rc!=SQLITE_DONE ){
|
||||
rc = SQLITE_ERROR;
|
||||
goto end_deserialize;
|
||||
}
|
||||
p = memdbFromDbSchema(db, zSchema);
|
||||
if( p==0 ){
|
||||
rc = SQLITE_ERROR;
|
||||
}else{
|
||||
p->aData = pData;
|
||||
p->sz = szDb;
|
||||
p->szMax = szBuf;
|
||||
p->mFlags = mFlags;
|
||||
rc = SQLITE_OK;
|
||||
}
|
||||
|
||||
end_deserialize:
|
||||
sqlite3_finalize(pStmt);
|
||||
sqlite3_mutex_leave(db->mutex);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** This routine is called when the extension is loaded.
|
||||
** Register the new VFS.
|
||||
*/
|
||||
int sqlite3MemdbInit(void){
|
||||
sqlite3_vfs *pLower = sqlite3_vfs_find(0);
|
||||
int sz = pLower->szOsFile;
|
||||
memdb_vfs.pAppData = pLower;
|
||||
/* In all known configurations of SQLite, the size of a default
|
||||
** sqlite3_file is greater than the size of a memdb sqlite3_file.
|
||||
** Should that ever change, remove the following NEVER() */
|
||||
if( NEVER(sz<sizeof(MemFile)) ) sz = sizeof(MemFile);
|
||||
memdb_vfs.szOsFile = sz;
|
||||
return sqlite3_vfs_register(&memdb_vfs, 0);
|
||||
}
|
||||
#endif /* SQLITE_ENABLE_DESERIALIZE */
|
||||
+23
-16
@@ -50,11 +50,12 @@ struct sqlite3_mutex {
|
||||
#endif
|
||||
};
|
||||
#if SQLITE_MUTEX_NREF
|
||||
#define SQLITE3_MUTEX_INITIALIZER {PTHREAD_MUTEX_INITIALIZER,0,0,(pthread_t)0,0}
|
||||
# define SQLITE3_MUTEX_INITIALIZER(id) \
|
||||
{PTHREAD_MUTEX_INITIALIZER,id,0,(pthread_t)0,0}
|
||||
#elif defined(SQLITE_ENABLE_API_ARMOR)
|
||||
#define SQLITE3_MUTEX_INITIALIZER { PTHREAD_MUTEX_INITIALIZER, 0 }
|
||||
# define SQLITE3_MUTEX_INITIALIZER(id) { PTHREAD_MUTEX_INITIALIZER, id }
|
||||
#else
|
||||
#define SQLITE3_MUTEX_INITIALIZER { PTHREAD_MUTEX_INITIALIZER }
|
||||
#define SQLITE3_MUTEX_INITIALIZER(id) { PTHREAD_MUTEX_INITIALIZER }
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -151,18 +152,18 @@ static int pthreadMutexEnd(void){ return SQLITE_OK; }
|
||||
*/
|
||||
static sqlite3_mutex *pthreadMutexAlloc(int iType){
|
||||
static sqlite3_mutex staticMutexes[] = {
|
||||
SQLITE3_MUTEX_INITIALIZER,
|
||||
SQLITE3_MUTEX_INITIALIZER,
|
||||
SQLITE3_MUTEX_INITIALIZER,
|
||||
SQLITE3_MUTEX_INITIALIZER,
|
||||
SQLITE3_MUTEX_INITIALIZER,
|
||||
SQLITE3_MUTEX_INITIALIZER,
|
||||
SQLITE3_MUTEX_INITIALIZER,
|
||||
SQLITE3_MUTEX_INITIALIZER,
|
||||
SQLITE3_MUTEX_INITIALIZER,
|
||||
SQLITE3_MUTEX_INITIALIZER,
|
||||
SQLITE3_MUTEX_INITIALIZER,
|
||||
SQLITE3_MUTEX_INITIALIZER
|
||||
SQLITE3_MUTEX_INITIALIZER(2),
|
||||
SQLITE3_MUTEX_INITIALIZER(3),
|
||||
SQLITE3_MUTEX_INITIALIZER(4),
|
||||
SQLITE3_MUTEX_INITIALIZER(5),
|
||||
SQLITE3_MUTEX_INITIALIZER(6),
|
||||
SQLITE3_MUTEX_INITIALIZER(7),
|
||||
SQLITE3_MUTEX_INITIALIZER(8),
|
||||
SQLITE3_MUTEX_INITIALIZER(9),
|
||||
SQLITE3_MUTEX_INITIALIZER(10),
|
||||
SQLITE3_MUTEX_INITIALIZER(11),
|
||||
SQLITE3_MUTEX_INITIALIZER(12),
|
||||
SQLITE3_MUTEX_INITIALIZER(13)
|
||||
};
|
||||
sqlite3_mutex *p;
|
||||
switch( iType ){
|
||||
@@ -180,6 +181,9 @@ static sqlite3_mutex *pthreadMutexAlloc(int iType){
|
||||
pthread_mutexattr_settype(&recursiveAttr, PTHREAD_MUTEX_RECURSIVE);
|
||||
pthread_mutex_init(&p->mutex, &recursiveAttr);
|
||||
pthread_mutexattr_destroy(&recursiveAttr);
|
||||
#endif
|
||||
#if SQLITE_MUTEX_NREF || defined(SQLITE_ENABLE_API_ARMOR)
|
||||
p->id = SQLITE_MUTEX_RECURSIVE;
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
@@ -188,6 +192,9 @@ static sqlite3_mutex *pthreadMutexAlloc(int iType){
|
||||
p = sqlite3MallocZero( sizeof(*p) );
|
||||
if( p ){
|
||||
pthread_mutex_init(&p->mutex, 0);
|
||||
#if SQLITE_MUTEX_NREF || defined(SQLITE_ENABLE_API_ARMOR)
|
||||
p->id = SQLITE_MUTEX_FAST;
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -203,7 +210,7 @@ static sqlite3_mutex *pthreadMutexAlloc(int iType){
|
||||
}
|
||||
}
|
||||
#if SQLITE_MUTEX_NREF || defined(SQLITE_ENABLE_API_ARMOR)
|
||||
if( p ) p->id = iType;
|
||||
assert( p==0 || p->id==iType );
|
||||
#endif
|
||||
return p;
|
||||
}
|
||||
|
||||
+17
-17
@@ -40,7 +40,7 @@ struct sqlite3_mutex {
|
||||
#ifdef SQLITE_DEBUG
|
||||
volatile int nRef; /* Number of enterances */
|
||||
volatile DWORD owner; /* Thread holding this mutex */
|
||||
volatile int trace; /* True to trace changes */
|
||||
volatile LONG trace; /* True to trace changes */
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -52,10 +52,10 @@ struct sqlite3_mutex {
|
||||
#define SQLITE_W32_MUTEX_INITIALIZER { 0 }
|
||||
|
||||
#ifdef SQLITE_DEBUG
|
||||
#define SQLITE3_MUTEX_INITIALIZER { SQLITE_W32_MUTEX_INITIALIZER, 0, \
|
||||
#define SQLITE3_MUTEX_INITIALIZER(id) { SQLITE_W32_MUTEX_INITIALIZER, id, \
|
||||
0L, (DWORD)0, 0 }
|
||||
#else
|
||||
#define SQLITE3_MUTEX_INITIALIZER { SQLITE_W32_MUTEX_INITIALIZER, 0 }
|
||||
#define SQLITE3_MUTEX_INITIALIZER(id) { SQLITE_W32_MUTEX_INITIALIZER, id }
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_DEBUG
|
||||
@@ -98,18 +98,18 @@ void sqlite3MemoryBarrier(void){
|
||||
** Initialize and deinitialize the mutex subsystem.
|
||||
*/
|
||||
static sqlite3_mutex winMutex_staticMutexes[] = {
|
||||
SQLITE3_MUTEX_INITIALIZER,
|
||||
SQLITE3_MUTEX_INITIALIZER,
|
||||
SQLITE3_MUTEX_INITIALIZER,
|
||||
SQLITE3_MUTEX_INITIALIZER,
|
||||
SQLITE3_MUTEX_INITIALIZER,
|
||||
SQLITE3_MUTEX_INITIALIZER,
|
||||
SQLITE3_MUTEX_INITIALIZER,
|
||||
SQLITE3_MUTEX_INITIALIZER,
|
||||
SQLITE3_MUTEX_INITIALIZER,
|
||||
SQLITE3_MUTEX_INITIALIZER,
|
||||
SQLITE3_MUTEX_INITIALIZER,
|
||||
SQLITE3_MUTEX_INITIALIZER
|
||||
SQLITE3_MUTEX_INITIALIZER(2),
|
||||
SQLITE3_MUTEX_INITIALIZER(3),
|
||||
SQLITE3_MUTEX_INITIALIZER(4),
|
||||
SQLITE3_MUTEX_INITIALIZER(5),
|
||||
SQLITE3_MUTEX_INITIALIZER(6),
|
||||
SQLITE3_MUTEX_INITIALIZER(7),
|
||||
SQLITE3_MUTEX_INITIALIZER(8),
|
||||
SQLITE3_MUTEX_INITIALIZER(9),
|
||||
SQLITE3_MUTEX_INITIALIZER(10),
|
||||
SQLITE3_MUTEX_INITIALIZER(11),
|
||||
SQLITE3_MUTEX_INITIALIZER(12),
|
||||
SQLITE3_MUTEX_INITIALIZER(13)
|
||||
};
|
||||
|
||||
static int winMutex_isInit = 0;
|
||||
@@ -239,15 +239,15 @@ static sqlite3_mutex *winMutexAlloc(int iType){
|
||||
}
|
||||
#endif
|
||||
p = &winMutex_staticMutexes[iType-2];
|
||||
p->id = iType;
|
||||
#ifdef SQLITE_DEBUG
|
||||
#ifdef SQLITE_WIN32_MUTEX_TRACE_STATIC
|
||||
p->trace = 1;
|
||||
InterlockedCompareExchange(&p->trace, 1, 0);
|
||||
#endif
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
assert( p==0 || p->id==iType );
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
+11
-7
@@ -468,7 +468,11 @@ static struct unix_syscall {
|
||||
#endif
|
||||
#define osFchown ((int(*)(int,uid_t,gid_t))aSyscall[20].pCurrent)
|
||||
|
||||
#if defined(HAVE_FCHOWN)
|
||||
{ "geteuid", (sqlite3_syscall_ptr)geteuid, 0 },
|
||||
#else
|
||||
{ "geteuid", (sqlite3_syscall_ptr)0, 0 },
|
||||
#endif
|
||||
#define osGeteuid ((uid_t(*)(void))aSyscall[21].pCurrent)
|
||||
|
||||
#if !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0
|
||||
@@ -696,15 +700,16 @@ static int robust_open(const char *z, int f, mode_t m){
|
||||
** assert( unixMutexHeld() );
|
||||
** unixEnterLeave()
|
||||
*/
|
||||
static sqlite3_mutex *unixBigLock = 0;
|
||||
static void unixEnterMutex(void){
|
||||
sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1));
|
||||
sqlite3_mutex_enter(unixBigLock);
|
||||
}
|
||||
static void unixLeaveMutex(void){
|
||||
sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1));
|
||||
sqlite3_mutex_leave(unixBigLock);
|
||||
}
|
||||
#ifdef SQLITE_DEBUG
|
||||
static int unixMutexHeld(void) {
|
||||
return sqlite3_mutex_held(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1));
|
||||
return sqlite3_mutex_held(unixBigLock);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -3950,7 +3955,7 @@ static void setDeviceCharacteristics(unixFile *pFile){
|
||||
pFile->sectorSize = SQLITE_DEFAULT_SECTOR_SIZE;
|
||||
pFile->deviceCharacteristics = 0;
|
||||
if( fstatvfs(pFile->h, &fsInfo) == -1 ) {
|
||||
return pFile->sectorSize;
|
||||
return;
|
||||
}
|
||||
|
||||
if( !strcmp(fsInfo.f_basetype, "tmp") ) {
|
||||
@@ -4175,12 +4180,10 @@ static int unixShmSystemLock(
|
||||
|
||||
if( pShmNode->h>=0 ){
|
||||
/* Initialize the locking parameters */
|
||||
memset(&f, 0, sizeof(f));
|
||||
f.l_type = lockType;
|
||||
f.l_whence = SEEK_SET;
|
||||
f.l_start = ofst;
|
||||
f.l_len = n;
|
||||
|
||||
rc = osFcntl(pShmNode->h, F_SETLK, &f);
|
||||
rc = (rc!=(-1)) ? SQLITE_OK : SQLITE_BUSY;
|
||||
}
|
||||
@@ -5846,7 +5849,6 @@ static int unixOpen(
|
||||
randomnessPid = osGetpid(0);
|
||||
sqlite3_randomness(0,0);
|
||||
}
|
||||
|
||||
memset(p, 0, sizeof(unixFile));
|
||||
|
||||
if( eType==SQLITE_OPEN_MAIN_DB ){
|
||||
@@ -7721,6 +7723,7 @@ int sqlite3_os_init(void){
|
||||
for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){
|
||||
sqlite3_vfs_register(&aVfs[i], i==0);
|
||||
}
|
||||
unixBigLock = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
@@ -7732,6 +7735,7 @@ int sqlite3_os_init(void){
|
||||
** This routine is a no-op for unix.
|
||||
*/
|
||||
int sqlite3_os_end(void){
|
||||
unixBigLock = 0;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
|
||||
+39
-27
@@ -3631,15 +3631,16 @@ static SYSTEM_INFO winSysInfo;
|
||||
** assert( winShmMutexHeld() );
|
||||
** winShmLeaveMutex()
|
||||
*/
|
||||
static sqlite3_mutex *winBigLock = 0;
|
||||
static void winShmEnterMutex(void){
|
||||
sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1));
|
||||
sqlite3_mutex_enter(winBigLock);
|
||||
}
|
||||
static void winShmLeaveMutex(void){
|
||||
sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1));
|
||||
sqlite3_mutex_leave(winBigLock);
|
||||
}
|
||||
#ifndef NDEBUG
|
||||
static int winShmMutexHeld(void) {
|
||||
return sqlite3_mutex_held(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1));
|
||||
return sqlite3_mutex_held(winBigLock);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -3865,7 +3866,6 @@ static int winOpenSharedMemory(winFile *pDbFd){
|
||||
struct winShm *p; /* The connection to be opened */
|
||||
winShmNode *pShmNode = 0; /* The underlying mmapped file */
|
||||
int rc = SQLITE_OK; /* Result code */
|
||||
int rc2 = SQLITE_ERROR; /* winOpen result code */
|
||||
winShmNode *pNew; /* Newly allocated winShmNode */
|
||||
int nName; /* Size of zName in bytes */
|
||||
|
||||
@@ -3899,6 +3899,9 @@ static int winOpenSharedMemory(winFile *pDbFd){
|
||||
if( pShmNode ){
|
||||
sqlite3_free(pNew);
|
||||
}else{
|
||||
int inFlags = SQLITE_OPEN_WAL;
|
||||
int outFlags = 0;
|
||||
|
||||
pShmNode = pNew;
|
||||
pNew = 0;
|
||||
((winFile*)(&pShmNode->hFile))->h = INVALID_HANDLE_VALUE;
|
||||
@@ -3914,25 +3917,19 @@ static int winOpenSharedMemory(winFile *pDbFd){
|
||||
}
|
||||
|
||||
if( 0==sqlite3_uri_boolean(pDbFd->zPath, "readonly_shm", 0) ){
|
||||
rc2 = winOpen(pDbFd->pVfs,
|
||||
pShmNode->zFilename,
|
||||
(sqlite3_file*)&pShmNode->hFile,
|
||||
SQLITE_OPEN_WAL|SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE,
|
||||
0);
|
||||
inFlags |= SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
|
||||
}else{
|
||||
inFlags |= SQLITE_OPEN_READONLY;
|
||||
}
|
||||
if( rc2!=SQLITE_OK ){
|
||||
rc2 = winOpen(pDbFd->pVfs,
|
||||
pShmNode->zFilename,
|
||||
(sqlite3_file*)&pShmNode->hFile,
|
||||
SQLITE_OPEN_WAL|SQLITE_OPEN_READONLY,
|
||||
0);
|
||||
if( rc2!=SQLITE_OK ){
|
||||
rc = winLogError(rc2, osGetLastError(), "winOpenShm",
|
||||
pShmNode->zFilename);
|
||||
goto shm_open_err;
|
||||
}
|
||||
pShmNode->isReadonly = 1;
|
||||
rc = winOpen(pDbFd->pVfs, pShmNode->zFilename,
|
||||
(sqlite3_file*)&pShmNode->hFile,
|
||||
inFlags, &outFlags);
|
||||
if( rc!=SQLITE_OK ){
|
||||
rc = winLogError(rc, osGetLastError(), "winOpenShm",
|
||||
pShmNode->zFilename);
|
||||
goto shm_open_err;
|
||||
}
|
||||
if( outFlags==SQLITE_OPEN_READONLY ) pShmNode->isReadonly = 1;
|
||||
|
||||
rc = winLockSharedMemory(pShmNode);
|
||||
if( rc!=SQLITE_OK && rc!=SQLITE_READONLY_CANTINIT ) goto shm_open_err;
|
||||
@@ -5118,8 +5115,10 @@ static int winOpen(
|
||||
&extendedParameters);
|
||||
if( h!=INVALID_HANDLE_VALUE ) break;
|
||||
if( isReadWrite ){
|
||||
int isRO = 0;
|
||||
int rc2 = winAccess(pVfs, zName, SQLITE_ACCESS_READ, &isRO);
|
||||
int rc2, isRO = 0;
|
||||
sqlite3BeginBenignMalloc();
|
||||
rc2 = winAccess(pVfs, zName, SQLITE_ACCESS_READ, &isRO);
|
||||
sqlite3EndBenignMalloc();
|
||||
if( rc2==SQLITE_OK && isRO ) break;
|
||||
}
|
||||
}while( winRetryIoerr(&cnt, &lastErrno) );
|
||||
@@ -5133,8 +5132,10 @@ static int winOpen(
|
||||
NULL);
|
||||
if( h!=INVALID_HANDLE_VALUE ) break;
|
||||
if( isReadWrite ){
|
||||
int isRO = 0;
|
||||
int rc2 = winAccess(pVfs, zName, SQLITE_ACCESS_READ, &isRO);
|
||||
int rc2, isRO = 0;
|
||||
sqlite3BeginBenignMalloc();
|
||||
rc2 = winAccess(pVfs, zName, SQLITE_ACCESS_READ, &isRO);
|
||||
sqlite3EndBenignMalloc();
|
||||
if( rc2==SQLITE_OK && isRO ) break;
|
||||
}
|
||||
}while( winRetryIoerr(&cnt, &lastErrno) );
|
||||
@@ -5151,8 +5152,10 @@ static int winOpen(
|
||||
NULL);
|
||||
if( h!=INVALID_HANDLE_VALUE ) break;
|
||||
if( isReadWrite ){
|
||||
int isRO = 0;
|
||||
int rc2 = winAccess(pVfs, zName, SQLITE_ACCESS_READ, &isRO);
|
||||
int rc2, isRO = 0;
|
||||
sqlite3BeginBenignMalloc();
|
||||
rc2 = winAccess(pVfs, zName, SQLITE_ACCESS_READ, &isRO);
|
||||
sqlite3EndBenignMalloc();
|
||||
if( rc2==SQLITE_OK && isRO ) break;
|
||||
}
|
||||
}while( winRetryIoerr(&cnt, &lastErrno) );
|
||||
@@ -6060,6 +6063,10 @@ int sqlite3_os_init(void){
|
||||
sqlite3_vfs_register(&winLongPathNolockVfs, 0);
|
||||
#endif
|
||||
|
||||
#ifndef SQLITE_OMIT_WAL
|
||||
winBigLock = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1);
|
||||
#endif
|
||||
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
@@ -6070,6 +6077,11 @@ int sqlite3_os_end(void){
|
||||
sleepObj = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef SQLITE_OMIT_WAL
|
||||
winBigLock = 0;
|
||||
#endif
|
||||
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
|
||||
+65
-42
@@ -699,7 +699,7 @@ struct Pager {
|
||||
char *zJournal; /* Name of the journal file */
|
||||
int (*xBusyHandler)(void*); /* Function to call when busy */
|
||||
void *pBusyHandlerArg; /* Context argument for xBusyHandler */
|
||||
int aStat[3]; /* Total cache hits, misses and writes */
|
||||
int aStat[4]; /* Total cache hits, misses, writes, spills */
|
||||
#ifdef SQLITE_TEST
|
||||
int nRead; /* Database pages read */
|
||||
#endif
|
||||
@@ -727,6 +727,7 @@ struct Pager {
|
||||
#define PAGER_STAT_HIT 0
|
||||
#define PAGER_STAT_MISS 1
|
||||
#define PAGER_STAT_WRITE 2
|
||||
#define PAGER_STAT_SPILL 3
|
||||
|
||||
/*
|
||||
** The following global variables hold counters used for
|
||||
@@ -1213,7 +1214,7 @@ static int jrnlBufferSize(Pager *pPager){
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_ENABLE_BATCH_ATOMIC_WRITE
|
||||
if( dc&SQLITE_IOCAP_BATCH_ATOMIC ){
|
||||
if( pPager->dbSize>0 && (dc&SQLITE_IOCAP_BATCH_ATOMIC) ){
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
@@ -4102,6 +4103,30 @@ static void pagerFreeMapHdrs(Pager *pPager){
|
||||
}
|
||||
}
|
||||
|
||||
/* Verify that the database file has not be deleted or renamed out from
|
||||
** under the pager. Return SQLITE_OK if the database is still where it ought
|
||||
** to be on disk. Return non-zero (SQLITE_READONLY_DBMOVED or some other error
|
||||
** code from sqlite3OsAccess()) if the database has gone missing.
|
||||
*/
|
||||
static int databaseIsUnmoved(Pager *pPager){
|
||||
int bHasMoved = 0;
|
||||
int rc;
|
||||
|
||||
if( pPager->tempFile ) return SQLITE_OK;
|
||||
if( pPager->dbSize==0 ) return SQLITE_OK;
|
||||
assert( pPager->zFilename && pPager->zFilename[0] );
|
||||
rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_HAS_MOVED, &bHasMoved);
|
||||
if( rc==SQLITE_NOTFOUND ){
|
||||
/* If the HAS_MOVED file-control is unimplemented, assume that the file
|
||||
** has not been moved. That is the historical behavior of SQLite: prior to
|
||||
** version 3.8.3, it never checked */
|
||||
rc = SQLITE_OK;
|
||||
}else if( rc==SQLITE_OK && bHasMoved ){
|
||||
rc = SQLITE_READONLY_DBMOVED;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Shutdown the page cache. Free all memory and close all files.
|
||||
@@ -4118,8 +4143,7 @@ static void pagerFreeMapHdrs(Pager *pPager){
|
||||
** to the caller.
|
||||
*/
|
||||
int sqlite3PagerClose(Pager *pPager, sqlite3 *db){
|
||||
u8 *pTmp = (u8 *)pPager->pTmpSpace;
|
||||
|
||||
u8 *pTmp = (u8*)pPager->pTmpSpace;
|
||||
assert( db || pagerUseWal(pPager)==0 );
|
||||
assert( assert_pager_state(pPager) );
|
||||
disable_simulated_io_errors();
|
||||
@@ -4128,11 +4152,17 @@ int sqlite3PagerClose(Pager *pPager, sqlite3 *db){
|
||||
/* pPager->errCode = 0; */
|
||||
pPager->exclusiveMode = 0;
|
||||
#ifndef SQLITE_OMIT_WAL
|
||||
assert( db || pPager->pWal==0 );
|
||||
sqlite3WalClose(pPager->pWal, db, pPager->walSyncFlags, pPager->pageSize,
|
||||
(db && (db->flags & SQLITE_NoCkptOnClose) ? 0 : pTmp)
|
||||
);
|
||||
pPager->pWal = 0;
|
||||
{
|
||||
u8 *a = 0;
|
||||
assert( db || pPager->pWal==0 );
|
||||
if( db && 0==(db->flags & SQLITE_NoCkptOnClose)
|
||||
&& SQLITE_OK==databaseIsUnmoved(pPager)
|
||||
){
|
||||
a = pTmp;
|
||||
}
|
||||
sqlite3WalClose(pPager->pWal, db, pPager->walSyncFlags, pPager->pageSize,a);
|
||||
pPager->pWal = 0;
|
||||
}
|
||||
#endif
|
||||
pager_reset(pPager);
|
||||
if( MEMDB ){
|
||||
@@ -4589,6 +4619,7 @@ static int pagerStress(void *p, PgHdr *pPg){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
pPager->aStat[PAGER_STAT_SPILL]++;
|
||||
pPg->pDirty = 0;
|
||||
if( pagerUseWal(pPager) ){
|
||||
/* Write a single frame for this page to the log. */
|
||||
@@ -4694,6 +4725,11 @@ int sqlite3PagerOpen(
|
||||
int rc = SQLITE_OK; /* Return code */
|
||||
int tempFile = 0; /* True for temp files (incl. in-memory files) */
|
||||
int memDb = 0; /* True if this is an in-memory file */
|
||||
#ifdef SQLITE_ENABLE_DESERIALIZE
|
||||
int memJM = 0; /* Memory journal mode */
|
||||
#else
|
||||
# define memJM 0
|
||||
#endif
|
||||
int readOnly = 0; /* True if this is a read-only file */
|
||||
int journalFileSize; /* Bytes to allocate for each journal fd */
|
||||
char *zPathname = 0; /* Full path to database file */
|
||||
@@ -4821,7 +4857,10 @@ int sqlite3PagerOpen(
|
||||
int fout = 0; /* VFS flags returned by xOpen() */
|
||||
rc = sqlite3OsOpen(pVfs, pPager->zFilename, pPager->fd, vfsFlags, &fout);
|
||||
assert( !memDb );
|
||||
readOnly = (fout&SQLITE_OPEN_READONLY);
|
||||
#ifdef SQLITE_ENABLE_DESERIALIZE
|
||||
memJM = (fout&SQLITE_OPEN_MEMORY)!=0;
|
||||
#endif
|
||||
readOnly = (fout&SQLITE_OPEN_READONLY)!=0;
|
||||
|
||||
/* If the file was successfully opened for read/write access,
|
||||
** choose a default page size in case we have to create the
|
||||
@@ -4952,7 +4991,7 @@ act_like_temp_file:
|
||||
setSectorSize(pPager);
|
||||
if( !useJournal ){
|
||||
pPager->journalMode = PAGER_JOURNALMODE_OFF;
|
||||
}else if( memDb ){
|
||||
}else if( memDb || memJM ){
|
||||
pPager->journalMode = PAGER_JOURNALMODE_MEMORY;
|
||||
}
|
||||
/* pPager->xBusyHandler = 0; */
|
||||
@@ -4967,30 +5006,6 @@ act_like_temp_file:
|
||||
}
|
||||
|
||||
|
||||
/* Verify that the database file has not be deleted or renamed out from
|
||||
** under the pager. Return SQLITE_OK if the database is still were it ought
|
||||
** to be on disk. Return non-zero (SQLITE_READONLY_DBMOVED or some other error
|
||||
** code from sqlite3OsAccess()) if the database has gone missing.
|
||||
*/
|
||||
static int databaseIsUnmoved(Pager *pPager){
|
||||
int bHasMoved = 0;
|
||||
int rc;
|
||||
|
||||
if( pPager->tempFile ) return SQLITE_OK;
|
||||
if( pPager->dbSize==0 ) return SQLITE_OK;
|
||||
assert( pPager->zFilename && pPager->zFilename[0] );
|
||||
rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_HAS_MOVED, &bHasMoved);
|
||||
if( rc==SQLITE_NOTFOUND ){
|
||||
/* If the HAS_MOVED file-control is unimplemented, assume that the file
|
||||
** has not been moved. That is the historical behavior of SQLite: prior to
|
||||
** version 3.8.3, it never checked */
|
||||
rc = SQLITE_OK;
|
||||
}else if( rc==SQLITE_OK && bHasMoved ){
|
||||
rc = SQLITE_READONLY_DBMOVED;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** This function is called after transitioning from PAGER_UNLOCK to
|
||||
@@ -6499,8 +6514,9 @@ int sqlite3PagerCommitPhaseOne(
|
||||
if( bBatch ){
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3OsFileControl(fd, SQLITE_FCNTL_COMMIT_ATOMIC_WRITE, 0);
|
||||
}else{
|
||||
sqlite3OsFileControl(fd, SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE, 0);
|
||||
}
|
||||
if( rc!=SQLITE_OK ){
|
||||
sqlite3OsFileControlHint(fd, SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6724,8 +6740,12 @@ int *sqlite3PagerStats(Pager *pPager){
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Parameter eStat must be either SQLITE_DBSTATUS_CACHE_HIT or
|
||||
** SQLITE_DBSTATUS_CACHE_MISS. Before returning, *pnVal is incremented by the
|
||||
** Parameter eStat must be one of SQLITE_DBSTATUS_CACHE_HIT, _MISS, _WRITE,
|
||||
** or _WRITE+1. The SQLITE_DBSTATUS_CACHE_WRITE+1 case is a translation
|
||||
** of SQLITE_DBSTATUS_CACHE_SPILL. The _SPILL case is not contiguous because
|
||||
** it was added later.
|
||||
**
|
||||
** Before returning, *pnVal is incremented by the
|
||||
** current cache hit or miss count, according to the value of eStat. If the
|
||||
** reset parameter is non-zero, the cache hit or miss count is zeroed before
|
||||
** returning.
|
||||
@@ -6735,15 +6755,18 @@ void sqlite3PagerCacheStat(Pager *pPager, int eStat, int reset, int *pnVal){
|
||||
assert( eStat==SQLITE_DBSTATUS_CACHE_HIT
|
||||
|| eStat==SQLITE_DBSTATUS_CACHE_MISS
|
||||
|| eStat==SQLITE_DBSTATUS_CACHE_WRITE
|
||||
|| eStat==SQLITE_DBSTATUS_CACHE_WRITE+1
|
||||
);
|
||||
|
||||
assert( SQLITE_DBSTATUS_CACHE_HIT+1==SQLITE_DBSTATUS_CACHE_MISS );
|
||||
assert( SQLITE_DBSTATUS_CACHE_HIT+2==SQLITE_DBSTATUS_CACHE_WRITE );
|
||||
assert( PAGER_STAT_HIT==0 && PAGER_STAT_MISS==1 && PAGER_STAT_WRITE==2 );
|
||||
assert( PAGER_STAT_HIT==0 && PAGER_STAT_MISS==1
|
||||
&& PAGER_STAT_WRITE==2 && PAGER_STAT_SPILL==3 );
|
||||
|
||||
*pnVal += pPager->aStat[eStat - SQLITE_DBSTATUS_CACHE_HIT];
|
||||
eStat -= SQLITE_DBSTATUS_CACHE_HIT;
|
||||
*pnVal += pPager->aStat[eStat];
|
||||
if( reset ){
|
||||
pPager->aStat[eStat - SQLITE_DBSTATUS_CACHE_HIT] = 0;
|
||||
pPager->aStat[eStat] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -313,6 +313,10 @@ ccons ::= DEFAULT MINUS(A) term(X) scanpt(Z). {
|
||||
}
|
||||
ccons ::= DEFAULT scanpt id(X). {
|
||||
Expr *p = tokenExpr(pParse, TK_STRING, X);
|
||||
if( p ){
|
||||
sqlite3ExprIdToTrueFalse(p);
|
||||
testcase( p->op==TK_TRUEFALSE && sqlite3ExprTruthValue(p) );
|
||||
}
|
||||
sqlite3AddDefaultValue(pParse,p,X.z,X.z+X.n);
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -431,7 +431,7 @@ int sqlite3PcacheFetchStress(
|
||||
sqlite3_log(SQLITE_FULL,
|
||||
"spill page %d making room for %d - cache used: %d/%d",
|
||||
pPg->pgno, pgno,
|
||||
sqlite3GlobalConfig.pcache.xPagecount(pCache->pCache),
|
||||
sqlite3GlobalConfig.pcache2.xPagecount(pCache->pCache),
|
||||
numberOfCachePages(pCache));
|
||||
#endif
|
||||
pcacheTrace(("%p.SPILL %d\n",pCache,pPg->pgno));
|
||||
|
||||
+1
-1
@@ -29,7 +29,7 @@ static void corruptSchema(
|
||||
char *z;
|
||||
if( zObj==0 ) zObj = "?";
|
||||
z = sqlite3MPrintf(db, "malformed database schema (%s)", zObj);
|
||||
if( zExtra ) z = sqlite3MPrintf(db, "%z - %s", z, zExtra);
|
||||
if( zExtra && zExtra[0] ) z = sqlite3MPrintf(db, "%z - %s", z, zExtra);
|
||||
sqlite3DbFree(db, *pData->pzErrMsg);
|
||||
*pData->pzErrMsg = z;
|
||||
}
|
||||
|
||||
+86
-15
@@ -206,6 +206,11 @@ void sqlite3VXPrintf(
|
||||
PrintfArguments *pArgList = 0; /* Arguments for SQLITE_PRINTF_SQLFUNC */
|
||||
char buf[etBUFSIZE]; /* Conversion buffer */
|
||||
|
||||
/* pAccum never starts out with an empty buffer that was obtained from
|
||||
** malloc(). This precondition is required by the mprintf("%z...")
|
||||
** optimization. */
|
||||
assert( pAccum->nChar>0 || (pAccum->printfFlags&SQLITE_PRINTF_MALLOCED)==0 );
|
||||
|
||||
bufpt = 0;
|
||||
if( (pAccum->printfFlags & SQLITE_PRINTF_SQLFUNC)!=0 ){
|
||||
pArgList = va_arg(ap, PrintfArguments*);
|
||||
@@ -624,9 +629,38 @@ void sqlite3VXPrintf(
|
||||
case etCHARX:
|
||||
if( bArgList ){
|
||||
bufpt = getTextArg(pArgList);
|
||||
c = bufpt ? bufpt[0] : 0;
|
||||
length = 1;
|
||||
if( bufpt ){
|
||||
buf[0] = c = *(bufpt++);
|
||||
if( (c&0xc0)==0xc0 ){
|
||||
while( length<4 && (bufpt[0]&0xc0)==0x80 ){
|
||||
buf[length++] = *(bufpt++);
|
||||
}
|
||||
}
|
||||
}else{
|
||||
buf[0] = 0;
|
||||
}
|
||||
}else{
|
||||
c = va_arg(ap,int);
|
||||
unsigned int ch = va_arg(ap,unsigned int);
|
||||
if( ch<0x00080 ){
|
||||
buf[0] = ch & 0xff;
|
||||
length = 1;
|
||||
}else if( ch<0x00800 ){
|
||||
buf[0] = 0xc0 + (u8)((ch>>6)&0x1f);
|
||||
buf[1] = 0x80 + (u8)(ch & 0x3f);
|
||||
length = 2;
|
||||
}else if( ch<0x10000 ){
|
||||
buf[0] = 0xe0 + (u8)((ch>>12)&0x0f);
|
||||
buf[1] = 0x80 + (u8)((ch>>6) & 0x3f);
|
||||
buf[2] = 0x80 + (u8)(ch & 0x3f);
|
||||
length = 3;
|
||||
}else{
|
||||
buf[0] = 0xf0 + (u8)((ch>>18) & 0x07);
|
||||
buf[1] = 0x80 + (u8)((ch>>12) & 0x3f);
|
||||
buf[2] = 0x80 + (u8)((ch>>6) & 0x3f);
|
||||
buf[3] = 0x80 + (u8)(ch & 0x3f);
|
||||
length = 4;
|
||||
}
|
||||
}
|
||||
if( precision>1 ){
|
||||
width -= precision-1;
|
||||
@@ -634,12 +668,13 @@ void sqlite3VXPrintf(
|
||||
sqlite3AppendChar(pAccum, width-1, ' ');
|
||||
width = 0;
|
||||
}
|
||||
sqlite3AppendChar(pAccum, precision-1, c);
|
||||
while( precision-- > 1 ){
|
||||
sqlite3StrAccumAppend(pAccum, buf, length);
|
||||
}
|
||||
}
|
||||
length = 1;
|
||||
buf[0] = c;
|
||||
bufpt = buf;
|
||||
break;
|
||||
flag_altform2 = 1;
|
||||
goto adjust_width_for_utf8;
|
||||
case etSTRING:
|
||||
case etDYNSTRING:
|
||||
if( bArgList ){
|
||||
@@ -651,17 +686,45 @@ void sqlite3VXPrintf(
|
||||
if( bufpt==0 ){
|
||||
bufpt = "";
|
||||
}else if( xtype==etDYNSTRING ){
|
||||
if( pAccum->nChar==0 && pAccum->mxAlloc && width==0 && precision<0 ){
|
||||
/* Special optimization for sqlite3_mprintf("%z..."):
|
||||
** Extend an existing memory allocation rather than creating
|
||||
** a new one. */
|
||||
assert( (pAccum->printfFlags&SQLITE_PRINTF_MALLOCED)==0 );
|
||||
pAccum->zText = bufpt;
|
||||
pAccum->nAlloc = sqlite3DbMallocSize(pAccum->db, bufpt);
|
||||
pAccum->nChar = 0x7fffffff & (int)strlen(bufpt);
|
||||
pAccum->printfFlags |= SQLITE_PRINTF_MALLOCED;
|
||||
length = 0;
|
||||
break;
|
||||
}
|
||||
zExtra = bufpt;
|
||||
}
|
||||
if( precision>=0 ){
|
||||
for(length=0; length<precision && bufpt[length]; length++){}
|
||||
if( flag_altform2 ){
|
||||
/* Set length to the number of bytes needed in order to display
|
||||
** precision characters */
|
||||
unsigned char *z = (unsigned char*)bufpt;
|
||||
while( precision-- > 0 && z[0] ){
|
||||
SQLITE_SKIP_UTF8(z);
|
||||
}
|
||||
length = (int)(z - (unsigned char*)bufpt);
|
||||
}else{
|
||||
for(length=0; length<precision && bufpt[length]; length++){}
|
||||
}
|
||||
}else{
|
||||
length = 0x7fffffff & (int)strlen(bufpt);
|
||||
}
|
||||
adjust_width_for_utf8:
|
||||
if( flag_altform2 && width>0 ){
|
||||
/* Adjust width to account for extra bytes in UTF-8 characters */
|
||||
int ii = length - 1;
|
||||
while( ii>=0 ) if( (bufpt[ii--] & 0xc0)==0x80 ) width++;
|
||||
}
|
||||
break;
|
||||
case etSQLESCAPE: /* Escape ' characters */
|
||||
case etSQLESCAPE2: /* Escape ' and enclose in '...' */
|
||||
case etSQLESCAPE3: { /* Escape " characters */
|
||||
case etSQLESCAPE: /* %q: Escape ' characters */
|
||||
case etSQLESCAPE2: /* %Q: Escape ' and enclose in '...' */
|
||||
case etSQLESCAPE3: { /* %w: Escape " characters */
|
||||
int i, j, k, n, isnull;
|
||||
int needQuote;
|
||||
char ch;
|
||||
@@ -675,9 +738,17 @@ void sqlite3VXPrintf(
|
||||
}
|
||||
isnull = escarg==0;
|
||||
if( isnull ) escarg = (xtype==etSQLESCAPE2 ? "NULL" : "(NULL)");
|
||||
/* For %q, %Q, and %w, the precision is the number of byte (or
|
||||
** characters if the ! flags is present) to use from the input.
|
||||
** Because of the extra quoting characters inserted, the number
|
||||
** of output characters may be larger than the precision.
|
||||
*/
|
||||
k = precision;
|
||||
for(i=n=0; k!=0 && (ch=escarg[i])!=0; i++, k--){
|
||||
if( ch==q ) n++;
|
||||
if( flag_altform2 && (ch&0xc0)==0xc0 ){
|
||||
while( (escarg[i+1]&0xc0)==0x80 ){ i++; }
|
||||
}
|
||||
}
|
||||
needQuote = !isnull && xtype==etSQLESCAPE2;
|
||||
n += i + 3;
|
||||
@@ -700,10 +771,7 @@ void sqlite3VXPrintf(
|
||||
if( needQuote ) bufpt[j++] = q;
|
||||
bufpt[j] = 0;
|
||||
length = j;
|
||||
/* The precision in %q and %Q means how many input characters to
|
||||
** consume, not the length of the output...
|
||||
** if( precision>=0 && precision<length ) length = precision; */
|
||||
break;
|
||||
goto adjust_width_for_utf8;
|
||||
}
|
||||
case etTOKEN: {
|
||||
Token *pToken;
|
||||
@@ -742,7 +810,10 @@ void sqlite3VXPrintf(
|
||||
/*
|
||||
** The text of the conversion is pointed to by "bufpt" and is
|
||||
** "length" characters long. The field width is "width". Do
|
||||
** the output.
|
||||
** the output. Both length and width are in bytes, not characters,
|
||||
** at this point. If the "!" flag was present on string conversions
|
||||
** indicating that width and precision should be expressed in characters,
|
||||
** then the values have been translated prior to reaching this point.
|
||||
*/
|
||||
width -= length;
|
||||
if( width>0 ){
|
||||
|
||||
+28
-7
@@ -431,10 +431,16 @@ static int lookupName(
|
||||
** Because no reference was made to outer contexts, the pNC->nRef
|
||||
** fields are not changed in any context.
|
||||
*/
|
||||
if( cnt==0 && zTab==0 && ExprHasProperty(pExpr,EP_DblQuoted) ){
|
||||
pExpr->op = TK_STRING;
|
||||
pExpr->pTab = 0;
|
||||
return WRC_Prune;
|
||||
if( cnt==0 && zTab==0 ){
|
||||
assert( pExpr->op==TK_ID );
|
||||
if( ExprHasProperty(pExpr,EP_DblQuoted) ){
|
||||
pExpr->op = TK_STRING;
|
||||
pExpr->pTab = 0;
|
||||
return WRC_Prune;
|
||||
}
|
||||
if( sqlite3ExprIdToTrueFalse(pExpr) ){
|
||||
return WRC_Prune;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -783,15 +789,30 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
|
||||
notValid(pParse, pNC, "parameters", NC_IsCheck|NC_PartIdx|NC_IdxExpr);
|
||||
break;
|
||||
}
|
||||
case TK_IS:
|
||||
case TK_ISNOT: {
|
||||
Expr *pRight;
|
||||
assert( !ExprHasProperty(pExpr, EP_Reduced) );
|
||||
/* Handle special cases of "x IS TRUE", "x IS FALSE", "x IS NOT TRUE",
|
||||
** and "x IS NOT FALSE". */
|
||||
if( (pRight = pExpr->pRight)->op==TK_ID ){
|
||||
int rc = resolveExprStep(pWalker, pRight);
|
||||
if( rc==WRC_Abort ) return WRC_Abort;
|
||||
if( pRight->op==TK_TRUEFALSE ){
|
||||
pExpr->op2 = pExpr->op;
|
||||
pExpr->op = TK_TRUTH;
|
||||
return WRC_Continue;
|
||||
}
|
||||
}
|
||||
/* Fall thru */
|
||||
}
|
||||
case TK_BETWEEN:
|
||||
case TK_EQ:
|
||||
case TK_NE:
|
||||
case TK_LT:
|
||||
case TK_LE:
|
||||
case TK_GT:
|
||||
case TK_GE:
|
||||
case TK_IS:
|
||||
case TK_ISNOT: {
|
||||
case TK_GE: {
|
||||
int nLeft, nRight;
|
||||
if( pParse->db->mallocFailed ) break;
|
||||
assert( pExpr->pLeft!=0 );
|
||||
|
||||
+13
-5
@@ -1266,12 +1266,15 @@ static void generateSortTail(
|
||||
iSortTab = iTab;
|
||||
bSeq = 1;
|
||||
}
|
||||
for(i=0, iCol=nKey+bSeq; i<nSortData; i++){
|
||||
for(i=0, iCol=nKey+bSeq-1; i<nSortData; i++){
|
||||
if( aOutEx[i].u.x.iOrderByCol==0 ) iCol++;
|
||||
}
|
||||
for(i=nSortData-1; i>=0; i--){
|
||||
int iRead;
|
||||
if( aOutEx[i].u.x.iOrderByCol ){
|
||||
iRead = aOutEx[i].u.x.iOrderByCol-1;
|
||||
}else{
|
||||
iRead = iCol++;
|
||||
iRead = iCol--;
|
||||
}
|
||||
sqlite3VdbeAddOp3(v, OP_Column, iSortTab, iRead, regRow+i);
|
||||
VdbeComment((v, "%s", aOutEx[i].zName ? aOutEx[i].zName : aOutEx[i].zSpan));
|
||||
@@ -2184,9 +2187,14 @@ static int multiSelectOrderBy(
|
||||
** on a VALUES clause.
|
||||
**
|
||||
** Because the Select object originates from a VALUES clause:
|
||||
** (1) It has no LIMIT or OFFSET
|
||||
** (1) There is no LIMIT or OFFSET or else there is a LIMIT of exactly 1
|
||||
** (2) All terms are UNION ALL
|
||||
** (3) There is no ORDER BY clause
|
||||
**
|
||||
** The "LIMIT of exactly 1" case of condition (1) comes about when a VALUES
|
||||
** clause occurs within scalar expression (ex: "SELECT (VALUES(1),(2),(3))").
|
||||
** The sqlite3CodeSubselect will have added the LIMIT 1 clause in tht case.
|
||||
** Since the limit is exactly 1, we only need to evalutes the left-most VALUES.
|
||||
*/
|
||||
static int multiSelectValues(
|
||||
Parse *pParse, /* Parsing context */
|
||||
@@ -2194,13 +2202,13 @@ static int multiSelectValues(
|
||||
SelectDest *pDest /* What to do with query results */
|
||||
){
|
||||
Select *pPrior;
|
||||
Select *pRightmost = p;
|
||||
int nRow = 1;
|
||||
int rc = 0;
|
||||
assert( p->selFlags & SF_MultiValue );
|
||||
do{
|
||||
assert( p->selFlags & SF_Values );
|
||||
assert( p->op==TK_ALL || (p->op==TK_SELECT && p->pPrior==0) );
|
||||
assert( p->pLimit==0 );
|
||||
assert( p->pNext==0 || p->pEList->nExpr==p->pNext->pEList->nExpr );
|
||||
if( p->pPrior==0 ) break;
|
||||
assert( p->pPrior->pNext==p );
|
||||
@@ -2212,7 +2220,7 @@ static int multiSelectValues(
|
||||
p->pPrior = 0;
|
||||
rc = sqlite3Select(pParse, p, pDest);
|
||||
p->pPrior = pPrior;
|
||||
if( rc ) break;
|
||||
if( rc || pRightmost->pLimit ) break;
|
||||
p->nSelectRow = nRow;
|
||||
p = p->pNext;
|
||||
}
|
||||
|
||||
+289
-125
@@ -865,6 +865,7 @@ static void shellModuleSchema(
|
||||
){
|
||||
const char *zName = (const char*)sqlite3_value_text(apVal[0]);
|
||||
char *zFake = shellFakeSchema(sqlite3_context_db_handle(pCtx), 0, zName);
|
||||
UNUSED_PARAMETER(nVal);
|
||||
if( zFake ){
|
||||
sqlite3_result_text(pCtx, sqlite3_mprintf("/* %s */", zFake),
|
||||
-1, sqlite3_free);
|
||||
@@ -909,6 +910,7 @@ static void shellAddSchemaName(
|
||||
const char *zSchema = (const char*)sqlite3_value_text(apVal[1]);
|
||||
const char *zName = (const char*)sqlite3_value_text(apVal[2]);
|
||||
sqlite3 *db = sqlite3_context_db_handle(pCtx);
|
||||
UNUSED_PARAMETER(nVal);
|
||||
if( zIn!=0 && strncmp(zIn, "CREATE ", 7)==0 ){
|
||||
for(i=0; i<(int)(sizeof(aPrefix)/sizeof(aPrefix[0])); i++){
|
||||
int n = strlen30(aPrefix[i]);
|
||||
@@ -1067,6 +1069,7 @@ struct ShellState {
|
||||
#define SHELL_OPEN_NORMAL 1 /* Normal database file */
|
||||
#define SHELL_OPEN_APPENDVFS 2 /* Use appendvfs */
|
||||
#define SHELL_OPEN_ZIPFILE 3 /* Use the zipfile virtual table */
|
||||
#define SHELL_OPEN_READONLY 4 /* Open a normal database read-only */
|
||||
|
||||
/*
|
||||
** These are the allowed shellFlgs values
|
||||
@@ -1152,6 +1155,7 @@ static void shellPutsFunc(
|
||||
sqlite3_value **apVal
|
||||
){
|
||||
ShellState *p = (ShellState*)sqlite3_user_data(pCtx);
|
||||
(void)nVal;
|
||||
utf8_printf(p->out, "%s\n", sqlite3_value_text(apVal[0]));
|
||||
sqlite3_result_value(pCtx, apVal[0]);
|
||||
}
|
||||
@@ -1172,6 +1176,7 @@ static void shellPutsFunc(
|
||||
**
|
||||
** Also throw an error if the EDITOR program returns a non-zero exit code.
|
||||
*/
|
||||
#ifndef SQLITE_NOHAVE_SYSTEM
|
||||
static void editFunc(
|
||||
sqlite3_context *context,
|
||||
int argc,
|
||||
@@ -1269,9 +1274,10 @@ static void editFunc(
|
||||
goto edit_func_end;
|
||||
}
|
||||
if( bBin ){
|
||||
sqlite3_result_blob(context, p, sz, sqlite3_free);
|
||||
sqlite3_result_blob64(context, p, sz, sqlite3_free);
|
||||
}else{
|
||||
sqlite3_result_text(context, (const char*)p, sz, sqlite3_free);
|
||||
sqlite3_result_text64(context, (const char*)p, sz,
|
||||
sqlite3_free, SQLITE_UTF8);
|
||||
}
|
||||
p = 0;
|
||||
|
||||
@@ -1281,6 +1287,7 @@ edit_func_end:
|
||||
sqlite3_free(zTempFile);
|
||||
sqlite3_free(p);
|
||||
}
|
||||
#endif /* SQLITE_NOHAVE_SYSTEM */
|
||||
|
||||
/*
|
||||
** Save or restore the current output mode
|
||||
@@ -2266,29 +2273,52 @@ static int display_stats(
|
||||
){
|
||||
int iCur;
|
||||
int iHiwtr;
|
||||
FILE *out;
|
||||
if( pArg==0 || pArg->out==0 ) return 0;
|
||||
out = pArg->out;
|
||||
|
||||
if( pArg && pArg->out ){
|
||||
displayStatLine(pArg, "Memory Used:",
|
||||
"%lld (max %lld) bytes", SQLITE_STATUS_MEMORY_USED, bReset);
|
||||
displayStatLine(pArg, "Number of Outstanding Allocations:",
|
||||
"%lld (max %lld)", SQLITE_STATUS_MALLOC_COUNT, bReset);
|
||||
if( pArg->shellFlgs & SHFLG_Pagecache ){
|
||||
displayStatLine(pArg, "Number of Pcache Pages Used:",
|
||||
"%lld (max %lld) pages", SQLITE_STATUS_PAGECACHE_USED, bReset);
|
||||
if( pArg->pStmt && (pArg->statsOn & 2) ){
|
||||
int nCol, i, x;
|
||||
sqlite3_stmt *pStmt = pArg->pStmt;
|
||||
char z[100];
|
||||
nCol = sqlite3_column_count(pStmt);
|
||||
raw_printf(out, "%-36s %d\n", "Number of output columns:", nCol);
|
||||
for(i=0; i<nCol; i++){
|
||||
sqlite3_snprintf(sizeof(z),z,"Column %d %nname:", i, &x);
|
||||
utf8_printf(out, "%-36s %s\n", z, sqlite3_column_name(pStmt,i));
|
||||
sqlite3_snprintf(30, z+x, "declared type:");
|
||||
utf8_printf(out, "%-36s %s\n", z, sqlite3_column_decltype(pStmt, i));
|
||||
#ifdef SQLITE_ENABLE_COLUMN_METADATA
|
||||
sqlite3_snprintf(30, z+x, "database name:");
|
||||
utf8_printf(out, "%-36s %s\n", z, sqlite3_column_database_name(pStmt,i));
|
||||
sqlite3_snprintf(30, z+x, "table name:");
|
||||
utf8_printf(out, "%-36s %s\n", z, sqlite3_column_table_name(pStmt,i));
|
||||
sqlite3_snprintf(30, z+x, "origin name:");
|
||||
utf8_printf(out, "%-36s %s\n", z, sqlite3_column_origin_name(pStmt,i));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
displayStatLine(pArg, "Number of Pcache Overflow Bytes:",
|
||||
"%lld (max %lld) bytes", SQLITE_STATUS_PAGECACHE_OVERFLOW, bReset);
|
||||
displayStatLine(pArg, "Largest Allocation:",
|
||||
"%lld bytes", SQLITE_STATUS_MALLOC_SIZE, bReset);
|
||||
displayStatLine(pArg, "Largest Pcache Allocation:",
|
||||
"%lld bytes", SQLITE_STATUS_PAGECACHE_SIZE, bReset);
|
||||
#ifdef YYTRACKMAXSTACKDEPTH
|
||||
displayStatLine(pArg, "Deepest Parser Stack:",
|
||||
"%lld (max %lld)", SQLITE_STATUS_PARSER_STACK, bReset);
|
||||
#endif
|
||||
}
|
||||
|
||||
if( pArg && pArg->out && db ){
|
||||
displayStatLine(pArg, "Memory Used:",
|
||||
"%lld (max %lld) bytes", SQLITE_STATUS_MEMORY_USED, bReset);
|
||||
displayStatLine(pArg, "Number of Outstanding Allocations:",
|
||||
"%lld (max %lld)", SQLITE_STATUS_MALLOC_COUNT, bReset);
|
||||
if( pArg->shellFlgs & SHFLG_Pagecache ){
|
||||
displayStatLine(pArg, "Number of Pcache Pages Used:",
|
||||
"%lld (max %lld) pages", SQLITE_STATUS_PAGECACHE_USED, bReset);
|
||||
}
|
||||
displayStatLine(pArg, "Number of Pcache Overflow Bytes:",
|
||||
"%lld (max %lld) bytes", SQLITE_STATUS_PAGECACHE_OVERFLOW, bReset);
|
||||
displayStatLine(pArg, "Largest Allocation:",
|
||||
"%lld bytes", SQLITE_STATUS_MALLOC_SIZE, bReset);
|
||||
displayStatLine(pArg, "Largest Pcache Allocation:",
|
||||
"%lld bytes", SQLITE_STATUS_PAGECACHE_SIZE, bReset);
|
||||
#ifdef YYTRACKMAXSTACKDEPTH
|
||||
displayStatLine(pArg, "Deepest Parser Stack:",
|
||||
"%lld (max %lld)", SQLITE_STATUS_PARSER_STACK, bReset);
|
||||
#endif
|
||||
|
||||
if( db ){
|
||||
if( pArg->shellFlgs & SHFLG_Lookaside ){
|
||||
iHiwtr = iCur = -1;
|
||||
sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_USED,
|
||||
@@ -2323,6 +2353,9 @@ static int display_stats(
|
||||
sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_WRITE, &iCur, &iHiwtr, 1);
|
||||
raw_printf(pArg->out, "Page cache writes: %d\n", iCur);
|
||||
iHiwtr = iCur = -1;
|
||||
sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_SPILL, &iCur, &iHiwtr, 1);
|
||||
raw_printf(pArg->out, "Page cache spills: %d\n", iCur);
|
||||
iHiwtr = iCur = -1;
|
||||
sqlite3_db_status(db, SQLITE_DBSTATUS_SCHEMA_USED, &iCur, &iHiwtr, bReset);
|
||||
raw_printf(pArg->out, "Schema Heap Usage: %d bytes\n",
|
||||
iCur);
|
||||
@@ -2332,7 +2365,7 @@ static int display_stats(
|
||||
iCur);
|
||||
}
|
||||
|
||||
if( pArg && pArg->out && db && pArg->pStmt ){
|
||||
if( pArg->pStmt ){
|
||||
iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FULLSCAN_STEP,
|
||||
bReset);
|
||||
raw_printf(pArg->out, "Fullscan Steps: %d\n", iCur);
|
||||
@@ -2342,6 +2375,12 @@ static int display_stats(
|
||||
raw_printf(pArg->out, "Autoindex Inserts: %d\n", iCur);
|
||||
iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_VM_STEP, bReset);
|
||||
raw_printf(pArg->out, "Virtual Machine Steps: %d\n", iCur);
|
||||
iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_REPREPARE, bReset);
|
||||
raw_printf(pArg->out, "Reprepare operations: %d\n", iCur);
|
||||
iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_RUN, bReset);
|
||||
raw_printf(pArg->out, "Number of times run: %d\n", iCur);
|
||||
iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_MEMUSED, bReset);
|
||||
raw_printf(pArg->out, "Memory used by prepared stmt: %d\n", iCur);
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
@@ -2557,8 +2596,7 @@ static void restore_debug_trace_modes(void){
|
||||
*/
|
||||
static void exec_prepared_stmt(
|
||||
ShellState *pArg, /* Pointer to ShellState */
|
||||
sqlite3_stmt *pStmt, /* Statment to run */
|
||||
int (*xCallback)(void*,int,char**,char**,int*) /* Callback function */
|
||||
sqlite3_stmt *pStmt /* Statment to run */
|
||||
){
|
||||
int rc;
|
||||
|
||||
@@ -2568,54 +2606,47 @@ static void exec_prepared_stmt(
|
||||
rc = sqlite3_step(pStmt);
|
||||
/* if we have a result set... */
|
||||
if( SQLITE_ROW == rc ){
|
||||
/* if we have a callback... */
|
||||
if( xCallback ){
|
||||
/* allocate space for col name ptr, value ptr, and type */
|
||||
int nCol = sqlite3_column_count(pStmt);
|
||||
void *pData = sqlite3_malloc64(3*nCol*sizeof(const char*) + 1);
|
||||
if( !pData ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
char **azCols = (char **)pData; /* Names of result columns */
|
||||
char **azVals = &azCols[nCol]; /* Results */
|
||||
int *aiTypes = (int *)&azVals[nCol]; /* Result types */
|
||||
int i, x;
|
||||
assert(sizeof(int) <= sizeof(char *));
|
||||
/* save off ptrs to column names */
|
||||
for(i=0; i<nCol; i++){
|
||||
azCols[i] = (char *)sqlite3_column_name(pStmt, i);
|
||||
}
|
||||
do{
|
||||
/* extract the data and data types */
|
||||
for(i=0; i<nCol; i++){
|
||||
aiTypes[i] = x = sqlite3_column_type(pStmt, i);
|
||||
if( x==SQLITE_BLOB && pArg && pArg->cMode==MODE_Insert ){
|
||||
azVals[i] = "";
|
||||
}else{
|
||||
azVals[i] = (char*)sqlite3_column_text(pStmt, i);
|
||||
}
|
||||
if( !azVals[i] && (aiTypes[i]!=SQLITE_NULL) ){
|
||||
rc = SQLITE_NOMEM;
|
||||
break; /* from for */
|
||||
}
|
||||
} /* end for */
|
||||
|
||||
/* if data and types extracted successfully... */
|
||||
if( SQLITE_ROW == rc ){
|
||||
/* call the supplied callback with the result row data */
|
||||
if( xCallback(pArg, nCol, azVals, azCols, aiTypes) ){
|
||||
rc = SQLITE_ABORT;
|
||||
}else{
|
||||
rc = sqlite3_step(pStmt);
|
||||
}
|
||||
}
|
||||
} while( SQLITE_ROW == rc );
|
||||
sqlite3_free(pData);
|
||||
}
|
||||
/* allocate space for col name ptr, value ptr, and type */
|
||||
int nCol = sqlite3_column_count(pStmt);
|
||||
void *pData = sqlite3_malloc64(3*nCol*sizeof(const char*) + 1);
|
||||
if( !pData ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
char **azCols = (char **)pData; /* Names of result columns */
|
||||
char **azVals = &azCols[nCol]; /* Results */
|
||||
int *aiTypes = (int *)&azVals[nCol]; /* Result types */
|
||||
int i, x;
|
||||
assert(sizeof(int) <= sizeof(char *));
|
||||
/* save off ptrs to column names */
|
||||
for(i=0; i<nCol; i++){
|
||||
azCols[i] = (char *)sqlite3_column_name(pStmt, i);
|
||||
}
|
||||
do{
|
||||
rc = sqlite3_step(pStmt);
|
||||
} while( rc == SQLITE_ROW );
|
||||
/* extract the data and data types */
|
||||
for(i=0; i<nCol; i++){
|
||||
aiTypes[i] = x = sqlite3_column_type(pStmt, i);
|
||||
if( x==SQLITE_BLOB && pArg && pArg->cMode==MODE_Insert ){
|
||||
azVals[i] = "";
|
||||
}else{
|
||||
azVals[i] = (char*)sqlite3_column_text(pStmt, i);
|
||||
}
|
||||
if( !azVals[i] && (aiTypes[i]!=SQLITE_NULL) ){
|
||||
rc = SQLITE_NOMEM;
|
||||
break; /* from for */
|
||||
}
|
||||
} /* end for */
|
||||
|
||||
/* if data and types extracted successfully... */
|
||||
if( SQLITE_ROW == rc ){
|
||||
/* call the supplied callback with the result row data */
|
||||
if( shell_callback(pArg, nCol, azVals, azCols, aiTypes) ){
|
||||
rc = SQLITE_ABORT;
|
||||
}else{
|
||||
rc = sqlite3_step(pStmt);
|
||||
}
|
||||
}
|
||||
} while( SQLITE_ROW == rc );
|
||||
sqlite3_free(pData);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2761,17 +2792,15 @@ static int expertDotCommand(
|
||||
** and callback data argument.
|
||||
*/
|
||||
static int shell_exec(
|
||||
sqlite3 *db, /* An open database */
|
||||
const char *zSql, /* SQL to be evaluated */
|
||||
int (*xCallback)(void*,int,char**,char**,int*), /* Callback function */
|
||||
/* (not the same as sqlite3_exec) */
|
||||
ShellState *pArg, /* Pointer to ShellState */
|
||||
const char *zSql, /* SQL to be evaluated */
|
||||
char **pzErrMsg /* Error msg written here */
|
||||
){
|
||||
sqlite3_stmt *pStmt = NULL; /* Statement to execute. */
|
||||
int rc = SQLITE_OK; /* Return Code */
|
||||
int rc2;
|
||||
const char *zLeftover; /* Tail of unprocessed SQL */
|
||||
sqlite3 *db = pArg->db;
|
||||
|
||||
if( pzErrMsg ){
|
||||
*pzErrMsg = NULL;
|
||||
@@ -2842,7 +2871,7 @@ static int shell_exec(
|
||||
if( rc==SQLITE_OK ){
|
||||
pArg->cMode = MODE_Explain;
|
||||
explain_data_prepare(pArg, pExplain);
|
||||
exec_prepared_stmt(pArg, pExplain, xCallback);
|
||||
exec_prepared_stmt(pArg, pExplain);
|
||||
explain_data_delete(pArg);
|
||||
}
|
||||
sqlite3_finalize(pExplain);
|
||||
@@ -2868,7 +2897,7 @@ static int shell_exec(
|
||||
}
|
||||
}
|
||||
|
||||
exec_prepared_stmt(pArg, pStmt, xCallback);
|
||||
exec_prepared_stmt(pArg, pStmt);
|
||||
explain_data_delete(pArg);
|
||||
|
||||
/* print usage stats if stats on */
|
||||
@@ -3131,11 +3160,11 @@ static int dump_callback(void *pArg, int nArg, char **azArg, char **azNotUsed){
|
||||
savedMode = p->mode;
|
||||
p->zDestTable = sTable.z;
|
||||
p->mode = p->cMode = MODE_Insert;
|
||||
rc = shell_exec(p->db, sSelect.z, shell_callback, p, 0);
|
||||
rc = shell_exec(p, sSelect.z, 0);
|
||||
if( (rc&0xff)==SQLITE_CORRUPT ){
|
||||
raw_printf(p->out, "/****** CORRUPTION ERROR *******/\n");
|
||||
toggleSelectOrder(p->db);
|
||||
shell_exec(p->db, sSelect.z, shell_callback, p, 0);
|
||||
shell_exec(p, sSelect.z, 0);
|
||||
toggleSelectOrder(p->db);
|
||||
}
|
||||
p->zDestTable = savedDestTable;
|
||||
@@ -3252,6 +3281,7 @@ static char zHelp[] =
|
||||
" on the output.\n"
|
||||
".open ?OPTIONS? ?FILE? Close existing database and reopen FILE\n"
|
||||
" The --new option starts with an empty file\n"
|
||||
" Other options: --readonly --append --zip\n"
|
||||
".output ?FILE? Send output to FILE or stdout\n"
|
||||
".print STRING... Print literal STRING\n"
|
||||
".prompt MAIN CONTINUE Replace the standard prompts\n"
|
||||
@@ -3269,10 +3299,14 @@ static char zHelp[] =
|
||||
".session CMD ... Create or control sessions\n"
|
||||
#endif
|
||||
".sha3sum ?OPTIONS...? Compute a SHA3 hash of database content\n"
|
||||
#ifndef SQLITE_NOHAVE_SYSTEM
|
||||
".shell CMD ARGS... Run CMD ARGS... in a system shell\n"
|
||||
#endif
|
||||
".show Show the current values for various settings\n"
|
||||
".stats ?on|off? Show stats or turn stats on or off\n"
|
||||
#ifndef SQLITE_NOHAVE_SYSTEM
|
||||
".system CMD ARGS... Run CMD ARGS... in a system shell\n"
|
||||
#endif
|
||||
".tables ?TABLE? List names of tables\n"
|
||||
" If TABLE specified, only list tables matching\n"
|
||||
" LIKE pattern TABLE.\n"
|
||||
@@ -3401,13 +3435,21 @@ static int session_filter(void *pCtx, const char *zTab){
|
||||
/*
|
||||
** Try to deduce the type of file for zName based on its content. Return
|
||||
** one of the SHELL_OPEN_* constants.
|
||||
**
|
||||
** If the file does not exist or is empty but its name looks like a ZIP
|
||||
** archive and the dfltZip flag is true, then assume it is a ZIP archive.
|
||||
** Otherwise, assume an ordinary database regardless of the filename if
|
||||
** the type cannot be determined from content.
|
||||
*/
|
||||
static int deduceDatabaseType(const char *zName){
|
||||
static int deduceDatabaseType(const char *zName, int dfltZip){
|
||||
FILE *f = fopen(zName, "rb");
|
||||
size_t n;
|
||||
int rc = SHELL_OPEN_UNSPEC;
|
||||
char zBuf[100];
|
||||
if( f==0 ) return SHELL_OPEN_NORMAL;
|
||||
if( f==0 ){
|
||||
if( dfltZip && sqlite3_strlike("%.zip",zName,0)==0 ) return SHELL_OPEN_ZIPFILE;
|
||||
return SHELL_OPEN_NORMAL;
|
||||
}
|
||||
fseek(f, -25, SEEK_END);
|
||||
n = fread(zBuf, 25, 1, f);
|
||||
if( n==1 && memcmp(zBuf, "Start-Of-SQLite3-", 17)==0 ){
|
||||
@@ -3418,6 +3460,8 @@ static int deduceDatabaseType(const char *zName){
|
||||
if( n==1 && zBuf[0]==0x50 && zBuf[1]==0x4b && zBuf[2]==0x05
|
||||
&& zBuf[3]==0x06 ){
|
||||
rc = SHELL_OPEN_ZIPFILE;
|
||||
}else if( n==0 && dfltZip && sqlite3_strlike("%.zip",zName,0)==0 ){
|
||||
return SHELL_OPEN_ZIPFILE;
|
||||
}
|
||||
}
|
||||
fclose(f);
|
||||
@@ -3432,7 +3476,7 @@ static void open_db(ShellState *p, int keepAlive){
|
||||
if( p->db==0 ){
|
||||
sqlite3_initialize();
|
||||
if( p->openMode==SHELL_OPEN_UNSPEC && access(p->zDbFilename,0)==0 ){
|
||||
p->openMode = deduceDatabaseType(p->zDbFilename);
|
||||
p->openMode = (u8)deduceDatabaseType(p->zDbFilename, 0);
|
||||
}
|
||||
switch( p->openMode ){
|
||||
case SHELL_OPEN_APPENDVFS: {
|
||||
@@ -3444,6 +3488,10 @@ static void open_db(ShellState *p, int keepAlive){
|
||||
sqlite3_open(":memory:", &p->db);
|
||||
break;
|
||||
}
|
||||
case SHELL_OPEN_READONLY: {
|
||||
sqlite3_open_v2(p->zDbFilename, &p->db, SQLITE_OPEN_READONLY, 0);
|
||||
break;
|
||||
}
|
||||
case SHELL_OPEN_UNSPEC:
|
||||
case SHELL_OPEN_NORMAL: {
|
||||
sqlite3_open(p->zDbFilename, &p->db);
|
||||
@@ -3473,10 +3521,12 @@ static void open_db(ShellState *p, int keepAlive){
|
||||
shellModuleSchema, 0, 0);
|
||||
sqlite3_create_function(p->db, "shell_putsnl", 1, SQLITE_UTF8, p,
|
||||
shellPutsFunc, 0, 0);
|
||||
#ifndef SQLITE_NOHAVE_SYSTEM
|
||||
sqlite3_create_function(p->db, "edit", 1, SQLITE_UTF8, 0,
|
||||
editFunc, 0, 0);
|
||||
sqlite3_create_function(p->db, "edit", 2, SQLITE_UTF8, 0,
|
||||
editFunc, 0, 0);
|
||||
#endif
|
||||
if( p->openMode==SHELL_OPEN_ZIPFILE ){
|
||||
char *zSql = sqlite3_mprintf(
|
||||
"CREATE VIRTUAL TABLE zip USING zipfile(%Q);", p->zDbFilename);
|
||||
@@ -4091,6 +4141,7 @@ static void output_reset(ShellState *p){
|
||||
#endif
|
||||
}else{
|
||||
output_file_close(p->out);
|
||||
#ifndef SQLITE_NOHAVE_SYSTEM
|
||||
if( p->doXdgOpen ){
|
||||
const char *zXdgOpenCmd =
|
||||
#if defined(_WIN32)
|
||||
@@ -4109,6 +4160,7 @@ static void output_reset(ShellState *p){
|
||||
outputModePop(p);
|
||||
p->doXdgOpen = 0;
|
||||
}
|
||||
#endif /* !defined(SQLITE_NOHAVE_SYSTEM) */
|
||||
}
|
||||
p->outfile[0] = 0;
|
||||
p->out = stdout;
|
||||
@@ -5219,8 +5271,8 @@ static int arCreateOrUpdateCommand(
|
||||
" data BLOB -- compressed content\n"
|
||||
")";
|
||||
const char *zDrop = "DROP TABLE IF EXISTS sqlar";
|
||||
const char *zInsertFmt =
|
||||
"REPLACE INTO sqlar(name,mode,mtime,sz,data)\n"
|
||||
const char *zInsertFmt[2] = {
|
||||
"REPLACE INTO %s(name,mode,mtime,sz,data)\n"
|
||||
" SELECT\n"
|
||||
" %s,\n"
|
||||
" mode,\n"
|
||||
@@ -5229,30 +5281,70 @@ static int arCreateOrUpdateCommand(
|
||||
" WHEN '-' THEN length(data)\n"
|
||||
" WHEN 'd' THEN 0\n"
|
||||
" ELSE -1 END,\n"
|
||||
" CASE WHEN lsmode(mode) LIKE 'd%%' THEN NULL else data END\n"
|
||||
" sqlar_compress(data)\n"
|
||||
" FROM fsdir(%Q,%Q)\n"
|
||||
" WHERE lsmode(mode) NOT LIKE '?%%';";
|
||||
" WHERE lsmode(mode) NOT LIKE '?%%';",
|
||||
"REPLACE INTO %s(name,mode,mtime,data)\n"
|
||||
" SELECT\n"
|
||||
" %s,\n"
|
||||
" mode,\n"
|
||||
" mtime,\n"
|
||||
" data\n"
|
||||
" FROM fsdir(%Q,%Q)\n"
|
||||
" WHERE lsmode(mode) NOT LIKE '?%%';"
|
||||
};
|
||||
int i; /* For iterating through azFile[] */
|
||||
int rc; /* Return code */
|
||||
const char *zTab = 0; /* SQL table into which to insert */
|
||||
char *zSql;
|
||||
char zTemp[50];
|
||||
|
||||
arExecSql(pAr, "PRAGMA page_size=512");
|
||||
rc = arExecSql(pAr, "SAVEPOINT ar;");
|
||||
if( rc!=SQLITE_OK ) return rc;
|
||||
if( bUpdate==0 ){
|
||||
rc = arExecSql(pAr, zDrop);
|
||||
if( rc!=SQLITE_OK ) return rc;
|
||||
zTemp[0] = 0;
|
||||
if( pAr->bZip ){
|
||||
/* Initialize the zipfile virtual table, if necessary */
|
||||
if( pAr->zFile ){
|
||||
sqlite3_uint64 r;
|
||||
sqlite3_randomness(sizeof(r),&r);
|
||||
sqlite3_snprintf(sizeof(zTemp),zTemp,"zip%016llx",r);
|
||||
zTab = zTemp;
|
||||
zSql = sqlite3_mprintf(
|
||||
"CREATE VIRTUAL TABLE temp.%s USING zipfile(%Q)",
|
||||
zTab, pAr->zFile
|
||||
);
|
||||
rc = arExecSql(pAr, zSql);
|
||||
sqlite3_free(zSql);
|
||||
}else{
|
||||
zTab = "zip";
|
||||
}
|
||||
}else{
|
||||
/* Initialize the table for an SQLAR */
|
||||
zTab = "sqlar";
|
||||
if( bUpdate==0 ){
|
||||
rc = arExecSql(pAr, zDrop);
|
||||
if( rc!=SQLITE_OK ) goto end_ar_transaction;
|
||||
}
|
||||
rc = arExecSql(pAr, zCreate);
|
||||
}
|
||||
rc = arExecSql(pAr, zCreate);
|
||||
for(i=0; i<pAr->nArg && rc==SQLITE_OK; i++){
|
||||
char *zSql = sqlite3_mprintf(zInsertFmt,
|
||||
char *zSql = sqlite3_mprintf(zInsertFmt[pAr->bZip], zTab,
|
||||
pAr->bVerbose ? "shell_putsnl(name)" : "name",
|
||||
pAr->azArg[i], pAr->zDir);
|
||||
rc = arExecSql(pAr, zSql);
|
||||
sqlite3_free(zSql);
|
||||
}
|
||||
end_ar_transaction:
|
||||
if( rc!=SQLITE_OK ){
|
||||
arExecSql(pAr, "ROLLBACK TO ar; RELEASE ar;");
|
||||
}else{
|
||||
rc = arExecSql(pAr, "RELEASE ar;");
|
||||
if( pAr->bZip && pAr->zFile ){
|
||||
zSql = sqlite3_mprintf("DROP TABLE %s", zTemp);
|
||||
arExecSql(pAr, zSql);
|
||||
sqlite3_free(zSql);
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
@@ -5274,20 +5366,17 @@ static int arDotCommand(
|
||||
cmd.p = pState;
|
||||
cmd.db = pState->db;
|
||||
if( cmd.zFile ){
|
||||
eDbType = deduceDatabaseType(cmd.zFile);
|
||||
eDbType = deduceDatabaseType(cmd.zFile, 1);
|
||||
}else{
|
||||
eDbType = pState->openMode;
|
||||
}
|
||||
if( eDbType==SHELL_OPEN_ZIPFILE ){
|
||||
if( cmd.zFile==0 ){
|
||||
cmd.zSrcTable = sqlite3_mprintf("zip");
|
||||
}else{
|
||||
cmd.zSrcTable = sqlite3_mprintf("zipfile(%Q)", cmd.zFile);
|
||||
}
|
||||
if( cmd.eCmd==AR_CMD_CREATE || cmd.eCmd==AR_CMD_UPDATE ){
|
||||
utf8_printf(stderr, "zip archives are read-only\n");
|
||||
rc = SQLITE_ERROR;
|
||||
goto end_ar_command;
|
||||
if( cmd.eCmd==AR_CMD_EXTRACT || cmd.eCmd==AR_CMD_LIST ){
|
||||
if( cmd.zFile==0 ){
|
||||
cmd.zSrcTable = sqlite3_mprintf("zip");
|
||||
}else{
|
||||
cmd.zSrcTable = sqlite3_mprintf("zipfile(%Q)", cmd.zFile);
|
||||
}
|
||||
}
|
||||
cmd.bZip = 1;
|
||||
}else if( cmd.zFile ){
|
||||
@@ -5312,14 +5401,12 @@ static int arDotCommand(
|
||||
goto end_ar_command;
|
||||
}
|
||||
sqlite3_fileio_init(cmd.db, 0, 0);
|
||||
#ifdef SQLITE_HAVE_ZLIB
|
||||
sqlite3_sqlar_init(cmd.db, 0, 0);
|
||||
#endif
|
||||
sqlite3_create_function(cmd.db, "shell_putsnl", 1, SQLITE_UTF8, cmd.p,
|
||||
shellPutsFunc, 0, 0);
|
||||
|
||||
}
|
||||
if( cmd.zSrcTable==0 ){
|
||||
if( cmd.zSrcTable==0 && cmd.bZip==0 ){
|
||||
if( cmd.eCmd!=AR_CMD_CREATE
|
||||
&& sqlite3_table_column_metadata(cmd.db,0,"sqlar","name",0,0,0,0,0)
|
||||
){
|
||||
@@ -5712,7 +5799,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
}else if( strcmp(azArg[1],"trigger")==0 ){
|
||||
p->autoEQP = AUTOEQP_trigger;
|
||||
}else{
|
||||
p->autoEQP = booleanValue(azArg[1]);
|
||||
p->autoEQP = (u8)booleanValue(azArg[1]);
|
||||
}
|
||||
}else{
|
||||
raw_printf(stderr, "Usage: .eqp off|on|trigger|full\n");
|
||||
@@ -5799,14 +5886,11 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
callback, &data, &zErrMsg);
|
||||
data.cMode = data.mode = MODE_Insert;
|
||||
data.zDestTable = "sqlite_stat1";
|
||||
shell_exec(p->db, "SELECT * FROM sqlite_stat1",
|
||||
shell_callback, &data,&zErrMsg);
|
||||
shell_exec(p, "SELECT * FROM sqlite_stat1", &zErrMsg);
|
||||
data.zDestTable = "sqlite_stat3";
|
||||
shell_exec(p->db, "SELECT * FROM sqlite_stat3",
|
||||
shell_callback, &data,&zErrMsg);
|
||||
shell_exec(p, "SELECT * FROM sqlite_stat3", &zErrMsg);
|
||||
data.zDestTable = "sqlite_stat4";
|
||||
shell_exec(p->db, "SELECT * FROM sqlite_stat4",
|
||||
shell_callback, &data, &zErrMsg);
|
||||
shell_exec(p, "SELECT * FROM sqlite_stat4", &zErrMsg);
|
||||
raw_printf(p->out, "ANALYZE sqlite_master;\n");
|
||||
}
|
||||
}else
|
||||
@@ -6287,12 +6371,14 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
const char *z = azArg[iName];
|
||||
if( optionMatch(z,"new") ){
|
||||
newFlag = 1;
|
||||
#ifdef SQLITE_HAVE_ZIP
|
||||
#ifdef SQLITE_HAVE_ZLIB
|
||||
}else if( optionMatch(z, "zip") ){
|
||||
p->openMode = SHELL_OPEN_ZIPFILE;
|
||||
#endif
|
||||
}else if( optionMatch(z, "append") ){
|
||||
p->openMode = SHELL_OPEN_APPENDVFS;
|
||||
}else if( optionMatch(z, "readonly") ){
|
||||
p->openMode = SHELL_OPEN_READONLY;
|
||||
}else if( z[0]=='-' ){
|
||||
utf8_printf(stderr, "unknown option: %s\n", z);
|
||||
rc = 1;
|
||||
@@ -6349,6 +6435,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
}
|
||||
output_reset(p);
|
||||
if( zFile[0]=='-' && zFile[1]=='-' ) zFile++;
|
||||
#ifndef SQLITE_NOHAVE_SYSTEM
|
||||
if( strcmp(zFile, "-e")==0 || strcmp(zFile, "-x")==0 ){
|
||||
p->doXdgOpen = 1;
|
||||
outputModePush(p);
|
||||
@@ -6363,6 +6450,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
}
|
||||
zFile = p->zTempFile;
|
||||
}
|
||||
#endif /* SQLITE_NOHAVE_SYSTEM */
|
||||
if( zFile[0]=='|' ){
|
||||
#ifdef SQLITE_OMIT_POPEN
|
||||
raw_printf(stderr, "Error: pipes are not supported in this OS\n");
|
||||
@@ -6482,10 +6570,9 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
sqlite3_close(pSrc);
|
||||
}else
|
||||
|
||||
|
||||
if( c=='s' && strncmp(azArg[0], "scanstats", n)==0 ){
|
||||
if( nArg==2 ){
|
||||
p->scanstatsOn = booleanValue(azArg[1]);
|
||||
p->scanstatsOn = (u8)booleanValue(azArg[1]);
|
||||
#ifndef SQLITE_ENABLE_STMT_SCANSTATUS
|
||||
raw_printf(stderr, "Warning: .scanstats not available in this build.\n");
|
||||
#endif
|
||||
@@ -7073,11 +7160,12 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
if( bDebug ){
|
||||
utf8_printf(p->out, "%s\n", zSql);
|
||||
}else{
|
||||
shell_exec(p->db, zSql, shell_callback, p, 0);
|
||||
shell_exec(p, zSql, 0);
|
||||
}
|
||||
sqlite3_free(zSql);
|
||||
}else
|
||||
|
||||
#ifndef SQLITE_NOHAVE_SYSTEM
|
||||
if( c=='s'
|
||||
&& (strncmp(azArg[0], "shell", n)==0 || strncmp(azArg[0],"system",n)==0)
|
||||
){
|
||||
@@ -7097,6 +7185,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
sqlite3_free(zCmd);
|
||||
if( x ) raw_printf(stderr, "System command returns %d\n", x);
|
||||
}else
|
||||
#endif /* !defined(SQLITE_NOHAVE_SYSTEM) */
|
||||
|
||||
if( c=='s' && strncmp(azArg[0], "show", n)==0 ){
|
||||
static const char *azBool[] = { "off", "on", "trigger", "full"};
|
||||
@@ -7136,7 +7225,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
|
||||
if( c=='s' && strncmp(azArg[0], "stats", n)==0 ){
|
||||
if( nArg==2 ){
|
||||
p->statsOn = booleanValue(azArg[1]);
|
||||
p->statsOn = (u8)booleanValue(azArg[1]);
|
||||
}else if( nArg==1 ){
|
||||
display_stats(p->db, p, 0);
|
||||
}else{
|
||||
@@ -7537,6 +7626,20 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
if( c=='v' && strncmp(azArg[0], "version", n)==0 ){
|
||||
utf8_printf(p->out, "SQLite %s %s\n" /*extra-version-info*/,
|
||||
sqlite3_libversion(), sqlite3_sourceid());
|
||||
#if SQLITE_HAVE_ZLIB
|
||||
utf8_printf(p->out, "zlib version %s\n", zlibVersion());
|
||||
#endif
|
||||
#define CTIMEOPT_VAL_(opt) #opt
|
||||
#define CTIMEOPT_VAL(opt) CTIMEOPT_VAL_(opt)
|
||||
#if defined(__clang__) && defined(__clang_major__)
|
||||
utf8_printf(p->out, "clang-" CTIMEOPT_VAL(__clang_major__) "."
|
||||
CTIMEOPT_VAL(__clang_minor__) "."
|
||||
CTIMEOPT_VAL(__clang_patchlevel__) "\n");
|
||||
#elif defined(_MSC_VER)
|
||||
utf8_printf(p->out, "msvc-" CTIMEOPT_VAL(_MSC_VER) "\n");
|
||||
#elif defined(__GNUC__) && defined(__VERSION__)
|
||||
utf8_printf(p->out, "gcc-" __VERSION__ "\n");
|
||||
#endif
|
||||
}else
|
||||
|
||||
if( c=='v' && strncmp(azArg[0], "vfsinfo", n)==0 ){
|
||||
@@ -7662,6 +7765,16 @@ static int line_is_command_terminator(const char *zLine){
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** We need a default sqlite3_complete() implementation to use in case
|
||||
** the shell is compiled with SQLITE_OMIT_COMPLETE. The default assumes
|
||||
** any arbitrary text is a complete SQL statement. This is not very
|
||||
** user-friendly, but it does seem to work.
|
||||
*/
|
||||
#ifdef SQLITE_OMIT_COMPLETE
|
||||
int sqlite3_complete(const char *zSql){ return 1; }
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Return true if zSql is a complete SQL statement. Return false if it
|
||||
** ends in the middle of a string literal or C-style comment.
|
||||
@@ -7686,7 +7799,7 @@ static int runOneSqlLine(ShellState *p, char *zSql, FILE *in, int startline){
|
||||
open_db(p, 0);
|
||||
if( ShellHasFlag(p,SHFLG_Backslash) ) resolve_backslashes(zSql);
|
||||
BEGIN_TIMER;
|
||||
rc = shell_exec(p->db, zSql, shell_callback, p, &zErrMsg);
|
||||
rc = shell_exec(p, zSql, &zErrMsg);
|
||||
END_TIMER;
|
||||
if( rc || zErrMsg ){
|
||||
char zPrefix[100];
|
||||
@@ -7918,6 +8031,10 @@ static void process_sqliterc(
|
||||
** Show available command line options
|
||||
*/
|
||||
static const char zOptions[] =
|
||||
#if defined(SQLITE_HAVE_ZLIB) && !defined(SQLITE_OMIT_VIRTUALTABLE)
|
||||
" -A ARGS... run \".archive ARGS\" and exit\n"
|
||||
#endif
|
||||
" -append append the database to the end of the file\n"
|
||||
" -ascii set output mode to 'ascii'\n"
|
||||
" -bail stop after hitting an error\n"
|
||||
" -batch force batch I/O\n"
|
||||
@@ -7944,6 +8061,7 @@ static const char zOptions[] =
|
||||
" -nullvalue TEXT set text string for NULL values. Default ''\n"
|
||||
" -pagecache SIZE N use N slots of SZ bytes each for page cache memory\n"
|
||||
" -quote set output mode to 'quote'\n"
|
||||
" -readonly open the database read-only\n"
|
||||
" -separator SEP set output column separator. Default: '|'\n"
|
||||
" -stats print memory stats before each finalize\n"
|
||||
" -version show SQLite version\n"
|
||||
@@ -7951,6 +8069,9 @@ static const char zOptions[] =
|
||||
#ifdef SQLITE_ENABLE_VFSTRACE
|
||||
" -vfstrace enable tracing of all VFS calls\n"
|
||||
#endif
|
||||
#ifdef SQLITE_HAVE_ZLIB
|
||||
" -zip open the file as a ZIP Archive\n"
|
||||
#endif
|
||||
;
|
||||
static void usage(int showDetail){
|
||||
utf8_printf(stderr,
|
||||
@@ -8053,21 +8174,39 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
|
||||
}
|
||||
#endif
|
||||
main_init(&data);
|
||||
|
||||
/* On Windows, we must translate command-line arguments into UTF-8.
|
||||
** The SQLite memory allocator subsystem has to be enabled in order to
|
||||
** do this. But we want to run an sqlite3_shutdown() afterwards so that
|
||||
** subsequent sqlite3_config() calls will work. So copy all results into
|
||||
** memory that does not come from the SQLite memory allocator.
|
||||
*/
|
||||
#if !SQLITE_SHELL_IS_UTF8
|
||||
sqlite3_initialize();
|
||||
argv = sqlite3_malloc64(sizeof(argv[0])*argc);
|
||||
argv = malloc(sizeof(argv[0])*argc);
|
||||
if( argv==0 ){
|
||||
raw_printf(stderr, "out of memory\n");
|
||||
exit(1);
|
||||
}
|
||||
for(i=0; i<argc; i++){
|
||||
argv[i] = sqlite3_win32_unicode_to_utf8(wargv[i]);
|
||||
char *z = sqlite3_win32_unicode_to_utf8(wargv[i]);
|
||||
int n;
|
||||
if( z==0 ){
|
||||
raw_printf(stderr, "out of memory\n");
|
||||
exit(1);
|
||||
}
|
||||
n = (int)strlen(z);
|
||||
argv[i] = malloc( n+1 );
|
||||
if( argv[i]==0 ){
|
||||
raw_printf(stderr, "out of memory\n");
|
||||
exit(1);
|
||||
}
|
||||
memcpy(argv[i], z, n+1);
|
||||
sqlite3_free(z);
|
||||
}
|
||||
sqlite3_shutdown();
|
||||
#endif
|
||||
|
||||
assert( argc>=1 && argv && argv[0] );
|
||||
Argv0 = argv[0];
|
||||
|
||||
@@ -8187,12 +8326,20 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
|
||||
utf8_printf(stderr, "no such VFS: \"%s\"\n", argv[i]);
|
||||
exit(1);
|
||||
}
|
||||
#ifdef SQLITE_HAVE_ZIP
|
||||
#ifdef SQLITE_HAVE_ZLIB
|
||||
}else if( strcmp(z,"-zip")==0 ){
|
||||
data.openMode = SHELL_OPEN_ZIPFILE;
|
||||
#endif
|
||||
}else if( strcmp(z,"-append")==0 ){
|
||||
data.openMode = SHELL_OPEN_APPENDVFS;
|
||||
}else if( strcmp(z,"-readonly")==0 ){
|
||||
data.openMode = SHELL_OPEN_READONLY;
|
||||
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
|
||||
}else if( strncmp(z, "-A",2)==0 ){
|
||||
/* All remaining command-line arguments are passed to the ".archive"
|
||||
** command, so ignore them */
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
if( data.zDbFilename==0 ){
|
||||
@@ -8246,7 +8393,7 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
|
||||
}else if( strcmp(z,"-csv")==0 ){
|
||||
data.mode = MODE_Csv;
|
||||
memcpy(data.colSeparator,",",2);
|
||||
#ifdef SQLITE_HAVE_ZIP
|
||||
#ifdef SQLITE_HAVE_ZLIB
|
||||
}else if( strcmp(z,"-zip")==0 ){
|
||||
data.openMode = SHELL_OPEN_ZIPFILE;
|
||||
#endif
|
||||
@@ -8329,7 +8476,7 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
|
||||
if( rc && bail_on_error ) return rc==2 ? 0 : rc;
|
||||
}else{
|
||||
open_db(&data, 0);
|
||||
rc = shell_exec(data.db, z, shell_callback, &data, &zErrMsg);
|
||||
rc = shell_exec(&data, z, &zErrMsg);
|
||||
if( zErrMsg!=0 ){
|
||||
utf8_printf(stderr,"Error: %s\n", zErrMsg);
|
||||
if( bail_on_error ) return rc!=0 ? rc : 1;
|
||||
@@ -8338,6 +8485,23 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
|
||||
if( bail_on_error ) return rc;
|
||||
}
|
||||
}
|
||||
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
|
||||
}else if( strncmp(z, "-A", 2)==0 ){
|
||||
if( nCmd>0 ){
|
||||
utf8_printf(stderr, "Error: cannot mix regular SQL or dot-commands"
|
||||
" with \"%s\"\n", z);
|
||||
return 1;
|
||||
}
|
||||
open_db(&data, 0);
|
||||
if( z[2] ){
|
||||
argv[i] = &z[2];
|
||||
arDotCommand(&data, argv+(i-1), argc-(i-1));
|
||||
}else{
|
||||
arDotCommand(&data, argv+i, argc-i);
|
||||
}
|
||||
readStdin = 0;
|
||||
break;
|
||||
#endif
|
||||
}else{
|
||||
utf8_printf(stderr,"%s: Error: unknown option: %s\n", Argv0, z);
|
||||
raw_printf(stderr,"Use -help for a list of options.\n");
|
||||
@@ -8357,7 +8521,7 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
|
||||
if( rc ) return rc==2 ? 0 : rc;
|
||||
}else{
|
||||
open_db(&data, 0);
|
||||
rc = shell_exec(data.db, azCmd[i], shell_callback, &data, &zErrMsg);
|
||||
rc = shell_exec(&data, azCmd[i], &zErrMsg);
|
||||
if( zErrMsg!=0 ){
|
||||
utf8_printf(stderr,"Error: %s\n", zErrMsg);
|
||||
return rc!=0 ? rc : 1;
|
||||
@@ -8420,8 +8584,8 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
|
||||
data.doXdgOpen = 0;
|
||||
clearTempFile(&data);
|
||||
#if !SQLITE_SHELL_IS_UTF8
|
||||
for(i=0; i<argc; i++) sqlite3_free(argv[i]);
|
||||
sqlite3_free(argv);
|
||||
for(i=0; i<argc; i++) free(argv[i]);
|
||||
free(argv);
|
||||
#endif
|
||||
return rc;
|
||||
}
|
||||
|
||||
+167
-76
@@ -510,7 +510,6 @@ int sqlite3_exec(
|
||||
#define SQLITE_CANTOPEN_ISDIR (SQLITE_CANTOPEN | (2<<8))
|
||||
#define SQLITE_CANTOPEN_FULLPATH (SQLITE_CANTOPEN | (3<<8))
|
||||
#define SQLITE_CANTOPEN_CONVPATH (SQLITE_CANTOPEN | (4<<8))
|
||||
#define SQLITE_CANTOPEN_DIRTYWAL (SQLITE_CANTOPEN | (5<<8))
|
||||
#define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8))
|
||||
#define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8))
|
||||
#define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8))
|
||||
@@ -2497,16 +2496,16 @@ void sqlite3_free_table(char **result);
|
||||
**
|
||||
** These routines are work-alikes of the "printf()" family of functions
|
||||
** from the standard C library.
|
||||
** These routines understand most of the common K&R formatting options,
|
||||
** plus some additional non-standard formats, detailed below.
|
||||
** Note that some of the more obscure formatting options from recent
|
||||
** C-library standards are omitted from this implementation.
|
||||
** These routines understand most of the common formatting options from
|
||||
** the standard library printf()
|
||||
** plus some additional non-standard formats ([%q], [%Q], [%w], and [%z]).
|
||||
** See the [built-in printf()] documentation for details.
|
||||
**
|
||||
** ^The sqlite3_mprintf() and sqlite3_vmprintf() routines write their
|
||||
** results into memory obtained from [sqlite3_malloc()].
|
||||
** results into memory obtained from [sqlite3_malloc64()].
|
||||
** The strings returned by these two routines should be
|
||||
** released by [sqlite3_free()]. ^Both routines return a
|
||||
** NULL pointer if [sqlite3_malloc()] is unable to allocate enough
|
||||
** NULL pointer if [sqlite3_malloc64()] is unable to allocate enough
|
||||
** memory to hold the resulting string.
|
||||
**
|
||||
** ^(The sqlite3_snprintf() routine is similar to "snprintf()" from
|
||||
@@ -2530,71 +2529,7 @@ void sqlite3_free_table(char **result);
|
||||
**
|
||||
** ^The sqlite3_vsnprintf() routine is a varargs version of sqlite3_snprintf().
|
||||
**
|
||||
** These routines all implement some additional formatting
|
||||
** options that are useful for constructing SQL statements.
|
||||
** All of the usual printf() formatting options apply. In addition, there
|
||||
** is are "%q", "%Q", "%w" and "%z" options.
|
||||
**
|
||||
** ^(The %q option works like %s in that it substitutes a nul-terminated
|
||||
** string from the argument list. But %q also doubles every '\'' character.
|
||||
** %q is designed for use inside a string literal.)^ By doubling each '\''
|
||||
** character it escapes that character and allows it to be inserted into
|
||||
** the string.
|
||||
**
|
||||
** For example, assume the string variable zText contains text as follows:
|
||||
**
|
||||
** <blockquote><pre>
|
||||
** char *zText = "It's a happy day!";
|
||||
** </pre></blockquote>
|
||||
**
|
||||
** One can use this text in an SQL statement as follows:
|
||||
**
|
||||
** <blockquote><pre>
|
||||
** char *zSQL = sqlite3_mprintf("INSERT INTO table VALUES('%q')", zText);
|
||||
** sqlite3_exec(db, zSQL, 0, 0, 0);
|
||||
** sqlite3_free(zSQL);
|
||||
** </pre></blockquote>
|
||||
**
|
||||
** Because the %q format string is used, the '\'' character in zText
|
||||
** is escaped and the SQL generated is as follows:
|
||||
**
|
||||
** <blockquote><pre>
|
||||
** INSERT INTO table1 VALUES('It''s a happy day!')
|
||||
** </pre></blockquote>
|
||||
**
|
||||
** This is correct. Had we used %s instead of %q, the generated SQL
|
||||
** would have looked like this:
|
||||
**
|
||||
** <blockquote><pre>
|
||||
** INSERT INTO table1 VALUES('It's a happy day!');
|
||||
** </pre></blockquote>
|
||||
**
|
||||
** This second example is an SQL syntax error. As a general rule you should
|
||||
** always use %q instead of %s when inserting text into a string literal.
|
||||
**
|
||||
** ^(The %Q option works like %q except it also adds single quotes around
|
||||
** the outside of the total string. Additionally, if the parameter in the
|
||||
** argument list is a NULL pointer, %Q substitutes the text "NULL" (without
|
||||
** single quotes).)^ So, for example, one could say:
|
||||
**
|
||||
** <blockquote><pre>
|
||||
** char *zSQL = sqlite3_mprintf("INSERT INTO table VALUES(%Q)", zText);
|
||||
** sqlite3_exec(db, zSQL, 0, 0, 0);
|
||||
** sqlite3_free(zSQL);
|
||||
** </pre></blockquote>
|
||||
**
|
||||
** The code above will render a correct SQL statement in the zSQL
|
||||
** variable even if the zText variable is a NULL pointer.
|
||||
**
|
||||
** ^(The "%w" formatting option is like "%q" except that it expects to
|
||||
** be contained within double-quotes instead of single quotes, and it
|
||||
** escapes the double-quote character instead of the single-quote
|
||||
** character.)^ The "%w" formatting option is intended for safely inserting
|
||||
** table and column names into a constructed SQL statement.
|
||||
**
|
||||
** ^(The "%z" formatting option works like "%s" but with the
|
||||
** addition that after the string has been read and copied into
|
||||
** the result, [sqlite3_free()] is called on the input string.)^
|
||||
** See also: [built-in printf()], [printf() SQL function]
|
||||
*/
|
||||
char *sqlite3_mprintf(const char*,...);
|
||||
char *sqlite3_vmprintf(const char*, va_list);
|
||||
@@ -2952,8 +2887,8 @@ SQLITE_DEPRECATED void *sqlite3_profile(sqlite3*,
|
||||
** KEYWORDS: SQLITE_TRACE
|
||||
**
|
||||
** These constants identify classes of events that can be monitored
|
||||
** using the [sqlite3_trace_v2()] tracing logic. The third argument
|
||||
** to [sqlite3_trace_v2()] is an OR-ed combination of one or more of
|
||||
** using the [sqlite3_trace_v2()] tracing logic. The M argument
|
||||
** to [sqlite3_trace_v2(D,M,X,P)] is an OR-ed combination of one or more of
|
||||
** the following constants. ^The first argument to the trace callback
|
||||
** is one of the following constants.
|
||||
**
|
||||
@@ -3660,13 +3595,13 @@ int sqlite3_limit(sqlite3*, int id, int newVal);
|
||||
** or [GLOB] operator or if the parameter is compared to an indexed column
|
||||
** and the [SQLITE_ENABLE_STAT3] compile-time option is enabled.
|
||||
** </li>
|
||||
** </ol>
|
||||
**
|
||||
** <p>^sqlite3_prepare_v3() differs from sqlite3_prepare_v2() only in having
|
||||
** the extra prepFlags parameter, which is a bit array consisting of zero or
|
||||
** more of the [SQLITE_PREPARE_PERSISTENT|SQLITE_PREPARE_*] flags. ^The
|
||||
** sqlite3_prepare_v2() interface works exactly the same as
|
||||
** sqlite3_prepare_v3() with a zero prepFlags parameter.
|
||||
** </ol>
|
||||
*/
|
||||
int sqlite3_prepare(
|
||||
sqlite3 *db, /* Database handle */
|
||||
@@ -4799,6 +4734,9 @@ SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int),
|
||||
** datatype of the value
|
||||
** <tr><td><b>sqlite3_value_numeric_type </b>
|
||||
** <td>→ <td>Best numeric datatype of the value
|
||||
** <tr><td><b>sqlite3_value_nochange </b>
|
||||
** <td>→ <td>True if the column is unchanged in an UPDATE
|
||||
** against a virtual table.
|
||||
** </table></blockquote>
|
||||
**
|
||||
** <b>Details:</b>
|
||||
@@ -4847,6 +4785,19 @@ SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int),
|
||||
** then the conversion is performed. Otherwise no conversion occurs.
|
||||
** The [SQLITE_INTEGER | datatype] after conversion is returned.)^
|
||||
**
|
||||
** ^Within the [xUpdate] method of a [virtual table], the
|
||||
** sqlite3_value_nochange(X) interface returns true if and only if
|
||||
** the column corresponding to X is unchanged by the UPDATE operation
|
||||
** that the xUpdate method call was invoked to implement and if
|
||||
** and the prior [xColumn] method call that was invoked to extracted
|
||||
** the value for that column returned without setting a result (probably
|
||||
** because it queried [sqlite3_vtab_nochange()] and found that the column
|
||||
** was unchanging). ^Within an [xUpdate] method, any value for which
|
||||
** sqlite3_value_nochange(X) is true will in all other respects appear
|
||||
** to be a NULL value. If sqlite3_value_nochange(X) is invoked anywhere other
|
||||
** than within an [xUpdate] method call for an UPDATE statement, then
|
||||
** the return value is arbitrary and meaningless.
|
||||
**
|
||||
** Please pay particular attention to the fact that the pointer returned
|
||||
** from [sqlite3_value_blob()], [sqlite3_value_text()], or
|
||||
** [sqlite3_value_text16()] can be invalidated by a subsequent call to
|
||||
@@ -4869,6 +4820,7 @@ int sqlite3_value_bytes(sqlite3_value*);
|
||||
int sqlite3_value_bytes16(sqlite3_value*);
|
||||
int sqlite3_value_type(sqlite3_value*);
|
||||
int sqlite3_value_numeric_type(sqlite3_value*);
|
||||
int sqlite3_value_nochange(sqlite3_value*);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Finding The Subtype Of SQL Values
|
||||
@@ -7278,6 +7230,15 @@ int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg);
|
||||
** highwater mark associated with SQLITE_DBSTATUS_CACHE_WRITE is always 0.
|
||||
** </dd>
|
||||
**
|
||||
** [[SQLITE_DBSTATUS_CACHE_SPILL]] ^(<dt>SQLITE_DBSTATUS_CACHE_SPILL</dt>
|
||||
** <dd>This parameter returns the number of dirty cache entries that have
|
||||
** been written to disk in the middle of a transaction due to the page
|
||||
** cache overflowing. Transactions are more efficient if they are written
|
||||
** to disk all at once. When pages spill mid-transaction, that introduces
|
||||
** additional overhead. This parameter can be used help identify
|
||||
** inefficiencies that can be resolve by increasing the cache size.
|
||||
** </dd>
|
||||
**
|
||||
** [[SQLITE_DBSTATUS_DEFERRED_FKS]] ^(<dt>SQLITE_DBSTATUS_DEFERRED_FKS</dt>
|
||||
** <dd>This parameter returns zero for the current value if and only if
|
||||
** all foreign key constraints (deferred or immediate) have been
|
||||
@@ -7297,7 +7258,8 @@ int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg);
|
||||
#define SQLITE_DBSTATUS_CACHE_WRITE 9
|
||||
#define SQLITE_DBSTATUS_DEFERRED_FKS 10
|
||||
#define SQLITE_DBSTATUS_CACHE_USED_SHARED 11
|
||||
#define SQLITE_DBSTATUS_MAX 11 /* Largest defined DBSTATUS */
|
||||
#define SQLITE_DBSTATUS_CACHE_SPILL 12
|
||||
#define SQLITE_DBSTATUS_MAX 12 /* Largest defined DBSTATUS */
|
||||
|
||||
|
||||
/*
|
||||
@@ -8306,6 +8268,13 @@ int sqlite3_vtab_on_conflict(sqlite3 *);
|
||||
** column value will not change. Applications might use this to substitute
|
||||
** a lighter-weight value to return that the corresponding [xUpdate] method
|
||||
** understands as a "no-change" value.
|
||||
**
|
||||
** If the [xColumn] method calls sqlite3_vtab_nochange() and finds that
|
||||
** the column is not changed by the UPDATE statement, they the xColumn
|
||||
** method can optionally return without setting a result, without calling
|
||||
** any of the [sqlite3_result_int|sqlite3_result_xxxxx() interfaces].
|
||||
** In that case, [sqlite3_value_nochange(X)] will return true for the
|
||||
** same column in the [xUpdate] method.
|
||||
*/
|
||||
int sqlite3_vtab_nochange(sqlite3_context*);
|
||||
|
||||
@@ -8770,6 +8739,128 @@ SQLITE_EXPERIMENTAL int sqlite3_snapshot_cmp(
|
||||
*/
|
||||
SQLITE_EXPERIMENTAL int sqlite3_snapshot_recover(sqlite3 *db, const char *zDb);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Serialize a database
|
||||
**
|
||||
** The sqlite3_serialize(D,S,P,F) interface returns a pointer to memory
|
||||
** that is a serialization of the S database on [database connection] D.
|
||||
** If P is not a NULL pointer, then the size of the database in bytes
|
||||
** is written into *P.
|
||||
**
|
||||
** For an ordinary on-disk database file, the serialization is just a
|
||||
** copy of the disk file. For an in-memory database or a "TEMP" database,
|
||||
** the serialization is the same sequence of bytes which would be written
|
||||
** to disk if that database where backed up to disk.
|
||||
**
|
||||
** The usual case is that sqlite3_serialize() copies the serialization of
|
||||
** the database into memory obtained from [sqlite3_malloc64()] and returns
|
||||
** a pointer to that memory. The caller is responsible for freeing the
|
||||
** returned value to avoid a memory leak. However, if the F argument
|
||||
** contains the SQLITE_SERIALIZE_NOCOPY bit, then no memory allocations
|
||||
** are made, and the sqlite3_serialize() function will return a pointer
|
||||
** to the contiguous memory representation of the database that SQLite
|
||||
** is currently using for that database, or NULL if the no such contiguous
|
||||
** memory representation of the database exists. A contiguous memory
|
||||
** representation of the database will usually only exist if there has
|
||||
** been a prior call to [sqlite3_deserialize(D,S,...)] with the same
|
||||
** values of D and S.
|
||||
** The size of the database is written into *P even if the
|
||||
** SQLITE_SERIALIZE_NOCOPY bit is set but no contigious copy
|
||||
** of the database exists.
|
||||
**
|
||||
** A call to sqlite3_serialize(D,S,P,F) might return NULL even if the
|
||||
** SQLITE_SERIALIZE_NOCOPY bit is omitted from argument F if a memory
|
||||
** allocation error occurs.
|
||||
**
|
||||
** This interface is only available if SQLite is compiled with the
|
||||
** [SQLITE_ENABLE_DESERIALIZE] option.
|
||||
*/
|
||||
unsigned char *sqlite3_serialize(
|
||||
sqlite3 *db, /* The database connection */
|
||||
const char *zSchema, /* Which DB to serialize. ex: "main", "temp", ... */
|
||||
sqlite3_int64 *piSize, /* Write size of the DB here, if not NULL */
|
||||
unsigned int mFlags /* Zero or more SQLITE_SERIALIZE_* flags */
|
||||
);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Flags for sqlite3_serialize
|
||||
**
|
||||
** Zero or more of the following constants can be OR-ed together for
|
||||
** the F argument to [sqlite3_serialize(D,S,P,F)].
|
||||
**
|
||||
** SQLITE_SERIALIZE_NOCOPY means that [sqlite3_serialize()] will return
|
||||
** a pointer to contiguous in-memory database that it is currently using,
|
||||
** without making a copy of the database. If SQLite is not currently using
|
||||
** a contiguous in-memory database, then this option causes
|
||||
** [sqlite3_serialize()] to return a NULL pointer. SQLite will only be
|
||||
** using a contiguous in-memory database if it has been initialized by a
|
||||
** prior call to [sqlite3_deserialize()].
|
||||
*/
|
||||
#define SQLITE_SERIALIZE_NOCOPY 0x001 /* Do no memory allocations */
|
||||
|
||||
/*
|
||||
** CAPI3REF: Deserialize a database
|
||||
**
|
||||
** The sqlite3_deserialize(D,S,P,N,M,F) interface causes the
|
||||
** [database connection] D to disconnection from database S and then
|
||||
** reopen S as an in-memory database based on the serialization contained
|
||||
** in P. The serialized database P is N bytes in size. M is the size of
|
||||
** the buffer P, which might be larger than N. If M is larger than N, and
|
||||
** the SQLITE_DESERIALIZE_READONLY bit is not set in F, then SQLite is
|
||||
** permitted to add content to the in-memory database as long as the total
|
||||
** size does not exceed M bytes.
|
||||
**
|
||||
** If the SQLITE_DESERIALIZE_FREEONCLOSE bit is set in F, then SQLite will
|
||||
** invoke sqlite3_free() on the serialization buffer when the database
|
||||
** connection closes. If the SQLITE_DESERIALIZE_RESIZEABLE bit is set, then
|
||||
** SQLite will try to increase the buffer size using sqlite3_realloc64()
|
||||
** if writes on the database cause it to grow larger than M bytes.
|
||||
**
|
||||
** The sqlite3_deserialize() interface will fail with SQLITE_BUSY if the
|
||||
** database is currently in a read transaction or is involved in a backup
|
||||
** operation.
|
||||
**
|
||||
** If sqlite3_deserialize(D,S,P,N,M,F) fails for any reason and if the
|
||||
** SQLITE_DESERIALIZE_FREEONCLOSE bit is set in argument F, then
|
||||
** [sqlite3_free()] is invoked on argument P prior to returning.
|
||||
**
|
||||
** This interface is only available if SQLite is compiled with the
|
||||
** [SQLITE_ENABLE_DESERIALIZE] option.
|
||||
*/
|
||||
int sqlite3_deserialize(
|
||||
sqlite3 *db, /* The database connection */
|
||||
const char *zSchema, /* Which DB to reopen with the deserialization */
|
||||
unsigned char *pData, /* The serialized database content */
|
||||
sqlite3_int64 szDb, /* Number bytes in the deserialization */
|
||||
sqlite3_int64 szBuf, /* Total size of buffer pData[] */
|
||||
unsigned mFlags /* Zero or more SQLITE_DESERIALIZE_* flags */
|
||||
);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Flags for sqlite3_deserialize()
|
||||
**
|
||||
** The following are allowed values for 6th argument (the F argument) to
|
||||
** the [sqlite3_deserialize(D,S,P,N,M,F)] interface.
|
||||
**
|
||||
** The SQLITE_DESERIALIZE_FREEONCLOSE means that the database serialization
|
||||
** in the P argument is held in memory obtained from [sqlite3_malloc64()]
|
||||
** and that SQLite should take ownership of this memory and automatically
|
||||
** free it when it has finished using it. Without this flag, the caller
|
||||
** is resposible for freeing any dynamically allocated memory.
|
||||
**
|
||||
** The SQLITE_DESERIALIZE_RESIZEABLE flag means that SQLite is allowed to
|
||||
** grow the size of the database using calls to [sqlite3_realloc64()]. This
|
||||
** flag should only be used if SQLITE_DESERIALIZE_FREEONCLOSE is also used.
|
||||
** Without this flag, the deserialized database cannot increase in size beyond
|
||||
** the number of bytes specified by the M parameter.
|
||||
**
|
||||
** The SQLITE_DESERIALIZE_READONLY flag means that the deserialized database
|
||||
** should be treated as read-only.
|
||||
*/
|
||||
#define SQLITE_DESERIALIZE_FREEONCLOSE 1 /* Call sqlite3_free() on close */
|
||||
#define SQLITE_DESERIALIZE_RESIZEABLE 2 /* Resize using sqlite3_realloc64() */
|
||||
#define SQLITE_DESERIALIZE_READONLY 4 /* Database is read-only */
|
||||
|
||||
/*
|
||||
** Undo the hack that converts floating point types to integer for
|
||||
** builds on processors without floating point support.
|
||||
|
||||
@@ -292,6 +292,9 @@ struct sqlite3_api_routines {
|
||||
int (*bind_pointer)(sqlite3_stmt*,int,void*,const char*,void(*)(void*));
|
||||
void (*result_pointer)(sqlite3_context*,void*,const char*,void(*)(void*));
|
||||
void *(*value_pointer)(sqlite3_value*,const char*);
|
||||
int (*vtab_nochange)(sqlite3_context*);
|
||||
int (*value_nochange)(sqlite3_value*);
|
||||
const char *(*vtab_collation)(sqlite3_index_info*,int);
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -558,6 +561,10 @@ typedef int (*sqlite3_loadext_entry)(
|
||||
#define sqlite3_bind_pointer sqlite3_api->bind_pointer
|
||||
#define sqlite3_result_pointer sqlite3_api->result_pointer
|
||||
#define sqlite3_value_pointer sqlite3_api->value_pointer
|
||||
/* Version 3.22.0 and later */
|
||||
#define sqlite3_vtab_nochange sqlite3_api->vtab_nochange
|
||||
#define sqlite3_value_nochange sqlite3_api->value_nochange
|
||||
#define sqlite3_vtab_collation sqlite3_api->vtab_collation
|
||||
#endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */
|
||||
|
||||
#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
|
||||
|
||||
+14
-2
@@ -1365,8 +1365,9 @@ struct sqlite3 {
|
||||
int newTnum; /* Rootpage of table being initialized */
|
||||
u8 iDb; /* Which db file is being initialized */
|
||||
u8 busy; /* TRUE if currently initializing */
|
||||
u8 orphanTrigger; /* Last statement is orphaned TEMP trigger */
|
||||
u8 imposterTable; /* Building an imposter table */
|
||||
unsigned orphanTrigger : 1; /* Last statement is orphaned TEMP trigger */
|
||||
unsigned imposterTable : 1; /* Building an imposter table */
|
||||
unsigned reopenMemdb : 1; /* ATTACH is really a reopen using MemDB */
|
||||
} init;
|
||||
int nVdbeActive; /* Number of VDBEs currently running */
|
||||
int nVdbeRead; /* Number of active VDBEs that read or write */
|
||||
@@ -1754,6 +1755,7 @@ struct Column {
|
||||
#define COLFLAG_PRIMKEY 0x0001 /* Column is part of the primary key */
|
||||
#define COLFLAG_HIDDEN 0x0002 /* A hidden column in a virtual table */
|
||||
#define COLFLAG_HASTYPE 0x0004 /* Type name follows column name */
|
||||
#define COLFLAG_UNIQUE 0x0008 /* Column def contains "UNIQUE" or "PK" */
|
||||
|
||||
/*
|
||||
** A "Collating Sequence" is defined by an instance of the following
|
||||
@@ -3117,6 +3119,7 @@ struct AuthContext {
|
||||
#define OPFLAG_PERMUTE 0x01 /* OP_Compare: use the permutation */
|
||||
#define OPFLAG_SAVEPOSITION 0x02 /* OP_Delete/Insert: save cursor pos */
|
||||
#define OPFLAG_AUXDELETE 0x04 /* OP_Delete: index in a DELETE op */
|
||||
#define OPFLAG_NOCHNG_MAGIC 0x6d /* OP_MakeRecord: serialtype 10 is ok */
|
||||
|
||||
/*
|
||||
* Each trigger present in the database schema is stored as an instance of
|
||||
@@ -3837,6 +3840,8 @@ void sqlite3EndTransaction(Parse*,int);
|
||||
void sqlite3Savepoint(Parse*, int, Token*);
|
||||
void sqlite3CloseSavepoints(sqlite3 *);
|
||||
void sqlite3LeaveMutexAndCloseZombie(sqlite3*);
|
||||
int sqlite3ExprIdToTrueFalse(Expr*);
|
||||
int sqlite3ExprTruthValue(const Expr*);
|
||||
int sqlite3ExprIsConstant(Expr*);
|
||||
int sqlite3ExprIsConstantNotJoin(Expr*);
|
||||
int sqlite3ExprIsConstantOrFunction(Expr*, u8);
|
||||
@@ -4019,6 +4024,10 @@ int sqlite3TwoPartName(Parse *, Token *, Token *, Token **);
|
||||
const char *sqlite3ErrName(int);
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_ENABLE_DESERIALIZE
|
||||
int sqlite3MemdbInit(void);
|
||||
#endif
|
||||
|
||||
const char *sqlite3ErrStr(int);
|
||||
int sqlite3ReadSchema(Parse *pParse);
|
||||
CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char*,int);
|
||||
@@ -4067,6 +4076,9 @@ extern FuncDefHash sqlite3BuiltinFunctions;
|
||||
extern int sqlite3PendingByte;
|
||||
#endif
|
||||
#endif
|
||||
#ifdef VDBE_PROFILE
|
||||
extern sqlite3_uint64 sqlite3NProfileCnt;
|
||||
#endif
|
||||
void sqlite3RootPageMoved(sqlite3*, int, int, int);
|
||||
void sqlite3Reindex(Parse*, Token*, Token*);
|
||||
void sqlite3AlterFunctions(void);
|
||||
|
||||
@@ -337,6 +337,9 @@ int sqlite3_db_status(
|
||||
** pagers the database handle is connected to. *pHighwater is always set
|
||||
** to zero.
|
||||
*/
|
||||
case SQLITE_DBSTATUS_CACHE_SPILL:
|
||||
op = SQLITE_DBSTATUS_CACHE_WRITE+1;
|
||||
/* Fall through into the next case */
|
||||
case SQLITE_DBSTATUS_CACHE_HIT:
|
||||
case SQLITE_DBSTATUS_CACHE_MISS:
|
||||
case SQLITE_DBSTATUS_CACHE_WRITE:{
|
||||
|
||||
+148
-50
@@ -64,7 +64,9 @@
|
||||
# define GETPID getpid
|
||||
#elif !defined(_WIN32_WCE)
|
||||
# ifndef SQLITE_AMALGAMATION
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
# ifndef WIN32_LEAN_AND_MEAN
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
# endif
|
||||
# include <windows.h>
|
||||
# endif
|
||||
# define GETPID (int)GetCurrentProcessId
|
||||
@@ -646,7 +648,7 @@ static int DbTraceV2Handler(
|
||||
}
|
||||
case SQLITE_TRACE_PROFILE: {
|
||||
sqlite3_stmt *pStmt = (sqlite3_stmt *)pd;
|
||||
sqlite3_int64 ns = (sqlite3_int64)xd;
|
||||
sqlite3_int64 ns = *(sqlite3_int64*)xd;
|
||||
|
||||
pCmd = Tcl_NewStringObj(pDb->zTraceV2, -1);
|
||||
Tcl_IncrRefCount(pCmd);
|
||||
@@ -1846,35 +1848,35 @@ static int SQLITE_TCLAPI DbObjCmd(
|
||||
int choice;
|
||||
int rc = TCL_OK;
|
||||
static const char *DB_strs[] = {
|
||||
"authorizer", "backup", "busy",
|
||||
"cache", "changes", "close",
|
||||
"collate", "collation_needed", "commit_hook",
|
||||
"complete", "copy", "enable_load_extension",
|
||||
"errorcode", "eval", "exists",
|
||||
"function", "incrblob", "interrupt",
|
||||
"last_insert_rowid", "nullvalue", "onecolumn",
|
||||
"preupdate", "profile", "progress",
|
||||
"rekey", "restore", "rollback_hook",
|
||||
"status", "timeout", "total_changes",
|
||||
"trace", "trace_v2", "transaction",
|
||||
"unlock_notify", "update_hook", "version",
|
||||
"wal_hook",
|
||||
0
|
||||
"authorizer", "backup", "busy",
|
||||
"cache", "changes", "close",
|
||||
"collate", "collation_needed", "commit_hook",
|
||||
"complete", "copy", "deserialize",
|
||||
"enable_load_extension", "errorcode", "eval",
|
||||
"exists", "function", "incrblob",
|
||||
"interrupt", "last_insert_rowid", "nullvalue",
|
||||
"onecolumn", "preupdate", "profile",
|
||||
"progress", "rekey", "restore",
|
||||
"rollback_hook", "serialize", "status",
|
||||
"timeout", "total_changes", "trace",
|
||||
"trace_v2", "transaction", "unlock_notify",
|
||||
"update_hook", "version", "wal_hook",
|
||||
0
|
||||
};
|
||||
enum DB_enum {
|
||||
DB_AUTHORIZER, DB_BACKUP, DB_BUSY,
|
||||
DB_CACHE, DB_CHANGES, DB_CLOSE,
|
||||
DB_COLLATE, DB_COLLATION_NEEDED, DB_COMMIT_HOOK,
|
||||
DB_COMPLETE, DB_COPY, DB_ENABLE_LOAD_EXTENSION,
|
||||
DB_ERRORCODE, DB_EVAL, DB_EXISTS,
|
||||
DB_FUNCTION, DB_INCRBLOB, DB_INTERRUPT,
|
||||
DB_LAST_INSERT_ROWID, DB_NULLVALUE, DB_ONECOLUMN,
|
||||
DB_PREUPDATE, DB_PROFILE, DB_PROGRESS,
|
||||
DB_REKEY, DB_RESTORE, DB_ROLLBACK_HOOK,
|
||||
DB_STATUS, DB_TIMEOUT, DB_TOTAL_CHANGES,
|
||||
DB_TRACE, DB_TRACE_V2, DB_TRANSACTION,
|
||||
DB_UNLOCK_NOTIFY, DB_UPDATE_HOOK, DB_VERSION,
|
||||
DB_WAL_HOOK,
|
||||
DB_AUTHORIZER, DB_BACKUP, DB_BUSY,
|
||||
DB_CACHE, DB_CHANGES, DB_CLOSE,
|
||||
DB_COLLATE, DB_COLLATION_NEEDED, DB_COMMIT_HOOK,
|
||||
DB_COMPLETE, DB_COPY, DB_DESERIALIZE,
|
||||
DB_ENABLE_LOAD_EXTENSION, DB_ERRORCODE, DB_EVAL,
|
||||
DB_EXISTS, DB_FUNCTION, DB_INCRBLOB,
|
||||
DB_INTERRUPT, DB_LAST_INSERT_ROWID, DB_NULLVALUE,
|
||||
DB_ONECOLUMN, DB_PREUPDATE, DB_PROFILE,
|
||||
DB_PROGRESS, DB_REKEY, DB_RESTORE,
|
||||
DB_ROLLBACK_HOOK, DB_SERIALIZE, DB_STATUS,
|
||||
DB_TIMEOUT, DB_TOTAL_CHANGES, DB_TRACE,
|
||||
DB_TRACE_V2, DB_TRANSACTION, DB_UNLOCK_NOTIFY,
|
||||
DB_UPDATE_HOOK, DB_VERSION, DB_WAL_HOOK
|
||||
};
|
||||
/* don't leave trailing commas on DB_enum, it confuses the AIX xlc compiler */
|
||||
|
||||
@@ -2412,6 +2414,53 @@ static int SQLITE_TCLAPI DbObjCmd(
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
** $db deserialize ?DATABASE? VALUE
|
||||
**
|
||||
** Reopen DATABASE (default "main") using the content in $VALUE
|
||||
*/
|
||||
case DB_DESERIALIZE: {
|
||||
#ifndef SQLITE_ENABLE_DESERIALIZE
|
||||
Tcl_AppendResult(interp, "MEMDB not available in this build",
|
||||
(char*)0);
|
||||
rc = TCL_ERROR;
|
||||
#else
|
||||
const char *zSchema;
|
||||
Tcl_Obj *pValue;
|
||||
unsigned char *pBA;
|
||||
unsigned char *pData;
|
||||
int len, xrc;
|
||||
|
||||
if( objc==3 ){
|
||||
zSchema = 0;
|
||||
pValue = objv[2];
|
||||
}else if( objc==4 ){
|
||||
zSchema = Tcl_GetString(objv[2]);
|
||||
pValue = objv[3];
|
||||
}else{
|
||||
Tcl_WrongNumArgs(interp, 2, objv, "?DATABASE? VALUE");
|
||||
rc = TCL_ERROR;
|
||||
break;
|
||||
}
|
||||
pBA = Tcl_GetByteArrayFromObj(pValue, &len);
|
||||
pData = sqlite3_malloc64( len );
|
||||
if( pData==0 && len>0 ){
|
||||
Tcl_AppendResult(interp, "out of memory", (char*)0);
|
||||
rc = TCL_ERROR;
|
||||
}else{
|
||||
if( len>0 ) memcpy(pData, pBA, len);
|
||||
xrc = sqlite3_deserialize(pDb->db, zSchema, pData, len, len,
|
||||
SQLITE_DESERIALIZE_FREEONCLOSE |
|
||||
SQLITE_DESERIALIZE_RESIZEABLE);
|
||||
if( xrc ){
|
||||
Tcl_AppendResult(interp, "unable to set MEMDB content", (char*)0);
|
||||
rc = TCL_ERROR;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
** $db enable_load_extension BOOLEAN
|
||||
**
|
||||
@@ -2887,6 +2936,39 @@ static int SQLITE_TCLAPI DbObjCmd(
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
** $db serialize ?DATABASE?
|
||||
**
|
||||
** Return a serialization of a database.
|
||||
*/
|
||||
case DB_SERIALIZE: {
|
||||
#ifndef SQLITE_ENABLE_DESERIALIZE
|
||||
Tcl_AppendResult(interp, "MEMDB not available in this build",
|
||||
(char*)0);
|
||||
rc = TCL_ERROR;
|
||||
#else
|
||||
const char *zSchema = objc>=3 ? Tcl_GetString(objv[2]) : "main";
|
||||
sqlite3_int64 sz = 0;
|
||||
unsigned char *pData;
|
||||
if( objc!=2 && objc!=3 ){
|
||||
Tcl_WrongNumArgs(interp, 2, objv, "?DATABASE?");
|
||||
rc = TCL_ERROR;
|
||||
}else{
|
||||
int needFree;
|
||||
pData = sqlite3_serialize(pDb->db, zSchema, &sz, SQLITE_SERIALIZE_NOCOPY);
|
||||
if( pData ){
|
||||
needFree = 0;
|
||||
}else{
|
||||
pData = sqlite3_serialize(pDb->db, zSchema, &sz, 0);
|
||||
needFree = 1;
|
||||
}
|
||||
Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(pData,sz));
|
||||
if( needFree ) sqlite3_free(pData);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
** $db status (step|sort|autoindex|vmstep)
|
||||
**
|
||||
@@ -3347,6 +3429,24 @@ static int SQLITE_TCLAPI DbObjCmdAdaptor(
|
||||
}
|
||||
#endif /* SQLITE_TCL_NRE */
|
||||
|
||||
/*
|
||||
** Issue the usage message when the "sqlite3" command arguments are
|
||||
** incorrect.
|
||||
*/
|
||||
static int sqliteCmdUsage(
|
||||
Tcl_Interp *interp,
|
||||
Tcl_Obj *const*objv
|
||||
){
|
||||
Tcl_WrongNumArgs(interp, 1, objv,
|
||||
"HANDLE ?FILENAME? ?-vfs VFSNAME? ?-readonly BOOLEAN? ?-create BOOLEAN?"
|
||||
" ?-nomutex BOOLEAN? ?-fullmutex BOOLEAN? ?-uri BOOLEAN?"
|
||||
#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_CODEC_FROM_TCL)
|
||||
" ?-key CODECKEY?"
|
||||
#endif
|
||||
);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
** sqlite3 DBNAME FILENAME ?-vfs VFSNAME? ?-key KEY? ?-readonly BOOLEAN?
|
||||
** ?-create BOOLEAN? ?-nomutex BOOLEAN?
|
||||
@@ -3372,7 +3472,7 @@ static int SQLITE_TCLAPI DbMain(
|
||||
const char *zArg;
|
||||
char *zErrMsg;
|
||||
int i;
|
||||
const char *zFile;
|
||||
const char *zFile = 0;
|
||||
const char *zVfs = 0;
|
||||
int flags;
|
||||
Tcl_DString translatedFilename;
|
||||
@@ -3383,7 +3483,7 @@ static int SQLITE_TCLAPI DbMain(
|
||||
int rc;
|
||||
|
||||
/* In normal use, each TCL interpreter runs in a single thread. So
|
||||
** by default, we can turn of mutexing on SQLite database connections.
|
||||
** by default, we can turn off mutexing on SQLite database connections.
|
||||
** However, for testing purposes it is useful to have mutexes turned
|
||||
** on. So, by default, mutexes default off. But if compiled with
|
||||
** SQLITE_TCL_DEFAULT_FULLMUTEX then mutexes default on.
|
||||
@@ -3412,18 +3512,26 @@ static int SQLITE_TCLAPI DbMain(
|
||||
#endif
|
||||
return TCL_OK;
|
||||
}
|
||||
if( zArg[0]=='-' ) return sqliteCmdUsage(interp, objv);
|
||||
}
|
||||
for(i=3; i+1<objc; i+=2){
|
||||
for(i=2; i<objc; i++){
|
||||
zArg = Tcl_GetString(objv[i]);
|
||||
if( zArg[0]!='-' ){
|
||||
if( zFile!=0 ) return sqliteCmdUsage(interp, objv);
|
||||
zFile = zArg;
|
||||
continue;
|
||||
}
|
||||
if( i==objc-1 ) return sqliteCmdUsage(interp, objv);
|
||||
i++;
|
||||
if( strcmp(zArg,"-key")==0 ){
|
||||
#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_CODEC_FROM_TCL)
|
||||
pKey = Tcl_GetByteArrayFromObj(objv[i+1], &nKey);
|
||||
pKey = Tcl_GetByteArrayFromObj(objv[i], &nKey);
|
||||
#endif
|
||||
}else if( strcmp(zArg, "-vfs")==0 ){
|
||||
zVfs = Tcl_GetString(objv[i+1]);
|
||||
zVfs = Tcl_GetString(objv[i]);
|
||||
}else if( strcmp(zArg, "-readonly")==0 ){
|
||||
int b;
|
||||
if( Tcl_GetBooleanFromObj(interp, objv[i+1], &b) ) return TCL_ERROR;
|
||||
if( Tcl_GetBooleanFromObj(interp, objv[i], &b) ) return TCL_ERROR;
|
||||
if( b ){
|
||||
flags &= ~(SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE);
|
||||
flags |= SQLITE_OPEN_READONLY;
|
||||
@@ -3433,7 +3541,7 @@ static int SQLITE_TCLAPI DbMain(
|
||||
}
|
||||
}else if( strcmp(zArg, "-create")==0 ){
|
||||
int b;
|
||||
if( Tcl_GetBooleanFromObj(interp, objv[i+1], &b) ) return TCL_ERROR;
|
||||
if( Tcl_GetBooleanFromObj(interp, objv[i], &b) ) return TCL_ERROR;
|
||||
if( b && (flags & SQLITE_OPEN_READONLY)==0 ){
|
||||
flags |= SQLITE_OPEN_CREATE;
|
||||
}else{
|
||||
@@ -3441,7 +3549,7 @@ static int SQLITE_TCLAPI DbMain(
|
||||
}
|
||||
}else if( strcmp(zArg, "-nomutex")==0 ){
|
||||
int b;
|
||||
if( Tcl_GetBooleanFromObj(interp, objv[i+1], &b) ) return TCL_ERROR;
|
||||
if( Tcl_GetBooleanFromObj(interp, objv[i], &b) ) return TCL_ERROR;
|
||||
if( b ){
|
||||
flags |= SQLITE_OPEN_NOMUTEX;
|
||||
flags &= ~SQLITE_OPEN_FULLMUTEX;
|
||||
@@ -3450,7 +3558,7 @@ static int SQLITE_TCLAPI DbMain(
|
||||
}
|
||||
}else if( strcmp(zArg, "-fullmutex")==0 ){
|
||||
int b;
|
||||
if( Tcl_GetBooleanFromObj(interp, objv[i+1], &b) ) return TCL_ERROR;
|
||||
if( Tcl_GetBooleanFromObj(interp, objv[i], &b) ) return TCL_ERROR;
|
||||
if( b ){
|
||||
flags |= SQLITE_OPEN_FULLMUTEX;
|
||||
flags &= ~SQLITE_OPEN_NOMUTEX;
|
||||
@@ -3459,7 +3567,7 @@ static int SQLITE_TCLAPI DbMain(
|
||||
}
|
||||
}else if( strcmp(zArg, "-uri")==0 ){
|
||||
int b;
|
||||
if( Tcl_GetBooleanFromObj(interp, objv[i+1], &b) ) return TCL_ERROR;
|
||||
if( Tcl_GetBooleanFromObj(interp, objv[i], &b) ) return TCL_ERROR;
|
||||
if( b ){
|
||||
flags |= SQLITE_OPEN_URI;
|
||||
}else{
|
||||
@@ -3470,20 +3578,10 @@ static int SQLITE_TCLAPI DbMain(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
}
|
||||
if( objc<3 || (objc&1)!=1 ){
|
||||
Tcl_WrongNumArgs(interp, 1, objv,
|
||||
"HANDLE FILENAME ?-vfs VFSNAME? ?-readonly BOOLEAN? ?-create BOOLEAN?"
|
||||
" ?-nomutex BOOLEAN? ?-fullmutex BOOLEAN? ?-uri BOOLEAN?"
|
||||
#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_CODEC_FROM_TCL)
|
||||
" ?-key CODECKEY?"
|
||||
#endif
|
||||
);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
zErrMsg = 0;
|
||||
p = (SqliteDb*)Tcl_Alloc( sizeof(*p) );
|
||||
memset(p, 0, sizeof(*p));
|
||||
zFile = Tcl_GetStringFromObj(objv[2], 0);
|
||||
if( zFile==0 ) zFile = "";
|
||||
zFile = Tcl_TranslateFileName(interp, zFile, &translatedFilename);
|
||||
rc = sqlite3_open_v2(zFile, &p->db, flags, zVfs);
|
||||
Tcl_DStringFree(&translatedFilename);
|
||||
|
||||
+30
@@ -4559,6 +4559,35 @@ static int SQLITE_TCLAPI test_complete16(
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Usage: sqlite3_normalize SQL
|
||||
**
|
||||
** Return the normalized value for an SQL statement.
|
||||
*/
|
||||
static int SQLITE_TCLAPI test_normalize(
|
||||
void * clientData,
|
||||
Tcl_Interp *interp,
|
||||
int objc,
|
||||
Tcl_Obj *CONST objv[]
|
||||
){
|
||||
char *zSql;
|
||||
char *zNorm;
|
||||
extern char *sqlite3_normalize(const char*);
|
||||
|
||||
if( objc!=2 ){
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "SQL");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
zSql = (char*)Tcl_GetString(objv[1]);
|
||||
zNorm = sqlite3_normalize(zSql);
|
||||
if( zNorm ){
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(zNorm, -1));
|
||||
sqlite3_free(zNorm);
|
||||
}
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Usage: sqlite3_step STMT
|
||||
**
|
||||
@@ -7547,6 +7576,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
|
||||
{ "sqlite3_open16", test_open16 ,0 },
|
||||
{ "sqlite3_open_v2", test_open_v2 ,0 },
|
||||
{ "sqlite3_complete16", test_complete16 ,0 },
|
||||
{ "sqlite3_normalize", test_normalize ,0 },
|
||||
|
||||
{ "sqlite3_prepare", test_prepare ,0 },
|
||||
{ "sqlite3_prepare16", test_prepare16 ,0 },
|
||||
|
||||
@@ -148,6 +148,12 @@ static void set_options(Tcl_Interp *interp){
|
||||
Tcl_SetVar2(interp, "sqlite_options", "hiddencolumns", "0", TCL_GLOBAL_ONLY);
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_ENABLE_DESERIALIZE
|
||||
Tcl_SetVar2(interp, "sqlite_options", "deserialize", "1", TCL_GLOBAL_ONLY);
|
||||
#else
|
||||
Tcl_SetVar2(interp, "sqlite_options", "deserialize", "0", TCL_GLOBAL_ONLY);
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_ENABLE_MEMSYS3
|
||||
Tcl_SetVar2(interp, "sqlite_options", "mem3", "1", TCL_GLOBAL_ONLY);
|
||||
#else
|
||||
@@ -501,6 +507,12 @@ Tcl_SetVar2(interp, "sqlite_options", "long_double",
|
||||
|
||||
Tcl_SetVar2(interp, "sqlite_options", "mergesort", "1", TCL_GLOBAL_ONLY);
|
||||
|
||||
#ifdef SQLITE_ENABLE_NULL_TRIM
|
||||
Tcl_SetVar2(interp, "sqlite_options", "null_trim", "1", TCL_GLOBAL_ONLY);
|
||||
#else
|
||||
Tcl_SetVar2(interp, "sqlite_options", "null_trim", "0", TCL_GLOBAL_ONLY);
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_OMIT_OR_OPTIMIZATION
|
||||
Tcl_SetVar2(interp, "sqlite_options", "or_opt", "0", TCL_GLOBAL_ONLY);
|
||||
#else
|
||||
|
||||
@@ -1383,6 +1383,7 @@ static int SQLITE_TCLAPI test_db_status(
|
||||
{ "CACHE_WRITE", SQLITE_DBSTATUS_CACHE_WRITE },
|
||||
{ "DEFERRED_FKS", SQLITE_DBSTATUS_DEFERRED_FKS },
|
||||
{ "CACHE_USED_SHARED", SQLITE_DBSTATUS_CACHE_USED_SHARED },
|
||||
{ "CACHE_SPILL", SQLITE_DBSTATUS_CACHE_SPILL },
|
||||
};
|
||||
Tcl_Obj *pResult;
|
||||
if( objc!=4 ){
|
||||
|
||||
@@ -20,7 +20,10 @@
|
||||
** We need several data types from the Windows SDK header.
|
||||
*/
|
||||
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
|
||||
#include "windows.h"
|
||||
|
||||
/*
|
||||
|
||||
@@ -292,6 +292,11 @@ void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){
|
||||
sqlite3TreeViewLine(pView,"NULL");
|
||||
break;
|
||||
}
|
||||
case TK_TRUEFALSE: {
|
||||
sqlite3TreeViewLine(pView,
|
||||
sqlite3ExprTruthValue(pExpr) ? "TRUE" : "FALSE");
|
||||
break;
|
||||
}
|
||||
#ifndef SQLITE_OMIT_BLOB_LITERAL
|
||||
case TK_BLOB: {
|
||||
sqlite3TreeViewLine(pView,"%s", pExpr->u.zToken);
|
||||
@@ -348,6 +353,19 @@ void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){
|
||||
case TK_ISNULL: zUniOp = "ISNULL"; break;
|
||||
case TK_NOTNULL: zUniOp = "NOTNULL"; break;
|
||||
|
||||
case TK_TRUTH: {
|
||||
int x;
|
||||
const char *azOp[] = {
|
||||
"IS-FALSE", "IS-TRUE", "IS-NOT-FALSE", "IS-NOT-TRUE"
|
||||
};
|
||||
assert( pExpr->op2==TK_IS || pExpr->op2==TK_ISNOT );
|
||||
assert( pExpr->pRight );
|
||||
assert( pExpr->pRight->op==TK_TRUEFALSE );
|
||||
x = (pExpr->op2==TK_ISNOT)*2 + sqlite3ExprTruthValue(pExpr->pRight);
|
||||
zUniOp = azOp[x];
|
||||
break;
|
||||
}
|
||||
|
||||
case TK_SPAN: {
|
||||
sqlite3TreeViewLine(pView, "SPAN %Q", pExpr->u.zToken);
|
||||
sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
|
||||
|
||||
+7
-1
@@ -827,7 +827,8 @@ static void updateVirtualTable(
|
||||
if( aXRef[i]>=0 ){
|
||||
sqlite3ExprCode(pParse, pChanges->a[aXRef[i]].pExpr, regArg+2+i);
|
||||
}else{
|
||||
sqlite3VdbeAddOp4Int(v, OP_VColumn, iCsr, i, regArg+2+i, 1);
|
||||
sqlite3VdbeAddOp3(v, OP_VColumn, iCsr, i, regArg+2+i);
|
||||
sqlite3VdbeChangeP5(v, 1); /* Enable sqlite3_vtab_nochange() */
|
||||
}
|
||||
}
|
||||
if( HasRowid(pTab) ){
|
||||
@@ -862,6 +863,11 @@ static void updateVirtualTable(
|
||||
/* Create a record from the argument register contents and insert it into
|
||||
** the ephemeral table. */
|
||||
sqlite3VdbeAddOp3(v, OP_MakeRecord, regArg, nArg, regRec);
|
||||
#ifdef SQLITE_DEBUG
|
||||
/* Signal an assert() within OP_MakeRecord that it is allowed to
|
||||
** accept no-change records with serial_type 10 */
|
||||
sqlite3VdbeChangeP5(v, OPFLAG_NOCHNG_MAGIC);
|
||||
#endif
|
||||
sqlite3VdbeAddOp2(v, OP_NewRowid, ephemTab, regRowid);
|
||||
sqlite3VdbeAddOp3(v, OP_Insert, ephemTab, regRec, regRowid);
|
||||
}
|
||||
|
||||
+52
-21
@@ -327,6 +327,26 @@ int sqlite3_strnicmp(const char *zLeft, const char *zRight, int N){
|
||||
** This routine only works for values of E between 1 and 341.
|
||||
*/
|
||||
static LONGDOUBLE_TYPE sqlite3Pow10(int E){
|
||||
#if defined(_MSC_VER)
|
||||
static const LONGDOUBLE_TYPE x[] = {
|
||||
1.0e+001,
|
||||
1.0e+002,
|
||||
1.0e+004,
|
||||
1.0e+008,
|
||||
1.0e+016,
|
||||
1.0e+032,
|
||||
1.0e+064,
|
||||
1.0e+128,
|
||||
1.0e+256
|
||||
};
|
||||
LONGDOUBLE_TYPE r = 1.0;
|
||||
int i;
|
||||
assert( E>=0 && E<=307 );
|
||||
for(i=0; E!=0; i++, E >>=1){
|
||||
if( E & 1 ) r *= x[i];
|
||||
}
|
||||
return r;
|
||||
#else
|
||||
LONGDOUBLE_TYPE x = 10.0;
|
||||
LONGDOUBLE_TYPE r = 1.0;
|
||||
while(1){
|
||||
@@ -336,6 +356,7 @@ static LONGDOUBLE_TYPE sqlite3Pow10(int E){
|
||||
x *= x;
|
||||
}
|
||||
return r;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -574,7 +595,7 @@ static int compare2pow63(const char *zNum, int incr){
|
||||
** Returns:
|
||||
**
|
||||
** 0 Successful transformation. Fits in a 64-bit signed integer.
|
||||
** 1 Excess text after the integer value
|
||||
** 1 Excess non-space text after the integer value
|
||||
** 2 Integer too large for a 64-bit signed integer or is malformed
|
||||
** 3 Special case of 9223372036854775808
|
||||
**
|
||||
@@ -617,47 +638,57 @@ int sqlite3Atoi64(const char *zNum, i64 *pNum, int length, u8 enc){
|
||||
for(i=0; &zNum[i]<zEnd && (c=zNum[i])>='0' && c<='9'; i+=incr){
|
||||
u = u*10 + c - '0';
|
||||
}
|
||||
testcase( i==18*incr );
|
||||
testcase( i==19*incr );
|
||||
testcase( i==20*incr );
|
||||
if( u>LARGEST_INT64 ){
|
||||
/* This test and assignment is needed only to suppress UB warnings
|
||||
** from clang and -fsanitize=undefined. This test and assignment make
|
||||
** the code a little larger and slower, and no harm comes from omitting
|
||||
** them, but we must appaise the undefined-behavior pharisees. */
|
||||
*pNum = neg ? SMALLEST_INT64 : LARGEST_INT64;
|
||||
}else if( neg ){
|
||||
*pNum = -(i64)u;
|
||||
}else{
|
||||
*pNum = (i64)u;
|
||||
}
|
||||
testcase( i==18 );
|
||||
testcase( i==19 );
|
||||
testcase( i==20 );
|
||||
if( &zNum[i]<zEnd /* Extra bytes at the end */
|
||||
|| (i==0 && zStart==zNum) /* No digits */
|
||||
rc = 0;
|
||||
if( (i==0 && zStart==zNum) /* No digits */
|
||||
|| nonNum /* UTF16 with high-order bytes non-zero */
|
||||
){
|
||||
rc = 1;
|
||||
}else{
|
||||
rc = 0;
|
||||
}else if( &zNum[i]<zEnd ){ /* Extra bytes at the end */
|
||||
int jj = i;
|
||||
do{
|
||||
if( !sqlite3Isspace(zNum[jj]) ){
|
||||
rc = 1; /* Extra non-space text after the integer */
|
||||
break;
|
||||
}
|
||||
jj += incr;
|
||||
}while( &zNum[jj]<zEnd );
|
||||
}
|
||||
if( i>19*incr ){ /* Too many digits */
|
||||
/* zNum is empty or contains non-numeric text or is longer
|
||||
** than 19 digits (thus guaranteeing that it is too large) */
|
||||
return 2;
|
||||
}else if( i<19*incr ){
|
||||
if( i<19*incr ){
|
||||
/* Less than 19 digits, so we know that it fits in 64 bits */
|
||||
assert( u<=LARGEST_INT64 );
|
||||
return rc;
|
||||
}else{
|
||||
/* zNum is a 19-digit numbers. Compare it against 9223372036854775808. */
|
||||
c = compare2pow63(zNum, incr);
|
||||
c = i>19*incr ? 1 : compare2pow63(zNum, incr);
|
||||
if( c<0 ){
|
||||
/* zNum is less than 9223372036854775808 so it fits */
|
||||
assert( u<=LARGEST_INT64 );
|
||||
return rc;
|
||||
}else if( c>0 ){
|
||||
/* zNum is greater than 9223372036854775808 so it overflows */
|
||||
return 2;
|
||||
}else{
|
||||
/* zNum is exactly 9223372036854775808. Fits if negative. The
|
||||
** special case 2 overflow if positive */
|
||||
assert( u-1==LARGEST_INT64 );
|
||||
return neg ? rc : 3;
|
||||
*pNum = neg ? SMALLEST_INT64 : LARGEST_INT64;
|
||||
if( c>0 ){
|
||||
/* zNum is greater than 9223372036854775808 so it overflows */
|
||||
return 2;
|
||||
}else{
|
||||
/* zNum is exactly 9223372036854775808. Fits if negative. The
|
||||
** special case 2 overflow if positive */
|
||||
assert( u-1==LARGEST_INT64 );
|
||||
return neg ? rc : 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -39,8 +39,8 @@ static int execSql(sqlite3 *db, char **pzErrMsg, const char *zSql){
|
||||
while( SQLITE_ROW==(rc = sqlite3_step(pStmt)) ){
|
||||
const char *zSubSql = (const char*)sqlite3_column_text(pStmt,0);
|
||||
assert( sqlite3_strnicmp(zSql,"SELECT",6)==0 );
|
||||
if( zSubSql ){
|
||||
assert( zSubSql[0]!='S' );
|
||||
assert( sqlite3_strnicmp(zSubSql,"SELECT",6)!=0 || CORRUPT_DB );
|
||||
if( zSubSql && zSubSql[0]!='S' ){
|
||||
rc = execSql(db, pzErrMsg, zSubSql);
|
||||
if( rc!=SQLITE_OK ) break;
|
||||
}
|
||||
|
||||
+123
-74
@@ -264,6 +264,11 @@ static void applyNumericAffinity(Mem *pRec, int bTryForInt){
|
||||
pRec->flags |= MEM_Real;
|
||||
if( bTryForInt ) sqlite3VdbeIntegerAffinity(pRec);
|
||||
}
|
||||
/* TEXT->NUMERIC is many->one. Hence, it is important to invalidate the
|
||||
** string representation after computing a numeric equivalent, because the
|
||||
** string representation might not be the canonical representation for the
|
||||
** numeric value. Ticket [343634942dd54ab57b7024] 2018-01-31. */
|
||||
pRec->flags &= ~MEM_Str;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -464,7 +469,7 @@ static void memTracePrint(Mem *p){
|
||||
if( p->flags & MEM_Undefined ){
|
||||
printf(" undefined");
|
||||
}else if( p->flags & MEM_Null ){
|
||||
printf(" NULL");
|
||||
printf(p->flags & MEM_Zero ? " NULL-nochng" : " NULL");
|
||||
}else if( (p->flags & (MEM_Int|MEM_Str))==(MEM_Int|MEM_Str) ){
|
||||
printf(" si:%lld", p->u.i);
|
||||
}else if( p->flags & MEM_Int ){
|
||||
@@ -643,7 +648,7 @@ int sqlite3VdbeExec(
|
||||
|
||||
assert( pOp>=aOp && pOp<&aOp[p->nOp]);
|
||||
#ifdef VDBE_PROFILE
|
||||
start = sqlite3Hwtime();
|
||||
start = sqlite3NProfileCnt ? sqlite3NProfileCnt : sqlite3Hwtime();
|
||||
#endif
|
||||
nVmStep++;
|
||||
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
|
||||
@@ -2167,18 +2172,8 @@ case OP_Or: { /* same as TK_OR, in1, in2, out3 */
|
||||
int v1; /* Left operand: 0==FALSE, 1==TRUE, 2==UNKNOWN or NULL */
|
||||
int v2; /* Right operand: 0==FALSE, 1==TRUE, 2==UNKNOWN or NULL */
|
||||
|
||||
pIn1 = &aMem[pOp->p1];
|
||||
if( pIn1->flags & MEM_Null ){
|
||||
v1 = 2;
|
||||
}else{
|
||||
v1 = sqlite3VdbeIntValue(pIn1)!=0;
|
||||
}
|
||||
pIn2 = &aMem[pOp->p2];
|
||||
if( pIn2->flags & MEM_Null ){
|
||||
v2 = 2;
|
||||
}else{
|
||||
v2 = sqlite3VdbeIntValue(pIn2)!=0;
|
||||
}
|
||||
v1 = sqlite3VdbeBooleanValue(&aMem[pOp->p1], 2);
|
||||
v2 = sqlite3VdbeBooleanValue(&aMem[pOp->p2], 2);
|
||||
if( pOp->opcode==OP_And ){
|
||||
static const unsigned char and_logic[] = { 0, 0, 0, 0, 1, 2, 0, 2, 2 };
|
||||
v1 = and_logic[v1*3+v2];
|
||||
@@ -2196,6 +2191,35 @@ case OP_Or: { /* same as TK_OR, in1, in2, out3 */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Opcode: IsTrue P1 P2 P3 P4 *
|
||||
** Synopsis: r[P2] = coalesce(r[P1]==TRUE,P3) ^ P4
|
||||
**
|
||||
** This opcode implements the IS TRUE, IS FALSE, IS NOT TRUE, and
|
||||
** IS NOT FALSE operators.
|
||||
**
|
||||
** Interpret the value in register P1 as a boolean value. Store that
|
||||
** boolean (a 0 or 1) in register P2. Or if the value in register P1 is
|
||||
** NULL, then the P3 is stored in register P2. Invert the answer if P4
|
||||
** is 1.
|
||||
**
|
||||
** The logic is summarized like this:
|
||||
**
|
||||
** <ul>
|
||||
** <li> If P3==0 and P4==0 then r[P2] := r[P1] IS TRUE
|
||||
** <li> If P3==1 and P4==1 then r[P2] := r[P1] IS FALSE
|
||||
** <li> If P3==0 and P4==1 then r[P2] := r[P1] IS NOT TRUE
|
||||
** <li> If P3==1 and P4==0 then r[P2] := r[P1] IS NOT FALSE
|
||||
** </ul>
|
||||
*/
|
||||
case OP_IsTrue: { /* in1, out2 */
|
||||
assert( pOp->p4type==P4_INT32 );
|
||||
assert( pOp->p4.i==0 || pOp->p4.i==1 );
|
||||
assert( pOp->p3==0 || pOp->p3==1 );
|
||||
sqlite3VdbeMemSetInt64(&aMem[pOp->p2],
|
||||
sqlite3VdbeBooleanValue(&aMem[pOp->p1], pOp->p3) ^ pOp->p4.i);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Opcode: Not P1 P2 * * *
|
||||
** Synopsis: r[P2]= !r[P1]
|
||||
**
|
||||
@@ -2206,10 +2230,10 @@ case OP_Or: { /* same as TK_OR, in1, in2, out3 */
|
||||
case OP_Not: { /* same as TK_NOT, in1, out2 */
|
||||
pIn1 = &aMem[pOp->p1];
|
||||
pOut = &aMem[pOp->p2];
|
||||
sqlite3VdbeMemSetNull(pOut);
|
||||
if( (pIn1->flags & MEM_Null)==0 ){
|
||||
pOut->flags = MEM_Int;
|
||||
pOut->u.i = !sqlite3VdbeIntValue(pIn1);
|
||||
sqlite3VdbeMemSetInt64(pOut, !sqlite3VdbeBooleanValue(pIn1,0));
|
||||
}else{
|
||||
sqlite3VdbeMemSetNull(pOut);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -2276,30 +2300,25 @@ case OP_Once: { /* jump */
|
||||
** is considered true if it is numeric and non-zero. If the value
|
||||
** in P1 is NULL then take the jump if and only if P3 is non-zero.
|
||||
*/
|
||||
case OP_If: { /* jump, in1 */
|
||||
int c;
|
||||
c = sqlite3VdbeBooleanValue(&aMem[pOp->p1], pOp->p3);
|
||||
VdbeBranchTaken(c!=0, 2);
|
||||
if( c ) goto jump_to_p2;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Opcode: IfNot P1 P2 P3 * *
|
||||
**
|
||||
** Jump to P2 if the value in register P1 is False. The value
|
||||
** is considered false if it has a numeric value of zero. If the value
|
||||
** in P1 is NULL then take the jump if and only if P3 is non-zero.
|
||||
*/
|
||||
case OP_If: /* jump, in1 */
|
||||
case OP_IfNot: { /* jump, in1 */
|
||||
int c;
|
||||
pIn1 = &aMem[pOp->p1];
|
||||
if( pIn1->flags & MEM_Null ){
|
||||
c = pOp->p3;
|
||||
}else{
|
||||
#ifdef SQLITE_OMIT_FLOATING_POINT
|
||||
c = sqlite3VdbeIntValue(pIn1)!=0;
|
||||
#else
|
||||
c = sqlite3VdbeRealValue(pIn1)!=0.0;
|
||||
#endif
|
||||
if( pOp->opcode==OP_IfNot ) c = !c;
|
||||
}
|
||||
c = !sqlite3VdbeBooleanValue(&aMem[pOp->p1], !pOp->p3);
|
||||
VdbeBranchTaken(c!=0, 2);
|
||||
if( c ){
|
||||
goto jump_to_p2;
|
||||
}
|
||||
if( c ) goto jump_to_p2;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -2360,7 +2379,7 @@ case OP_IfNullRow: { /* jump */
|
||||
** P2 is the column number for the argument to the sqlite_offset() function.
|
||||
** This opcode does not use P2 itself, but the P2 value is used by the
|
||||
** code generator. The P1, P2, and P3 operands to this opcode are the
|
||||
** as as for OP_Column.
|
||||
** same as for OP_Column.
|
||||
**
|
||||
** This opcode is only available if SQLite is compiled with the
|
||||
** -DSQLITE_ENABLE_OFFSET_SQL_FUNC option.
|
||||
@@ -2792,9 +2811,18 @@ case OP_MakeRecord: {
|
||||
pRec = pLast;
|
||||
do{
|
||||
assert( memIsValid(pRec) );
|
||||
pRec->uTemp = serial_type = sqlite3VdbeSerialType(pRec, file_format, &len);
|
||||
serial_type = sqlite3VdbeSerialType(pRec, file_format, &len);
|
||||
if( pRec->flags & MEM_Zero ){
|
||||
if( nData ){
|
||||
if( serial_type==0 ){
|
||||
/* Values with MEM_Null and MEM_Zero are created by xColumn virtual
|
||||
** table methods that never invoke sqlite3_result_xxxxx() while
|
||||
** computing an unchanging column value in an UPDATE statement.
|
||||
** Give such values a special internal-use-only serial-type of 10
|
||||
** so that they can be passed through to xUpdate and have
|
||||
** a true sqlite3_value_nochange(). */
|
||||
assert( pOp->p5==OPFLAG_NOCHNG_MAGIC || CORRUPT_DB );
|
||||
serial_type = 10;
|
||||
}else if( nData ){
|
||||
if( sqlite3VdbeMemExpandBlob(pRec) ) goto no_mem;
|
||||
}else{
|
||||
nZero += pRec->u.nZero;
|
||||
@@ -2805,6 +2833,7 @@ case OP_MakeRecord: {
|
||||
testcase( serial_type==127 );
|
||||
testcase( serial_type==128 );
|
||||
nHdr += serial_type<=127 ? 1 : sqlite3VarintLen(serial_type);
|
||||
pRec->uTemp = serial_type;
|
||||
if( pRec==pData0 ) break;
|
||||
pRec--;
|
||||
}while(1);
|
||||
@@ -4415,10 +4444,8 @@ case OP_InsertInt: {
|
||||
int seekResult; /* Result of prior seek or 0 if no USESEEKRESULT flag */
|
||||
const char *zDb; /* database name - used by the update hook */
|
||||
Table *pTab; /* Table structure - used by update and pre-update hooks */
|
||||
int op; /* Opcode for update hook: SQLITE_UPDATE or SQLITE_INSERT */
|
||||
BtreePayload x; /* Payload to be inserted */
|
||||
|
||||
op = 0;
|
||||
pData = &aMem[pOp->p2];
|
||||
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
|
||||
assert( memIsValid(pData) );
|
||||
@@ -4446,19 +4473,21 @@ case OP_InsertInt: {
|
||||
zDb = db->aDb[pC->iDb].zDbSName;
|
||||
pTab = pOp->p4.pTab;
|
||||
assert( (pOp->p5 & OPFLAG_ISNOOP) || HasRowid(pTab) );
|
||||
op = ((pOp->p5 & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_INSERT);
|
||||
}else{
|
||||
pTab = 0; /* Not needed. Silence a compiler warning. */
|
||||
pTab = 0;
|
||||
zDb = 0; /* Not needed. Silence a compiler warning. */
|
||||
}
|
||||
|
||||
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
|
||||
/* Invoke the pre-update hook, if any */
|
||||
if( db->xPreUpdateCallback
|
||||
&& pOp->p4type==P4_TABLE
|
||||
&& !(pOp->p5 & OPFLAG_ISUPDATE)
|
||||
){
|
||||
sqlite3VdbePreUpdateHook(p, pC, SQLITE_INSERT, zDb, pTab, x.nKey, pOp->p2);
|
||||
if( pTab ){
|
||||
if( db->xPreUpdateCallback && !(pOp->p5 & OPFLAG_ISUPDATE) ){
|
||||
sqlite3VdbePreUpdateHook(p, pC, SQLITE_INSERT, zDb, pTab, x.nKey,pOp->p2);
|
||||
}
|
||||
if( db->xUpdateCallback==0 || pTab->aCol==0 ){
|
||||
/* Prevent post-update hook from running in cases when it should not */
|
||||
pTab = 0;
|
||||
}
|
||||
}
|
||||
if( pOp->p5 & OPFLAG_ISNOOP ) break;
|
||||
#endif
|
||||
@@ -4483,8 +4512,12 @@ case OP_InsertInt: {
|
||||
|
||||
/* Invoke the update-hook if required. */
|
||||
if( rc ) goto abort_due_to_error;
|
||||
if( db->xUpdateCallback && op ){
|
||||
db->xUpdateCallback(db->pUpdateArg, op, zDb, pTab->zName, x.nKey);
|
||||
if( pTab ){
|
||||
assert( db->xUpdateCallback!=0 );
|
||||
assert( pTab->aCol!=0 );
|
||||
db->xUpdateCallback(db->pUpdateArg,
|
||||
(pOp->p5 & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_INSERT,
|
||||
zDb, pTab->zName, x.nKey);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -6190,12 +6223,17 @@ case OP_AggStep0: {
|
||||
assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) );
|
||||
assert( n==0 || (pOp->p2>0 && pOp->p2+n<=(p->nMem+1 - p->nCursor)+1) );
|
||||
assert( pOp->p3<pOp->p2 || pOp->p3>=pOp->p2+n );
|
||||
pCtx = sqlite3DbMallocRawNN(db, sizeof(*pCtx) + (n-1)*sizeof(sqlite3_value*));
|
||||
pCtx = sqlite3DbMallocRawNN(db, n*sizeof(sqlite3_value*) +
|
||||
(sizeof(pCtx[0]) + sizeof(Mem) - sizeof(sqlite3_value*)));
|
||||
if( pCtx==0 ) goto no_mem;
|
||||
pCtx->pMem = 0;
|
||||
pCtx->pOut = (Mem*)&(pCtx->argv[n]);
|
||||
sqlite3VdbeMemInit(pCtx->pOut, db, MEM_Null);
|
||||
pCtx->pFunc = pOp->p4.pFunc;
|
||||
pCtx->iOp = (int)(pOp - aOp);
|
||||
pCtx->pVdbe = p;
|
||||
pCtx->skipFlag = 0;
|
||||
pCtx->isError = 0;
|
||||
pCtx->argc = n;
|
||||
pOp->p4type = P4_FUNCCTX;
|
||||
pOp->p4.pCtx = pCtx;
|
||||
@@ -6206,7 +6244,6 @@ case OP_AggStep: {
|
||||
int i;
|
||||
sqlite3_context *pCtx;
|
||||
Mem *pMem;
|
||||
Mem t;
|
||||
|
||||
assert( pOp->p4type==P4_FUNCCTX );
|
||||
pCtx = pOp->p4.pCtx;
|
||||
@@ -6229,26 +6266,28 @@ case OP_AggStep: {
|
||||
#endif
|
||||
|
||||
pMem->n++;
|
||||
sqlite3VdbeMemInit(&t, db, MEM_Null);
|
||||
pCtx->pOut = &t;
|
||||
pCtx->fErrorOrAux = 0;
|
||||
pCtx->skipFlag = 0;
|
||||
assert( pCtx->pOut->flags==MEM_Null );
|
||||
assert( pCtx->isError==0 );
|
||||
assert( pCtx->skipFlag==0 );
|
||||
(pCtx->pFunc->xSFunc)(pCtx,pCtx->argc,pCtx->argv); /* IMP: R-24505-23230 */
|
||||
if( pCtx->fErrorOrAux ){
|
||||
if( pCtx->isError ){
|
||||
sqlite3VdbeError(p, "%s", sqlite3_value_text(&t));
|
||||
if( pCtx->isError ){
|
||||
if( pCtx->isError>0 ){
|
||||
sqlite3VdbeError(p, "%s", sqlite3_value_text(pCtx->pOut));
|
||||
rc = pCtx->isError;
|
||||
}
|
||||
sqlite3VdbeMemRelease(&t);
|
||||
if( pCtx->skipFlag ){
|
||||
assert( pOp[-1].opcode==OP_CollSeq );
|
||||
i = pOp[-1].p1;
|
||||
if( i ) sqlite3VdbeMemSetInt64(&aMem[i], 1);
|
||||
pCtx->skipFlag = 0;
|
||||
}
|
||||
sqlite3VdbeMemRelease(pCtx->pOut);
|
||||
pCtx->pOut->flags = MEM_Null;
|
||||
pCtx->isError = 0;
|
||||
if( rc ) goto abort_due_to_error;
|
||||
}else{
|
||||
assert( t.flags==MEM_Null );
|
||||
}
|
||||
if( pCtx->skipFlag ){
|
||||
assert( pOp[-1].opcode==OP_CollSeq );
|
||||
i = pOp[-1].p1;
|
||||
if( i ) sqlite3VdbeMemSetInt64(&aMem[i], 1);
|
||||
}
|
||||
assert( pCtx->pOut->flags==MEM_Null );
|
||||
assert( pCtx->skipFlag==0 );
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -6693,15 +6732,15 @@ case OP_VFilter: { /* jump */
|
||||
#endif /* SQLITE_OMIT_VIRTUALTABLE */
|
||||
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
/* Opcode: VColumn P1 P2 P3 P4 *
|
||||
/* Opcode: VColumn P1 P2 P3 * P5
|
||||
** Synopsis: r[P3]=vcolumn(P2)
|
||||
**
|
||||
** Store in register P3 the value of the P2-th column of
|
||||
** the current row of the virtual-table of cursor P1.
|
||||
**
|
||||
** If the VColumn opcode is being used to fetch the value of
|
||||
** an unchanging column during an UPDATE operation, then the P4
|
||||
** value is 1. Otherwise, P4 is 0. The P4 value is returned
|
||||
** an unchanging column during an UPDATE operation, then the P5
|
||||
** value is 1. Otherwise, P5 is 0. The P5 value is returned
|
||||
** by sqlite3_vtab_nochange() routine can can be used
|
||||
** by virtual table implementations to return special "no-change"
|
||||
** marks which can be more efficient, depending on the virtual table.
|
||||
@@ -6726,11 +6765,17 @@ case OP_VColumn: {
|
||||
assert( pModule->xColumn );
|
||||
memset(&sContext, 0, sizeof(sContext));
|
||||
sContext.pOut = pDest;
|
||||
sContext.bVtabNoChng = pOp->p4.i!=0;
|
||||
MemSetTypeFlag(pDest, MEM_Null);
|
||||
if( pOp->p5 ){
|
||||
sqlite3VdbeMemSetNull(pDest);
|
||||
pDest->flags = MEM_Null|MEM_Zero;
|
||||
pDest->u.nZero = 0;
|
||||
}else{
|
||||
MemSetTypeFlag(pDest, MEM_Null);
|
||||
}
|
||||
rc = pModule->xColumn(pCur->uc.pVCur, &sContext, pOp->p2);
|
||||
sqlite3VtabImportErrmsg(p, pVtab);
|
||||
if( sContext.isError ){
|
||||
if( sContext.isError>0 ){
|
||||
sqlite3VdbeError(p, "%s", sqlite3_value_text(pDest));
|
||||
rc = sContext.isError;
|
||||
}
|
||||
sqlite3VdbeChangeEncoding(pDest, encoding);
|
||||
@@ -6995,6 +7040,7 @@ case OP_Function0: {
|
||||
pCtx->pFunc = pOp->p4.pFunc;
|
||||
pCtx->iOp = (int)(pOp - aOp);
|
||||
pCtx->pVdbe = p;
|
||||
pCtx->isError = 0;
|
||||
pCtx->argc = n;
|
||||
pOp->p4type = P4_FUNCCTX;
|
||||
pOp->p4.pCtx = pCtx;
|
||||
@@ -7029,16 +7075,17 @@ case OP_Function: {
|
||||
}
|
||||
#endif
|
||||
MemSetTypeFlag(pOut, MEM_Null);
|
||||
pCtx->fErrorOrAux = 0;
|
||||
assert( pCtx->isError==0 );
|
||||
(*pCtx->pFunc->xSFunc)(pCtx, pCtx->argc, pCtx->argv);/* IMP: R-24505-23230 */
|
||||
|
||||
/* If the function returned an error, throw an exception */
|
||||
if( pCtx->fErrorOrAux ){
|
||||
if( pCtx->isError ){
|
||||
if( pCtx->isError ){
|
||||
if( pCtx->isError>0 ){
|
||||
sqlite3VdbeError(p, "%s", sqlite3_value_text(pOut));
|
||||
rc = pCtx->isError;
|
||||
}
|
||||
sqlite3VdbeDeleteAuxData(db, &p->pAuxData, pCtx->iOp, pOp->p1);
|
||||
pCtx->isError = 0;
|
||||
if( rc ) goto abort_due_to_error;
|
||||
}
|
||||
|
||||
@@ -7080,8 +7127,10 @@ case OP_Function: {
|
||||
*/
|
||||
case OP_Trace:
|
||||
case OP_Init: { /* jump */
|
||||
char *zTrace;
|
||||
int i;
|
||||
#ifndef SQLITE_OMIT_TRACE
|
||||
char *zTrace;
|
||||
#endif
|
||||
|
||||
/* If the P4 argument is not NULL, then it must be an SQL comment string.
|
||||
** The "--" string is broken up to prevent false-positives with srcck1.c.
|
||||
@@ -7198,7 +7247,7 @@ default: { /* This is really OP_Noop and OP_Explain */
|
||||
|
||||
#ifdef VDBE_PROFILE
|
||||
{
|
||||
u64 endTime = sqlite3Hwtime();
|
||||
u64 endTime = sqlite3NProfileCnt ? sqlite3NProfileCnt : sqlite3Hwtime();
|
||||
if( endTime>start ) pOrigOp->cycles += endTime - start;
|
||||
pOrigOp->cnt++;
|
||||
}
|
||||
|
||||
@@ -127,6 +127,7 @@ typedef struct VdbeOpList VdbeOpList;
|
||||
#define P4_INT64 (-14) /* P4 is a 64-bit signed integer */
|
||||
#define P4_INTARRAY (-15) /* P4 is a vector of 32-bit integers */
|
||||
#define P4_FUNCCTX (-16) /* P4 is a pointer to an sqlite3_context object */
|
||||
#define P4_DYNBLOB (-17) /* Pointer to memory from sqliteMalloc() */
|
||||
|
||||
/* Error message codes for OP_Halt */
|
||||
#define P5_ConstraintNotNull 1
|
||||
|
||||
+1
-2
@@ -317,8 +317,6 @@ struct sqlite3_context {
|
||||
int iOp; /* Instruction number of OP_Function */
|
||||
int isError; /* Error code returned by the function. */
|
||||
u8 skipFlag; /* Skip accumulator loading if true */
|
||||
u8 fErrorOrAux; /* isError!=0 or pVdbe->pAuxData modified */
|
||||
u8 bVtabNoChng; /* Fetching an unchanging column in a vtab UPDATE */
|
||||
u8 argc; /* Number of arguments */
|
||||
sqlite3_value *argv[1]; /* Argument set */
|
||||
};
|
||||
@@ -488,6 +486,7 @@ int sqlite3VdbeMemStringify(Mem*, u8, u8);
|
||||
i64 sqlite3VdbeIntValue(Mem*);
|
||||
int sqlite3VdbeMemIntegerify(Mem*);
|
||||
double sqlite3VdbeRealValue(Mem*);
|
||||
int sqlite3VdbeBooleanValue(Mem*, int ifNull);
|
||||
void sqlite3VdbeIntegerAffinity(Mem*);
|
||||
int sqlite3VdbeMemRealify(Mem*);
|
||||
int sqlite3VdbeMemNumerify(Mem*);
|
||||
|
||||
+11
-12
@@ -268,6 +268,11 @@ int sqlite3_value_type(sqlite3_value* pVal){
|
||||
return aType[pVal->flags&MEM_AffMask];
|
||||
}
|
||||
|
||||
/* Return true if a parameter to xUpdate represents an unchanged column */
|
||||
int sqlite3_value_nochange(sqlite3_value *pVal){
|
||||
return (pVal->flags&(MEM_Null|MEM_Zero))==(MEM_Null|MEM_Zero);
|
||||
}
|
||||
|
||||
/* Make a copy of an sqlite3_value object
|
||||
*/
|
||||
sqlite3_value *sqlite3_value_dup(const sqlite3_value *pOrig){
|
||||
@@ -367,14 +372,12 @@ void sqlite3_result_double(sqlite3_context *pCtx, double rVal){
|
||||
void sqlite3_result_error(sqlite3_context *pCtx, const char *z, int n){
|
||||
assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
|
||||
pCtx->isError = SQLITE_ERROR;
|
||||
pCtx->fErrorOrAux = 1;
|
||||
sqlite3VdbeMemSetStr(pCtx->pOut, z, n, SQLITE_UTF8, SQLITE_TRANSIENT);
|
||||
}
|
||||
#ifndef SQLITE_OMIT_UTF16
|
||||
void sqlite3_result_error16(sqlite3_context *pCtx, const void *z, int n){
|
||||
assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
|
||||
pCtx->isError = SQLITE_ERROR;
|
||||
pCtx->fErrorOrAux = 1;
|
||||
sqlite3VdbeMemSetStr(pCtx->pOut, z, n, SQLITE_UTF16NATIVE, SQLITE_TRANSIENT);
|
||||
}
|
||||
#endif
|
||||
@@ -480,8 +483,7 @@ int sqlite3_result_zeroblob64(sqlite3_context *pCtx, u64 n){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
void sqlite3_result_error_code(sqlite3_context *pCtx, int errCode){
|
||||
pCtx->isError = errCode;
|
||||
pCtx->fErrorOrAux = 1;
|
||||
pCtx->isError = errCode ? errCode : -1;
|
||||
#ifdef SQLITE_DEBUG
|
||||
if( pCtx->pVdbe ) pCtx->pVdbe->rcApp = errCode;
|
||||
#endif
|
||||
@@ -495,7 +497,6 @@ void sqlite3_result_error_code(sqlite3_context *pCtx, int errCode){
|
||||
void sqlite3_result_error_toobig(sqlite3_context *pCtx){
|
||||
assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
|
||||
pCtx->isError = SQLITE_TOOBIG;
|
||||
pCtx->fErrorOrAux = 1;
|
||||
sqlite3VdbeMemSetStr(pCtx->pOut, "string or blob too big", -1,
|
||||
SQLITE_UTF8, SQLITE_STATIC);
|
||||
}
|
||||
@@ -505,7 +506,6 @@ void sqlite3_result_error_nomem(sqlite3_context *pCtx){
|
||||
assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
|
||||
sqlite3VdbeMemSetNull(pCtx->pOut);
|
||||
pCtx->isError = SQLITE_NOMEM_BKPT;
|
||||
pCtx->fErrorOrAux = 1;
|
||||
sqlite3OomFault(pCtx->pOut->db);
|
||||
}
|
||||
|
||||
@@ -761,7 +761,7 @@ sqlite3 *sqlite3_context_db_handle(sqlite3_context *p){
|
||||
*/
|
||||
int sqlite3_vtab_nochange(sqlite3_context *p){
|
||||
assert( p );
|
||||
return p->bVtabNoChng;
|
||||
return sqlite3_value_nochange(p->pOut);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -912,10 +912,7 @@ void sqlite3_set_auxdata(
|
||||
pAuxData->iAuxArg = iArg;
|
||||
pAuxData->pNextAux = pVdbe->pAuxData;
|
||||
pVdbe->pAuxData = pAuxData;
|
||||
if( pCtx->fErrorOrAux==0 ){
|
||||
pCtx->isError = 0;
|
||||
pCtx->fErrorOrAux = 1;
|
||||
}
|
||||
if( pCtx->isError==0 ) pCtx->isError = -1;
|
||||
}else if( pAuxData->xDeleteAux ){
|
||||
pAuxData->xDeleteAux(pAuxData->pAux);
|
||||
}
|
||||
@@ -1671,7 +1668,9 @@ int sqlite3_stmt_status(sqlite3_stmt *pStmt, int op, int resetFlag){
|
||||
Vdbe *pVdbe = (Vdbe*)pStmt;
|
||||
u32 v;
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( !pStmt ){
|
||||
if( !pStmt
|
||||
|| (op!=SQLITE_STMTSTATUS_MEMUSED && (op<0||op>=ArraySize(pVdbe->aCounter)))
|
||||
){
|
||||
(void)SQLITE_MISUSE_BKPT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
+9
-1
@@ -866,6 +866,7 @@ static void freeP4(sqlite3 *db, int p4type, void *p4){
|
||||
case P4_REAL:
|
||||
case P4_INT64:
|
||||
case P4_DYNAMIC:
|
||||
case P4_DYNBLOB:
|
||||
case P4_INTARRAY: {
|
||||
sqlite3DbFree(db, p4);
|
||||
break;
|
||||
@@ -1407,6 +1408,7 @@ static char *displayP4(Op *pOp, char *zTemp, int nTemp){
|
||||
sqlite3XPrintf(&x, "program");
|
||||
break;
|
||||
}
|
||||
case P4_DYNBLOB:
|
||||
case P4_ADVANCE: {
|
||||
zTemp[0] = 0;
|
||||
break;
|
||||
@@ -3452,7 +3454,13 @@ u32 sqlite3VdbeSerialGet(
|
||||
Mem *pMem /* Memory cell to write value into */
|
||||
){
|
||||
switch( serial_type ){
|
||||
case 10: /* Reserved for future use */
|
||||
case 10: { /* Internal use only: NULL with virtual table
|
||||
** UPDATE no-change flag set */
|
||||
pMem->flags = MEM_Null|MEM_Zero;
|
||||
pMem->n = 0;
|
||||
pMem->u.nZero = 0;
|
||||
break;
|
||||
}
|
||||
case 11: /* Reserved for future use */
|
||||
case 0: { /* Null */
|
||||
/* EVIDENCE-OF: R-24078-09375 Value is a NULL. */
|
||||
|
||||
+71
-2
@@ -43,7 +43,7 @@ int sqlite3VdbeCheckMemInvariants(Mem *p){
|
||||
if( p->flags & MEM_Null ){
|
||||
/* Cannot be both MEM_Null and some other type */
|
||||
assert( (p->flags & (MEM_Int|MEM_Real|MEM_Str|MEM_Blob
|
||||
|MEM_RowSet|MEM_Frame|MEM_Agg|MEM_Zero))==0 );
|
||||
|MEM_RowSet|MEM_Frame|MEM_Agg))==0 );
|
||||
|
||||
/* If MEM_Null is set, then either the value is a pure NULL (the usual
|
||||
** case) or it is a pointer set using sqlite3_bind_pointer() or
|
||||
@@ -93,6 +93,51 @@ int sqlite3VdbeCheckMemInvariants(Mem *p){
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_DEBUG
|
||||
/*
|
||||
** Check that string value of pMem agrees with its integer or real value.
|
||||
**
|
||||
** A single int or real value always converts to the same strings. But
|
||||
** many different strings can be converted into the same int or real.
|
||||
** If a table contains a numeric value and an index is based on the
|
||||
** corresponding string value, then it is important that the string be
|
||||
** derived from the numeric value, not the other way around, to ensure
|
||||
** that the index and table are consistent. See ticket
|
||||
** https://www.sqlite.org/src/info/343634942dd54ab (2018-01-31) for
|
||||
** an example.
|
||||
**
|
||||
** This routine looks at pMem to verify that if it has both a numeric
|
||||
** representation and a string representation then the string rep has
|
||||
** been derived from the numeric and not the other way around. It returns
|
||||
** true if everything is ok and false if there is a problem.
|
||||
**
|
||||
** This routine is for use inside of assert() statements only.
|
||||
*/
|
||||
int sqlite3VdbeMemConsistentDualRep(Mem *p){
|
||||
char zBuf[100];
|
||||
char *z;
|
||||
int i, j, incr;
|
||||
if( (p->flags & MEM_Str)==0 ) return 1;
|
||||
if( (p->flags & (MEM_Int|MEM_Real))==0 ) return 1;
|
||||
if( p->flags & MEM_Int ){
|
||||
sqlite3_snprintf(sizeof(zBuf),zBuf,"%lld",p->u.i);
|
||||
}else{
|
||||
sqlite3_snprintf(sizeof(zBuf),zBuf,"%!.15g",p->u.r);
|
||||
}
|
||||
z = p->z;
|
||||
i = j = 0;
|
||||
incr = 1;
|
||||
if( p->enc!=SQLITE_UTF8 ){
|
||||
incr = 2;
|
||||
if( p->enc==SQLITE_UTF16BE ) z++;
|
||||
}
|
||||
while( zBuf[j] ){
|
||||
if( zBuf[j++]!=z[i] ) return 0;
|
||||
i += incr;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
#endif /* SQLITE_DEBUG */
|
||||
|
||||
/*
|
||||
** If pMem is an object with a valid string representation, this routine
|
||||
@@ -527,6 +572,16 @@ double sqlite3VdbeRealValue(Mem *pMem){
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Return 1 if pMem represents true, and return 0 if pMem represents false.
|
||||
** Return the value ifNull if pMem is NULL.
|
||||
*/
|
||||
int sqlite3VdbeBooleanValue(Mem *pMem, int ifNull){
|
||||
if( pMem->flags & MEM_Int ) return pMem->u.i!=0;
|
||||
if( pMem->flags & MEM_Null ) return ifNull;
|
||||
return sqlite3VdbeRealValue(pMem)!=0.0;
|
||||
}
|
||||
|
||||
/*
|
||||
** The MEM structure is already a MEM_Real. Try to also make it a
|
||||
** MEM_Int if we can.
|
||||
@@ -582,6 +637,18 @@ int sqlite3VdbeMemRealify(Mem *pMem){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/* Compare a floating point value to an integer. Return true if the two
|
||||
** values are the same within the precision of the floating point value.
|
||||
**
|
||||
** For some versions of GCC on 32-bit machines, if you do the more obvious
|
||||
** comparison of "r1==(double)i" you sometimes get an answer of false even
|
||||
** though the r1 and (double)i values are bit-for-bit the same.
|
||||
*/
|
||||
static int sqlite3RealSameAsInt(double r1, sqlite3_int64 i){
|
||||
double r2 = (double)i;
|
||||
return memcmp(&r1, &r2, sizeof(r1))==0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Convert pMem so that it has types MEM_Real or MEM_Int or both.
|
||||
** Invalidate any prior representations.
|
||||
@@ -601,7 +668,7 @@ int sqlite3VdbeMemNumerify(Mem *pMem){
|
||||
}else{
|
||||
i64 i = pMem->u.i;
|
||||
sqlite3AtoF(pMem->z, &pMem->u.r, pMem->n, pMem->enc);
|
||||
if( rc==1 && pMem->u.r==(double)i ){
|
||||
if( rc==1 && sqlite3RealSameAsInt(pMem->u.r, i) ){
|
||||
pMem->u.i = i;
|
||||
MemSetTypeFlag(pMem, MEM_Int);
|
||||
}else{
|
||||
@@ -1084,6 +1151,7 @@ static SQLITE_NOINLINE const void *valueToText(sqlite3_value* pVal, u8 enc){
|
||||
assert(pVal->enc==(enc & ~SQLITE_UTF16_ALIGNED) || pVal->db==0
|
||||
|| pVal->db->mallocFailed );
|
||||
if( pVal->enc==(enc & ~SQLITE_UTF16_ALIGNED) ){
|
||||
assert( sqlite3VdbeMemConsistentDualRep(pVal) );
|
||||
return pVal->z;
|
||||
}else{
|
||||
return 0;
|
||||
@@ -1106,6 +1174,7 @@ const void *sqlite3ValueText(sqlite3_value* pVal, u8 enc){
|
||||
assert( (enc&3)==(enc&~SQLITE_UTF16_ALIGNED) );
|
||||
assert( (pVal->flags & MEM_RowSet)==0 );
|
||||
if( (pVal->flags&(MEM_Str|MEM_Term))==(MEM_Str|MEM_Term) && pVal->enc==enc ){
|
||||
assert( sqlite3VdbeMemConsistentDualRep(pVal) );
|
||||
return pVal->z;
|
||||
}
|
||||
if( pVal->flags&MEM_Null ){
|
||||
|
||||
@@ -554,7 +554,11 @@ struct WalIterator {
|
||||
** page and SQLITE_OK is returned. If an error (an OOM or VFS error) occurs,
|
||||
** then an SQLite error code is returned and *ppPage is set to 0.
|
||||
*/
|
||||
static int walIndexPage(Wal *pWal, int iPage, volatile u32 **ppPage){
|
||||
static SQLITE_NOINLINE int walIndexPageRealloc(
|
||||
Wal *pWal, /* The WAL context */
|
||||
int iPage, /* The page we seek */
|
||||
volatile u32 **ppPage /* Write the page pointer here */
|
||||
){
|
||||
int rc = SQLITE_OK;
|
||||
|
||||
/* Enlarge the pWal->apWiData[] array if required */
|
||||
@@ -573,21 +577,20 @@ static int walIndexPage(Wal *pWal, int iPage, volatile u32 **ppPage){
|
||||
}
|
||||
|
||||
/* Request a pointer to the required page from the VFS */
|
||||
if( pWal->apWiData[iPage]==0 ){
|
||||
if( pWal->exclusiveMode==WAL_HEAPMEMORY_MODE ){
|
||||
pWal->apWiData[iPage] = (u32 volatile *)sqlite3MallocZero(WALINDEX_PGSZ);
|
||||
if( !pWal->apWiData[iPage] ) rc = SQLITE_NOMEM_BKPT;
|
||||
}else{
|
||||
rc = sqlite3OsShmMap(pWal->pDbFd, iPage, WALINDEX_PGSZ,
|
||||
pWal->writeLock, (void volatile **)&pWal->apWiData[iPage]
|
||||
);
|
||||
assert( pWal->apWiData[iPage]!=0 || rc!=SQLITE_OK || pWal->writeLock==0 );
|
||||
testcase( pWal->apWiData[iPage]==0 && rc==SQLITE_OK );
|
||||
if( (rc&0xff)==SQLITE_READONLY ){
|
||||
pWal->readOnly |= WAL_SHM_RDONLY;
|
||||
if( rc==SQLITE_READONLY ){
|
||||
rc = SQLITE_OK;
|
||||
}
|
||||
assert( pWal->apWiData[iPage]==0 );
|
||||
if( pWal->exclusiveMode==WAL_HEAPMEMORY_MODE ){
|
||||
pWal->apWiData[iPage] = (u32 volatile *)sqlite3MallocZero(WALINDEX_PGSZ);
|
||||
if( !pWal->apWiData[iPage] ) rc = SQLITE_NOMEM_BKPT;
|
||||
}else{
|
||||
rc = sqlite3OsShmMap(pWal->pDbFd, iPage, WALINDEX_PGSZ,
|
||||
pWal->writeLock, (void volatile **)&pWal->apWiData[iPage]
|
||||
);
|
||||
assert( pWal->apWiData[iPage]!=0 || rc!=SQLITE_OK || pWal->writeLock==0 );
|
||||
testcase( pWal->apWiData[iPage]==0 && rc==SQLITE_OK );
|
||||
if( (rc&0xff)==SQLITE_READONLY ){
|
||||
pWal->readOnly |= WAL_SHM_RDONLY;
|
||||
if( rc==SQLITE_READONLY ){
|
||||
rc = SQLITE_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -596,6 +599,16 @@ static int walIndexPage(Wal *pWal, int iPage, volatile u32 **ppPage){
|
||||
assert( iPage==0 || *ppPage || rc!=SQLITE_OK );
|
||||
return rc;
|
||||
}
|
||||
static int walIndexPage(
|
||||
Wal *pWal, /* The WAL context */
|
||||
int iPage, /* The page we seek */
|
||||
volatile u32 **ppPage /* Write the page pointer here */
|
||||
){
|
||||
if( pWal->nWiData<=iPage || (*ppPage = pWal->apWiData[iPage])==0 ){
|
||||
return walIndexPageRealloc(pWal, iPage, ppPage);
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return a pointer to the WalCkptInfo structure in the wal-index.
|
||||
@@ -1572,8 +1585,9 @@ static void walIteratorFree(WalIterator *p){
|
||||
|
||||
/*
|
||||
** Construct a WalInterator object that can be used to loop over all
|
||||
** pages in the WAL in ascending order. The caller must hold the checkpoint
|
||||
** lock.
|
||||
** pages in the WAL following frame nBackfill in ascending order. Frames
|
||||
** nBackfill or earlier may be included - excluding them is an optimization
|
||||
** only. The caller must hold the checkpoint lock.
|
||||
**
|
||||
** On success, make *pp point to the newly allocated WalInterator object
|
||||
** return SQLITE_OK. Otherwise, return an error code. If this routine
|
||||
@@ -1582,7 +1596,7 @@ static void walIteratorFree(WalIterator *p){
|
||||
** The calling routine should invoke walIteratorFree() to destroy the
|
||||
** WalIterator object when it has finished with it.
|
||||
*/
|
||||
static int walIteratorInit(Wal *pWal, WalIterator **pp){
|
||||
static int walIteratorInit(Wal *pWal, u32 nBackfill, WalIterator **pp){
|
||||
WalIterator *p; /* Return value */
|
||||
int nSegment; /* Number of segments to merge */
|
||||
u32 iLast; /* Last frame in log */
|
||||
@@ -1619,7 +1633,7 @@ static int walIteratorInit(Wal *pWal, WalIterator **pp){
|
||||
rc = SQLITE_NOMEM_BKPT;
|
||||
}
|
||||
|
||||
for(i=0; rc==SQLITE_OK && i<nSegment; i++){
|
||||
for(i=walFramePage(nBackfill+1); rc==SQLITE_OK && i<nSegment; i++){
|
||||
volatile ht_slot *aHash;
|
||||
u32 iZero;
|
||||
volatile u32 *aPgno;
|
||||
@@ -1653,6 +1667,7 @@ static int walIteratorInit(Wal *pWal, WalIterator **pp){
|
||||
|
||||
if( rc!=SQLITE_OK ){
|
||||
walIteratorFree(p);
|
||||
p = 0;
|
||||
}
|
||||
*pp = p;
|
||||
return rc;
|
||||
@@ -1775,13 +1790,6 @@ static int walCheckpoint(
|
||||
pInfo = walCkptInfo(pWal);
|
||||
if( pInfo->nBackfill<pWal->hdr.mxFrame ){
|
||||
|
||||
/* Allocate the iterator */
|
||||
rc = walIteratorInit(pWal, &pIter);
|
||||
if( rc!=SQLITE_OK ){
|
||||
return rc;
|
||||
}
|
||||
assert( pIter );
|
||||
|
||||
/* EVIDENCE-OF: R-62920-47450 The busy-handler callback is never invoked
|
||||
** in the SQLITE_CHECKPOINT_PASSIVE mode. */
|
||||
assert( eMode!=SQLITE_CHECKPOINT_PASSIVE || xBusy==0 );
|
||||
@@ -1818,7 +1826,13 @@ static int walCheckpoint(
|
||||
}
|
||||
}
|
||||
|
||||
if( pInfo->nBackfill<mxSafeFrame
|
||||
/* Allocate the iterator */
|
||||
if( pInfo->nBackfill<mxSafeFrame ){
|
||||
rc = walIteratorInit(pWal, pInfo->nBackfill, &pIter);
|
||||
assert( rc==SQLITE_OK || pIter==0 );
|
||||
}
|
||||
|
||||
if( pIter
|
||||
&& (rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(0),1))==SQLITE_OK
|
||||
){
|
||||
i64 nSize; /* Current size of database file */
|
||||
@@ -2868,7 +2882,7 @@ int sqlite3WalFindFrame(
|
||||
** table after the current read-transaction had started.
|
||||
*/
|
||||
iMinHash = walFramePage(pWal->minFrame);
|
||||
for(iHash=walFramePage(iLast); iHash>=iMinHash && iRead==0; iHash--){
|
||||
for(iHash=walFramePage(iLast); iHash>=iMinHash; iHash--){
|
||||
volatile ht_slot *aHash; /* Pointer to hash table */
|
||||
volatile u32 *aPgno; /* Pointer to array of page numbers */
|
||||
u32 iZero; /* Frame number corresponding to aPgno[0] */
|
||||
@@ -2891,6 +2905,7 @@ int sqlite3WalFindFrame(
|
||||
return SQLITE_CORRUPT_BKPT;
|
||||
}
|
||||
}
|
||||
if( iRead ) break;
|
||||
}
|
||||
|
||||
#ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT
|
||||
|
||||
+27
-7
@@ -2481,10 +2481,12 @@ static int whereLoopAddBtreeIndex(
|
||||
if( iCol==XN_ROWID
|
||||
|| (iCol>=0 && nInMul==0 && saved_nEq==pProbe->nKeyCol-1)
|
||||
){
|
||||
if( iCol>=0 && pProbe->uniqNotNull==0 ){
|
||||
pNew->wsFlags |= WHERE_UNQ_WANTED;
|
||||
}else{
|
||||
if( iCol==XN_ROWID || pProbe->uniqNotNull
|
||||
|| (pProbe->nKeyCol==1 && pProbe->onError && eOp==WO_EQ)
|
||||
){
|
||||
pNew->wsFlags |= WHERE_ONEROW;
|
||||
}else{
|
||||
pNew->wsFlags |= WHERE_UNQ_WANTED;
|
||||
}
|
||||
}
|
||||
}else if( eOp & WO_ISNULL ){
|
||||
@@ -4631,6 +4633,7 @@ WhereInfo *sqlite3WhereBegin(
|
||||
*/
|
||||
for(ii=0; ii<sWLB.pWC->nTerm; ii++){
|
||||
WhereTerm *pT = &sWLB.pWC->a[ii];
|
||||
if( pT->wtFlags & TERM_VIRTUAL ) continue;
|
||||
if( pT->prereqAll==0 && (nTabList==0 || exprIsDeterministic(pT->pExpr)) ){
|
||||
sqlite3ExprIfFalse(pParse, pT->pExpr, pWInfo->iBreak, SQLITE_JUMPIFNULL);
|
||||
pT->wtFlags |= TERM_CODED;
|
||||
@@ -4801,15 +4804,32 @@ WhereInfo *sqlite3WhereBegin(
|
||||
|
||||
/* If the caller is an UPDATE or DELETE statement that is requesting
|
||||
** to use a one-pass algorithm, determine if this is appropriate.
|
||||
**
|
||||
** A one-pass approach can be used if the caller has requested one
|
||||
** and either (a) the scan visits at most one row or (b) each
|
||||
** of the following are true:
|
||||
**
|
||||
** * the caller has indicated that a one-pass approach can be used
|
||||
** with multiple rows (by setting WHERE_ONEPASS_MULTIROW), and
|
||||
** * the table is not a virtual table, and
|
||||
** * either the scan does not use the OR optimization or the caller
|
||||
** is a DELETE operation (WHERE_DUPLICATES_OK is only specified
|
||||
** for DELETE).
|
||||
**
|
||||
** The last qualification is because an UPDATE statement uses
|
||||
** WhereInfo.aiCurOnePass[1] to determine whether or not it really can
|
||||
** use a one-pass approach, and this is not set accurately for scans
|
||||
** that use the OR optimization.
|
||||
*/
|
||||
assert( (wctrlFlags & WHERE_ONEPASS_DESIRED)==0 || pWInfo->nLevel==1 );
|
||||
if( (wctrlFlags & WHERE_ONEPASS_DESIRED)!=0 ){
|
||||
int wsFlags = pWInfo->a[0].pWLoop->wsFlags;
|
||||
int bOnerow = (wsFlags & WHERE_ONEROW)!=0;
|
||||
if( bOnerow
|
||||
|| ((wctrlFlags & WHERE_ONEPASS_MULTIROW)!=0
|
||||
&& 0==(wsFlags & WHERE_VIRTUALTABLE))
|
||||
){
|
||||
if( bOnerow || (
|
||||
0!=(wctrlFlags & WHERE_ONEPASS_MULTIROW)
|
||||
&& 0==(wsFlags & WHERE_VIRTUALTABLE)
|
||||
&& (0==(wsFlags & WHERE_MULTI_OR) || (wctrlFlags & WHERE_DUPLICATES_OK))
|
||||
)){
|
||||
pWInfo->eOnePass = bOnerow ? ONEPASS_SINGLE : ONEPASS_MULTI;
|
||||
if( HasRowid(pTabList->a[0].pTab) && (wsFlags & WHERE_IDX_ONLY) ){
|
||||
if( wctrlFlags & WHERE_ONEPASS_MULTIROW ){
|
||||
|
||||
+15
-1
@@ -1395,7 +1395,15 @@ Bitmask sqlite3WhereCodeOneLoopStart(
|
||||
if( sqlite3ExprIsVector(pX->pRight) ){
|
||||
r1 = rTemp = sqlite3GetTempReg(pParse);
|
||||
codeExprOrVector(pParse, pX->pRight, r1, 1);
|
||||
op = aMoveOp[(pX->op - TK_GT) | 0x0001];
|
||||
testcase( pX->op==TK_GT );
|
||||
testcase( pX->op==TK_GE );
|
||||
testcase( pX->op==TK_LT );
|
||||
testcase( pX->op==TK_LE );
|
||||
op = aMoveOp[((pX->op - TK_GT - 1) & 0x3) | 0x1];
|
||||
assert( pX->op!=TK_GT || op==OP_SeekGE );
|
||||
assert( pX->op!=TK_GE || op==OP_SeekGE );
|
||||
assert( pX->op!=TK_LT || op==OP_SeekLE );
|
||||
assert( pX->op!=TK_LE || op==OP_SeekLE );
|
||||
}else{
|
||||
r1 = sqlite3ExprCodeTemp(pParse, pX->pRight, &rTemp);
|
||||
disableTerm(pLevel, pStart);
|
||||
@@ -2170,6 +2178,12 @@ Bitmask sqlite3WhereCodeOneLoopStart(
|
||||
WO_EQ|WO_IN|WO_IS, 0);
|
||||
if( pAlt==0 ) continue;
|
||||
if( pAlt->wtFlags & (TERM_CODED) ) continue;
|
||||
if( (pAlt->eOperator & WO_IN)
|
||||
&& (pAlt->pExpr->flags & EP_xIsSelect)
|
||||
&& (pAlt->pExpr->x.pSelect->pEList->nExpr>1)
|
||||
){
|
||||
continue;
|
||||
}
|
||||
testcase( pAlt->eOperator & WO_EQ );
|
||||
testcase( pAlt->eOperator & WO_IS );
|
||||
testcase( pAlt->eOperator & WO_IN );
|
||||
|
||||
+4
-1
@@ -876,6 +876,9 @@ static Bitmask exprSelectUsage(WhereMaskSet *pMaskSet, Select *pS){
|
||||
for(i=0; i<pSrc->nSrc; i++){
|
||||
mask |= exprSelectUsage(pMaskSet, pSrc->a[i].pSelect);
|
||||
mask |= sqlite3WhereExprUsage(pMaskSet, pSrc->a[i].pOn);
|
||||
if( pSrc->a[i].fg.isTabFunc ){
|
||||
mask |= sqlite3WhereExprListUsage(pMaskSet, pSrc->a[i].u1.pFuncArg);
|
||||
}
|
||||
}
|
||||
}
|
||||
pS = pS->pPrior;
|
||||
@@ -1288,7 +1291,7 @@ static void exprAnalyze(
|
||||
exprAnalyze(pSrc, pWC, idxNew);
|
||||
}
|
||||
pTerm = &pWC->a[idxTerm];
|
||||
pTerm->wtFlags = TERM_CODED|TERM_VIRTUAL; /* Disable the original */
|
||||
pTerm->wtFlags |= TERM_CODED|TERM_VIRTUAL; /* Disable the original */
|
||||
pTerm->eOperator = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -343,4 +343,49 @@ do_test cast-4.4 {
|
||||
}
|
||||
} {0 abc 0.0 abc}
|
||||
|
||||
# Added 2018-01-26
|
||||
#
|
||||
# EVIDENCE-OF: R-48741-32454 If the prefix integer is greater than
|
||||
# +9223372036854775807 then the result of the cast is exactly
|
||||
# +9223372036854775807.
|
||||
do_execsql_test cast-5.1 {
|
||||
SELECT CAST('9223372036854775808' AS integer);
|
||||
SELECT CAST(' +000009223372036854775808' AS integer);
|
||||
SELECT CAST('12345678901234567890123' AS INTEGER);
|
||||
} {9223372036854775807 9223372036854775807 9223372036854775807}
|
||||
|
||||
# EVIDENCE-OF: R-06028-16857 Similarly, if the prefix integer is less
|
||||
# than -9223372036854775808 then the result of the cast is exactly
|
||||
# -9223372036854775808.
|
||||
do_execsql_test cast-5.2 {
|
||||
SELECT CAST('-9223372036854775808' AS integer);
|
||||
SELECT CAST('-9223372036854775809' AS integer);
|
||||
SELECT CAST('-12345678901234567890123' AS INTEGER);
|
||||
} {-9223372036854775808 -9223372036854775808 -9223372036854775808}
|
||||
|
||||
# EVIDENCE-OF: R-33990-33527 When casting to INTEGER, if the text looks
|
||||
# like a floating point value with an exponent, the exponent will be
|
||||
# ignored because it is no part of the integer prefix.
|
||||
# EVIDENCE-OF: R-24225-46995 For example, "(CAST '123e+5' AS INTEGER)"
|
||||
# results in 123, not in 12300000.
|
||||
do_execsql_test case-5.3 {
|
||||
SELECT CAST('123e+5' AS INTEGER);
|
||||
SELECT CAST('123e+5' AS NUMERIC);
|
||||
} {123 12300000.0}
|
||||
|
||||
|
||||
# The following does not have anything to do with the CAST operator,
|
||||
# but it does deal with affinity transformations.
|
||||
#
|
||||
do_execsql_test case-6.1 {
|
||||
DROP TABLE IF EXISTS t1;
|
||||
CREATE TABLE t1(a NUMERIC);
|
||||
INSERT INTO t1 VALUES
|
||||
('9000000000000000001'),
|
||||
('9000000000000000001 '),
|
||||
(' 9000000000000000001'),
|
||||
(' 9000000000000000001 ');
|
||||
SELECT * FROM t1;
|
||||
} {9000000000000000001 9000000000000000001 9000000000000000001 9000000000000000001}
|
||||
|
||||
finish_test
|
||||
|
||||
+13
-3
@@ -142,6 +142,7 @@ proc write_file {zFile zData} {
|
||||
# b) Less than 512, or
|
||||
# c) Greater than SQLITE_MAX_PAGE_SIZE
|
||||
#
|
||||
if {[atomic_batch_write test.db]==0} {
|
||||
do_test crash8-3.1 {
|
||||
list [file exists test.db-joural] [file exists test.db]
|
||||
} {0 1}
|
||||
@@ -228,6 +229,7 @@ do_test crash8-3.11 {
|
||||
PRAGMA integrity_check
|
||||
}
|
||||
} {6 ok}
|
||||
}
|
||||
|
||||
|
||||
# If a connection running in persistent-journal mode is part of a
|
||||
@@ -266,8 +268,12 @@ ifcapable pragma {
|
||||
UPDATE aux.ab SET b = randstr(1000,1000) WHERE a>=1;
|
||||
UPDATE ab SET b = randstr(1000,1000) WHERE a>=1;
|
||||
}
|
||||
list [file exists test.db-journal] [file exists test2.db-journal]
|
||||
} {1 1}
|
||||
} {persist persist}
|
||||
if {[atomic_batch_write test.db]==0} {
|
||||
do_test crash8.4.1.1 {
|
||||
list [file exists test.db-journal] [file exists test2.db-journal]
|
||||
} {1 1}
|
||||
}
|
||||
|
||||
do_test crash8-4.2 {
|
||||
execsql {
|
||||
@@ -346,7 +352,11 @@ ifcapable pragma {
|
||||
# Since the following tests (crash8-5.*) rely upon being able
|
||||
# to copy a file while open, they will not work on Windows.
|
||||
#
|
||||
if {$::tcl_platform(platform)=="unix"} {
|
||||
# They also depend on being able to copy the journal file, which
|
||||
# is not created on F2FS file-systems that support atomic
|
||||
# write. So do not run these tests in that case either.
|
||||
#
|
||||
if {$::tcl_platform(platform)=="unix" && [atomic_batch_write test.db]==0 } {
|
||||
for {set i 1} {$i < 10} {incr i} {
|
||||
catch { db close }
|
||||
forcedelete test.db test.db-journal
|
||||
|
||||
@@ -415,4 +415,43 @@ ifcapable shared_cache {
|
||||
}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test that passing an out-of-range value to sqlite3_stmt_status does
|
||||
# not cause a crash.
|
||||
reset_db
|
||||
do_execsql_test 5.0 {
|
||||
CREATE TABLE t1(x, y);
|
||||
INSERT INTO t1 VALUES(1, 2);
|
||||
INSERT INTO t1 VALUES(3, 4);
|
||||
}
|
||||
|
||||
do_test 5.1 {
|
||||
set ::stmt [sqlite3_prepare db "SELECT * FROM t1" -1 dummy]
|
||||
sqlite3_step $::stmt
|
||||
sqlite3_step $::stmt
|
||||
sqlite3_step $::stmt
|
||||
sqlite3_reset $::stmt
|
||||
} {SQLITE_OK}
|
||||
|
||||
ifcapable api_armor {
|
||||
do_test 5.2 { sqlite3_stmt_status $::stmt -1 0 } 0
|
||||
}
|
||||
do_test 5.3 { sqlite3_stmt_status $::stmt 0 0 } 0
|
||||
do_test 5.4 {
|
||||
expr [sqlite3_stmt_status $::stmt 99 0]>0
|
||||
} 1
|
||||
foreach {tn id res} {
|
||||
1 SQLITE_STMTSTATUS_MEMUSED 1
|
||||
2 SQLITE_STMTSTATUS_FULLSCAN_STEP 1
|
||||
3 SQLITE_STMTSTATUS_SORT 0
|
||||
4 SQLITE_STMTSTATUS_AUTOINDEX 0
|
||||
5 SQLITE_STMTSTATUS_VM_STEP 1
|
||||
6 SQLITE_STMTSTATUS_REPREPARE 0
|
||||
7 SQLITE_STMTSTATUS_RUN 1
|
||||
} {
|
||||
if {$tn==2} breakpoint
|
||||
do_test 5.5.$tn { expr [sqlite3_stmt_status $::stmt $id 0]>0 } $res
|
||||
}
|
||||
|
||||
sqlite3_finalize $::stmt
|
||||
finish_test
|
||||
|
||||
@@ -37,6 +37,10 @@ proc db_write {db {reset 0}} {
|
||||
sqlite3_db_status $db CACHE_WRITE $reset
|
||||
}
|
||||
|
||||
proc db_spill {db {reset 0}} {
|
||||
sqlite3_db_status $db CACHE_SPILL $reset
|
||||
}
|
||||
|
||||
do_test 1.1 {
|
||||
db close
|
||||
sqlite3 db test.db
|
||||
@@ -98,5 +102,14 @@ do_test 2.7 {
|
||||
} {0 4 0}
|
||||
do_test 2.8 { db_write db 1 } {0 4 0}
|
||||
do_test 2.9 { db_write db 0 } {0 0 0}
|
||||
|
||||
do_test 3.0 { db_spill db 1 } {0 0 0}
|
||||
do_test 3.1 { db_spill db 0 } {0 0 0}
|
||||
do_execsql_test 3.2 {
|
||||
PRAGMA journal_mode=DELETE;
|
||||
PRAGMA cache_size=3;
|
||||
UPDATE t1 SET b=randomblob(1000);
|
||||
} {delete}
|
||||
do_test 3.3 { db_spill db 0 } {0 8 0}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -17,6 +17,11 @@ set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix delete_db
|
||||
|
||||
if {[atomic_batch_write test.db]} {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
proc delete_all {} {
|
||||
foreach f [glob -nocomplain test2*] { file delete $f }
|
||||
foreach f [glob -nocomplain test3*] { file delete $f }
|
||||
|
||||
+6
-1
@@ -252,7 +252,9 @@ db2 close
|
||||
# opens the journal file for exclusive access, preventing its contents
|
||||
# from being inspected externally.
|
||||
#
|
||||
if {$tcl_platform(platform) != "windows"} {
|
||||
if {$tcl_platform(platform) != "windows"
|
||||
&& [atomic_batch_write test.db]==0
|
||||
} {
|
||||
|
||||
# Return a list of two booleans (either 0 or 1). The first is true
|
||||
# if the named file exists. The second is true only if the file
|
||||
@@ -391,6 +393,7 @@ do_test exclusive-4.5 {
|
||||
# Tests exclusive-5.X - test that statement journals are truncated
|
||||
# instead of deleted when in exclusive access mode.
|
||||
#
|
||||
if {[atomic_batch_write test.db]==0} {
|
||||
|
||||
# Close and reopen the database so that the temp database is no
|
||||
# longer active.
|
||||
@@ -508,4 +511,6 @@ do_execsql_test exclusive-6.5 {
|
||||
SELECT * FROM sqlite_master;
|
||||
} {exclusive}
|
||||
|
||||
} ;# atomic_batch_write==0
|
||||
|
||||
finish_test
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user