Compare commits
219 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 4c3ab545a9 | |||
| 297472a2fc | |||
| d3a4dbe4b8 | |||
| 84a231eb61 | |||
| 3afd5b6d65 | |||
| 99ac2324aa | |||
| 317b7416a6 | |||
| d591a5b93d | |||
| ec14ef80b0 | |||
| ddc6bd9f21 | |||
| 23afc2c4ec | |||
| c859f0267c | |||
| f8e195159f | |||
| 0868d58e2c | |||
| dfa6289153 | |||
| 35b771e221 | |||
| 5b27ecafbc | |||
| b065eceb56 | |||
| 99200b2f07 | |||
| 14602eafa7 | |||
| 0309fb919a | |||
| 3ac612dd7d | |||
| 642e950e63 | |||
| 6e6dfd6a23 | |||
| 46435a04fd | |||
| 5d8daf184d | |||
| 0a42e9913b | |||
| 4f2f6c74ca | |||
| 2469350ad9 | |||
| 2c26adb873 | |||
| db2a33a3dd | |||
| 5749e1ee43 | |||
| d737feeacf | |||
| 0526db32e2 | |||
| 06915d0145 | |||
| 0221cacea7 | |||
| 6f4e5ee4c9 | |||
| 1d40237bc8 | |||
| ae7ede4a4f | |||
| 366b419d00 | |||
| c494fdb580 | |||
| b6d108f0b3 | |||
| 495ce22d49 | |||
| 73a50fa42c | |||
| d21d5b21db | |||
| 1278ac411c | |||
| d59afcfbfe | |||
| 0389d5f8d0 | |||
| ac94cf3ece | |||
| 5b613ed41b | |||
| fa4c4247a5 | |||
| 1152def76e | |||
| 660322f96f | |||
| 05c6d13027 | |||
| 6951c49779 | |||
| ed27183d83 | |||
| 8181cc6c10 | |||
| de6a4be9b5 | |||
| 743ae4c68b | |||
| b411c4d69e | |||
| 65a1d7a284 | |||
| 7fd9b53308 | |||
| f895173c5f | |||
| 634f434686 | |||
| efe9500af7 | |||
| 13f5910889 | |||
| 307f290b32 | |||
| 8ce73ce15b | |||
| 7f7d0b19f8 | |||
| 9352cfa30b | |||
| 69dbd7a4e7 | |||
| cfd4507c83 | |||
| 6921a2d205 | |||
| ed517a7082 | |||
| dcc121999c | |||
| a509a90958 | |||
| ca3b9096c4 | |||
| 1872f8d844 | |||
| eb5bd4db91 | |||
| 791b6f36cc | |||
| f7aab656ff | |||
| ed6c9aa6ab | |||
| bcf97e70f5 | |||
| 99b4e6e254 | |||
| 41c9945c74 | |||
| 4397d28378 | |||
| 55051d661c | |||
| d2b3b72a2b | |||
| cf84ae0189 | |||
| 4a402b80c5 | |||
| a631eb378d | |||
| d9eee787bd | |||
| 378bf82e2b | |||
| 2faaf3830e | |||
| 006a9b51aa | |||
| 529ed1a3a3 | |||
| af64a22762 | |||
| 296ae1e467 | |||
| 219b4f2061 | |||
| e555bd4f02 | |||
| daee74c3ac | |||
| 7128c789bd | |||
| 697e122a11 | |||
| 254729edb7 | |||
| 36f01f2ee3 | |||
| 4aa21492d1 | |||
| 27ea83f66e | |||
| ffbe492553 | |||
| e9feb0acfc | |||
| f891ef8d61 | |||
| a10c2a9055 | |||
| 967c303212 | |||
| d75bdf51c7 | |||
| 261c6dfe7b | |||
| 4b42b5259f | |||
| 1fe31dcfab | |||
| 5ed044e893 | |||
| 108dd6a52d | |||
| 28cd72ac52 | |||
| 365b6e9769 | |||
| fc2d862318 | |||
| 43a511927d | |||
| 2ad2584581 | |||
| c195e2374b | |||
| b03805b70b | |||
| ac7c6f5854 | |||
| 871786b792 | |||
| 27a5ee855d | |||
| 75924d3ae2 | |||
| 2f4a8cc2d8 | |||
| 54bf109e80 | |||
| e4a1b4da4f | |||
| 1c5257dafc | |||
| ec00a4d111 | |||
| 7dc3e923c4 | |||
| 4713b2d73c | |||
| b918a0f821 | |||
| bf4105d768 | |||
| 40514dd1f6 | |||
| f696591dd4 | |||
| d31fc6e9cf | |||
| 825596481f | |||
| 0ebd1c382c | |||
| 932b5f4575 | |||
| 26a3ef7557 | |||
| 400992b1c4 | |||
| f0f4323824 | |||
| 5a0fd81fce | |||
| a06c046e29 | |||
| 56be6f6c08 | |||
| aa2e244e14 | |||
| 35057fb4bc | |||
| 81a244c514 | |||
| 693d3867ea | |||
| e116fa153f | |||
| 609aba00d9 | |||
| 6bb6a9c941 | |||
| 4565c8417b | |||
| 4659ec34c1 | |||
| 9b6e535609 | |||
| c2764dbb33 | |||
| 484193fe7f | |||
| 1769640c8b | |||
| 3de08a6ee0 | |||
| eea6bdce84 | |||
| 5badd048d2 | |||
| f99ab38bdb | |||
| 3ac5c08180 | |||
| 38152d9d04 | |||
| f4783d4d7f | |||
| 2dbf276e93 | |||
| c6481e0289 | |||
| 815e055bff | |||
| 5dfff386e5 | |||
| 289507d78b | |||
| 88abf9ad44 | |||
| bf030d53b1 | |||
| 5007833f5f | |||
| aa13f4c132 | |||
| 61b77a6fe1 | |||
| 96f5ae6bd7 | |||
| 744e5672bf | |||
| 926fb60b05 | |||
| b89aa10cd0 | |||
| 3041642b1a | |||
| a219fb5bb9 | |||
| f10de5360a | |||
| 67fc3e0ac2 | |||
| 84016759dd | |||
| ffa0fa69b6 | |||
| 61405c463d | |||
| c395f08099 | |||
| 5fb718aaab | |||
| 2b6cce16ff | |||
| 1b977e3ae8 | |||
| 1bd583e201 | |||
| 31c3ac9049 | |||
| b4e7d59f4f | |||
| a64342ee9c | |||
| 53ca213e73 | |||
| 7ab40cda7b | |||
| 75aed69158 | |||
| 28001204f4 | |||
| 891aa05450 | |||
| 7eb0ddf68b | |||
| d5045a9246 | |||
| 2c3973fdff | |||
| 18281494a2 | |||
| 4cf953731f | |||
| 90170503b4 | |||
| 3f273db39b | |||
| 8d25d07d50 | |||
| 2775f10ebc | |||
| bae55a7685 | |||
| e6af60c14f | |||
| aefa7afddb | |||
| ebc14e409f | |||
| f52afaf738 | |||
| 6964005847 |
+34
-34
@@ -817,8 +817,7 @@ has_tclsh85:
|
||||
touch .target_source
|
||||
|
||||
sqlite3.c: .target_source $(TOP)/tool/mksqlite3c.tcl src-verify has_tclsh84
|
||||
$(TCLSH_CMD) $(TOP)/tool/mksqlite3c.tcl $(AMALGAMATION_LINE_MACROS) \
|
||||
$(EXTRA_SRC)
|
||||
$(TCLSH_CMD) $(TOP)/tool/mksqlite3c.tcl $(AMALGAMATION_LINE_MACROS) $(EXTRA_SRC)
|
||||
cp tsrc/sqlite3ext.h .
|
||||
cp $(TOP)/ext/session/sqlite3session.h .
|
||||
|
||||
@@ -829,8 +828,7 @@ sqlite3r.c: sqlite3.c sqlite3r.h has_tclsh84
|
||||
cp $(TOP)/ext/recover/sqlite3recover.c tsrc/
|
||||
cp $(TOP)/ext/recover/sqlite3recover.h tsrc/
|
||||
cp $(TOP)/ext/recover/dbdata.c tsrc/
|
||||
$(TCLSH_CMD) $(TOP)/tool/mksqlite3c.tcl --enable-recover \
|
||||
$(AMALGAMATION_LINE_MACROS) $(EXTRA_SRC)
|
||||
$(TCLSH_CMD) $(TOP)/tool/mksqlite3c.tcl --enable-recover $(AMALGAMATION_LINE_MACROS) $(EXTRA_SRC)
|
||||
|
||||
sqlite3ext.h: .target_source
|
||||
cp tsrc/sqlite3ext.h .
|
||||
@@ -1156,35 +1154,37 @@ keywordhash.h: $(TOP)/tool/mkkeywordhash.c
|
||||
$(BCC) -o mkkeywordhash$(BEXE) $(OPT_FEATURE_FLAGS) $(OPTS) $(TOP)/tool/mkkeywordhash.c
|
||||
./mkkeywordhash$(BEXE) >keywordhash.h
|
||||
|
||||
# Source files that go into making shell.c
|
||||
SHELL_SRC = \
|
||||
$(TOP)/src/shell.c.in \
|
||||
$(TOP)/ext/consio/console_io.c \
|
||||
$(TOP)/ext/consio/console_io.h \
|
||||
$(TOP)/ext/misc/appendvfs.c \
|
||||
$(TOP)/ext/misc/completion.c \
|
||||
$(TOP)/ext/misc/decimal.c \
|
||||
$(TOP)/ext/misc/basexx.c \
|
||||
$(TOP)/ext/misc/base64.c \
|
||||
$(TOP)/ext/misc/base85.c \
|
||||
$(TOP)/ext/misc/fileio.c \
|
||||
$(TOP)/ext/misc/ieee754.c \
|
||||
$(TOP)/ext/misc/regexp.c \
|
||||
$(TOP)/ext/misc/series.c \
|
||||
$(TOP)/ext/misc/shathree.c \
|
||||
$(TOP)/ext/misc/sqlar.c \
|
||||
$(TOP)/ext/misc/uint.c \
|
||||
$(TOP)/ext/expert/sqlite3expert.c \
|
||||
$(TOP)/ext/expert/sqlite3expert.h \
|
||||
$(TOP)/ext/misc/zipfile.c \
|
||||
$(TOP)/ext/misc/memtrace.c \
|
||||
$(TOP)/ext/misc/pcachetrace.c \
|
||||
$(TOP)/ext/recover/dbdata.c \
|
||||
$(TOP)/ext/recover/sqlite3recover.c \
|
||||
$(TOP)/ext/recover/sqlite3recover.h \
|
||||
$(TOP)/src/test_windirent.c
|
||||
# Source and header files that shell.c depends on
|
||||
SHELL_DEP = \
|
||||
$(TOP)/src/shell.c.in \
|
||||
$(TOP)/ext/consio/console_io.c \
|
||||
$(TOP)/ext/consio/console_io.h \
|
||||
$(TOP)/ext/expert/sqlite3expert.c \
|
||||
$(TOP)/ext/expert/sqlite3expert.h \
|
||||
$(TOP)/ext/intck/sqlite3intck.c \
|
||||
$(TOP)/ext/intck/sqlite3intck.h \
|
||||
$(TOP)/ext/misc/appendvfs.c \
|
||||
$(TOP)/ext/misc/base64.c \
|
||||
$(TOP)/ext/misc/base85.c \
|
||||
$(TOP)/ext/misc/completion.c \
|
||||
$(TOP)/ext/misc/decimal.c \
|
||||
$(TOP)/ext/misc/fileio.c \
|
||||
$(TOP)/ext/misc/ieee754.c \
|
||||
$(TOP)/ext/misc/memtrace.c \
|
||||
$(TOP)/ext/misc/pcachetrace.c \
|
||||
$(TOP)/ext/misc/regexp.c \
|
||||
$(TOP)/ext/misc/series.c \
|
||||
$(TOP)/ext/misc/shathree.c \
|
||||
$(TOP)/ext/misc/sqlar.c \
|
||||
$(TOP)/ext/misc/uint.c \
|
||||
$(TOP)/ext/misc/zipfile.c \
|
||||
$(TOP)/ext/recover/dbdata.c \
|
||||
$(TOP)/ext/recover/sqlite3recover.c \
|
||||
$(TOP)/ext/recover/sqlite3recover.h \
|
||||
$(TOP)/src/test_windirent.c \
|
||||
$(TOP)/src/test_windirent.h
|
||||
|
||||
shell.c: $(SHELL_SRC) $(TOP)/tool/mkshellc.tcl has_tclsh84
|
||||
shell.c: $(SHELL_DEP) $(TOP)/tool/mkshellc.tcl has_tclsh84
|
||||
$(TCLSH_CMD) $(TOP)/tool/mkshellc.tcl >shell.c
|
||||
|
||||
|
||||
@@ -1312,9 +1312,9 @@ testfixture$(TEXE): has_tclsh85 $(TESTFIXTURE_SRC)
|
||||
$(LTLINK) -DSQLITE_NO_SYNC=1 $(TEMP_STORE) $(TESTFIXTURE_FLAGS) \
|
||||
-o $@ $(TESTFIXTURE_SRC) $(LIBTCL) $(TLIBS)
|
||||
|
||||
coretestprogs: $(TESTPROGS)
|
||||
coretestprogs: testfixture$(BEXE) sqlite3$(BEXE)
|
||||
|
||||
testprogs: coretestprogs srcck1$(BEXE) fuzzcheck$(TEXE) sessionfuzz$(TEXE)
|
||||
testprogs: $(TESTPROGS) srcck1$(BEXE) fuzzcheck$(TEXE) sessionfuzz$(TEXE)
|
||||
|
||||
# A very detailed test running most or all test cases
|
||||
fulltest: alltest fuzztest
|
||||
|
||||
+35
-30
@@ -2272,39 +2272,44 @@ mkkeywordhash.exe: $(TOP)\tool\mkkeywordhash.c
|
||||
keywordhash.h: $(TOP)\tool\mkkeywordhash.c mkkeywordhash.exe
|
||||
.\mkkeywordhash.exe > keywordhash.h
|
||||
|
||||
# Source files that go into making shell.c
|
||||
SHELL_SRC = \
|
||||
$(TOP)\src\shell.c.in \
|
||||
$(TOP)\ext\consio\console_io.c \
|
||||
$(TOP)\ext\consio\console_io.h \
|
||||
$(TOP)\ext\misc\appendvfs.c \
|
||||
$(TOP)\ext\misc\completion.c \
|
||||
$(TOP)\ext\misc\base64.c \
|
||||
$(TOP)\ext\misc\base85.c \
|
||||
$(TOP)\ext\misc\decimal.c \
|
||||
$(TOP)\ext\misc\fileio.c \
|
||||
$(TOP)\ext\misc\ieee754.c \
|
||||
$(TOP)\ext\misc\regexp.c \
|
||||
$(TOP)\ext\misc\series.c \
|
||||
$(TOP)\ext\misc\shathree.c \
|
||||
$(TOP)\ext\misc\uint.c \
|
||||
$(TOP)\ext\expert\sqlite3expert.c \
|
||||
$(TOP)\ext\expert\sqlite3expert.h \
|
||||
$(TOP)\ext\misc\memtrace.c \
|
||||
$(TOP)\ext\misc\pcachetrace.c \
|
||||
$(TOP)\ext\recover\dbdata.c \
|
||||
$(TOP)\ext\recover\sqlite3recover.c \
|
||||
$(TOP)\ext\recover\sqlite3recover.h \
|
||||
$(TOP)\src\test_windirent.c
|
||||
# Source and header files that shell.c depends on
|
||||
SHELL_DEP = \
|
||||
$(TOP)\src\shell.c.in \
|
||||
$(TOP)\ext\consio\console_io.c \
|
||||
$(TOP)\ext\consio\console_io.h \
|
||||
$(TOP)\ext\expert\sqlite3expert.c \
|
||||
$(TOP)\ext\expert\sqlite3expert.h \
|
||||
$(TOP)\ext\intck\sqlite3intck.c \
|
||||
$(TOP)\ext\intck\sqlite3intck.h \
|
||||
$(TOP)\ext\misc\appendvfs.c \
|
||||
$(TOP)\ext\misc\base64.c \
|
||||
$(TOP)\ext\misc\base85.c \
|
||||
$(TOP)\ext\misc\completion.c \
|
||||
$(TOP)\ext\misc\decimal.c \
|
||||
$(TOP)\ext\misc\fileio.c \
|
||||
$(TOP)\ext\misc\ieee754.c \
|
||||
$(TOP)\ext\misc\memtrace.c \
|
||||
$(TOP)\ext\misc\pcachetrace.c \
|
||||
$(TOP)\ext\misc\regexp.c \
|
||||
$(TOP)\ext\misc\series.c \
|
||||
$(TOP)\ext\misc\shathree.c \
|
||||
$(TOP)\ext\misc\sqlar.c \
|
||||
$(TOP)\ext\misc\uint.c \
|
||||
$(TOP)\ext\misc\zipfile.c \
|
||||
$(TOP)\ext\recover\dbdata.c \
|
||||
$(TOP)\ext\recover\sqlite3recover.c \
|
||||
$(TOP)\ext\recover\sqlite3recover.h \
|
||||
$(TOP)\src\test_windirent.c \
|
||||
$(TOP)\src\test_windirent.h
|
||||
|
||||
# If use of zlib is enabled, add the "zipfile.c" source file.
|
||||
#
|
||||
!IF $(USE_ZLIB)!=0
|
||||
SHELL_SRC = $(SHELL_SRC) $(TOP)\ext\misc\sqlar.c
|
||||
SHELL_SRC = $(SHELL_SRC) $(TOP)\ext\misc\zipfile.c
|
||||
SHELL_DEP = $(SHELL_DEP) $(TOP)\ext\misc\sqlar.c
|
||||
SHELL_DEP = $(SHELL_DEP) $(TOP)\ext\misc\zipfile.c
|
||||
!ENDIF
|
||||
|
||||
shell.c: $(SHELL_SRC) $(TOP)\tool\mkshellc.tcl
|
||||
shell.c: $(SHELL_DEP) $(TOP)\tool\mkshellc.tcl
|
||||
$(TCLSH_CMD) $(TOP)\tool\mkshellc.tcl > shell.c
|
||||
|
||||
zlib:
|
||||
@@ -2491,9 +2496,9 @@ extensiontest: testfixture.exe testloadext.dll
|
||||
tool-zip: testfixture.exe sqlite3.exe sqldiff.exe sqlite3_analyzer.exe $(TOP)\tool\mktoolzip.tcl
|
||||
.\testfixture.exe $(TOP)\tool\mktoolzip.tcl
|
||||
|
||||
coretestprogs: $(TESTPROGS)
|
||||
coretestprogs: testfixture.exe sqlite3.exe
|
||||
|
||||
testprogs: coretestprogs srcck1.exe fuzzcheck.exe sessionfuzz.exe
|
||||
testprogs: $(TESTPROGS) srcck1.exe fuzzcheck.exe sessionfuzz.exe
|
||||
|
||||
fulltest: alltest fuzztest
|
||||
|
||||
@@ -2548,7 +2553,7 @@ mdevtest:
|
||||
|
||||
# Testing for a release
|
||||
#
|
||||
releasetest: testfixture.exe fuzztest
|
||||
releasetest: testfixture.exe
|
||||
testfixture.exe $(TOP)\test\testrunner.tcl release
|
||||
|
||||
|
||||
|
||||
+25
-13
@@ -17,7 +17,6 @@
|
||||
<li> 3.3. <a href=#source_code_test_failures>Investigating Source Code Test Failures</a>
|
||||
</ul>
|
||||
<li> 4. <a href=#testrunner_options>Extra testrunner.tcl Options</a>
|
||||
# 4. Extra testrunner.tcl Options
|
||||
<li> 5. <a href=#cpu_cores>Controlling CPU Core Utilization</a>
|
||||
</ul>
|
||||
|
||||
@@ -29,12 +28,18 @@ multiple jobs. It supports the following types of tests:
|
||||
|
||||
* Tcl test scripts.
|
||||
|
||||
* Tests run with [make] commands. Specifically, at time of writing,
|
||||
[make fuzztest], [make mptest], [make sourcetest] and [make threadtest].
|
||||
* Tests run with `make` commands. Examples:
|
||||
- `make mdevtest`
|
||||
- `make releasetest`
|
||||
- `make sdevtest`
|
||||
- `make testrunner`
|
||||
|
||||
testrunner.tcl pipes the output of all tests and builds run into log file
|
||||
**testrunner.log**, created in the cwd directory. Searching this file for
|
||||
"failed" is a good way to find the output of a failed test.
|
||||
**testrunner.log**, created in the current working directory. Search this
|
||||
file to find details of errors. Suggested search commands:
|
||||
|
||||
* `grep "^!" testrunner.log`
|
||||
* `grep failed testrunner.log`
|
||||
|
||||
testrunner.tcl also populates SQLite database **testrunner.db**. This database
|
||||
contains details of all tests run, running and to be run. A useful query
|
||||
@@ -60,7 +65,7 @@ Running:
|
||||
|
||||
in another terminal is a good way to keep an eye on a long running test.
|
||||
|
||||
Sometimes testrunner.tcl uses the [testfixture] binary that it is run with
|
||||
Sometimes testrunner.tcl uses the `testfixture` binary that it is run with
|
||||
to run tests (see "Binary Tests" below). Sometimes it builds testfixture and
|
||||
other binaries in specific configurations to test (see "Source Tests").
|
||||
|
||||
@@ -68,9 +73,9 @@ other binaries in specific configurations to test (see "Source Tests").
|
||||
# 2. Binary Tests
|
||||
|
||||
The commands described in this section all run various combinations of the Tcl
|
||||
test scripts using the [testfixture] binary used to run the testrunner.tcl
|
||||
test scripts using the `testfixture` binary used to run the testrunner.tcl
|
||||
script (i.e. they do not invoke the compiler to build new binaries, or the
|
||||
[make] command to run tests that are not Tcl scripts). The procedure to run
|
||||
`make` command to run tests that are not Tcl scripts). The procedure to run
|
||||
these tests is therefore:
|
||||
|
||||
1. Build the "testfixture" (or "testfixture.exe" for windows) binary using
|
||||
@@ -193,7 +198,7 @@ TODO: ./configure + Makefile.msc build systems.
|
||||
## 3.1. Commands to Run SQLite Tests
|
||||
|
||||
The **mdevtest** command is equivalent to running the veryquick tests and
|
||||
the [make fuzztest] target once for each of two --enable-all builds - one
|
||||
the `make fuzztest` target once for each of two --enable-all builds - one
|
||||
with debugging enabled and one without:
|
||||
|
||||
```
|
||||
@@ -283,7 +288,7 @@ a dos \*.bat file on windows. For example:
|
||||
```
|
||||
|
||||
The generated bash or \*.bat file script accepts a single argument - a makefile
|
||||
target to build. This may be used either to run a [make] command test directly,
|
||||
target to build. This may be used either to run a `make` command test directly,
|
||||
or else to build a testfixture (or testfixture.exe) binary with which to
|
||||
run a Tcl test script, as <a href=#binary_test_failures>described above</a>.
|
||||
|
||||
@@ -310,6 +315,16 @@ would normally execute into the testrunner.log file. Example:
|
||||
tclsh $TESTDIR/testrunner.tcl --dryrun mdevtest"
|
||||
```
|
||||
|
||||
The **--explain** option is similar to --dryrun in that it prevents testrunner.tcl
|
||||
from building any binaries or running any tests. The difference is that --explain
|
||||
prints on standard output a human-readable summary of all the builds and tests that
|
||||
would have been run.
|
||||
|
||||
```
|
||||
# Show what builds and tests would have been run
|
||||
tclsh $TESTDIR/testrunner.tcl --explain mdevtest
|
||||
```
|
||||
|
||||
<a name=cpu_cores></a>
|
||||
# 5. Controlling CPU Core Utilization
|
||||
|
||||
@@ -339,6 +354,3 @@ testrunner.log and testrunner.db files:
|
||||
```
|
||||
$ ./testfixture $TESTDIR/testrunner.tcl njob $NEW_NUMBER_OF_JOBS
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
# TESTRUNNER: shell
|
||||
#
|
||||
# The focus of this file is testing the CLI shell tool. Specifically,
|
||||
# the ".recommend" command.
|
||||
|
||||
@@ -1948,7 +1948,7 @@ sqlite3expert *sqlite3_expert_new(sqlite3 *db, char **pzErrmsg){
|
||||
sqlite3_stmt *pSql = 0;
|
||||
rc = idxPrintfPrepareStmt(pNew->db, &pSql, pzErrmsg,
|
||||
"SELECT sql FROM sqlite_schema WHERE name NOT LIKE 'sqlite_%%'"
|
||||
" AND sql NOT LIKE 'CREATE VIRTUAL %%'"
|
||||
" AND sql NOT LIKE 'CREATE VIRTUAL %%' ORDER BY rowid"
|
||||
);
|
||||
while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){
|
||||
const char *zSql = (const char*)sqlite3_column_text(pSql, 0);
|
||||
|
||||
@@ -446,7 +446,7 @@ static void fts3SnippetDetails(
|
||||
}
|
||||
mCover |= mPhrase;
|
||||
|
||||
for(j=0; j<pPhrase->nToken; j++){
|
||||
for(j=0; j<pPhrase->nToken && j<pIter->nSnippet; j++){
|
||||
mHighlight |= (mPos>>j);
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -55,8 +55,8 @@ struct Fts5PhraseIter {
|
||||
** EXTENSION API FUNCTIONS
|
||||
**
|
||||
** xUserData(pFts):
|
||||
** Return a copy of the context pointer the extension function was
|
||||
** registered with.
|
||||
** Return a copy of the pUserData pointer passed to the xCreateFunction()
|
||||
** API when the extension function was registered.
|
||||
**
|
||||
** xColumnTotalSize(pFts, iCol, pnToken):
|
||||
** If parameter iCol is less than zero, set output variable *pnToken
|
||||
|
||||
+35
-2
@@ -471,7 +471,7 @@ static void icuLoadCollation(
|
||||
UCollator *pUCollator; /* ICU library collation object */
|
||||
int rc; /* Return code from sqlite3_create_collation_x() */
|
||||
|
||||
assert(nArg==2);
|
||||
assert(nArg==2 || nArg==3);
|
||||
(void)nArg; /* Unused parameter */
|
||||
zLocale = (const char *)sqlite3_value_text(apArg[0]);
|
||||
zName = (const char *)sqlite3_value_text(apArg[1]);
|
||||
@@ -486,7 +486,39 @@ static void icuLoadCollation(
|
||||
return;
|
||||
}
|
||||
assert(p);
|
||||
|
||||
if(nArg==3){
|
||||
const char *zOption = (const char*)sqlite3_value_text(apArg[2]);
|
||||
static const struct {
|
||||
const char *zName;
|
||||
UColAttributeValue val;
|
||||
} aStrength[] = {
|
||||
{ "PRIMARY", UCOL_PRIMARY },
|
||||
{ "SECONDARY", UCOL_SECONDARY },
|
||||
{ "TERTIARY", UCOL_TERTIARY },
|
||||
{ "DEFAULT", UCOL_DEFAULT_STRENGTH },
|
||||
{ "QUARTERNARY", UCOL_QUATERNARY },
|
||||
{ "IDENTICAL", UCOL_IDENTICAL },
|
||||
};
|
||||
unsigned int i;
|
||||
for(i=0; i<sizeof(aStrength)/sizeof(aStrength[0]); i++){
|
||||
if( sqlite3_stricmp(zOption,aStrength[i].zName)==0 ){
|
||||
ucol_setStrength(pUCollator, aStrength[i].val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( i>=sizeof(aStrength)/sizeof(aStrength[0]) ){
|
||||
sqlite3_str *pStr = sqlite3_str_new(sqlite3_context_db_handle(p));
|
||||
sqlite3_str_appendf(pStr,
|
||||
"unknown collation strength \"%s\" - should be one of:",
|
||||
zOption);
|
||||
for(i=0; i<sizeof(aStrength)/sizeof(aStrength[0]); i++){
|
||||
sqlite3_str_appendf(pStr, " %s", aStrength[i].zName);
|
||||
}
|
||||
sqlite3_result_error(p, sqlite3_str_value(pStr), -1);
|
||||
sqlite3_free(sqlite3_str_finish(pStr));
|
||||
return;
|
||||
}
|
||||
}
|
||||
rc = sqlite3_create_collation_v2(db, zName, SQLITE_UTF16, (void *)pUCollator,
|
||||
icuCollationColl, icuCollationDel
|
||||
);
|
||||
@@ -509,6 +541,7 @@ int sqlite3IcuInit(sqlite3 *db){
|
||||
void (*xFunc)(sqlite3_context*,int,sqlite3_value**);
|
||||
} scalars[] = {
|
||||
{"icu_load_collation",2,SQLITE_UTF8|SQLITE_DIRECTONLY,1, icuLoadCollation},
|
||||
{"icu_load_collation",3,SQLITE_UTF8|SQLITE_DIRECTONLY,1, icuLoadCollation},
|
||||
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_ICU)
|
||||
{"regexp", 2, SQLITE_ANY|SQLITEICU_EXTRAFLAGS, 0, icuRegexpFunc},
|
||||
{"lower", 1, SQLITE_UTF16|SQLITEICU_EXTRAFLAGS, 0, icuCaseFunc16},
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
|
||||
source [file join [file dirname [info script]] intck_common.tcl]
|
||||
set testprefix intck1
|
||||
return_if_no_intck
|
||||
|
||||
foreach {tn sql} {
|
||||
1 "CREATE TABLE t1(a PRIMARY KEY, b)"
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
|
||||
source [file join [file dirname [info script]] intck_common.tcl]
|
||||
set testprefix intck2
|
||||
return_if_no_intck
|
||||
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
|
||||
@@ -15,6 +15,16 @@ if {![info exists testdir]} {
|
||||
}
|
||||
source $testdir/tester.tcl
|
||||
|
||||
ifcapable !vtab||!pragma {
|
||||
proc return_if_no_intck {} {
|
||||
finish_test
|
||||
return -code return
|
||||
}
|
||||
return
|
||||
} else {
|
||||
proc return_if_no_intck {} {}
|
||||
}
|
||||
|
||||
proc do_intck {db {bSuspend 0}} {
|
||||
set ic [sqlite3_intck $db main]
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
source [file join [file dirname [info script]] intck_common.tcl]
|
||||
set testprefix intckbusy
|
||||
return_if_no_intck
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
|
||||
source [file join [file dirname [info script]] intck_common.tcl]
|
||||
set testprefix intckcorrupt
|
||||
return_if_no_intck
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
|
||||
@@ -12,8 +12,7 @@
|
||||
|
||||
source [file join [file dirname [info script]] intck_common.tcl]
|
||||
set testprefix intckfault
|
||||
|
||||
|
||||
return_if_no_intck
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
|
||||
@@ -36,8 +35,6 @@ do_faultsim_test 1 -faults oom-t* -prep {
|
||||
set res
|
||||
} -test {
|
||||
catch { $::ic close }
|
||||
puts $testresult
|
||||
puts $testnfail
|
||||
faultsim_test_result {0 {SQLITE_OK {}}} {0 {SQLITE_NOMEM {}}} {0 {SQLITE_NOMEM {out of memory}}}
|
||||
}
|
||||
|
||||
|
||||
@@ -422,7 +422,7 @@ static const char *intckParseCreateIndex(const char *z, int iCol, int *pnByte){
|
||||
int n = intckGetToken(&z[iOff]);
|
||||
if( n==5 && 0==sqlite3_strnicmp(&z[iOff], "where", 5) ){
|
||||
zRet = &z[iOff+5];
|
||||
nRet = strlen(zRet);
|
||||
nRet = (int)strlen(zRet);
|
||||
}
|
||||
iOff += n;
|
||||
}
|
||||
@@ -785,7 +785,7 @@ int sqlite3_intck_open(
|
||||
sqlite3_intck *pNew = 0;
|
||||
int rc = SQLITE_OK;
|
||||
const char *zDb = zDbArg ? zDbArg : "main";
|
||||
int nDb = strlen(zDb);
|
||||
int nDb = (int)strlen(zDb);
|
||||
|
||||
pNew = (sqlite3_intck*)sqlite3_malloc(sizeof(*pNew) + nDb + 1);
|
||||
if( pNew==0 ){
|
||||
@@ -938,4 +938,3 @@ const char *sqlite3_intck_test_sql(sqlite3_intck *p, const char *zObj){
|
||||
}
|
||||
return p->zTestSql;
|
||||
}
|
||||
|
||||
|
||||
@@ -79,7 +79,7 @@ static int testIntckCmd(
|
||||
}
|
||||
|
||||
case 1: assert( 0==strcmp("step", aCmd[iIdx].zName) ); {
|
||||
int rc = sqlite3_intck_step(p->intck);
|
||||
rc = sqlite3_intck_step(p->intck);
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
|
||||
break;
|
||||
}
|
||||
@@ -92,7 +92,7 @@ static int testIntckCmd(
|
||||
|
||||
case 3: assert( 0==strcmp("error", aCmd[iIdx].zName) ); {
|
||||
const char *zErr = 0;
|
||||
int rc = sqlite3_intck_error(p->intck, 0);
|
||||
rc = sqlite3_intck_error(p->intck, 0);
|
||||
Tcl_Obj *pRes = Tcl_NewObj();
|
||||
Tcl_ListObjAppendElement(
|
||||
interp, pRes, Tcl_NewStringObj(sqlite3ErrName(rc), -1)
|
||||
@@ -106,7 +106,7 @@ static int testIntckCmd(
|
||||
}
|
||||
|
||||
case 4: assert( 0==strcmp("unlock", aCmd[iIdx].zName) ); {
|
||||
int rc = sqlite3_intck_unlock(p->intck);
|
||||
rc = sqlite3_intck_unlock(p->intck);
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
|
||||
break;
|
||||
}
|
||||
|
||||
+3
-3
@@ -446,9 +446,9 @@ static int cksmRead(
|
||||
** (2) checksum verification is enabled
|
||||
** (3) we are not in the middle of checkpoint
|
||||
*/
|
||||
if( iAmt>=512 /* (1) */
|
||||
&& p->verifyCksm /* (2) */
|
||||
&& !p->inCkpt /* (3) */
|
||||
if( iAmt>=512 && (iAmt & (iAmt-1))==0 /* (1) */
|
||||
&& p->verifyCksm /* (2) */
|
||||
&& !p->inCkpt /* (3) */
|
||||
){
|
||||
u8 cksum[8];
|
||||
cksmCompute((u8*)zBuf, iAmt-8, cksum);
|
||||
|
||||
+77
-25
@@ -376,13 +376,13 @@ static int seriesEof(sqlite3_vtab_cursor *cur){
|
||||
** parameter. (idxStr is not used in this implementation.) idxNum
|
||||
** is a bitmask showing which constraints are available:
|
||||
**
|
||||
** 1: start=VALUE
|
||||
** 2: stop=VALUE
|
||||
** 4: step=VALUE
|
||||
**
|
||||
** Also, if bit 8 is set, that means that the series should be output
|
||||
** in descending order rather than in ascending order. If bit 16 is
|
||||
** set, then output must appear in ascending order.
|
||||
** 0x01: start=VALUE
|
||||
** 0x02: stop=VALUE
|
||||
** 0x04: step=VALUE
|
||||
** 0x08: descending order
|
||||
** 0x10: ascending order
|
||||
** 0x20: LIMIT VALUE
|
||||
** 0x40: OFFSET VALUE
|
||||
**
|
||||
** This routine should initialize the cursor and position it so that it
|
||||
** is pointing at the first row, or pointing off the end of the table
|
||||
@@ -396,26 +396,44 @@ static int seriesFilter(
|
||||
series_cursor *pCur = (series_cursor *)pVtabCursor;
|
||||
int i = 0;
|
||||
(void)idxStrUnused;
|
||||
if( idxNum & 1 ){
|
||||
if( idxNum & 0x01 ){
|
||||
pCur->ss.iBase = sqlite3_value_int64(argv[i++]);
|
||||
}else{
|
||||
pCur->ss.iBase = 0;
|
||||
}
|
||||
if( idxNum & 2 ){
|
||||
if( idxNum & 0x02 ){
|
||||
pCur->ss.iTerm = sqlite3_value_int64(argv[i++]);
|
||||
}else{
|
||||
pCur->ss.iTerm = 0xffffffff;
|
||||
}
|
||||
if( idxNum & 4 ){
|
||||
if( idxNum & 0x04 ){
|
||||
pCur->ss.iStep = sqlite3_value_int64(argv[i++]);
|
||||
if( pCur->ss.iStep==0 ){
|
||||
pCur->ss.iStep = 1;
|
||||
}else if( pCur->ss.iStep<0 ){
|
||||
if( (idxNum & 16)==0 ) idxNum |= 8;
|
||||
if( (idxNum & 0x10)==0 ) idxNum |= 0x08;
|
||||
}
|
||||
}else{
|
||||
pCur->ss.iStep = 1;
|
||||
}
|
||||
if( idxNum & 0x20 ){
|
||||
sqlite3_int64 iLimit = sqlite3_value_int64(argv[i++]);
|
||||
sqlite3_int64 iTerm;
|
||||
if( idxNum & 0x40 ){
|
||||
sqlite3_int64 iOffset = sqlite3_value_int64(argv[i++]);
|
||||
if( iOffset>0 ){
|
||||
pCur->ss.iBase += pCur->ss.iStep*iOffset;
|
||||
}
|
||||
}
|
||||
if( iLimit>=0 ){
|
||||
iTerm = pCur->ss.iBase + (iLimit - 1)*pCur->ss.iStep;
|
||||
if( pCur->ss.iStep<0 ){
|
||||
if( iTerm>pCur->ss.iTerm ) pCur->ss.iTerm = iTerm;
|
||||
}else{
|
||||
if( iTerm<pCur->ss.iTerm ) pCur->ss.iTerm = iTerm;
|
||||
}
|
||||
}
|
||||
}
|
||||
for(i=0; i<argc; i++){
|
||||
if( sqlite3_value_type(argv[i])==SQLITE_NULL ){
|
||||
/* If any of the constraints have a NULL value, then return no rows.
|
||||
@@ -426,7 +444,7 @@ static int seriesFilter(
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( idxNum & 8 ){
|
||||
if( idxNum & 0x08 ){
|
||||
pCur->ss.isReversing = pCur->ss.iStep > 0;
|
||||
}else{
|
||||
pCur->ss.isReversing = pCur->ss.iStep < 0;
|
||||
@@ -446,10 +464,13 @@ static int seriesFilter(
|
||||
**
|
||||
** The query plan is represented by bits in idxNum:
|
||||
**
|
||||
** (1) start = $value -- constraint exists
|
||||
** (2) stop = $value -- constraint exists
|
||||
** (4) step = $value -- constraint exists
|
||||
** (8) output in descending order
|
||||
** 0x01 start = $value -- constraint exists
|
||||
** 0x02 stop = $value -- constraint exists
|
||||
** 0x04 step = $value -- constraint exists
|
||||
** 0x08 output is in descending order
|
||||
** 0x10 output is in ascending order
|
||||
** 0x20 LIMIT $value -- constraint exists
|
||||
** 0x40 OFFSET $value -- constraint exists
|
||||
*/
|
||||
static int seriesBestIndex(
|
||||
sqlite3_vtab *pVTab,
|
||||
@@ -457,10 +478,12 @@ static int seriesBestIndex(
|
||||
){
|
||||
int i, j; /* Loop over constraints */
|
||||
int idxNum = 0; /* The query plan bitmask */
|
||||
#ifndef ZERO_ARGUMENT_GENERATE_SERIES
|
||||
int bStartSeen = 0; /* EQ constraint seen on the START column */
|
||||
#endif
|
||||
int unusableMask = 0; /* Mask of unusable constraints */
|
||||
int nArg = 0; /* Number of arguments that seriesFilter() expects */
|
||||
int aIdx[3]; /* Constraints on start, stop, and step */
|
||||
int aIdx[5]; /* Constraints on start, stop, step, LIMIT, OFFSET */
|
||||
const struct sqlite3_index_constraint *pConstraint;
|
||||
|
||||
/* This implementation assumes that the start, stop, and step columns
|
||||
@@ -468,28 +491,54 @@ static int seriesBestIndex(
|
||||
assert( SERIES_COLUMN_STOP == SERIES_COLUMN_START+1 );
|
||||
assert( SERIES_COLUMN_STEP == SERIES_COLUMN_START+2 );
|
||||
|
||||
aIdx[0] = aIdx[1] = aIdx[2] = -1;
|
||||
aIdx[0] = aIdx[1] = aIdx[2] = aIdx[3] = aIdx[4] = -1;
|
||||
pConstraint = pIdxInfo->aConstraint;
|
||||
for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
|
||||
int iCol; /* 0 for start, 1 for stop, 2 for step */
|
||||
int iMask; /* bitmask for those column */
|
||||
int op = pConstraint->op;
|
||||
if( op>=SQLITE_INDEX_CONSTRAINT_LIMIT
|
||||
&& op<=SQLITE_INDEX_CONSTRAINT_OFFSET
|
||||
){
|
||||
if( pConstraint->usable==0 ){
|
||||
/* do nothing */
|
||||
}else if( op==SQLITE_INDEX_CONSTRAINT_LIMIT ){
|
||||
aIdx[3] = i;
|
||||
idxNum |= 0x20;
|
||||
}else{
|
||||
assert( op==SQLITE_INDEX_CONSTRAINT_OFFSET );
|
||||
aIdx[4] = i;
|
||||
idxNum |= 0x40;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if( pConstraint->iColumn<SERIES_COLUMN_START ) continue;
|
||||
iCol = pConstraint->iColumn - SERIES_COLUMN_START;
|
||||
assert( iCol>=0 && iCol<=2 );
|
||||
iMask = 1 << iCol;
|
||||
if( iCol==0 ) bStartSeen = 1;
|
||||
#ifndef ZERO_ARGUMENT_GENERATE_SERIES
|
||||
if( iCol==0 && op==SQLITE_INDEX_CONSTRAINT_EQ ){
|
||||
bStartSeen = 1;
|
||||
}
|
||||
#endif
|
||||
if( pConstraint->usable==0 ){
|
||||
unusableMask |= iMask;
|
||||
continue;
|
||||
}else if( pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ ){
|
||||
}else if( op==SQLITE_INDEX_CONSTRAINT_EQ ){
|
||||
idxNum |= iMask;
|
||||
aIdx[iCol] = i;
|
||||
}
|
||||
}
|
||||
for(i=0; i<3; i++){
|
||||
if( aIdx[3]==0 ){
|
||||
/* Ignore OFFSET if LIMIT is omitted */
|
||||
idxNum &= ~0x60;
|
||||
aIdx[4] = 0;
|
||||
}
|
||||
for(i=0; i<5; i++){
|
||||
if( (j = aIdx[i])>=0 ){
|
||||
pIdxInfo->aConstraintUsage[j].argvIndex = ++nArg;
|
||||
pIdxInfo->aConstraintUsage[j].omit = !SQLITE_SERIES_CONSTRAINT_VERIFY;
|
||||
pIdxInfo->aConstraintUsage[j].omit =
|
||||
!SQLITE_SERIES_CONSTRAINT_VERIFY || i>=3;
|
||||
}
|
||||
}
|
||||
/* The current generate_column() implementation requires at least one
|
||||
@@ -510,19 +559,22 @@ static int seriesBestIndex(
|
||||
** this plan is unusable */
|
||||
return SQLITE_CONSTRAINT;
|
||||
}
|
||||
if( (idxNum & 3)==3 ){
|
||||
if( (idxNum & 0x03)==0x03 ){
|
||||
/* Both start= and stop= boundaries are available. This is the
|
||||
** the preferred case */
|
||||
pIdxInfo->estimatedCost = (double)(2 - ((idxNum&4)!=0));
|
||||
pIdxInfo->estimatedRows = 1000;
|
||||
if( pIdxInfo->nOrderBy>=1 && pIdxInfo->aOrderBy[0].iColumn==0 ){
|
||||
if( pIdxInfo->aOrderBy[0].desc ){
|
||||
idxNum |= 8;
|
||||
idxNum |= 0x08;
|
||||
}else{
|
||||
idxNum |= 16;
|
||||
idxNum |= 0x10;
|
||||
}
|
||||
pIdxInfo->orderByConsumed = 1;
|
||||
}
|
||||
}else if( (idxNum & 0x21)==0x21 ){
|
||||
/* We have start= and LIMIT */
|
||||
pIdxInfo->estimatedRows = 2500;
|
||||
}else{
|
||||
/* If either boundary is missing, we have to generate a huge span
|
||||
** of numbers. Make this case very expensive so that the query
|
||||
|
||||
+154
-40
@@ -38,8 +38,9 @@ SQLITE_EXTENSION_INIT1
|
||||
typedef struct vtablog_vtab vtablog_vtab;
|
||||
struct vtablog_vtab {
|
||||
sqlite3_vtab base; /* Base class - must be first */
|
||||
char *zDb; /* Schema name. argv[1] of xConnect/xCreate */
|
||||
char *zName; /* Table name. argv[2] of xConnect/xCreate */
|
||||
int nRow; /* Number of rows in the table */
|
||||
int iInst; /* Instance number for this vtablog table */
|
||||
int nCursor; /* Number of cursors created */
|
||||
};
|
||||
|
||||
@@ -167,15 +168,14 @@ static int vtablogConnectCreate(
|
||||
char **pzErr,
|
||||
int isCreate
|
||||
){
|
||||
static int nInst = 0;
|
||||
vtablog_vtab *pNew;
|
||||
int i;
|
||||
int rc;
|
||||
int iInst = ++nInst;
|
||||
char *zSchema = 0;
|
||||
char *zNRow = 0;
|
||||
|
||||
printf("vtablog%s(tab=%d):\n", isCreate ? "Create" : "Connect", iInst);
|
||||
printf("%s.%s.%s():\n", argv[1], argv[2],
|
||||
isCreate ? "xCreate" : "xConnect");
|
||||
printf(" argc=%d\n", argc);
|
||||
for(i=0; i<argc; i++){
|
||||
printf(" argv[%d] = ", i);
|
||||
@@ -189,17 +189,18 @@ static int vtablogConnectCreate(
|
||||
for(i=3; i<argc; i++){
|
||||
const char *z = argv[i];
|
||||
if( vtablog_string_parameter(pzErr, "schema", z, &zSchema) ){
|
||||
return SQLITE_ERROR;
|
||||
rc = SQLITE_ERROR;
|
||||
goto vtablog_end_connect;
|
||||
}
|
||||
if( vtablog_string_parameter(pzErr, "rows", z, &zNRow) ){
|
||||
return SQLITE_ERROR;
|
||||
rc = SQLITE_ERROR;
|
||||
goto vtablog_end_connect;
|
||||
}
|
||||
}
|
||||
|
||||
if( zSchema==0 ){
|
||||
*pzErr = sqlite3_mprintf("no schema defined");
|
||||
return SQLITE_ERROR;
|
||||
zSchema = sqlite3_mprintf("%s","CREATE TABLE x(a,b);");
|
||||
}
|
||||
printf(" schema = '%s'\n", zSchema);
|
||||
rc = sqlite3_declare_vtab(db, zSchema);
|
||||
if( rc==SQLITE_OK ){
|
||||
pNew = sqlite3_malloc( sizeof(*pNew) );
|
||||
@@ -208,8 +209,14 @@ static int vtablogConnectCreate(
|
||||
memset(pNew, 0, sizeof(*pNew));
|
||||
pNew->nRow = 10;
|
||||
if( zNRow ) pNew->nRow = atoi(zNRow);
|
||||
pNew->iInst = iInst;
|
||||
printf(" nrow = %d\n", pNew->nRow);
|
||||
pNew->zDb = sqlite3_mprintf("%s", argv[1]);
|
||||
pNew->zName = sqlite3_mprintf("%s", argv[2]);
|
||||
}
|
||||
|
||||
vtablog_end_connect:
|
||||
sqlite3_free(zSchema);
|
||||
sqlite3_free(zNRow);
|
||||
return rc;
|
||||
}
|
||||
static int vtablogCreate(
|
||||
@@ -237,7 +244,9 @@ static int vtablogConnect(
|
||||
*/
|
||||
static int vtablogDisconnect(sqlite3_vtab *pVtab){
|
||||
vtablog_vtab *pTab = (vtablog_vtab*)pVtab;
|
||||
printf("vtablogDisconnect(%d)\n", pTab->iInst);
|
||||
printf("%s.%s.xDisconnect()\n", pTab->zDb, pTab->zName);
|
||||
sqlite3_free(pTab->zDb);
|
||||
sqlite3_free(pTab->zName);
|
||||
sqlite3_free(pVtab);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
@@ -247,7 +256,9 @@ static int vtablogDisconnect(sqlite3_vtab *pVtab){
|
||||
*/
|
||||
static int vtablogDestroy(sqlite3_vtab *pVtab){
|
||||
vtablog_vtab *pTab = (vtablog_vtab*)pVtab;
|
||||
printf("vtablogDestroy(%d)\n", pTab->iInst);
|
||||
printf("%s.%s.xDestroy()\n", pTab->zDb, pTab->zName);
|
||||
sqlite3_free(pTab->zDb);
|
||||
sqlite3_free(pTab->zName);
|
||||
sqlite3_free(pVtab);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
@@ -258,7 +269,8 @@ static int vtablogDestroy(sqlite3_vtab *pVtab){
|
||||
static int vtablogOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
|
||||
vtablog_vtab *pTab = (vtablog_vtab*)p;
|
||||
vtablog_cursor *pCur;
|
||||
printf("vtablogOpen(tab=%d, cursor=%d)\n", pTab->iInst, ++pTab->nCursor);
|
||||
printf("%s.%s.xOpen(cursor=%d)\n", pTab->zDb, pTab->zName,
|
||||
++pTab->nCursor);
|
||||
pCur = sqlite3_malloc( sizeof(*pCur) );
|
||||
if( pCur==0 ) return SQLITE_NOMEM;
|
||||
memset(pCur, 0, sizeof(*pCur));
|
||||
@@ -273,7 +285,7 @@ static int vtablogOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
|
||||
static int vtablogClose(sqlite3_vtab_cursor *cur){
|
||||
vtablog_cursor *pCur = (vtablog_cursor*)cur;
|
||||
vtablog_vtab *pTab = (vtablog_vtab*)cur->pVtab;
|
||||
printf("vtablogClose(tab=%d, cursor=%d)\n", pTab->iInst, pCur->iCursor);
|
||||
printf("%s.%s.xClose(cursor=%d)\n", pTab->zDb, pTab->zName, pCur->iCursor);
|
||||
sqlite3_free(cur);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
@@ -285,8 +297,9 @@ static int vtablogClose(sqlite3_vtab_cursor *cur){
|
||||
static int vtablogNext(sqlite3_vtab_cursor *cur){
|
||||
vtablog_cursor *pCur = (vtablog_cursor*)cur;
|
||||
vtablog_vtab *pTab = (vtablog_vtab*)cur->pVtab;
|
||||
printf("vtablogNext(tab=%d, cursor=%d) rowid %d -> %d\n",
|
||||
pTab->iInst, pCur->iCursor, (int)pCur->iRowid, (int)pCur->iRowid+1);
|
||||
printf("%s.%s.xNext(cursor=%d) rowid %d -> %d\n",
|
||||
pTab->zDb, pTab->zName, pCur->iCursor,
|
||||
(int)pCur->iRowid, (int)pCur->iRowid+1);
|
||||
pCur->iRowid++;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
@@ -310,8 +323,8 @@ static int vtablogColumn(
|
||||
}else{
|
||||
sqlite3_snprintf(sizeof(zVal),zVal,"{%d}%d", i, pCur->iRowid);
|
||||
}
|
||||
printf("vtablogColumn(tab=%d, cursor=%d, i=%d): [%s]\n",
|
||||
pTab->iInst, pCur->iCursor, i, zVal);
|
||||
printf("%s.%s.xColumn(cursor=%d, i=%d): [%s]\n",
|
||||
pTab->zDb, pTab->zName, pCur->iCursor, i, zVal);
|
||||
sqlite3_result_text(ctx, zVal, -1, SQLITE_TRANSIENT);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
@@ -323,8 +336,8 @@ static int vtablogColumn(
|
||||
static int vtablogRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
|
||||
vtablog_cursor *pCur = (vtablog_cursor*)cur;
|
||||
vtablog_vtab *pTab = (vtablog_vtab*)cur->pVtab;
|
||||
printf("vtablogRowid(tab=%d, cursor=%d): %d\n",
|
||||
pTab->iInst, pCur->iCursor, (int)pCur->iRowid);
|
||||
printf("%s.%s.xRowid(cursor=%d): %d\n",
|
||||
pTab->zDb, pTab->zName, pCur->iCursor, (int)pCur->iRowid);
|
||||
*pRowid = pCur->iRowid;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
@@ -337,8 +350,8 @@ static int vtablogEof(sqlite3_vtab_cursor *cur){
|
||||
vtablog_cursor *pCur = (vtablog_cursor*)cur;
|
||||
vtablog_vtab *pTab = (vtablog_vtab*)cur->pVtab;
|
||||
int rc = pCur->iRowid >= pTab->nRow;
|
||||
printf("vtablogEof(tab=%d, cursor=%d): %d\n",
|
||||
pTab->iInst, pCur->iCursor, rc);
|
||||
printf("%s.%s.xEof(cursor=%d): %d\n",
|
||||
pTab->zDb, pTab->zName, pCur->iCursor, rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -417,7 +430,7 @@ static int vtablogFilter(
|
||||
){
|
||||
vtablog_cursor *pCur = (vtablog_cursor *)cur;
|
||||
vtablog_vtab *pTab = (vtablog_vtab*)cur->pVtab;
|
||||
printf("vtablogFilter(tab=%d, cursor=%d):\n", pTab->iInst, pCur->iCursor);
|
||||
printf("%s.%s.xFilter(cursor=%d):\n", pTab->zDb, pTab->zName, pCur->iCursor);
|
||||
pCur->iRowid = 0;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
@@ -430,12 +443,37 @@ static int vtablogFilter(
|
||||
*/
|
||||
static int vtablogBestIndex(
|
||||
sqlite3_vtab *tab,
|
||||
sqlite3_index_info *pIdxInfo
|
||||
sqlite3_index_info *p
|
||||
){
|
||||
vtablog_vtab *pTab = (vtablog_vtab*)tab;
|
||||
printf("vtablogBestIndex(tab=%d):\n", pTab->iInst);
|
||||
pIdxInfo->estimatedCost = (double)500;
|
||||
pIdxInfo->estimatedRows = 500;
|
||||
int i;
|
||||
printf("%s.%s.xBestIndex():\n", pTab->zDb, pTab->zName);
|
||||
printf(" colUsed: 0x%016llx\n", p->colUsed);
|
||||
printf(" nConstraint: %d\n", p->nConstraint);
|
||||
for(i=0; i<p->nConstraint; i++){
|
||||
printf(
|
||||
" constraint[%d]: col=%d termid=%d op=%d usabled=%d collseq=%s\n",
|
||||
i,
|
||||
p->aConstraint[i].iColumn,
|
||||
p->aConstraint[i].iTermOffset,
|
||||
p->aConstraint[i].op,
|
||||
p->aConstraint[i].usable,
|
||||
sqlite3_vtab_collation(p,i));
|
||||
}
|
||||
printf(" nOrderBy: %d\n", p->nOrderBy);
|
||||
for(i=0; i<p->nOrderBy; i++){
|
||||
printf(" orderby[%d]: col=%d desc=%d\n",
|
||||
i,
|
||||
p->aOrderBy[i].iColumn,
|
||||
p->aOrderBy[i].desc);
|
||||
}
|
||||
p->estimatedCost = (double)500;
|
||||
p->estimatedRows = 500;
|
||||
printf(" idxNum=%d\n", p->idxNum);
|
||||
printf(" idxStr=NULL\n");
|
||||
printf(" orderByConsumed=%d\n", p->orderByConsumed);
|
||||
printf(" estimatedCost=%g\n", p->estimatedCost);
|
||||
printf(" estimatedRows=%lld\n", p->estimatedRows);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
@@ -454,7 +492,7 @@ static int vtablogUpdate(
|
||||
){
|
||||
vtablog_vtab *pTab = (vtablog_vtab*)tab;
|
||||
int i;
|
||||
printf("vtablogUpdate(tab=%d):\n", pTab->iInst);
|
||||
printf("%s.%s.xUpdate():\n", pTab->zDb, pTab->zName);
|
||||
printf(" argc=%d\n", argc);
|
||||
for(i=0; i<argc; i++){
|
||||
printf(" argv[%d]=", i);
|
||||
@@ -464,12 +502,88 @@ static int vtablogUpdate(
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
static int vtablogBegin(sqlite3_vtab *tab){
|
||||
vtablog_vtab *pTab = (vtablog_vtab*)tab;
|
||||
printf("%s.%s.xBegin()\n", pTab->zDb, pTab->zName);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
static int vtablogSync(sqlite3_vtab *tab){
|
||||
vtablog_vtab *pTab = (vtablog_vtab*)tab;
|
||||
printf("%s.%s.xSync()\n", pTab->zDb, pTab->zName);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
static int vtablogCommit(sqlite3_vtab *tab){
|
||||
vtablog_vtab *pTab = (vtablog_vtab*)tab;
|
||||
printf("%s.%s.xCommit()\n", pTab->zDb, pTab->zName);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
static int vtablogRollback(sqlite3_vtab *tab){
|
||||
vtablog_vtab *pTab = (vtablog_vtab*)tab;
|
||||
printf("%s.%s.xRollback()\n", pTab->zDb, pTab->zName);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
static int vtablogSavepoint(sqlite3_vtab *tab, int N){
|
||||
vtablog_vtab *pTab = (vtablog_vtab*)tab;
|
||||
printf("%s.%s.xSavepoint(%d)\n", pTab->zDb, pTab->zName, N);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
static int vtablogRelease(sqlite3_vtab *tab, int N){
|
||||
vtablog_vtab *pTab = (vtablog_vtab*)tab;
|
||||
printf("%s.%s.xRelease(%d)\n", pTab->zDb, pTab->zName, N);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
static int vtablogRollbackTo(sqlite3_vtab *tab, int N){
|
||||
vtablog_vtab *pTab = (vtablog_vtab*)tab;
|
||||
printf("%s.%s.xRollbackTo(%d)\n", pTab->zDb, pTab->zName, N);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
static int vtablogFindMethod(
|
||||
sqlite3_vtab *tab,
|
||||
int nArg,
|
||||
const char *zName,
|
||||
void (**pxFunc)(sqlite3_context*,int,sqlite3_value**),
|
||||
void **ppArg
|
||||
){
|
||||
vtablog_vtab *pTab = (vtablog_vtab*)tab;
|
||||
printf("%s.%s.xFindMethod(nArg=%d, zName=%s)\n",
|
||||
pTab->zDb, pTab->zName, nArg, zName);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
static int vtablogRename(sqlite3_vtab *tab, const char *zNew){
|
||||
vtablog_vtab *pTab = (vtablog_vtab*)tab;
|
||||
printf("%s.%s.xRename('%s')\n", pTab->zDb, pTab->zName, zNew);
|
||||
sqlite3_free(pTab->zName);
|
||||
pTab->zName = sqlite3_mprintf("%s", zNew);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/* Any table name that contains the text "shadow" is seen as a
|
||||
** shadow table. Nothing else is.
|
||||
*/
|
||||
static int vtablogShadowName(const char *zName){
|
||||
printf("vtablog.xShadowName('%s')\n", zName);
|
||||
return sqlite3_strglob("*shadow*", zName)==0;
|
||||
}
|
||||
|
||||
static int vtablogIntegrity(
|
||||
sqlite3_vtab *tab,
|
||||
const char *zSchema,
|
||||
const char *zTabName,
|
||||
int mFlags,
|
||||
char **pzErr
|
||||
){
|
||||
vtablog_vtab *pTab = (vtablog_vtab*)tab;
|
||||
printf("%s.%s.xIntegrity(mFlags=0x%x)\n", pTab->zDb, pTab->zName, mFlags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** This following structure defines all the methods for the
|
||||
** vtablog virtual table.
|
||||
*/
|
||||
static sqlite3_module vtablogModule = {
|
||||
0, /* iVersion */
|
||||
4, /* iVersion */
|
||||
vtablogCreate, /* xCreate */
|
||||
vtablogConnect, /* xConnect */
|
||||
vtablogBestIndex, /* xBestIndex */
|
||||
@@ -483,17 +597,17 @@ static sqlite3_module vtablogModule = {
|
||||
vtablogColumn, /* xColumn - read data */
|
||||
vtablogRowid, /* xRowid - read data */
|
||||
vtablogUpdate, /* xUpdate */
|
||||
0, /* xBegin */
|
||||
0, /* xSync */
|
||||
0, /* xCommit */
|
||||
0, /* xRollback */
|
||||
0, /* xFindMethod */
|
||||
0, /* xRename */
|
||||
0, /* xSavepoint */
|
||||
0, /* xRelease */
|
||||
0, /* xRollbackTo */
|
||||
0, /* xShadowName */
|
||||
0 /* xIntegrity */
|
||||
vtablogBegin, /* xBegin */
|
||||
vtablogSync, /* xSync */
|
||||
vtablogCommit, /* xCommit */
|
||||
vtablogRollback, /* xRollback */
|
||||
vtablogFindMethod, /* xFindMethod */
|
||||
vtablogRename, /* xRename */
|
||||
vtablogSavepoint, /* xSavepoint */
|
||||
vtablogRelease, /* xRelease */
|
||||
vtablogRollbackTo, /* xRollbackTo */
|
||||
vtablogShadowName, /* xShadowName */
|
||||
vtablogIntegrity /* xIntegrity */
|
||||
};
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
@@ -199,6 +199,7 @@ typedef unsigned int u32;
|
||||
typedef unsigned short u16;
|
||||
typedef unsigned char u8;
|
||||
typedef sqlite3_int64 i64;
|
||||
typedef sqlite3_uint64 u64;
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -885,6 +886,7 @@ static int rbuObjIterNext(sqlite3rbu *p, RbuObjIter *pIter){
|
||||
if( rc!=SQLITE_ROW ){
|
||||
rc = resetAndCollectError(pIter->pTblIter, &p->zErrmsg);
|
||||
pIter->zTbl = 0;
|
||||
pIter->zDataTbl = 0;
|
||||
}else{
|
||||
pIter->zTbl = (const char*)sqlite3_column_text(pIter->pTblIter, 0);
|
||||
pIter->zDataTbl = (const char*)sqlite3_column_text(pIter->pTblIter,1);
|
||||
@@ -2979,7 +2981,7 @@ static i64 rbuShmChecksum(sqlite3rbu *p){
|
||||
u32 volatile *ptr;
|
||||
p->rc = pDb->pMethods->xShmMap(pDb, 0, 32*1024, 0, (void volatile**)&ptr);
|
||||
if( p->rc==SQLITE_OK ){
|
||||
iRet = ((i64)ptr[10] << 32) + ptr[11];
|
||||
iRet = (i64)(((u64)ptr[10] << 32) + ptr[11]);
|
||||
}
|
||||
}
|
||||
return iRet;
|
||||
|
||||
+19
-5
@@ -494,6 +494,15 @@ static void dbdataValue(
|
||||
}
|
||||
}
|
||||
|
||||
/* This macro is a copy of the MX_CELL() macro in the SQLite core. Given
|
||||
** a page-size, it returns the maximum number of cells that may be present
|
||||
** on the page. */
|
||||
#define DBDATA_MX_CELL(pgsz) ((pgsz-8)/6)
|
||||
|
||||
/* Maximum number of fields that may appear in a single record. This is
|
||||
** the "hard-limit", according to comments in sqliteLimit.h. */
|
||||
#define DBDATA_MX_FIELD 32676
|
||||
|
||||
/*
|
||||
** Move an sqlite_dbdata or sqlite_dbptr cursor to the next entry.
|
||||
*/
|
||||
@@ -522,6 +531,9 @@ static int dbdataNext(sqlite3_vtab_cursor *pCursor){
|
||||
assert( iOff+3+2<=pCsr->nPage );
|
||||
pCsr->iCell = pTab->bPtr ? -2 : 0;
|
||||
pCsr->nCell = get_uint16(&pCsr->aPage[iOff+3]);
|
||||
if( pCsr->nCell>DBDATA_MX_CELL(pCsr->nPage) ){
|
||||
pCsr->nCell = DBDATA_MX_CELL(pCsr->nPage);
|
||||
}
|
||||
}
|
||||
|
||||
if( pTab->bPtr ){
|
||||
@@ -566,19 +578,19 @@ static int dbdataNext(sqlite3_vtab_cursor *pCursor){
|
||||
if( pCsr->iCell>=pCsr->nCell ){
|
||||
bNextPage = 1;
|
||||
}else{
|
||||
int iCellPtr = iOff + 8 + nPointer + pCsr->iCell*2;
|
||||
|
||||
iOff += 8 + nPointer + pCsr->iCell*2;
|
||||
if( iOff>pCsr->nPage ){
|
||||
if( iCellPtr>pCsr->nPage ){
|
||||
bNextPage = 1;
|
||||
}else{
|
||||
iOff = get_uint16(&pCsr->aPage[iOff]);
|
||||
iOff = get_uint16(&pCsr->aPage[iCellPtr]);
|
||||
}
|
||||
|
||||
/* For an interior node cell, skip past the child-page number */
|
||||
iOff += nPointer;
|
||||
|
||||
/* Load the "byte of payload including overflow" field */
|
||||
if( bNextPage || iOff>pCsr->nPage ){
|
||||
if( bNextPage || iOff>pCsr->nPage || iOff<=iCellPtr ){
|
||||
bNextPage = 1;
|
||||
}else{
|
||||
iOff += dbdataGetVarintU32(&pCsr->aPage[iOff], &nPayload);
|
||||
@@ -661,7 +673,9 @@ static int dbdataNext(sqlite3_vtab_cursor *pCursor){
|
||||
pCsr->iField++;
|
||||
if( pCsr->iField>0 ){
|
||||
sqlite3_int64 iType;
|
||||
if( pCsr->pHdrPtr>&pCsr->pRec[pCsr->nRec] ){
|
||||
if( pCsr->pHdrPtr>=&pCsr->pRec[pCsr->nRec]
|
||||
|| pCsr->iField>=DBDATA_MX_FIELD
|
||||
){
|
||||
bNextPage = 1;
|
||||
}else{
|
||||
int szField = 0;
|
||||
|
||||
@@ -524,5 +524,33 @@ do_test 7.1 {
|
||||
list [catch { $R finish } msg] $msg
|
||||
} {1 {file is not a database}}
|
||||
|
||||
reset_db
|
||||
breakpoint
|
||||
do_test 8.0 {
|
||||
sqlite3 db {}
|
||||
db deserialize [decode_hexdb {
|
||||
| size 8192 pagesize 4096 filename db.sqlite
|
||||
| page 1 offset 0
|
||||
| 0: ac ae b3 76 74 65 20 66 6f 72 6d 61 74 20 33 00 ...vte format 3.
|
||||
| 16: 10 00 01 01 00 40 20 20 00 00 00 01 00 00 00 02 .....@ ........
|
||||
| 32: 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 04 ................
|
||||
| 48: 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 ................
|
||||
| 80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 ................
|
||||
| 96: 00 2e 76 8a 0d ff ff ff 1e 0f cb 00 0f cb 00 00 ..v.............
|
||||
| 4032: 00 00 00 00 00 00 00 00 00 00 00 33 01 06 17 19 ...........3....
|
||||
| 4048: 19 01 43 74 61 62 6c 65 54 61 62 6c 65 30 54 61 ..CtableTable0Ta
|
||||
| 4064: 62 6c 65 30 02 43 52 45 41 54 45 20 54 41 42 4c ble0.CREATE TABL
|
||||
| 4080: 45 20 54 61 62 6c 65 30 20 28 43 6f 6c 30 20 29 E Table0 (Col0 )
|
||||
| page 2 offset 4096
|
||||
| 0: 0d 00 00 00 00 10 00 00 00 00 00 00 00 00 00 00 ................
|
||||
| end db.sqlite
|
||||
}]} {}
|
||||
|
||||
do_test 8.1 {
|
||||
set R [sqlite3_recover_init db main test.db2]
|
||||
catch { $R run }
|
||||
list [catch { $R finish } msg] $msg
|
||||
} {0 {}}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -1189,7 +1189,7 @@ static int recoverWriteSchema1(sqlite3_recover *p){
|
||||
if( bTable && !bVirtual ){
|
||||
if( SQLITE_ROW==sqlite3_step(pTblname) ){
|
||||
const char *zTbl = (const char*)sqlite3_column_text(pTblname, 0);
|
||||
recoverAddTable(p, zTbl, iRoot);
|
||||
if( zTbl ) recoverAddTable(p, zTbl, iRoot);
|
||||
}
|
||||
recoverReset(p, pTblname);
|
||||
}
|
||||
|
||||
+7
-4
@@ -1053,9 +1053,9 @@ static int rtreeDestroy(sqlite3_vtab *pVtab){
|
||||
Rtree *pRtree = (Rtree *)pVtab;
|
||||
int rc;
|
||||
char *zCreate = sqlite3_mprintf(
|
||||
"DROP TABLE '%q'.'%q_node',"
|
||||
"'%q'.'%q_rowid',"
|
||||
"'%q'.'%q_parent';",
|
||||
"DROP TABLE '%q'.'%q_node';"
|
||||
"DROP TABLE '%q'.'%q_rowid';"
|
||||
"DROP TABLE '%q'.'%q_parent';",
|
||||
pRtree->zDb, pRtree->zName,
|
||||
pRtree->zDb, pRtree->zName,
|
||||
pRtree->zDb, pRtree->zName
|
||||
@@ -1841,6 +1841,8 @@ static int deserializeGeometry(sqlite3_value *pValue, RtreeConstraint *pCons){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
int sqlite3IntFloatCompare(i64,double);
|
||||
|
||||
/*
|
||||
** Rtree virtual table module xFilter method.
|
||||
*/
|
||||
@@ -1870,7 +1872,8 @@ static int rtreeFilter(
|
||||
i64 iNode = 0;
|
||||
int eType = sqlite3_value_numeric_type(argv[0]);
|
||||
if( eType==SQLITE_INTEGER
|
||||
|| (eType==SQLITE_FLOAT && sqlite3_value_double(argv[0])==iRowid)
|
||||
|| (eType==SQLITE_FLOAT
|
||||
&& 0==sqlite3IntFloatCompare(iRowid,sqlite3_value_double(argv[0])))
|
||||
){
|
||||
rc = findLeafNode(pRtree, iRowid, &pLeaf, &iNode);
|
||||
}else{
|
||||
|
||||
@@ -797,4 +797,22 @@ do_test 23.0 {
|
||||
db eval {PRAGMA integrity_check;}
|
||||
} {ok}
|
||||
|
||||
reset_db
|
||||
do_execsql_test 24.0 {
|
||||
CREATE VIRTUAL TABLE rt1 USING rtree_i32(rid, c1, c2);
|
||||
INSERT INTO rt1(rid, c1, c2) VALUES (9223372036854775807, 10, 18);
|
||||
}
|
||||
|
||||
do_execsql_test 24.1 {
|
||||
SELECT (rid = (CAST (9223372036854775807 AS REAL)))
|
||||
FROM rt1 WHERE
|
||||
(rid = (CAST (9223372036854775807 AS REAL)));
|
||||
}
|
||||
|
||||
do_execsql_test 24.2 {
|
||||
DELETE FROM rt1;
|
||||
INSERT INTO rt1(rid, c1, c2) VALUES(1,2,3);
|
||||
SELECT * FROM rt1 WHERE rid=1.005;
|
||||
} {}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
# 2011 March 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 regression tests for SQLite library.
|
||||
#
|
||||
|
||||
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 sessionconflict
|
||||
|
||||
sqlite3_shutdown
|
||||
test_sqlite3_log log
|
||||
proc log {code msg} { puts "LOG $code $msg" }
|
||||
sqlite3 db test.db
|
||||
|
||||
forcedelete test.db2
|
||||
sqlite3 db2 test.db2
|
||||
|
||||
do_test 1.0 {
|
||||
do_common_sql {
|
||||
CREATE TABLE t1(a PRIMARY KEY, b, c UNIQUE);
|
||||
INSERT INTO t1 VALUES(1, 1, 1);
|
||||
INSERT INTO t1 VALUES(2, 2, 2);
|
||||
INSERT INTO t1 VALUES(3, 3, 3);
|
||||
}
|
||||
} {}
|
||||
|
||||
do_execsql_test -db db2 1.1 {
|
||||
INSERT INTO t1 VALUES(6, 6, 6);
|
||||
}
|
||||
|
||||
proc xConflict {args} {
|
||||
return "ABORT"
|
||||
}
|
||||
|
||||
|
||||
do_test 1.2 {
|
||||
set chng [changeset_from_sql {
|
||||
UPDATE t1 SET b=10, c=10 WHERE a=1;
|
||||
UPDATE t1 SET b=444 WHERE a=2;
|
||||
INSERT INTO t1 VALUES(4, 4, 4);
|
||||
INSERT INTO t1 VALUES(5, 5, 5);
|
||||
INSERT INTO t1 VALUES(6, 6, 6);
|
||||
}]
|
||||
|
||||
execsql BEGIN db2
|
||||
set res [list [catch { sqlite3changeset_apply db2 $chng xConflict } msg] $msg]
|
||||
execsql ROLLBACK db2
|
||||
set res
|
||||
} {1 SQLITE_ABORT}
|
||||
|
||||
do_execsql_test -db db2 1.3 {
|
||||
SELECT * FROM t1;
|
||||
} {
|
||||
1 1 1
|
||||
2 2 2
|
||||
3 3 3
|
||||
6 6 6
|
||||
}
|
||||
|
||||
|
||||
|
||||
finish_test
|
||||
+59
-14
@@ -289,6 +289,12 @@ endif
|
||||
# embedding in the JS files and in building the distribution zip file.
|
||||
# It must NOT be in $(dir.tmp) because we need it to survive the
|
||||
# cleanup process for the dist build to work properly.
|
||||
#
|
||||
# Slight caveat: this uses the version info from the in-tree
|
||||
# sqlite3.c/h, which may diff from a user-provided $(sqlite3.c). The
|
||||
# end result is that the generated JS files may have static version
|
||||
# info from $(bin.version-info) which differ from their runtime-emited
|
||||
# version info (e.g. from sqlite3_libversion()).
|
||||
bin.version-info := $(dir.top)/version-info
|
||||
.NOTPARALLEL: $(bin.version-info)
|
||||
$(bin.version-info): $(dir.tool)/version-info.c $(sqlite3.h) $(dir.top)/Makefile
|
||||
@@ -307,8 +313,9 @@ DISTCLEAN_FILES += $(bin.stripccomments)
|
||||
|
||||
|
||||
########################################################################
|
||||
# C-PP.FILTER: a $(call)able to transform $(1) to $(2) via ./c-pp -f
|
||||
# $(1) ...
|
||||
# C-PP.FILTER: a $(call)able to transform $(1) to $(2) via:
|
||||
#
|
||||
# ./c-pp -f $(1) -o $(2) $(3)
|
||||
#
|
||||
# Historical notes:
|
||||
#
|
||||
@@ -334,19 +341,26 @@ DISTCLEAN_FILES += $(bin.stripccomments)
|
||||
#
|
||||
# Note that the SQLITE_... build flags used here have NO EFFECT on the
|
||||
# JS/WASM build. They are solely for use with $(bin.c-pp) itself.
|
||||
#
|
||||
# -D... flags which should be included in all invocations should be
|
||||
# appended to $(C-PP.FILTER.global).
|
||||
bin.c-pp := ./c-pp
|
||||
$(bin.c-pp): c-pp.c $(sqlite3.c) $(MAKEFILE)
|
||||
$(CC) -O0 -o $@ c-pp.c $(sqlite3.c) '-DCMPP_DEFAULT_DELIM="//#"' -I$(dir.top) \
|
||||
-DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_UTF16 \
|
||||
-DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_WAL -DSQLITE_THREADSAFE=0 \
|
||||
-DSQLITE_TEMP_STORE=3
|
||||
C-PP.FILTER.global ?=
|
||||
ifeq (1,$(SQLITE_C_IS_SEE))
|
||||
C-PP.FILTER.global += -Denable-see
|
||||
endif
|
||||
define C-PP.FILTER
|
||||
# Create $2 from $1 using $(bin.c-pp)
|
||||
# $1 = Input file: c-pp -f $(1).js
|
||||
# $2 = Output file: c-pp -o $(2).js
|
||||
# $3 = optional c-pp -D... flags
|
||||
$(2): $(1) $$(MAKEFILE) $$(bin.c-pp)
|
||||
$$(bin.c-pp) -f $(1) -o $$@ $(3)
|
||||
$$(bin.c-pp) -f $(1) -o $$@ $(3) $(C-PP.FILTER.global)
|
||||
CLEAN_FILES += $(2)
|
||||
endef
|
||||
# /end C-PP.FILTER
|
||||
@@ -452,13 +466,14 @@ sqlite3-api.jses += $(dir.api)/sqlite3-api-cleanup.js
|
||||
# the first OPFS VFS and necessarily an external file.
|
||||
SOAP.js := $(dir.api)/sqlite3-opfs-async-proxy.js
|
||||
SOAP.js.bld := $(dir.dout)/$(notdir $(SOAP.js))
|
||||
sqlite3-api.ext.jses += $(SOAP.js.bld)
|
||||
#
|
||||
# $(sqlite3-api.ext.jses) = API-related files which are standalone files,
|
||||
# not part of the amalgamation.
|
||||
#
|
||||
sqlite3-api.ext.jses := $(SOAP.js.bld)
|
||||
$(SOAP.js.bld): $(SOAP.js)
|
||||
cp $< $@
|
||||
|
||||
all quick: $(sqlite3-api.ext.jses)
|
||||
q: quick
|
||||
|
||||
########################################################################
|
||||
# $(sqlite3-api*.*js) contain the core library code but not the
|
||||
# Emscripten-related glue which deals with loading sqlite3.wasm. In
|
||||
@@ -531,6 +546,10 @@ emcc.jsflags += -sSTRICT_JS=0
|
||||
# 3.1.31. The fix for that in newer emcc's is to throw a built-time
|
||||
# error if STRICT_JS is used together with those options.
|
||||
|
||||
# emcc.jsflags += -sSTRICT=1
|
||||
# -sSTRICT=1 Causes failures about unknown symbols which the build
|
||||
# tools should be installing, e.g. __syscall_geteuid32
|
||||
|
||||
# -sENVIRONMENT values for the various build modes:
|
||||
emcc.environment.vanilla := web,worker
|
||||
emcc.environment.bundler-friendly := $(emcc.environment.vanilla)
|
||||
@@ -551,6 +570,11 @@ emcc.environment.node := node
|
||||
# time with 16mb+ memory and 3X time when starting with 8MB. However,
|
||||
# such test results are inconsistent due to browser internals which
|
||||
# are opaque to us.
|
||||
#
|
||||
# 2024-03-04: emsdk 3.1.55 replaces INITIAL_MEMORY with INITIAL_HEAP,
|
||||
# but also says (in its changelog): "Note that it is currently not
|
||||
# supported in all configurations (#21071)."
|
||||
# https://github.com/emscripten-core/emscripten/blob/main/ChangeLog.md
|
||||
emcc.jsflags += -sALLOW_MEMORY_GROWTH
|
||||
emcc.INITIAL_MEMORY.128 := 134217728
|
||||
emcc.INITIAL_MEMORY.96 := 100663296
|
||||
@@ -816,13 +840,13 @@ pre-post-jses.deps.common := $(extern-pre-js.js) $(sqlite3-license-version.js)
|
||||
# $4 = resulting sqlite-api JS/MJS file
|
||||
# $5 = resulting JS/MJS file
|
||||
# $6 = -D... flags for $(bin.c-pp)
|
||||
# $7 = emcc -sXYZ flags (CURRENTLY UNUSED - was factored out)
|
||||
# $7 = optional extra flags for emcc
|
||||
#
|
||||
# Maintenance reminder: be careful not to introduce spaces around args
|
||||
# ($1, $2), otherwise string concatenation will malfunction.
|
||||
#
|
||||
# emcc.environment.$(2) must be set to a value for emcc's
|
||||
# -sENVIRONMENT flag.
|
||||
# Before calling this, emcc.environment.$(2) must be set to a value
|
||||
# for emcc's -sENVIRONMENT flag.
|
||||
#
|
||||
# $(cflags.$(1)) and $(cflags.$(1).$(2)) may be defined to append
|
||||
# CFLAGS to a given build mode.
|
||||
@@ -929,18 +953,39 @@ sqlite3-worker1.js.in := $(dir.api)/sqlite3-worker1.c-pp.js
|
||||
sqlite3-worker1-promiser.js.in := $(dir.api)/sqlite3-worker1-promiser.c-pp.js
|
||||
sqlite3-worker1.js := $(dir.dout)/sqlite3-worker1.js
|
||||
sqlite3-worker1-promiser.js := $(dir.dout)/sqlite3-worker1-promiser.js
|
||||
sqlite3-worker1-bundler-friendly.js := $(dir.dout)/sqlite3-worker1-bundler-friendly.mjs
|
||||
sqlite3-worker1-promiser.mjs := $(dir.dout)/sqlite3-worker1-promiser.mjs
|
||||
sqlite3-worker1-bundler-friendly.mjs := $(dir.dout)/sqlite3-worker1-bundler-friendly.mjs
|
||||
sqlite3-worker1-promiser-bundler-friendly.js := $(dir.dout)/sqlite3-worker1-promiser-bundler-friendly.js
|
||||
$(eval $(call C-PP.FILTER,$(sqlite3-worker1.js.in),$(sqlite3-worker1.js)))
|
||||
$(eval $(call C-PP.FILTER,$(sqlite3-worker1.js.in),$(sqlite3-worker1-bundler-friendly.js),\
|
||||
$(eval $(call C-PP.FILTER,$(sqlite3-worker1.js.in),$(sqlite3-worker1-bundler-friendly.mjs),\
|
||||
$(c-pp.D.sqlite3-bundler-friendly)))
|
||||
$(eval $(call C-PP.FILTER,$(sqlite3-worker1-promiser.js.in),$(sqlite3-worker1-promiser.js)))
|
||||
$(eval $(call C-PP.FILTER,$(sqlite3-worker1-promiser.js.in),\
|
||||
$(sqlite3-worker1-promiser-bundler-friendly.js),\
|
||||
$(c-pp.D.sqlite3-bundler-friendly)))
|
||||
$(sqlite3-bundler-friendly.mjs): $(sqlite3-worker1-bundler-friendly.js) \
|
||||
$(eval $(call C-PP.FILTER,$(sqlite3-worker1-promiser.js.in),$(sqlite3-worker1-promiser.mjs),\
|
||||
-Dtarget=es6-module -Dtarget=es6-bundler-friendly))
|
||||
$(sqlite3-bundler-friendly.mjs): $(sqlite3-worker1-bundler-friendly.mjs) \
|
||||
$(sqlite3-worker1-promiser-bundler-friendly.js)
|
||||
$(sqlite3.js) $(sqlite3.mjs): $(sqlite3-worker1.js) $(sqlite3-worker1-promiser.js)
|
||||
$(eval $(call C-PP.FILTER,demo-worker1-promiser.c-pp.js,demo-worker1-promiser.js))
|
||||
$(eval $(call C-PP.FILTER,demo-worker1-promiser.c-pp.js,demo-worker1-promiser.mjs,\
|
||||
-Dtarget=es6-module))
|
||||
$(eval $(call C-PP.FILTER,demo-worker1-promiser.c-pp.html,demo-worker1-promiser.html))
|
||||
$(eval $(call C-PP.FILTER,demo-worker1-promiser.c-pp.html,demo-worker1-promiser-esm.html,\
|
||||
-Dtarget=es6-module))
|
||||
all: $(sqlite3-worker1.js) \
|
||||
$(sqlite3-worker1-promiser.js) $(sqlite3-worker1-promiser.mjs)
|
||||
|
||||
demo-worker1-promiser.html: $(sqlite3-worker1-promiser.js) demo-worker1-promiser.js
|
||||
demo-worker1-promiser-esm.html: $(sqlite3-worker1-promiser.mjs) demo-worker1-promiser.mjs
|
||||
all: demo-worker1-promiser.html demo-worker1-promiser-esm.html
|
||||
|
||||
sqlite3-api.ext.jses += \
|
||||
$(sqlite3-worker1-promiser.mjs) \
|
||||
$(sqlite3-worker1-bundler-friendly.mjs) \
|
||||
$(sqlite3-worker1.js)
|
||||
all quick: $(sqlite3-api.ext.jses)
|
||||
q: quick
|
||||
|
||||
########################################################################
|
||||
# batch-runner.js is part of one of the test apps which reads in SQL
|
||||
|
||||
@@ -329,7 +329,8 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
wasm.bindingSignatures.push(["sqlite3_normalized_sql", "string", "sqlite3_stmt*"]);
|
||||
}
|
||||
|
||||
if(wasm.exports.sqlite3_activate_see instanceof Function){
|
||||
//#if enable-see
|
||||
if(wasm.exports.sqlite3_key_v2 instanceof Function){
|
||||
/**
|
||||
This code is capable of using an SEE build but note that an SEE
|
||||
WASM build is generally incompatible with SEE's license
|
||||
@@ -346,6 +347,8 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
["sqlite3_activate_see", undefined, "string"]
|
||||
);
|
||||
}
|
||||
//#endif enable-see
|
||||
|
||||
/**
|
||||
Functions which require BigInt (int64) support are separated from
|
||||
the others because we need to conditionally bind them or apply
|
||||
@@ -624,10 +627,14 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
wasm.bindingSignatures.wasmInternal = [
|
||||
["sqlite3__wasm_db_reset", "int", "sqlite3*"],
|
||||
["sqlite3__wasm_db_vfs", "sqlite3_vfs*", "sqlite3*","string"],
|
||||
["sqlite3__wasm_vfs_create_file", "int",
|
||||
"sqlite3_vfs*","string","*", "int"],
|
||||
[/* DO NOT USE. This is deprecated since 2023-08-11 because it can
|
||||
trigger assert() in debug builds when used with file sizes
|
||||
which are not sizes to a multiple of a valid db page size. */
|
||||
"sqlite3__wasm_vfs_create_file", "int", "sqlite3_vfs*","string","*", "int"
|
||||
],
|
||||
["sqlite3__wasm_posix_create_file", "int", "string","*", "int"],
|
||||
["sqlite3__wasm_vfs_unlink", "int", "sqlite3_vfs*","string"]
|
||||
["sqlite3__wasm_vfs_unlink", "int", "sqlite3_vfs*","string"],
|
||||
["sqlite3__wasm_qfmt_token","string:dealloc", "string","int"]
|
||||
];
|
||||
|
||||
/**
|
||||
@@ -1547,6 +1554,10 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
case capi.SQLITE_CONFIG_SQLLOG: // 21 /* xSqllog, void* */
|
||||
case capi.SQLITE_CONFIG_WIN32_HEAPSIZE: // 23 /* int nByte */
|
||||
default:
|
||||
/* maintenance note: we specifically do not include
|
||||
SQLITE_CONFIG_ROWID_IN_VIEW here, on the grounds that
|
||||
it's only for legacy support and no apps written with
|
||||
this API require that. */
|
||||
return capi.SQLITE_NOTFOUND;
|
||||
}
|
||||
};
|
||||
|
||||
+222
-50
@@ -87,6 +87,104 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
*/
|
||||
const __vfsPostOpenSql = Object.create(null);
|
||||
|
||||
//#if enable-see
|
||||
/**
|
||||
Converts ArrayBuffer or Uint8Array ba into a string of hex
|
||||
digits.
|
||||
*/
|
||||
const byteArrayToHex = function(ba){
|
||||
if( ba instanceof ArrayBuffer ){
|
||||
ba = new Uint8Array(ba);
|
||||
}
|
||||
const li = [];
|
||||
const digits = "0123456789abcdef";
|
||||
for( const d of ba ){
|
||||
li.push( digits[(d & 0xf0) >> 4], digits[d & 0x0f] );
|
||||
}
|
||||
return li.join('');
|
||||
};
|
||||
|
||||
/**
|
||||
Internal helper to apply an SEE key to a just-opened
|
||||
database. Requires that db be-a DB object which has just been
|
||||
opened, opt be the options object processed by its ctor, and opt
|
||||
must have either the key, hexkey, or textkey properties, either
|
||||
as a string, an ArrayBuffer, or a Uint8Array.
|
||||
|
||||
This is a no-op in non-SEE builds. It throws on error and returns
|
||||
without side effects if none of the key/textkey/hexkey options
|
||||
are set. It throws if more than one is set or if any are set to
|
||||
values of an invalid type.
|
||||
|
||||
Returns true if it applies the key, else an unspecified falsy value.
|
||||
*/
|
||||
const dbCtorApplySEEKey = function(db,opt){
|
||||
if( !capi.sqlite3_key_v2 ) return;
|
||||
let keytype;
|
||||
let key;
|
||||
const check = (opt.key ? 1 : 0) + (opt.hexkey ? 1 : 0) + (opt.textkey ? 1 : 0);
|
||||
if( !check ) return;
|
||||
else if( check>1 ){
|
||||
toss3(capi.SQLITE_MISUSE,
|
||||
"Only ONE of (key, hexkey, textkey) may be provided.");
|
||||
}
|
||||
if( opt.key ){
|
||||
/* It is not legal to bind an argument to PRAGMA key=?, so we
|
||||
convert it to a hexkey... */
|
||||
keytype = 'key';
|
||||
key = opt.key;
|
||||
if('string'===typeof key){
|
||||
key = new TextEncoder('utf-8').encode(key);
|
||||
}
|
||||
if((key instanceof ArrayBuffer) || (key instanceof Uint8Array)){
|
||||
key = byteArrayToHex(key);
|
||||
keytype = 'hexkey';
|
||||
}else{
|
||||
toss3(capi.SQLITE_MISUSE,
|
||||
"Invalid value for the 'key' option. Expecting a string,",
|
||||
"ArrayBuffer, or Uint8Array.");
|
||||
return;
|
||||
}
|
||||
}else if( opt.textkey ){
|
||||
/* For textkey we need it to be in string form, so convert it to
|
||||
a string if it's a byte array... */
|
||||
keytype = 'textkey';
|
||||
key = opt.textkey;
|
||||
if(key instanceof ArrayBuffer){
|
||||
key = new Uint8Array(key);
|
||||
}
|
||||
if(key instanceof Uint8Array){
|
||||
key = new TextDecoder('utf-8').decode(key);
|
||||
}else if('string'!==typeof key){
|
||||
toss3(capi.SQLITE_MISUSE,
|
||||
"Invalid value for the 'textkey' option. Expecting a string,",
|
||||
"ArrayBuffer, or Uint8Array.");
|
||||
}
|
||||
}else if( opt.hexkey ){
|
||||
keytype = 'hexkey';
|
||||
key = opt.hexkey;
|
||||
if((key instanceof ArrayBuffer) || (key instanceof Uint8Array)){
|
||||
key = byteArrayToHex(key);
|
||||
}else if('string'!==typeof key){
|
||||
toss3(capi.SQLITE_MISUSE,
|
||||
"Invalid value for the 'hexkey' option. Expecting a string,",
|
||||
"ArrayBuffer, or Uint8Array.");
|
||||
}
|
||||
/* else assume it's valid hex codes */
|
||||
}else{
|
||||
return;
|
||||
}
|
||||
let stmt;
|
||||
try{
|
||||
stmt = db.prepare("PRAGMA "+keytype+"="+util.sqlite3__wasm_qfmt_token(key, 1));
|
||||
stmt.step();
|
||||
}finally{
|
||||
if(stmt) stmt.finalize();
|
||||
}
|
||||
return true;
|
||||
};
|
||||
//#endif enable-see
|
||||
|
||||
/**
|
||||
A proxy for DB class constructors. It must be called with the
|
||||
being-construct DB object as its "this". See the DB constructor
|
||||
@@ -175,16 +273,28 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
__ptrMap.set(this, pDb);
|
||||
__stmtMap.set(this, Object.create(null));
|
||||
try{
|
||||
//#if enable-see
|
||||
dbCtorApplySEEKey(this,opt);
|
||||
//#endif
|
||||
// Check for per-VFS post-open SQL/callback...
|
||||
const pVfs = capi.sqlite3_js_db_vfs(pDb);
|
||||
if(!pVfs) toss3("Internal error: cannot get VFS for new db handle.");
|
||||
const pVfs = capi.sqlite3_js_db_vfs(pDb)
|
||||
|| toss3("Internal error: cannot get VFS for new db handle.");
|
||||
const postInitSql = __vfsPostOpenSql[pVfs];
|
||||
if(postInitSql instanceof Function){
|
||||
postInitSql(this, sqlite3);
|
||||
}else if(postInitSql){
|
||||
checkSqlite3Rc(
|
||||
pDb, capi.sqlite3_exec(pDb, postInitSql, 0, 0, 0)
|
||||
);
|
||||
if(postInitSql){
|
||||
/**
|
||||
Reminder: if this db is encrypted and the client did _not_ pass
|
||||
in the key, any init code will fail, causing the ctor to throw.
|
||||
We don't actually know whether the db is encrypted, so we cannot
|
||||
sensibly apply any heuristics which skip the init code only for
|
||||
encrypted databases for which no key has yet been supplied.
|
||||
*/
|
||||
if(postInitSql instanceof Function){
|
||||
postInitSql(this, sqlite3);
|
||||
}else{
|
||||
checkSqlite3Rc(
|
||||
pDb, capi.sqlite3_exec(pDb, postInitSql, 0, 0, 0)
|
||||
);
|
||||
}
|
||||
}
|
||||
}catch(e){
|
||||
this.close();
|
||||
@@ -280,6 +390,36 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
- `flags`: open-mode flags
|
||||
- `vfs`: the VFS fname
|
||||
|
||||
//#if enable-see
|
||||
|
||||
SEE-capable builds optionally support ONE of the following
|
||||
additional options:
|
||||
|
||||
- `key`, `hexkey`, or `textkey`: encryption key as a string,
|
||||
ArrayBuffer, or Uint8Array. These flags function as documented
|
||||
for the SEE pragmas of the same names. Using a byte array for
|
||||
`hexkey` is equivalent to the same series of hex codes in
|
||||
string form, so `'666f6f'` is equivalent to
|
||||
`Uint8Array([0x66,0x6f,0x6f])`. A `textkey` byte array is
|
||||
assumed to be UTF-8. A `key` string is transformed into a UTF-8
|
||||
byte array, and a `key` byte array is transformed into a
|
||||
`hexkey` with the same bytes.
|
||||
|
||||
In non-SEE builds, these options are ignored. In SEE builds,
|
||||
`PRAGMA key/textkey/hexkey=X` is executed immediately after
|
||||
opening the db. If more than one of the options is provided,
|
||||
or any option has an invalid argument type, an exception is
|
||||
thrown.
|
||||
|
||||
Note that some DB subclasses may run post-initialization SQL
|
||||
code, e.g. to set a busy-handler timeout or tweak the page cache
|
||||
size. Such code is run _after_ the SEE key is applied. If no key
|
||||
is supplied and the database is encrypted, execution of the
|
||||
post-initialization SQL will fail, causing the constructor to
|
||||
throw.
|
||||
|
||||
//#endif enable-see
|
||||
|
||||
The `filename` and `vfs` arguments may be either JS strings or
|
||||
C-strings allocated via WASM. `flags` is required to be a JS
|
||||
string (because it's specific to this API, which is specific
|
||||
@@ -288,7 +428,8 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
For purposes of passing a DB instance to C-style sqlite3
|
||||
functions, the DB object's read-only `pointer` property holds its
|
||||
`sqlite3*` pointer value. That property can also be used to check
|
||||
whether this DB instance is still open.
|
||||
whether this DB instance is still open: it will evaluate to
|
||||
`undefined` after the DB object's close() method is called.
|
||||
|
||||
In the main window thread, the filenames `":localStorage:"` and
|
||||
`":sessionStorage:"` are special: they cause the db to use either
|
||||
@@ -433,40 +574,56 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
out.returnVal = ()=>opt.resultRows;
|
||||
}
|
||||
if(opt.callback || opt.resultRows){
|
||||
switch((undefined===opt.rowMode)
|
||||
? 'array' : opt.rowMode) {
|
||||
case 'object': out.cbArg = (stmt)=>stmt.get(Object.create(null)); break;
|
||||
case 'array': out.cbArg = (stmt)=>stmt.get([]); break;
|
||||
case 'stmt':
|
||||
if(Array.isArray(opt.resultRows)){
|
||||
toss3("exec(): invalid rowMode for a resultRows array: must",
|
||||
"be one of 'array', 'object',",
|
||||
"a result column number, or column name reference.");
|
||||
}
|
||||
out.cbArg = (stmt)=>stmt;
|
||||
switch((undefined===opt.rowMode) ? 'array' : opt.rowMode) {
|
||||
case 'object':
|
||||
out.cbArg = (stmt,cache)=>{
|
||||
if( !cache.columnNames ) cache.columnNames = stmt.getColumnNames([]);
|
||||
/* https://sqlite.org/forum/forumpost/3632183d2470617d:
|
||||
conversion of rows to objects (key/val pairs) is
|
||||
somewhat expensive for large data sets because of the
|
||||
native-to-JS conversion of the column names. If we
|
||||
instead cache the names and build objects from that
|
||||
list of strings, it can run twice as fast. The
|
||||
difference is not noticeable for small data sets but
|
||||
becomes human-perceivable when enough rows are
|
||||
involved. */
|
||||
const row = stmt.get([]);
|
||||
const rv = Object.create(null);
|
||||
for( const i in cache.columnNames ) rv[cache.columnNames[i]] = row[i];
|
||||
return rv;
|
||||
};
|
||||
break;
|
||||
case 'array': out.cbArg = (stmt)=>stmt.get([]); break;
|
||||
case 'stmt':
|
||||
if(Array.isArray(opt.resultRows)){
|
||||
toss3("exec(): invalid rowMode for a resultRows array: must",
|
||||
"be one of 'array', 'object',",
|
||||
"a result column number, or column name reference.");
|
||||
}
|
||||
out.cbArg = (stmt)=>stmt;
|
||||
break;
|
||||
default:
|
||||
if(util.isInt32(opt.rowMode)){
|
||||
out.cbArg = (stmt)=>stmt.get(opt.rowMode);
|
||||
break;
|
||||
default:
|
||||
if(util.isInt32(opt.rowMode)){
|
||||
out.cbArg = (stmt)=>stmt.get(opt.rowMode);
|
||||
break;
|
||||
}else if('string'===typeof opt.rowMode
|
||||
&& opt.rowMode.length>1
|
||||
&& '$'===opt.rowMode[0]){
|
||||
/* "$X": fetch column named "X" (case-sensitive!). Prior
|
||||
to 2022-12-14 ":X" and "@X" were also permitted, but
|
||||
having so many options is unnecessary and likely to
|
||||
cause confusion. */
|
||||
const $colName = opt.rowMode.substr(1);
|
||||
out.cbArg = (stmt)=>{
|
||||
const rc = stmt.get(Object.create(null))[$colName];
|
||||
return (undefined===rc)
|
||||
? toss3(capi.SQLITE_NOTFOUND,
|
||||
"exec(): unknown result column:",$colName)
|
||||
: rc;
|
||||
};
|
||||
break;
|
||||
}
|
||||
toss3("Invalid rowMode:",opt.rowMode);
|
||||
}else if('string'===typeof opt.rowMode
|
||||
&& opt.rowMode.length>1
|
||||
&& '$'===opt.rowMode[0]){
|
||||
/* "$X": fetch column named "X" (case-sensitive!). Prior
|
||||
to 2022-12-14 ":X" and "@X" were also permitted, but
|
||||
having so many options is unnecessary and likely to
|
||||
cause confusion. */
|
||||
const $colName = opt.rowMode.substr(1);
|
||||
out.cbArg = (stmt)=>{
|
||||
const rc = stmt.get(Object.create(null))[$colName];
|
||||
return (undefined===rc)
|
||||
? toss3(capi.SQLITE_NOTFOUND,
|
||||
"exec(): unknown result column:",$colName)
|
||||
: rc;
|
||||
};
|
||||
break;
|
||||
}
|
||||
toss3("Invalid rowMode:",opt.rowMode);
|
||||
}
|
||||
}
|
||||
return out;
|
||||
@@ -884,10 +1041,15 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
and names. */) ? 0 : 1;
|
||||
evalFirstResult = false;
|
||||
if(arg.cbArg || resultRows){
|
||||
const cbArgCache = Object.create(null)
|
||||
/* 2nd arg for arg.cbArg, used by (at least) row-to-object
|
||||
converter */;
|
||||
for(; stmt.step(); stmt._lockedByExec = false){
|
||||
if(0===gotColNames++) stmt.getColumnNames(opt.columnNames);
|
||||
if(0===gotColNames++){
|
||||
stmt.getColumnNames(cbArgCache.columnNames = (opt.columnNames || []));
|
||||
}
|
||||
stmt._lockedByExec = true;
|
||||
const row = arg.cbArg(stmt);
|
||||
const row = arg.cbArg(stmt,cbArgCache);
|
||||
if(resultRows) resultRows.push(row);
|
||||
if(callback && false === callback.call(opt, row, stmt)){
|
||||
break;
|
||||
@@ -1522,7 +1684,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
they are larger than 32 bits, else double or int32, depending
|
||||
on whether they have a fractional part. Booleans are bound as
|
||||
integer 0 or 1. It is not expected the distinction of binding
|
||||
doubles which have no fractional parts is integers is
|
||||
doubles which have no fractional parts and integers is
|
||||
significant for the majority of clients due to sqlite3's data
|
||||
typing model. If [BigInt] support is enabled then this
|
||||
routine will bind BigInt values as 64-bit integers if they'll
|
||||
@@ -1906,16 +2068,26 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
Functionally equivalent to DB(storageName,'c','kvvfs') except
|
||||
that it throws if the given storage name is not one of 'local'
|
||||
or 'session'.
|
||||
|
||||
As of version 3.46, the argument may optionally be an options
|
||||
object in the form:
|
||||
|
||||
{
|
||||
filename: 'session'|'local',
|
||||
... etc. (all options supported by the DB ctor)
|
||||
}
|
||||
|
||||
noting that the 'vfs' option supported by main DB
|
||||
constructor is ignored here: the vfs is always 'kvvfs'.
|
||||
*/
|
||||
sqlite3.oo1.JsStorageDb = function(storageName='session'){
|
||||
const opt = dbCtorHelper.normalizeArgs(...arguments);
|
||||
storageName = opt.filename;
|
||||
if('session'!==storageName && 'local'!==storageName){
|
||||
toss3("JsStorageDb db name must be one of 'session' or 'local'.");
|
||||
}
|
||||
dbCtorHelper.call(this, {
|
||||
filename: storageName,
|
||||
flags: 'c',
|
||||
vfs: "kvvfs"
|
||||
});
|
||||
opt.vfs = 'kvvfs';
|
||||
dbCtorHelper.call(this, opt);
|
||||
};
|
||||
const jdb = sqlite3.oo1.JsStorageDb;
|
||||
jdb.prototype = Object.create(DB.prototype);
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
|
||||
This function expects a configuration object, intended to abstract
|
||||
away details specific to any given WASM environment, primarily so
|
||||
that it can be used without any _direct_ dependency on
|
||||
that it can be used without any direct dependency on
|
||||
Emscripten. (Note the default values for the config object!) The
|
||||
config object is only honored the first time this is
|
||||
called. Subsequent calls ignore the argument and return the same
|
||||
@@ -98,14 +98,37 @@
|
||||
|
||||
The returned object is the top-level sqlite3 namespace object.
|
||||
|
||||
|
||||
Client code may optionally assign sqlite3ApiBootstrap.defaultConfig
|
||||
an object-type value before calling sqlite3ApiBootstrap() (without
|
||||
arguments) in order to tell that call to use this object as its
|
||||
default config value. The intention of this is to provide
|
||||
downstream clients with a reasonably flexible approach for plugging
|
||||
in an environment-suitable configuration without having to define a
|
||||
new global-scope symbol.
|
||||
|
||||
However, because clients who access this library via an
|
||||
Emscripten-hosted module will not have an opportunity to call
|
||||
sqlite3ApiBootstrap() themselves, nor to access it before it is
|
||||
called, an alternative option for setting the configuration is to
|
||||
define globalThis.sqlite3ApiConfig to an object. If it is set, it
|
||||
is used instead of sqlite3ApiBootstrap.defaultConfig if
|
||||
sqlite3ApiBootstrap() is called without arguments.
|
||||
|
||||
Both sqlite3ApiBootstrap.defaultConfig and
|
||||
globalThis.sqlite3ApiConfig get deleted by sqlite3ApiBootstrap()
|
||||
because any changes to them made after that point would have no
|
||||
useful effect.
|
||||
*/
|
||||
'use strict';
|
||||
globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
|
||||
apiConfig = (globalThis.sqlite3ApiConfig || sqlite3ApiBootstrap.defaultConfig)
|
||||
){
|
||||
if(sqlite3ApiBootstrap.sqlite3){ /* already initalized */
|
||||
console.warn("sqlite3ApiBootstrap() called multiple times.",
|
||||
"Config and external initializers are ignored on calls after the first.");
|
||||
(sqlite3ApiBootstrap.sqlite3.config || console).warn(
|
||||
"sqlite3ApiBootstrap() called multiple times.",
|
||||
"Config and external initializers are ignored on calls after the first."
|
||||
);
|
||||
return sqlite3ApiBootstrap.sqlite3;
|
||||
}
|
||||
const config = Object.assign(Object.create(null),{
|
||||
@@ -114,8 +137,16 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
|
||||
bigIntEnabled: (()=>{
|
||||
if('undefined'!==typeof Module){
|
||||
/* Emscripten module will contain HEAPU64 when built with
|
||||
-sWASM_BIGINT=1, else it will not. */
|
||||
return !!Module.HEAPU64;
|
||||
-sWASM_BIGINT=1, else it will not.
|
||||
|
||||
As of emsdk 3.1.55, when building in strict mode, HEAPxyz
|
||||
are only available if _explicitly_ included in the exports,
|
||||
else they are not. We do not (as of 2024-03-04) use -sSTRICT
|
||||
for the canonical builds.
|
||||
*/
|
||||
if( !!Module.HEAPU64 ) return true;
|
||||
/* Else fall through and hope for the best. Nobody _really_
|
||||
builds this without BigInt support, do they? */
|
||||
}
|
||||
return !!globalThis.BigInt64Array;
|
||||
})(),
|
||||
@@ -149,6 +180,15 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
|
||||
config[k] = config[k]();
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
Eliminate any confusion about whether these config objects may
|
||||
be used after library initialization by eliminating the outward-facing
|
||||
objects...
|
||||
*/
|
||||
delete globalThis.sqlite3ApiConfig;
|
||||
delete sqlite3ApiBootstrap.defaultConfig;
|
||||
|
||||
/**
|
||||
The main sqlite3 binding API gets installed into this object,
|
||||
mimicking the C API as closely as we can. The numerous members
|
||||
@@ -205,7 +245,7 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
|
||||
|
||||
The exception's message is created by concatenating its
|
||||
arguments with a space between each, except for the
|
||||
two-args-with-an-objec form and that the first argument will
|
||||
two-args-with-an-object form and that the first argument will
|
||||
get coerced to a string, as described above, if it's an
|
||||
integer.
|
||||
|
||||
|
||||
@@ -459,11 +459,6 @@ sqlite3.initWorker1API = function(){
|
||||
return wState.dbList[0] && getDbId(wState.dbList[0]);
|
||||
};
|
||||
|
||||
const guessVfs = function(filename){
|
||||
const m = /^file:.+(vfs=(\w+))/.exec(filename);
|
||||
return sqlite3.capi.sqlite3_vfs_find(m ? m[2] : 0);
|
||||
};
|
||||
|
||||
const isSpecialDbFilename = (n)=>{
|
||||
return ""===n || ':'===n[0];
|
||||
};
|
||||
@@ -485,36 +480,8 @@ sqlite3.initWorker1API = function(){
|
||||
toss("Throwing because of simulateError flag.");
|
||||
}
|
||||
const rc = Object.create(null);
|
||||
let byteArray, pVfs;
|
||||
oargs.vfs = args.vfs;
|
||||
if(isSpecialDbFilename(args.filename)){
|
||||
oargs.filename = args.filename || "";
|
||||
}else{
|
||||
oargs.filename = args.filename;
|
||||
byteArray = args.byteArray;
|
||||
if(byteArray) pVfs = guessVfs(args.filename);
|
||||
}
|
||||
if(pVfs){
|
||||
/* 2022-11-02: this feature is as-yet untested except that
|
||||
sqlite3__wasm_vfs_create_file() has been tested from the
|
||||
browser dev console. */
|
||||
let pMem;
|
||||
try{
|
||||
pMem = sqlite3.wasm.allocFromTypedArray(byteArray);
|
||||
const rc = util.sqlite3__wasm_vfs_create_file(
|
||||
pVfs, oargs.filename, pMem, byteArray.byteLength
|
||||
);
|
||||
if(rc) sqlite3.SQLite3Error.toss(rc);
|
||||
}catch(e){
|
||||
throw new sqlite3.SQLite3Error(
|
||||
e.name+' creating '+args.filename+": "+e.message, {
|
||||
cause: e
|
||||
}
|
||||
);
|
||||
}finally{
|
||||
if(pMem) sqlite3.wasm.dealloc(pMem);
|
||||
}
|
||||
}
|
||||
oargs.filename = args.filename || "";
|
||||
const db = wState.open(oargs);
|
||||
rc.filename = db.filename;
|
||||
rc.persistent = !!sqlite3.capi.sqlite3_js_db_uses_vfs(db.pointer, "opfs");
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
*/
|
||||
"use strict";
|
||||
const wPost = (type,...args)=>postMessage({type, payload:args});
|
||||
const installAsyncProxy = function(self){
|
||||
const installAsyncProxy = function(){
|
||||
const toss = function(...args){throw new Error(args.join(' '))};
|
||||
if(globalThis.window === globalThis){
|
||||
toss("This code cannot run from the main thread.",
|
||||
@@ -562,6 +562,14 @@ const installAsyncProxy = function(self){
|
||||
wTimeEnd();
|
||||
return;
|
||||
}
|
||||
if( state.opfsFlags.OPFS_UNLINK_BEFORE_OPEN & opfsFlags ){
|
||||
try{
|
||||
await hDir.removeEntry(filenamePart);
|
||||
}catch(e){
|
||||
/* ignoring */
|
||||
//warn("Ignoring failed Unlink of",filename,":",e);
|
||||
}
|
||||
}
|
||||
const hFile = await hDir.getFileHandle(filenamePart, {create});
|
||||
wTimeEnd();
|
||||
const fh = Object.assign(Object.create(null),{
|
||||
@@ -911,5 +919,5 @@ if(!globalThis.SharedArrayBuffer){
|
||||
!navigator?.storage?.getDirectory){
|
||||
wPost('opfs-unavailable',"Missing required OPFS APIs.");
|
||||
}else{
|
||||
installAsyncProxy(self);
|
||||
installAsyncProxy();
|
||||
}
|
||||
|
||||
@@ -1272,7 +1272,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
return poolUtil;
|
||||
}).catch(async (e)=>{
|
||||
await thePool.removeVfs().catch(()=>{});
|
||||
return e;
|
||||
throw e;
|
||||
});
|
||||
}).catch((err)=>{
|
||||
//error("rejecting promise:",err);
|
||||
|
||||
@@ -423,10 +423,25 @@ const installOpfsVfs = function callee(options){
|
||||
});
|
||||
state.opfsFlags = Object.assign(Object.create(null),{
|
||||
/**
|
||||
Flag for use with xOpen(). "opfs-unlock-asap=1" enables
|
||||
this. See defaultUnlockAsap, below.
|
||||
Flag for use with xOpen(). URI flag "opfs-unlock-asap=1"
|
||||
enables this. See defaultUnlockAsap, below.
|
||||
*/
|
||||
OPFS_UNLOCK_ASAP: 0x01,
|
||||
/**
|
||||
Flag for use with xOpen(). URI flag "delete-before-open=1"
|
||||
tells the VFS to delete the db file before attempting to open
|
||||
it. This can be used, e.g., to replace a db which has been
|
||||
corrupted (without forcing us to expose a delete/unlink()
|
||||
function in the public API).
|
||||
|
||||
Failure to unlink the file is ignored but may lead to
|
||||
downstream errors. An unlink can fail if, e.g., another tab
|
||||
has the handle open.
|
||||
|
||||
It goes without saying that deleting a file out from under another
|
||||
instance results in Undefined Behavior.
|
||||
*/
|
||||
OPFS_UNLINK_BEFORE_OPEN: 0x02,
|
||||
/**
|
||||
If true, any async routine which implicitly acquires a sync
|
||||
access handle (i.e. an OPFS lock) will release that locks at
|
||||
@@ -875,13 +890,17 @@ const installOpfsVfs = function callee(options){
|
||||
let opfsFlags = 0;
|
||||
if(0===zName){
|
||||
zName = randomFilename();
|
||||
}else if('number'===typeof zName){
|
||||
}else if(wasm.isPtr(zName)){
|
||||
if(capi.sqlite3_uri_boolean(zName, "opfs-unlock-asap", 0)){
|
||||
/* -----------------------^^^^^ MUST pass the untranslated
|
||||
C-string here. */
|
||||
opfsFlags |= state.opfsFlags.OPFS_UNLOCK_ASAP;
|
||||
}
|
||||
if(capi.sqlite3_uri_boolean(zName, "delete-before-open", 0)){
|
||||
opfsFlags |= state.opfsFlags.OPFS_UNLINK_BEFORE_OPEN;
|
||||
}
|
||||
zName = wasm.cstrToJs(zName);
|
||||
//warn("xOpen zName =",zName, "opfsFlags =",opfsFlags);
|
||||
}
|
||||
const fh = Object.create(null);
|
||||
fh.fid = pFile;
|
||||
|
||||
+16
-23
@@ -545,6 +545,10 @@ const char * sqlite3__wasm_enum_json(void){
|
||||
DefInt(SQLITE_CONFIG_SMALL_MALLOC);
|
||||
DefInt(SQLITE_CONFIG_SORTERREF_SIZE);
|
||||
DefInt(SQLITE_CONFIG_MEMDB_MAXSIZE);
|
||||
/* maintenance note: we specifically do not include
|
||||
SQLITE_CONFIG_ROWID_IN_VIEW here, on the grounds that
|
||||
it's only for legacy support and no apps written with
|
||||
this API require that. */
|
||||
} _DefGroup;
|
||||
|
||||
DefGroup(dataTypes) {
|
||||
@@ -1674,35 +1678,24 @@ int sqlite3__wasm_config_j(int op, sqlite3_int64 arg){
|
||||
return sqlite3_config(op, arg);
|
||||
}
|
||||
|
||||
#if 0
|
||||
// Pending removal after verification of a workaround discussed in the
|
||||
// forum post linked to below.
|
||||
/*
|
||||
** This function is NOT part of the sqlite3 public API. It is strictly
|
||||
** for use by the sqlite project's own JS/WASM bindings.
|
||||
**
|
||||
** Returns a pointer to sqlite3_free(). In compliant browsers the
|
||||
** return value, when passed to sqlite3.wasm.exports.functionEntry(),
|
||||
** must resolve to the same function as
|
||||
** sqlite3.wasm.exports.sqlite3_free. i.e. from a dev console where
|
||||
** sqlite3 is exported globally, the following must be true:
|
||||
**
|
||||
** ```
|
||||
** sqlite3.wasm.functionEntry(
|
||||
** sqlite3.wasm.exports.sqlite3__wasm_ptr_to_sqlite3_free()
|
||||
** ) === sqlite3.wasm.exports.sqlite3_free
|
||||
** ```
|
||||
**
|
||||
** Using a function to return this pointer, as opposed to exporting it
|
||||
** via sqlite3__wasm_enum_json(), is an attempt to work around a
|
||||
** Safari-specific quirk covered at
|
||||
** https://sqlite.org/forum/info/e5b20e1feb37a19a.
|
||||
**/
|
||||
** If z is not NULL, returns the result of passing z to
|
||||
** sqlite3_mprintf()'s %Q modifier (if addQuotes is true) or %q (if
|
||||
** addQuotes is 0). Returns NULL if z is NULL or on OOM.
|
||||
*/
|
||||
SQLITE_WASM_EXPORT
|
||||
void * sqlite3__wasm_ptr_to_sqlite3_free(void){
|
||||
return (void*)sqlite3_free;
|
||||
char * sqlite3__wasm_qfmt_token(char *z, int addQuotes){
|
||||
char * rc = 0;
|
||||
if( z ){
|
||||
rc = addQuotes
|
||||
? sqlite3_mprintf("%Q", z)
|
||||
: sqlite3_mprintf("%q", z);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__EMSCRIPTEN__) && defined(SQLITE_ENABLE_WASMFS)
|
||||
#include <emscripten/wasmfs.h>
|
||||
|
||||
@@ -42,9 +42,13 @@
|
||||
- `onready` (optional, but...): this callback is called with no
|
||||
arguments when the worker fires its initial
|
||||
'sqlite3-api'/'worker1-ready' message, which it does when
|
||||
sqlite3.initWorker1API() completes its initialization. This is
|
||||
the simplest way to tell the worker to kick off work at the
|
||||
earliest opportunity.
|
||||
sqlite3.initWorker1API() completes its initialization. This is the
|
||||
simplest way to tell the worker to kick off work at the earliest
|
||||
opportunity, and the only way to know when the worker module has
|
||||
completed loading. The irony of using a callback for this, instead
|
||||
of returning a promise from sqlite3Worker1Promiser() is not lost on
|
||||
the developers: see sqlite3Worker1Promiser.v2() which uses a
|
||||
Promise instead.
|
||||
|
||||
- `onunhandled` (optional): a callback which gets passed the
|
||||
message event object for any worker.onmessage() events which
|
||||
@@ -247,9 +251,10 @@ globalThis.sqlite3Worker1Promiser = function callee(config = callee.defaultConfi
|
||||
return p;
|
||||
};
|
||||
}/*sqlite3Worker1Promiser()*/;
|
||||
|
||||
globalThis.sqlite3Worker1Promiser.defaultConfig = {
|
||||
worker: function(){
|
||||
//#if target=es6-bundler-friendly
|
||||
//#if target=es6-module
|
||||
return new Worker(new URL("sqlite3-worker1-bundler-friendly.mjs", import.meta.url),{
|
||||
type: 'module'
|
||||
});
|
||||
@@ -270,14 +275,72 @@ globalThis.sqlite3Worker1Promiser.defaultConfig = {
|
||||
return new Worker(theJs + globalThis.location.search);
|
||||
//#endif
|
||||
}
|
||||
//#ifnot target=es6-bundler-friendly
|
||||
//#ifnot target=es6-module
|
||||
.bind({
|
||||
currentScript: globalThis?.document?.currentScript
|
||||
})
|
||||
//#endif
|
||||
,
|
||||
onerror: (...args)=>console.error('worker1 promiser error',...args)
|
||||
};
|
||||
}/*defaultConfig*/;
|
||||
|
||||
/**
|
||||
sqlite3Worker1Promiser.v2(), added in 3.46, works identically to
|
||||
sqlite3Worker1Promiser() except that it returns a Promise instead
|
||||
of relying an an onready callback in the config object. The Promise
|
||||
resolves to the same factory function which
|
||||
sqlite3Worker1Promiser() returns.
|
||||
|
||||
If config is-a function or is an object which contains an onready
|
||||
function, that function is replaced by a proxy which will resolve
|
||||
after calling the original function and will reject if that
|
||||
function throws.
|
||||
*/
|
||||
sqlite3Worker1Promiser.v2 = function(config){
|
||||
let oldFunc;
|
||||
if( 'function' == typeof config ){
|
||||
oldFunc = config;
|
||||
config = {};
|
||||
}else if('function'===typeof config?.onready){
|
||||
oldFunc = config.onready;
|
||||
delete config.onready;
|
||||
}
|
||||
const promiseProxy = Object.create(null);
|
||||
config = Object.assign((config || Object.create(null)),{
|
||||
onready: async function(func){
|
||||
try {
|
||||
if( oldFunc ) await oldFunc(func);
|
||||
promiseProxy.resolve(func);
|
||||
}
|
||||
catch(e){promiseProxy.reject(e)}
|
||||
}
|
||||
});
|
||||
const p = new Promise(function(resolve,reject){
|
||||
promiseProxy.resolve = resolve;
|
||||
promiseProxy.reject = reject;
|
||||
});
|
||||
try{
|
||||
this.original(config);
|
||||
}catch(e){
|
||||
promiseProxy.reject(e);
|
||||
}
|
||||
return p;
|
||||
}.bind({
|
||||
/* We do this because clients are
|
||||
recommended to delete globalThis.sqlite3Worker1Promiser. */
|
||||
original: sqlite3Worker1Promiser
|
||||
});
|
||||
|
||||
//#if target=es6-module
|
||||
/**
|
||||
When built as a module, we export sqlite3Worker1Promiser.v2()
|
||||
instead of sqlite3Worker1Promise() because (A) its interface is more
|
||||
conventional for ESM usage and (B) the ESM option export option for
|
||||
this API did not exist until v2 was created, so there's no backwards
|
||||
incompatibility.
|
||||
*/
|
||||
export default sqlite3Worker1Promiser.v2;
|
||||
//#endif /* target=es6-module */
|
||||
//#else
|
||||
/* Built with the omit-oo1 flag. */
|
||||
//#endif ifnot omit-oo1
|
||||
|
||||
@@ -6,7 +6,11 @@
|
||||
<link rel="shortcut icon" href="data:image/x-icon;," type="image/x-icon">
|
||||
<link rel="stylesheet" href="common/emscripten.css"/>
|
||||
<link rel="stylesheet" href="common/testing.css"/>
|
||||
//#if target=es6-module
|
||||
<title>worker-promise (via ESM) tests</title>
|
||||
//#else
|
||||
<title>worker-promise tests</title>
|
||||
//#endif
|
||||
</head>
|
||||
<body>
|
||||
<header id='titlebar'><span>worker-promise tests</span></header>
|
||||
@@ -22,13 +26,17 @@
|
||||
</figure>
|
||||
<div class="emscripten" id="module-status">Downloading...</div>
|
||||
<div class="emscripten">
|
||||
<progress value="0" max="100" id="module-progress" hidden='1'></progress>
|
||||
<progress value="0" max="100" id="module-progress" hidden='1'></progress>
|
||||
</div><!-- /emscripten bits -->
|
||||
<div>Most stuff on this page happens in the dev console.</div>
|
||||
<hr>
|
||||
<div id='test-output'></div>
|
||||
<script src="common/SqliteTestUtil.js"></script>
|
||||
//#if target=es6-module
|
||||
<script src="demo-worker1-promiser.mjs" type="module"></script>
|
||||
//#else
|
||||
<script src="jswasm/sqlite3-worker1-promiser.js"></script>
|
||||
<script src="demo-worker1-promiser.js"></script>
|
||||
//#endif
|
||||
</body>
|
||||
</html>
|
||||
@@ -13,9 +13,15 @@
|
||||
Demonstration of the sqlite3 Worker API #1 Promiser: a Promise-based
|
||||
proxy for for the sqlite3 Worker #1 API.
|
||||
*/
|
||||
'use strict';
|
||||
(function(){
|
||||
const T = self.SqliteTestUtil;
|
||||
//#if target=es6-module
|
||||
import {default as promiserFactory} from "./jswasm/sqlite3-worker1-promiser.mjs";
|
||||
//#else
|
||||
"use strict";
|
||||
const promiserFactory = globalThis.sqlite3Worker1Promiser.v2;
|
||||
delete globalThis.sqlite3Worker1Promiser;
|
||||
//#endif
|
||||
(async function(){
|
||||
const T = globalThis.SqliteTestUtil;
|
||||
const eOutput = document.querySelector('#test-output');
|
||||
const warn = console.warn.bind(console);
|
||||
const error = console.error.bind(console);
|
||||
@@ -33,33 +39,35 @@
|
||||
logHtml("","Total test count:",T.counter+". Total time =",(performance.now() - startTime),"ms");
|
||||
};
|
||||
|
||||
//why is this triggered even when we catch() a Promise?
|
||||
//window.addEventListener('unhandledrejection', function(event) {
|
||||
// warn('unhandledrejection',event);
|
||||
//});
|
||||
|
||||
const promiserConfig = {
|
||||
worker: ()=>{
|
||||
const w = new Worker("jswasm/sqlite3-worker1.js");
|
||||
w.onerror = (event)=>error("worker.onerror",event);
|
||||
return w;
|
||||
//#ifnot target=es6-module
|
||||
/**
|
||||
The v1 interfaces uses an onready function. The v2 interface optionally
|
||||
accepts one but does not require it. If provided, it is called _before_
|
||||
the promise is resolved, and the promise is rejected if onready() throws.
|
||||
*/
|
||||
onready: function(f){
|
||||
/* f === the function returned by promiserFactory().
|
||||
Ostensibly (f === workerPromise) but this function is
|
||||
called before the promiserFactory() Promise resolves, so
|
||||
before workerPromise is set. */
|
||||
console.warn("This is the v2 interface - you don't need an onready() function.");
|
||||
},
|
||||
//#endif
|
||||
debug: 1 ? undefined : (...args)=>console.debug('worker debug',...args),
|
||||
onunhandled: function(ev){
|
||||
error("Unhandled worker message:",ev.data);
|
||||
},
|
||||
onready: function(){
|
||||
T.affirm(arguments[0] === workerPromise
|
||||
/* as of version 3.46. Prior to that this callback had no arguments */);
|
||||
self.sqlite3TestModule.setStatus(null)/*hide the HTML-side is-loading spinner*/;
|
||||
runTests();
|
||||
},
|
||||
onerror: function(ev){
|
||||
error("worker1 error:",ev);
|
||||
}
|
||||
};
|
||||
const workerPromise = self.sqlite3Worker1Promiser(promiserConfig);
|
||||
delete self.sqlite3Worker1Promiser;
|
||||
const workerPromise = await promiserFactory(promiserConfig)
|
||||
.then((func)=>{
|
||||
console.log("Init complete. Starting tests momentarily.");
|
||||
globalThis.sqlite3TestModule.setStatus(null)/*hide the HTML-side is-loading spinner*/;
|
||||
return func;
|
||||
});
|
||||
|
||||
const wtest = async function(msgType, msgArgs, callback){
|
||||
if(2===arguments.length && 'function'===typeof msgArgs){
|
||||
@@ -273,5 +281,5 @@
|
||||
}).finally(()=>logHtml('',"That's all, folks!"));
|
||||
}/*runTests2()*/;
|
||||
|
||||
log("Init complete, but async init bits may still be running.");
|
||||
runTests();
|
||||
})();
|
||||
+19
-6
@@ -19,10 +19,15 @@ MAKEFILE.dist := $(lastword $(MAKEFILE_LIST))
|
||||
# built, and won't be built until we expand the dependencies. Thus we
|
||||
# have to use a temporary name for the archive until we can get
|
||||
# that binary built.
|
||||
ifeq (,$(filter snapshot,$(MAKECMDGOALS)))
|
||||
dist-name-prefix := sqlite-wasm
|
||||
ifeq (1,$(SQLITE_C_IS_SEE))
|
||||
dist-name-extra := -see
|
||||
else
|
||||
dist-name-prefix := sqlite-wasm-snapshot-$(shell /usr/bin/date +%Y%m%d)
|
||||
dist-name-extra :=
|
||||
endif
|
||||
ifeq (,$(filter snapshot,$(MAKECMDGOALS)))
|
||||
dist-name-prefix := sqlite-wasm$(dist-name-extra)
|
||||
else
|
||||
dist-name-prefix := sqlite-wasm$(dist-name-extra)-snapshot-$(shell /usr/bin/date +%Y%m%d)
|
||||
endif
|
||||
dist-name := $(dist-name-prefix)-TEMP
|
||||
|
||||
@@ -49,12 +54,18 @@ dist.top.extras := \
|
||||
tester1.js tester1.mjs \
|
||||
demo-jsstorage.html demo-jsstorage.js \
|
||||
demo-worker1.html demo-worker1.js \
|
||||
demo-worker1-promiser.html demo-worker1-promiser.js
|
||||
dist.jswasm.extras := $(sqlite3-api.ext.jses) $(sqlite3.wasm)
|
||||
demo-worker1-promiser.html demo-worker1-promiser.js \
|
||||
demo-worker1-promiser-esm.html demo-worker1-promiser.mjs
|
||||
dist.jswasm.extras := $(sqlite3.wasm) \
|
||||
$(sqlite3-api.ext.jses)
|
||||
dist.common.extras := \
|
||||
$(wildcard $(dir.common)/*.css) \
|
||||
$(dir.common)/SqliteTestUtil.js
|
||||
|
||||
#$(info sqlite3-worker1-promiser.mjs = $(sqlite3-worker1-promiser.mjs))
|
||||
#$(info sqlite3-worker1.js = $(sqlite3-worker1.js))
|
||||
#$(info sqlite3-api.ext.jses = $(sqlite3-api.ext.jses))
|
||||
#$(info dist.jswasm.extras = $(dist.jswasm.extras))
|
||||
.PHONY: dist snapshot
|
||||
# DIST_STRIP_COMMENTS $(call)able to be used in stripping C-style
|
||||
# from the dist copies of certain files.
|
||||
@@ -67,7 +78,8 @@ endef
|
||||
# STRIP_K1.js = list of JS files which need to be passed through
|
||||
# $(bin.stripcomments) with a single -k flag.
|
||||
STRIP_K1.js := $(sqlite3-worker1.js) $(sqlite3-worker1-promiser.js) \
|
||||
$(sqlite3-worker1-bundler-friendly.js) $(sqlite3-worker1-promiser-bundler-friendly.js)
|
||||
$(sqlite3-worker1-bundler-friendly.js) \
|
||||
$(sqlite3-api.ext.jses)
|
||||
# STRIP_K2.js = list of JS files which need to be passed through
|
||||
# $(bin.stripcomments) with two -k flags.
|
||||
STRIP_K2.js := $(sqlite3.js) $(sqlite3.mjs) \
|
||||
@@ -88,6 +100,7 @@ STRIP_K2.js := $(sqlite3.js) $(sqlite3.mjs) \
|
||||
dist: \
|
||||
$(bin.stripccomments) $(bin.version-info) \
|
||||
$(dist.build) $(STRIP_K1.js) $(STRIP_K2.js) \
|
||||
$(dist.jswasm.extras) $(dist.common.extras) \
|
||||
$(MAKEFILE) $(MAKEFILE.dist)
|
||||
@echo "Making end-user deliverables..."
|
||||
@rm -fr $(dist-dir.top)
|
||||
|
||||
@@ -9,16 +9,18 @@ MAKEFILE.fiddle := $(lastword $(MAKEFILE_LIST))
|
||||
# shell.c and its build flags...
|
||||
make-np-0 := make -C $(dir.top) -n -p
|
||||
make-np-1 := sed -e 's/(TOP)/(dir.top)/g'
|
||||
# Extract SHELL_OPT and SHELL_DEP from the top-most makefile and import
|
||||
# them as vars here...
|
||||
$(eval $(shell $(make-np-0) | grep -e '^SHELL_OPT ' | $(make-np-1)))
|
||||
$(eval $(shell $(make-np-0) | grep -e '^SHELL_SRC ' | $(make-np-1)))
|
||||
$(eval $(shell $(make-np-0) | grep -e '^SHELL_DEP ' | $(make-np-1)))
|
||||
# ^^^ can't do that in 1 invocation b/c newlines get stripped
|
||||
ifeq (,$(SHELL_OPT))
|
||||
$(error Could not parse SHELL_OPT from $(dir.top)/Makefile.)
|
||||
endif
|
||||
ifeq (,$(SHELL_SRC))
|
||||
$(error Could not parse SHELL_SRC from $(dir.top)/Makefile.)
|
||||
ifeq (,$(SHELL_DEP))
|
||||
$(error Could not parse SHELL_DEP from $(dir.top)/Makefile.)
|
||||
endif
|
||||
$(dir.top)/shell.c: $(SHELL_SRC) $(dir.top)/tool/mkshellc.tcl $(sqlite3.c)
|
||||
$(dir.top)/shell.c: $(SHELL_DEP) $(dir.top)/tool/mkshellc.tcl $(sqlite3.c)
|
||||
$(MAKE) -C $(dir.top) shell.c
|
||||
# /shell.c
|
||||
########################################################################
|
||||
|
||||
@@ -166,11 +166,10 @@
|
||||
stdout("SQLite version", capi.sqlite3_libversion(),
|
||||
capi.sqlite3_sourceid().substr(0,19));
|
||||
stdout('Welcome to the "fiddle" shell.');
|
||||
if(sqlite3.opfs){
|
||||
if(capi.sqlite3_vfs_find("opfs")){
|
||||
stdout("\nOPFS is available. To open a persistent db, use:\n\n",
|
||||
" .open file:name?vfs=opfs\n\nbut note that some",
|
||||
"features (e.g. upload) do not yet work with OPFS.");
|
||||
sqlite3.opfs.registerVfs();
|
||||
}
|
||||
stdout('\nEnter ".help" for usage hints.');
|
||||
this.exec([ // initialization commands...
|
||||
@@ -317,7 +316,7 @@
|
||||
};
|
||||
console.warn("Unknown fiddle-worker message type:",ev);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
emscripten module for use with build mode -sMODULARIZE.
|
||||
*/
|
||||
|
||||
@@ -403,8 +403,10 @@
|
||||
E('#btn-reset').addEventListener('click',()=>SF.resetDb());
|
||||
const taInput = E('#input');
|
||||
const btnClearIn = E('#btn-clear');
|
||||
const selectExamples = E('#select-examples');
|
||||
btnClearIn.addEventListener('click',function(){
|
||||
taInput.value = '';
|
||||
selectExamples.selectedIndex = 0;
|
||||
},false);
|
||||
// Ctrl-enter and shift-enter both run the current SQL.
|
||||
taInput.addEventListener('keydown',function(ev){
|
||||
@@ -733,16 +735,15 @@
|
||||
]},
|
||||
//{name: "Timer on", sql: ".timer on"},
|
||||
// ^^^ re-enable if emscripten re-enables getrusage()
|
||||
{name: "Box Mode", sql: ".mode box"},
|
||||
{name: "Setup table T", sql:[
|
||||
".nullvalue NULL\n",
|
||||
"CREATE TABLE t(a,b);\n",
|
||||
"INSERT INTO t(a,b) VALUES('abc',123),('def',456),(NULL,789),('ghi',012);\n",
|
||||
"SELECT * FROM t;\n"
|
||||
]},
|
||||
{name: "Table list", sql: ".tables"},
|
||||
{name: "Box Mode", sql: ".mode box"},
|
||||
{name: "JSON Mode", sql: ".mode json"},
|
||||
{name: "Mandlebrot", sql:[
|
||||
{name: "sqlite_schema", sql: "select * from sqlite_schema"},
|
||||
{name: "Mandelbrot", sql:[
|
||||
"WITH RECURSIVE",
|
||||
" xaxis(x) AS (VALUES(-2.0) UNION ALL SELECT x+0.05 FROM xaxis WHERE x<1.2),\n",
|
||||
" yaxis(y) AS (VALUES(-1.0) UNION ALL SELECT y+0.1 FROM yaxis WHERE y<1.0),\n",
|
||||
@@ -760,7 +761,13 @@
|
||||
" FROM m2 GROUP BY cy\n",
|
||||
" )\n",
|
||||
"SELECT group_concat(rtrim(t),x'0a') as Mandelbrot FROM a;\n",
|
||||
]}
|
||||
]},
|
||||
{name: "JSON pretty-print",
|
||||
sql: "select json_pretty(json_object('ex',json('[52,3.14159]')))"
|
||||
},
|
||||
{name: "JSON pretty-print (with tabs)",
|
||||
sql: "select json_pretty(json_object('ex',json('[52,3.14159]')),char(0x09))"
|
||||
}
|
||||
];
|
||||
const newOpt = function(lbl,val){
|
||||
const o = document.createElement('option');
|
||||
|
||||
@@ -97,6 +97,8 @@
|
||||
wrapper is significantly easier to use, however.</li>
|
||||
<li><a href='demo-worker1-promiser.html'>demo-worker1-promiser</a>:
|
||||
a demo of the Promise-based wrapper of the Worker1 API.</li>
|
||||
<li><a href='demo-worker1-promiser-esm.html'>demo-worker1-promiser-esm</a>:
|
||||
same as the previous demo except loads the promiser from an ESM module.</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
@@ -84,6 +84,8 @@
|
||||
wrapper is significantly easier to use, however.</li>
|
||||
<li><a href='demo-worker1-promiser.html'>demo-worker1-promiser</a>:
|
||||
a demo of the Promise-based wrapper of the Worker1 API.</li>
|
||||
<li><a href='demo-worker1-promiser-esm.html'>demo-worker1-promiser-esm</a>:
|
||||
same as the previous demo except loads the promiser from an ESM module.</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>speedtest1 ports (sqlite3's primary benchmarking tool)...
|
||||
|
||||
+77
-17
@@ -1482,7 +1482,7 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
|
||||
/*step() skipped intentionally*/.reset(true);
|
||||
} finally {
|
||||
T.assert(0===st.finalize())
|
||||
.assert(undefined===st.finalize());
|
||||
.assert(undefined===st.finalize());
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -2587,7 +2587,7 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
|
||||
const pVfs = capi.sqlite3_vfs_find('kvvfs');
|
||||
T.assert(pVfs);
|
||||
const JDb = this.JDb = sqlite3.oo1.JsStorageDb;
|
||||
const unlink = this.kvvfsUnlink = ()=>{JDb.clearStorage(filename)};
|
||||
const unlink = this.kvvfsUnlink = ()=>JDb.clearStorage(this.kvvfsDbFile);
|
||||
unlink();
|
||||
let db = new JDb(filename);
|
||||
try {
|
||||
@@ -2605,6 +2605,60 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
|
||||
}
|
||||
}
|
||||
}/*kvvfs sanity checks*/)
|
||||
//#if enable-see
|
||||
.t({
|
||||
name: 'kvvfs with SEE encryption',
|
||||
predicate: ()=>(isUIThread()
|
||||
|| "Only available in main thread."),
|
||||
test: function(sqlite3){
|
||||
this.kvvfsUnlink();
|
||||
let db;
|
||||
const encOpt1 = 1
|
||||
? {textkey: 'foo'}
|
||||
: {key: 'foo'};
|
||||
const encOpt2 = encOpt1.textkey
|
||||
? encOpt1
|
||||
: {hexkey: new Uint8Array([0x66,0x6f,0x6f]/*==>"foo"*/)}
|
||||
try{
|
||||
db = new this.JDb({
|
||||
filename: this.kvvfsDbFile,
|
||||
...encOpt1
|
||||
});
|
||||
db.exec([
|
||||
"create table t(a,b);",
|
||||
"insert into t(a,b) values(1,2),(3,4)"
|
||||
]);
|
||||
db.close();
|
||||
let err;
|
||||
try{
|
||||
db = new this.JDb({
|
||||
filename: this.kvvfsDbFile,
|
||||
flags: 'ct'
|
||||
});
|
||||
T.assert(db) /* opening is fine, but... */;
|
||||
db.exec("select 1 from sqlite_schema");
|
||||
console.warn("sessionStorage =",sessionStorage);
|
||||
}catch(e){
|
||||
err = e;
|
||||
}finally{
|
||||
db.close();
|
||||
}
|
||||
T.assert(err,"Expecting an exception")
|
||||
.assert(sqlite3.capi.SQLITE_NOTADB==err.resultCode,
|
||||
"Expecting NOTADB");
|
||||
db = new sqlite3.oo1.DB({
|
||||
filename: this.kvvfsDbFile,
|
||||
vfs: 'kvvfs',
|
||||
...encOpt2
|
||||
});
|
||||
T.assert( 4===db.selectValue('select sum(a) from t') );
|
||||
}finally{
|
||||
if( db ) db.close();
|
||||
this.kvvfsUnlink();
|
||||
}
|
||||
}
|
||||
})/*kvvfs with SEE*/
|
||||
//#endif enable-see
|
||||
;/* end kvvfs tests */
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
@@ -2888,18 +2942,17 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
|
||||
.t({
|
||||
name: 'OPFS db sanity checks',
|
||||
test: async function(sqlite3){
|
||||
T.assert(capi.sqlite3_vfs_find('opfs'));
|
||||
const opfs = sqlite3.opfs;
|
||||
const filename = this.opfsDbFile = '/dir/sqlite3-tester1.db';
|
||||
const pVfs = this.opfsVfs = capi.sqlite3_vfs_find('opfs');
|
||||
T.assert(pVfs);
|
||||
const unlink = this.opfsUnlink =
|
||||
(fn=filename)=>{sqlite3.util.sqlite3__wasm_vfs_unlink(pVfs,fn)};
|
||||
unlink();
|
||||
let db = new sqlite3.oo1.OpfsDb(filename);
|
||||
const fileUri = 'file://'+filename+'?delete-before-open=1';
|
||||
const initSql = [
|
||||
'create table p(a);',
|
||||
'insert into p(a) values(1),(2),(3)'
|
||||
];
|
||||
let db = new sqlite3.oo1.OpfsDb(fileUri);
|
||||
try {
|
||||
db.exec([
|
||||
'create table p(a);',
|
||||
'insert into p(a) values(1),(2),(3)'
|
||||
]);
|
||||
db.exec(initSql);
|
||||
T.assert(3 === db.selectValue('select count(*) from p'));
|
||||
db.close();
|
||||
db = new sqlite3.oo1.OpfsDb(filename);
|
||||
@@ -2911,7 +2964,14 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
|
||||
&& 0===this.opfsDbExport.byteLength % 512);
|
||||
}finally{
|
||||
db.close();
|
||||
unlink();
|
||||
}
|
||||
T.assert(await opfs.entryExists(filename));
|
||||
try {
|
||||
db = new sqlite3.oo1.OpfsDb(fileUri);
|
||||
db.exec(initSql) /* will throw if delete-before-open did not work */;
|
||||
T.assert(3 === db.selectValue('select count(*) from p'));
|
||||
}finally{
|
||||
if(db) db.close();
|
||||
}
|
||||
}
|
||||
}/*OPFS db sanity checks*/)
|
||||
@@ -2919,15 +2979,17 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
|
||||
name: 'OPFS import',
|
||||
test: async function(sqlite3){
|
||||
let db;
|
||||
const filename = this.opfsDbFile;
|
||||
try {
|
||||
const exp = this.opfsDbExport;
|
||||
const filename = this.opfsDbFile;
|
||||
delete this.opfsDbExport;
|
||||
this.opfsImportSize = await sqlite3.oo1.OpfsDb.importDb(filename, exp);
|
||||
db = new sqlite3.oo1.OpfsDb(this.opfsDbFile);
|
||||
T.assert(6 === db.selectValue('select count(*) from p')).
|
||||
assert( this.opfsImportSize == exp.byteLength );
|
||||
db.close();
|
||||
const unlink = this.opfsUnlink =
|
||||
(fn=filename)=>sqlite3.util.sqlite3__wasm_vfs_unlink("opfs",fn);
|
||||
this.opfsUnlink(filename);
|
||||
T.assert(!(await sqlite3.opfs.entryExists(filename)));
|
||||
// Try again with a function as an input source:
|
||||
@@ -2954,11 +3016,9 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
|
||||
name: '(Internal-use) OPFS utility APIs',
|
||||
test: async function(sqlite3){
|
||||
const filename = this.opfsDbFile;
|
||||
const pVfs = this.opfsVfs;
|
||||
const unlink = this.opfsUnlink;
|
||||
T.assert(filename && pVfs && !!unlink);
|
||||
T.assert(filename && !!unlink);
|
||||
delete this.opfsDbFile;
|
||||
delete this.opfsVfs;
|
||||
delete this.opfsUnlink;
|
||||
/**************************************************************
|
||||
ATTENTION CLIENT-SIDE USERS: sqlite3.opfs is NOT intended
|
||||
|
||||
@@ -718,8 +718,7 @@ opcodes.c: opcodes.h $(TOP)/tool/mkopcodec.tcl
|
||||
tclsh $(TOP)/tool/mkopcodec.tcl opcodes.h >opcodes.c
|
||||
|
||||
opcodes.h: parse.h $(TOP)/src/vdbe.c $(TOP)/tool/mkopcodeh.tcl
|
||||
cat parse.h $(TOP)/src/vdbe.c | \
|
||||
tclsh $(TOP)/tool/mkopcodeh.tcl >opcodes.h
|
||||
cat parse.h $(TOP)/src/vdbe.c | tclsh $(TOP)/tool/mkopcodeh.tcl >opcodes.h
|
||||
|
||||
# Rules to build parse.c and parse.h - the outputs of lemon.
|
||||
#
|
||||
@@ -742,32 +741,37 @@ keywordhash.h: $(TOP)/tool/mkkeywordhash.c
|
||||
$(BCC) -o mkkeywordhash $(OPTS) $(TOP)/tool/mkkeywordhash.c
|
||||
./mkkeywordhash >keywordhash.h
|
||||
|
||||
# Source files that go into making shell.c
|
||||
SHELL_SRC = \
|
||||
$(TOP)/src/shell.c.in \
|
||||
$(TOP)/ext/misc/appendvfs.c \
|
||||
$(TOP)/ext/misc/completion.c \
|
||||
$(TOP)/ext/misc/base64.c \
|
||||
$(TOP)/ext/misc/base85.c \
|
||||
$(TOP)/ext/misc/decimal.c \
|
||||
$(TOP)/ext/misc/fileio.c \
|
||||
$(TOP)/ext/misc/ieee754.c \
|
||||
$(TOP)/ext/misc/regexp.c \
|
||||
$(TOP)/ext/misc/series.c \
|
||||
$(TOP)/ext/misc/shathree.c \
|
||||
$(TOP)/ext/misc/sqlar.c \
|
||||
$(TOP)/ext/misc/uint.c \
|
||||
$(TOP)/ext/expert/sqlite3expert.c \
|
||||
$(TOP)/ext/expert/sqlite3expert.h \
|
||||
$(TOP)/ext/misc/zipfile.c \
|
||||
$(TOP)/ext/misc/memtrace.c \
|
||||
$(TOP)/ext/misc/pcachetrace.c \
|
||||
$(TOP)/ext/recover/dbdata.c \
|
||||
$(TOP)/ext/recover/sqlite3recover.c \
|
||||
$(TOP)/ext/recover/sqlite3recover.h \
|
||||
$(TOP)/src/test_windirent.c
|
||||
# Source and header files that shell.c depends on
|
||||
SHELL_DEP = \
|
||||
$(TOP)/src/shell.c.in \
|
||||
$(TOP)/ext/consio/console_io.c \
|
||||
$(TOP)/ext/consio/console_io.h \
|
||||
$(TOP)/ext/expert/sqlite3expert.c \
|
||||
$(TOP)/ext/expert/sqlite3expert.h \
|
||||
$(TOP)/ext/intck/sqlite3intck.c \
|
||||
$(TOP)/ext/intck/sqlite3intck.h \
|
||||
$(TOP)/ext/misc/appendvfs.c \
|
||||
$(TOP)/ext/misc/base64.c \
|
||||
$(TOP)/ext/misc/base85.c \
|
||||
$(TOP)/ext/misc/completion.c \
|
||||
$(TOP)/ext/misc/decimal.c \
|
||||
$(TOP)/ext/misc/fileio.c \
|
||||
$(TOP)/ext/misc/ieee754.c \
|
||||
$(TOP)/ext/misc/memtrace.c \
|
||||
$(TOP)/ext/misc/pcachetrace.c \
|
||||
$(TOP)/ext/misc/regexp.c \
|
||||
$(TOP)/ext/misc/series.c \
|
||||
$(TOP)/ext/misc/shathree.c \
|
||||
$(TOP)/ext/misc/sqlar.c \
|
||||
$(TOP)/ext/misc/uint.c \
|
||||
$(TOP)/ext/misc/zipfile.c \
|
||||
$(TOP)/ext/recover/dbdata.c \
|
||||
$(TOP)/ext/recover/sqlite3recover.c \
|
||||
$(TOP)/ext/recover/sqlite3recover.h \
|
||||
$(TOP)/src/test_windirent.c \
|
||||
$(TOP)/src/test_windirent.h
|
||||
|
||||
shell.c: $(SHELL_SRC) $(TOP)/tool/mkshellc.tcl
|
||||
shell.c: $(SHELL_DEP) $(TOP)/tool/mkshellc.tcl
|
||||
tclsh $(TOP)/tool/mkshellc.tcl >shell.c
|
||||
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
C The\sability\sto\sDROP\smultiple\stables\s(or\sviews\sor\sindexes\sor\striggers)\sat\sonce,\nas\simplemented\sby\sthis\sbranch,\sappears\sto\swork.\s\sHowever,\sthis\sbranch\sadds\sover\n1000\sbytes\sto\sthe\scode\sfootprint.\s\sAnd\sthe\schanges\sis\ssignificant,\sadding\srisk.\nThe\sbenefit\sof\sbeing\sable\sto\sdrop\smultiple\stables\sin\sa\ssingle\sstatement\sis\snot\nseen\sto\sbe\senough\sto\sovercome\sthose\sdownsides,\sand\sso\sthere\sare\sno\simmediate\nplans\sto\smerge\sthis\sbranch.
|
||||
D 2024-03-04T18:02:36.966
|
||||
C Allow\svirtual\stable\simplementations\sto\shandle\sOFFSET\sbut\snot\sLIMIT,\sbut\snot\sLIMIT\sbut\snot\sOFFSET.
|
||||
D 2024-04-26T18:13:11.880
|
||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
|
||||
F Makefile.in 3c4f4879b2301e5486939f68cc64f84430861d246ac11430ff1a1d7347ed5b8c
|
||||
F Makefile.in 993a7874e3d3721df61846f03dda4a9ef7490da11953ae36ba1bb0c0346eaf4a
|
||||
F Makefile.linux-gcc f3842a0b1efbfbb74ac0ef60e56b301836d05b4d867d014f714fa750048f1ab6
|
||||
F Makefile.msc 15a875f6016c4200e7093db92365fabb8b32eb09f9e40e1aadeedeecad4050d5
|
||||
F Makefile.msc e64a52619310d3067f6c38f56eedd15918a82dade70954197d6da486ad99d7f4
|
||||
F README.md 6358805260a03ebead84e168bbf3740ddf3f683b477e478567186aa7afb490d3
|
||||
F VERSION c84541c6a9e8426462176fbb1f9ecb5cfd7d1bb56228053ff7eeba8841673eb6
|
||||
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
|
||||
@@ -44,7 +44,7 @@ F doc/json-enhancements.md e356fc834781f1f1aa22ee300027a270b2c960122468499bf347b
|
||||
F doc/jsonb.md 5fab4b8613aa9153fbeb6259297bd4697988af8b3d23900deba588fa7841456b
|
||||
F doc/lemon.html 8b266ff711d2ec7f867c3dca37634963f48a630329908cc282beebfa8c708706
|
||||
F doc/pager-invariants.txt 27fed9a70ddad2088750c4a2b493b63853da2710
|
||||
F doc/testrunner.md 8d36ec692cf4994bb66d84a4645b9afa1ce9d47dc12cbf8d437c5a5fb6ddeedb
|
||||
F doc/testrunner.md 15583cf8c7d8a1c3378fd5d4319ca769a14c4d950a5df9b015d01d5be290dc69
|
||||
F doc/trusted-schema.md 33625008620e879c7bcfbbfa079587612c434fa094d338b08242288d358c3e8a
|
||||
F doc/vdbesort-memory.md 4da2639c14cd24a31e0af694b1a8dd37eaf277aff3867e9a8cc14046bc49df56
|
||||
F doc/vfs-shm.txt e101f27ea02a8387ce46a05be2b1a902a021d37a
|
||||
@@ -57,8 +57,8 @@ F ext/consio/console_io.c f32b757c9ee7fdf68e7586bee306f8368759e7cd12febb2a683919
|
||||
F ext/consio/console_io.h 0548b83d7c4b7270ad544a67f2bb90cebc519637fa39b1838df4744cf0d87646
|
||||
F ext/expert/README.md b321c2762bb93c18ea102d5a5f7753a4b8bac646cb392b3b437f633caf2020c3
|
||||
F ext/expert/expert.c d548d603a4cc9e61f446cc179c120c6713511c413f82a4a32b1e1e69d3f086a4
|
||||
F ext/expert/expert1.test 0dd5cb096d66bed593e33053a3b364f6ef52ed72064bf5cf298364636dbf3cd6
|
||||
F ext/expert/sqlite3expert.c 90446bb1183429308c68ceb23e00cb8252f43b8886cf5efa3fc7e833b5fa24c8
|
||||
F ext/expert/expert1.test 53a749de08939e3bc14f804e97410927d46fa772cbce0247d7e8fa6fc2523b0c
|
||||
F ext/expert/sqlite3expert.c c8cea5ff15fbe792cccc4992a9b40b706411c41d32611f617897fecac6ff06a4
|
||||
F ext/expert/sqlite3expert.h ca81efc2679a92373a13a3e76a6138d0310e32be53d6c3bfaedabd158ea8969b
|
||||
F ext/expert/test_expert.c d56c194b769bdc90cf829a14c9ecbc1edca9c850b837a4d0b13be14095c32a72
|
||||
F ext/fts3/README.content b9078d0843a094d86af0d48dffbff13c906702b4c3558012e67b9c7cc3bf59ee
|
||||
@@ -74,7 +74,7 @@ F ext/fts3/fts3_hash.c 8b6e31bfb0844c27dc6092c2620bdb1fca17ed613072db057d96952c6
|
||||
F ext/fts3/fts3_hash.h 39cf6874dc239d6b4e30479b1975fe5b22a3caaf
|
||||
F ext/fts3/fts3_icu.c 305ce7fb6036484085b5556a9c8e62acdc7763f0f4cdf5fd538212a9f3720116
|
||||
F ext/fts3/fts3_porter.c e19807ce0ae31c1c6e9898e89ecc93183d7ec224ea101af039722a4f49e5f2b8
|
||||
F ext/fts3/fts3_snippet.c 4d6523e3eddeb7b46e7a82b3476a0a86a0c04821e0e2b8dd40f45ee28057cb13
|
||||
F ext/fts3/fts3_snippet.c 610328fe128c047c6b0eba77768982ccf3933daae095d497949a75c9dfd47409
|
||||
F ext/fts3/fts3_term.c 845f0e2456b1be42f7f1bec1da1dfc05bc347531eff90775ffc6698902c281de
|
||||
F ext/fts3/fts3_test.c d8d7b2734f894e8a489987447658e374cdd3a3bc8575c401decf1911cb7c6454
|
||||
F ext/fts3/fts3_tokenize_vtab.c 7fd9ef364f257b97218b9c331f2378e307375c592f70fd541f714e747d944962
|
||||
@@ -92,7 +92,7 @@ F ext/fts3/unicode/UnicodeData.txt cd07314edb62d49fde34debdaf92fa2aa69011e7
|
||||
F ext/fts3/unicode/mkunicode.tcl d5aebf022fa4577ee8cdf27468f0d847879993959101f6dbd6348ef0cfc324a7
|
||||
F ext/fts3/unicode/parseunicode.tcl a981bd6466d12dd17967515801c3ff23f74a281be1a03cf1e6f52a6959fc77eb
|
||||
F ext/fts5/extract_api_docs.tcl bc3a0ca78be7d3df08e7602c00ca48021ebae40682d75eb001bfdf6e54ffb44e
|
||||
F ext/fts5/fts5.h ecba24fed7b359b3a53016bb07e411b3b4c9cdf163aa141006536423a63b611e
|
||||
F ext/fts5/fts5.h 8856e11a5f0269cd346754cea0765efe8089635b80cad3222e8bfdb08cd5348a
|
||||
F ext/fts5/fts5Int.h defa43c0932265138ee910ca416e6baccf8b774e0f3d610e74be1ab2880e9834
|
||||
F ext/fts5/fts5_aux.c 4584e88878e54828bf7d4d0d83deedd232ec60628b7731be02bad6adb62304b1
|
||||
F ext/fts5/fts5_buffer.c 0eec58bff585f1a44ea9147eae5da2447292080ea435957f7488c70673cb6f09
|
||||
@@ -248,17 +248,17 @@ F ext/fts5/tool/loadfts5.tcl 95b03429ee6b138645703c6ca192c3ac96eaf093
|
||||
F ext/fts5/tool/mkfts5c.tcl 3eba8e9bee4221ed165f3304b51b2a74a705f4ec5df3d044573a2be539534af8
|
||||
F ext/fts5/tool/showfts5.tcl d54da0e067306663e2d5d523965ca487698e722c
|
||||
F ext/icu/README.txt 7ab7ced8ae78e3a645b57e78570ff589d4c672b71370f5aa9e1cd7024f400fc9
|
||||
F ext/icu/icu.c c074519b46baa484bb5396c7e01e051034da8884bad1a1cb7f09bbe6be3f0282
|
||||
F ext/icu/icu.c 3add8197e0a86c1761771a39500ebae749438bcf1836160b407a56b4eaa8721c
|
||||
F ext/icu/sqliteicu.h fa373836ed5a1ee7478bdf8a1650689294e41d0c89c1daab26e9ae78a32075a8
|
||||
F ext/intck/intck1.test 8a879640c90fdff5e91e6c2c41d509485ee634e8077fe0ca9f76be4cbd441fa3
|
||||
F ext/intck/intck2.test 47afb44681d13d11072cd8906e6aa877c967e65be788b01f6139922fd91474ef
|
||||
F ext/intck/intck_common.tcl 9e51458126576783f11051ac0fd25bea3f6b17f570a55884223737f3200b214b
|
||||
F ext/intck/intckbusy.test 0732fe3efbb9e0a53ffdcc240073f6ff2777ea82c3e08812b16494f650763fe1
|
||||
F ext/intck/intckcorrupt.test 3211ef68ac53e83951b6c8f6a8d2396506d123fe5898f97f848a25837744ec56
|
||||
F ext/intck/intckfault.test ba0213c9c8dce08d519d5251268a3bab076a184b4d07acdea23b65e89c9ae03c
|
||||
F ext/intck/sqlite3intck.c 52381a627637504a49e93400814b36e99afa0b972a9a24ef1732b8268bb27fa8
|
||||
F ext/intck/intck1.test f3a3cba14b6aeff145ffa5515546dd22f7510dad91512e519f43b92b56514012
|
||||
F ext/intck/intck2.test d2457c7e5e5b688046d15ebe08a1e1427cc5e7a6dc8d6af215f42e8bcaf67304
|
||||
F ext/intck/intck_common.tcl a61fd2697ae55b0a3d89847ca0b590c6e0d8ff64bebb70920d93724799894159
|
||||
F ext/intck/intckbusy.test d5ed4ef85a4b1dc1dee2484bd14a4bb68529659cca743327df0c775f005fa387
|
||||
F ext/intck/intckcorrupt.test f6c302792326fb3db9dcfc70b554c55369bc4b52882eaaf039cfe0b74c821029
|
||||
F ext/intck/intckfault.test cff3f75dff74abb3edfcb13f6aa53f6436746ab64b09fe5e2028f051e985efab
|
||||
F ext/intck/sqlite3intck.c 0d10df36e2b7b438aa80ecd3f5e584d41b747586b038258fe6b407f66b81e7c5
|
||||
F ext/intck/sqlite3intck.h 2b40c38e7063ab822c974c0bd4aed97dabb579ccfe2e180a4639bb3bbef0f1c9
|
||||
F ext/intck/test_intck.c d63f1707432802f5db125ee40b794923af77d4686869bd8d3a7eb43332344267
|
||||
F ext/intck/test_intck.c 34243458378a12d1356c79219a03f244800533b3ab65b4a02861f0403364df12
|
||||
F ext/jni/GNUmakefile 59eb05f2a363bdfac8d15d66bed624bfe1ff289229184f3861b95f98a19cf4b2
|
||||
F ext/jni/README.md d899789a9082a07b99bf30b1bbb6204ae57c060efcaa634536fa669323918f42
|
||||
F ext/jni/jar-dist.make 030aaa4ae71dd86e4ec5e7c1e6cd86f9dfa47c4592c070d2e35157e42498e1fa
|
||||
@@ -382,7 +382,7 @@ F ext/misc/blobio.c a867c4c4617f6ec223a307ebfe0eabb45e0992f74dd47722b96f3e631c0e
|
||||
F ext/misc/btreeinfo.c cb952620eedf5c0b7625b678f0f08e54d2ec0011d4e50efda5ebdc97f3df7d04
|
||||
F ext/misc/carray.c 34fac63770971611c5285de0a9f0ac67d504eaf66be891f637add9290f1c76a5
|
||||
F ext/misc/carray.h 503209952ccf2431c7fd899ebb92bf46bf7635b38aace42ec8aa1b8d7b6e98a5
|
||||
F ext/misc/cksumvfs.c 9224e33cc0cb6aa61ff1d7d7b8fd6fe56beca9f9c47954fa4ae0a69bef608f69
|
||||
F ext/misc/cksumvfs.c 3a7931dd30667be6348af919f3f9e6188dfd7646b42af8e399a499b327f5bd63
|
||||
F ext/misc/closure.c 0e04f52d93e678dd6f950f195f365992edf3c380df246f3d80425cba4c13891e
|
||||
F ext/misc/completion.c ef78835483b43ac18c96be312b90b615d8368189909be03513ab7a9338131298
|
||||
F ext/misc/compress.c 3354c77a7c8e86e07d849916000cdac451ed96500bfb5bd83b20eb61eee012c9
|
||||
@@ -411,7 +411,7 @@ F ext/misc/regexp.c 4bdd0045912f81c84908bd535ec5ad3b1c8540b4287c70ab840709636240
|
||||
F ext/misc/remember.c add730f0f7e7436cd15ea3fd6a90fd83c3f706ab44169f7f048438b7d6baa69c
|
||||
F ext/misc/rot13.c 51ac5f51e9d5fd811db58a9c23c628ad5f333c173f1fc53c8491a3603d38556c
|
||||
F ext/misc/scrub.c 2a44b0d44c69584c0580ad2553f6290a307a49df4668941d2812135bfb96a946
|
||||
F ext/misc/series.c 384f93a8a09cf45e1aa6575660cb580ed61d372c590aad05cdcd4a84fbd8f6ab
|
||||
F ext/misc/series.c d96e5aac21658c6b5d54f918ac140460ec7197734c1a4fba806950831a7b1e7a
|
||||
F ext/misc/sha1.c 4011aef176616872b2a0d5bccf0ecfb1f7ce3fe5c3d107f3a8e949d8e1e3f08d
|
||||
F ext/misc/shathree.c 543af7ce71d391cd3a9ab6924a6a1124efc63211fd0f2e240dc4b56077ba88ac
|
||||
F ext/misc/showauth.c 732578f0fe4ce42d577e1c86dc89dd14a006ab52
|
||||
@@ -426,7 +426,7 @@ F ext/misc/urifuncs.c f71360d14fa9e7626b563f1f781c6148109462741c5235ac63ae0f8917
|
||||
F ext/misc/uuid.c 5bb2264c1b64d163efa46509544fd7500cb8769cb7c16dd52052da8d961505cf
|
||||
F ext/misc/vfslog.c 3932ab932eeb2601dbc4447cb14d445aaa9fbe43b863ef5f014401c3420afd20
|
||||
F ext/misc/vfsstat.c a85df08654743922a19410d7b1e3111de41bb7cd07d20dd16eda4e2b808d269d
|
||||
F ext/misc/vtablog.c f2c9d41afe00b51b2c8307b79f508eb0c2dcd57bae074807944e73376fcf15b7
|
||||
F ext/misc/vtablog.c 1100250ce8782db37c833e3a9a5c9a3ecf1af5e15b8325572b82e6e0a138ffb5
|
||||
F ext/misc/vtshim.c 1976e6dd68dd0d64508c91a6dfab8e75f8aaf6cd
|
||||
F ext/misc/wholenumber.c 0fa0c082676b7868bf2fa918e911133f2b349bcdceabd1198bba5f65b4fc0668
|
||||
F ext/misc/zipfile.c 64cb3d98b6316586e6056d182051aa9d28fdedfbf4b908e6b7a7d70209b1db11
|
||||
@@ -475,16 +475,16 @@ F ext/rbu/rbuvacuum.test 542561741ff2b262e3694bc6012b44694ee62c545845319a06f3237
|
||||
F ext/rbu/rbuvacuum2.test ae097d04feb041446a74fac94b24bffeb3fdd60e32b848c5611e507ab702b81b
|
||||
F ext/rbu/rbuvacuum3.test 3ce42695fdf21aaa3499e857d7d4253bc499ad759bcd6c9362042c13cd37d8de
|
||||
F ext/rbu/rbuvacuum4.test ffccd22f67e2d0b380d2889685742159dfe0d19a3880ca3d2d1d69eefaebb205
|
||||
F ext/rbu/sqlite3rbu.c d4ddf8f0e93772556e452a6c2814063cf47efb760a0834391a9d0cd9859fa4b9
|
||||
F ext/rbu/sqlite3rbu.c 4a3376c0fb9a844a799ac529fb81260523f6b13c9f629bc270c632dbae5fc1f8
|
||||
F ext/rbu/sqlite3rbu.h 9d923eb135c5d04aa6afd7c39ca47b0d1d0707c100e02f19fdde6a494e414304
|
||||
F ext/rbu/test_rbu.c ee6ede75147bc081fe9bc3931e6b206277418d14d3fbceea6fdc6216d9b47055
|
||||
F ext/recover/dbdata.c b7746c2ec801b453840831311be4b31f8c8f9dd97791060a69bbf12392c78949
|
||||
F ext/recover/dbdata.c d2e00d3cac74319c9c6def2e56ab2146b4f4ba5d820ab275e8da24e9766c247e
|
||||
F ext/recover/recover1.test c484d01502239f11b61f23c1cee9f5dd19fa17617f8974e42e74d64639c524cf
|
||||
F ext/recover/recover_common.tcl a61306c1eb45c0c3fc45652c35b2d4ec19729e340bdf65a272ce4c229cefd85a
|
||||
F ext/recover/recoverbuild.test c74170e0f7b02456af41838afeb5353fdb985a48cc2331d661bbabbca7c6b8e3
|
||||
F ext/recover/recoverclobber.test 3ba6c0c373c5c63d17e82eced64c05c57ccaf26c1abe1ca7141334022a79f32e
|
||||
F ext/recover/recovercorrupt.test 64c081ad1200ae77b447da99eb724785d6bf71715f394543dc7689642e92bf49
|
||||
F ext/recover/recovercorrupt2.test b9b974f006340a1300b5a7e687bd6097c5238498181c6f92d87406a77ece430b
|
||||
F ext/recover/recovercorrupt2.test 1418f1710debc24ff38276cedfcea234beb37a34205708e7e3e6d76cc4a979db
|
||||
F ext/recover/recoverfault.test 9d9f88eeb222615a25e7514f234c950d46bee20d24cd8db49d8fff8d650dcfe1
|
||||
F ext/recover/recoverfault2.test 730e7371bcda769554d15460cb23126abba1be8eca9539ccabf63623e7bb7e09
|
||||
F ext/recover/recoverold.test 68db3d6f85dd2b98e785b6c4da4f5eea4bbe52ccf6674d9a94c7506dc92596aa
|
||||
@@ -492,7 +492,7 @@ F ext/recover/recoverpgsz.test 3658ab8e68475b1bb87d6af88baa04551c84b73280a566a1b
|
||||
F ext/recover/recoverrowid.test f948bf4024a5f41b0e21b8af80c60564c5b5d78c05a8d64fc00787715ff9f45f
|
||||
F ext/recover/recoverslowidx.test 5205a9742dd9490ee99950dabb622307355ef1662dea6a3a21030057bfd81411
|
||||
F ext/recover/recoversql.test e66d01f95302a223bcd3fd42b5ee58dc2b53d70afa90b0d00e41e4b8eab20486
|
||||
F ext/recover/sqlite3recover.c e6eb20c469bcdb96f297f2241860bccabf9f036bfa7f3d47bcc6ca1191b108dc
|
||||
F ext/recover/sqlite3recover.c 65ef0f56301a16c0536c9839fb7e23540c9c4f75da0afe3b7b4d163c8f624404
|
||||
F ext/recover/sqlite3recover.h 011c799f02deb70ab685916f6f538e6bb32c4e0025e79bfd0e24ff9c74820959
|
||||
F ext/recover/test_recover.c fd871a40f2238022bedcbdf3cb493b91225edaa94d6ae8892af97a10e7ccc4ba
|
||||
F ext/repair/README.md 92f5e8aae749a4dae14f02eea8e1bb42d4db2b6ce5e83dbcdd6b1446997e0c15
|
||||
@@ -506,9 +506,9 @@ F ext/repair/test/checkindex01.test b530f141413b587c9eb78ff734de6bb79bc3515c3350
|
||||
F ext/repair/test/test.tcl 686d76d888dffd021f64260abf29a55c57b2cedfa7fc69150b42b1d6119aac3c
|
||||
F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761
|
||||
F ext/rtree/geopoly.c 0dd4775e896cee6067979d67aff7c998e75c2c9d9cd8d62a1a790c09cde7adca
|
||||
F ext/rtree/rtree.c c65a133bb697d20c0ac60ac09dc3a1cbf55500bfd6e9e730d2469aa6113480ed
|
||||
F ext/rtree/rtree.c b6133dba5ae331fa6c1fc34df6aa623eba951b05ac35116f954a0bf7ab550436
|
||||
F ext/rtree/rtree.h 4a690463901cb5e6127cf05eb8e642f127012fd5003830dbc974eca5802d9412
|
||||
F ext/rtree/rtree1.test 2b5b8c719c6a4abe377f57766f428a49af36a93061cb146cccfdc3b30000c0a4
|
||||
F ext/rtree/rtree1.test e0608db762b2aadca0ecb6f97396cf66244490adc3ba88f2a292b27be3e1da3e
|
||||
F ext/rtree/rtree2.test 9d9deddbb16fd0c30c36e6b4fdc3ee3132d765567f0f9432ee71e1303d32603d
|
||||
F ext/rtree/rtree3.test 272594f88c344e973864008bbe4c71fd3a41a264c097d568593ee7886d83d409
|
||||
F ext/rtree/rtree4.test 304de65d484540111b896827e4261815e5dca4ce28eeecd58be648cd73452c4b
|
||||
@@ -566,6 +566,7 @@ F ext/session/session_speed_test.c dcf0ef58d76b70c8fbd9eab3be77cf9deb8bc1638fed8
|
||||
F ext/session/sessionalter.test 460bdac2832a550519f6bc32e5db2c0cee94f335870aaf25a3a403a81ab20e17
|
||||
F ext/session/sessionat.test 00c8badb35e43a2f12a716d2734a44d614ff62361979b6b85419035bc04b45ee
|
||||
F ext/session/sessionbig.test 47c381e7acfabeef17d98519a3080d69151723354d220afa2053852182ca7adf
|
||||
F ext/session/sessionconflict.test 28890457bb90457be772d3067cdb5f78db9b51d997e4f3d09f22cddc9be80a38
|
||||
F ext/session/sessiondiff.test ad13dd65664bae26744e1f18eb3cbd5588349b7e9118851d8f9364248d67bcec
|
||||
F ext/session/sessionfault.test 573bf027fb870d57bd4e7cf50822a3e4b17b2b923407438747aaa918dec57a09
|
||||
F ext/session/sessionfault2.test b0d6a7c1d7398a7e800d84657404909c7d385965ea8576dc79ed344c46fbf41c
|
||||
@@ -587,7 +588,7 @@ F ext/userauth/sqlite3userauth.h 7f3ea8c4686db8e40b0a0e7a8e0b00fac13aa7a3
|
||||
F ext/userauth/user-auth.txt ca7e9ee82ca4e1c1744295f8184dd70edfae1992865d26c64303f539eb6c084c
|
||||
F ext/userauth/userauth.c 7f00cded7dcaa5d47f54539b290a43d2e59f4b1eb5f447545fa865f002fc80cb
|
||||
F ext/wasm/EXPORTED_FUNCTIONS.fiddle.in 27450c8b8c70875a260aca55435ec927068b34cef801a96205adb81bdcefc65c
|
||||
F ext/wasm/GNUmakefile 316349101671037a30311fbb40bd0b8702d9a223b5205a6a5eae8bac7b8dc1a0
|
||||
F ext/wasm/GNUmakefile 21f015f342e4ed9b7ff632c10750512259d26c836a34f4f535673fae9a7c9fcc
|
||||
F ext/wasm/README-dist.txt 6382cb9548076fca472fb3330bbdba3a55c1ea0b180ff9253f084f07ff383576
|
||||
F ext/wasm/README.md a8a2962c3aebdf8d2104a9102e336c5554e78fc6072746e5daf9c61514e7d193
|
||||
F ext/wasm/SQLTester/GNUmakefile e0794f676d55819951bbfae45cc5e8d7818dc460492dc317ce7f0d2eca15caff
|
||||
@@ -605,18 +606,18 @@ F ext/wasm/api/post-js-footer.js cd0a8ec768501d9bd45d325ab0442037fb0e33d1f3b4f08
|
||||
F ext/wasm/api/post-js-header.js 04dc12c3edd666b64a1b4ef3b6690c88dcc653f26451fd4734472d8e29c1c122
|
||||
F ext/wasm/api/pre-js.c-pp.js ad906703f7429590f2fbf5e6498513bf727a1a4f0ebfa057afb08161d7511219
|
||||
F ext/wasm/api/sqlite3-api-cleanup.js d235ad237df6954145404305040991c72ef8b1881715d2a650dda7b3c2576d0e
|
||||
F ext/wasm/api/sqlite3-api-glue.js 587dc6db2d69329a5f4cb9635c377f516cf4a8e30f443f33380e5044889ec71b
|
||||
F ext/wasm/api/sqlite3-api-oo1.js 7f3bcf0549ac44cde4b9da0b642d771916738d3f6781fb8a1757c50a91e506c0
|
||||
F ext/wasm/api/sqlite3-api-prologue.js fffcee629bf020a8ccf5c367fbe6a169f5d5d73dfce1707a75c9fbf4aa21c7da
|
||||
F ext/wasm/api/sqlite3-api-worker1.js 8d9c0562831f62218170a3373468d8a0b7a6503b5985e309b69bf71187b525cf
|
||||
F ext/wasm/api/sqlite3-api-glue.js 114085f4dceb28e06d20d3fb597b2501a4aa69f4b6cd29234f7cc1cf81d5b92d
|
||||
F ext/wasm/api/sqlite3-api-oo1.js 40f6834314b60e636f0046a9c49b8566a992dcf04be9ea593e680c23f6984b2b
|
||||
F ext/wasm/api/sqlite3-api-prologue.js 34457b25dcf0005c81d76f011f207026ec164f6ff0f69f024b608025ca808ea9
|
||||
F ext/wasm/api/sqlite3-api-worker1.js 9704b77b5eb9d0d498ceeaf3e7a837021b14c52ac15d6556c7f97e278ec725c3
|
||||
F ext/wasm/api/sqlite3-license-version-header.js 0c807a421f0187e778dc1078f10d2994b915123c1223fe752b60afdcd1263f89
|
||||
F ext/wasm/api/sqlite3-opfs-async-proxy.js 8cf8a897726f14071fae6be6648125162b256dfb4f96555b865dbb7a6b65e379
|
||||
F ext/wasm/api/sqlite3-opfs-async-proxy.js 196ad83d36ca794e564044788c9d21b964679d63cad865f604da37c4afc9a285
|
||||
F ext/wasm/api/sqlite3-vfs-helper.c-pp.js 3f828cc66758acb40e9c5b4dcfd87fd478a14c8fb7f0630264e6c7fa0e57515d
|
||||
F ext/wasm/api/sqlite3-vfs-opfs-sahpool.c-pp.js 5a430874906ff3f4a6ca69aadf0c2aaedc1bb45489b8365bff7e955a83a8d42a
|
||||
F ext/wasm/api/sqlite3-vfs-opfs.c-pp.js fe427645e1499618f5fa7bc670af850577d8bcc132df982078690c9bf8400baa
|
||||
F ext/wasm/api/sqlite3-vfs-opfs-sahpool.c-pp.js 8433ee332d5f5e39fb19427fccb7bad7f44aa99b5504daad3343fc128c311e78
|
||||
F ext/wasm/api/sqlite3-vfs-opfs.c-pp.js 3c72f1a0e6a7343c8c882d29d01bb440f10be12c844651605b486e76f3d6cc8c
|
||||
F ext/wasm/api/sqlite3-vtab-helper.c-pp.js a2fcbc3fecdd0eea229283584ebc122f29d98194083675dbe5cb2cf3a17fe309
|
||||
F ext/wasm/api/sqlite3-wasm.c d33a16495ca871781e78812d3a18fed78b797468fffee657b8d7199b277ff359
|
||||
F ext/wasm/api/sqlite3-worker1-promiser.c-pp.js e8135b44a568badfe197e2379f6b42899f2240b5c3a77fa044331110f7ce8e50
|
||||
F ext/wasm/api/sqlite3-wasm.c 9267174b9b0591b4f71193542ab57adf95bb9415f7d3453acf4a8ca8052f5e6c
|
||||
F ext/wasm/api/sqlite3-worker1-promiser.c-pp.js 5bffc94b0ba45c658f7a70c683c536642cd95f4d6fc71d20785864111c396740
|
||||
F ext/wasm/api/sqlite3-worker1.c-pp.js 5e8706c2c4af2a57fbcdc02f4e7ef79869971bc21bb8ede777687786ce1c92d5
|
||||
F ext/wasm/batch-runner-sahpool.html e9a38fdeb36a13eac7b50241dfe7ae066fe3f51f5c0b0151e7baee5fce0d07a7
|
||||
F ext/wasm/batch-runner-sahpool.js 54a3ac228e6c4703fe72fb65c897e19156263a51fe9b7e21d2834a45e876aabd
|
||||
@@ -632,19 +633,19 @@ F ext/wasm/demo-123.html 8c70a412ce386bd3796534257935eb1e3ea5c581e5d5aea0490b823
|
||||
F ext/wasm/demo-123.js c7b3cca50c55841c381a9ca4f9396e5bbdc6114273d0b10a43e378e32e7be5bf
|
||||
F ext/wasm/demo-jsstorage.html 409c4be4af5f207fb2877160724b91b33ea36a3cd8c204e8da1acb828ffe588e
|
||||
F ext/wasm/demo-jsstorage.js 44e3ae7ec2483b6c511384c3c290beb6f305c721186bcf5398ca4e00004a06b8
|
||||
F ext/wasm/demo-worker1-promiser.html 1de7c248c7c2cfd4a5783d2aa154bce62d74c6de98ab22f5786620b3354ed15f
|
||||
F ext/wasm/demo-worker1-promiser.js 786ae8a3214c2a29f6fb2c80eb4f90cc401fcc5b524d95c35fdc66a454e32bad
|
||||
F ext/wasm/demo-worker1-promiser.c-pp.html 635cf90685805e21772a5f7a35d1ace80f98a9ef7c42ff04d7a125ddca7e5db8
|
||||
F ext/wasm/demo-worker1-promiser.c-pp.js fcc628cb42fcfaf07d250477801de1e6deb1e319d003976612a0db8d76b9fccc
|
||||
F ext/wasm/demo-worker1.html 2c178c1890a2beb5a5fecb1453e796d067a4b8d3d2a04d65ca2eb1ab2c68ef5d
|
||||
F ext/wasm/demo-worker1.js 836bece8615b17b1b572584f7b15912236a5947fe8c68b98d2737d7e287447ef
|
||||
F ext/wasm/dist.make 3a851858aad72e246a5d9c5aaf6b6a144305f1bf898ac1846760ea7bab95c9a3
|
||||
F ext/wasm/dist.make 653e212c1e84aa3be168d62a10616ccea45ee9585b0192745d2706707a5248ce
|
||||
F ext/wasm/example_extra_init.c 2347cd69d19d839ef4e5e77b7855103a7fe3ef2af86f2e8c95839afd8b05862f
|
||||
F ext/wasm/fiddle.make fa2ba6e90457ba2a71cb745f200d409caf773076df75ae5b177cc225d7627a11
|
||||
F ext/wasm/fiddle.make 3c2eace29255d6ddd219f5d8cc2728cb28b9fe717ea80b6062c2a6178947a16b
|
||||
F ext/wasm/fiddle/emscripten.css 3d253a6fdb8983a2ac983855bfbdd4b6fa1ff267c28d69513dd6ef1f289ada3f
|
||||
F ext/wasm/fiddle/fiddle-worker.js 9be57887756c6854dbdcb5e7d8b7a26935d565491333a2f91dc4113598c659b5
|
||||
F ext/wasm/fiddle/fiddle.js 974b995119ac443685d7d94d3b3c58c6a36540e9eb3fed7069d5653284071715
|
||||
F ext/wasm/fiddle/fiddle-worker.js 850e66fce39b89d59e161d1abac43a181a4caa89ddeea162765d660277cd84ce
|
||||
F ext/wasm/fiddle/fiddle.js b444a5646a9aac9f3fc06c53d78af5e1912eb235d69a8e6010723e4eb0e9d4a1
|
||||
F ext/wasm/fiddle/index.html 5daf54e8f3d7777cbb1ca4f93affe28858dbfff25841cb4ab81d694efed28ec2
|
||||
F ext/wasm/index-dist.html e91d76e4581185238fd3d42ed86ec600f7023ed3e3a944c5c356f25304bf1263
|
||||
F ext/wasm/index.html b31ce41c0da476d5ffcef23069b9d3415b419d65af5779096ebcfbcbade453a9
|
||||
F ext/wasm/index-dist.html 564b5ec5669676482c5a25dea9e721d8eafed426ecb155f93d29aeff8507511f
|
||||
F ext/wasm/index.html 4337f495416756802669f69f9f9f3df9f87ee4c1918e6718719b4b5718e4713a
|
||||
F ext/wasm/jaccwabyt/jaccwabyt.js 1264710db3cfbcb6887d95665b7aeba60c1126eaef789ca4cf1a4a17d5bc7f54
|
||||
F ext/wasm/jaccwabyt/jaccwabyt.md 59a20df389abcc3606eb4eaea7fb7ba14504beb3e345dbea9b99a0618ba3bec8
|
||||
F ext/wasm/module-symbols.html dc476b403369b26a1a23773e13b80f41b9a49f0825e81435fe3600a7cfbbe337
|
||||
@@ -662,7 +663,7 @@ F ext/wasm/test-opfs-vfs.html 1f2d672f3f3fce810dfd48a8d56914aba22e45c6834e262555
|
||||
F ext/wasm/test-opfs-vfs.js 1618670e466f424aa289859fe0ec8ded223e42e9e69b5c851f809baaaca1a00c
|
||||
F ext/wasm/tester1-worker.html ebc4b820a128963afce328ecf63ab200bd923309eb939f4110510ab449e9814c
|
||||
F ext/wasm/tester1.c-pp.html 1c1bc78b858af2019e663b1a31e76657b73dc24bede28ca92fbe917c3a972af2
|
||||
F ext/wasm/tester1.c-pp.js 7c51d19f3644904156a154ddedd7024539ffba1a4e2df5e1efe10333e5b91b8f
|
||||
F ext/wasm/tester1.c-pp.js 6d0a9aa44a97b4aadd582e0999ce45a2671b854a12ea3205d1c908da6bd4bdef
|
||||
F ext/wasm/tests/opfs/concurrency/index.html 0802373d57034d51835ff6041cda438c7a982deea6079efd98098d3e42fbcbc1
|
||||
F ext/wasm/tests/opfs/concurrency/test.js a98016113eaf71e81ddbf71655aa29b0fed9a8b79a3cdd3620d1658eb1cc9a5d
|
||||
F ext/wasm/tests/opfs/concurrency/worker.js 0a8c1a3e6ebb38aabbee24f122693f1fb29d599948915c76906681bb7da1d3d2
|
||||
@@ -670,7 +671,7 @@ F ext/wasm/wasmfs.make 8a4955882aaa0783b3f60a9484a1f0f3d8b6f775c0fcd17c082f31966
|
||||
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
|
||||
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
|
||||
F magic.txt 5ade0bc977aa135e79e3faaea894d5671b26107cc91e70783aa7dc83f22f3ba0
|
||||
F main.mk 2c8b556ba7a4a15f5440663f7b05da221355d1921d5c75298bb50e2bb8081d79
|
||||
F main.mk e5da4b6c13f2b15bba7f1efb0a47089dfdde0973e85a024785485655d59fd758
|
||||
F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
|
||||
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
|
||||
F mptest/crash01.test 61e61469e257df0850df4293d7d4d6c2af301421
|
||||
@@ -682,38 +683,38 @@ F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
|
||||
F sqlite3.1 acdff36db796e2d00225b911d3047d580cd136547298435426ce9d40347973cc
|
||||
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
|
||||
F sqlite_cfg.h.in baf2e409c63d4e7a765e17769b6ff17c5a82bbd9cbf1e284fd2e4cefaff3fcf2
|
||||
F src/alter.c 30c2333b8bb3af71e4eb9adeadee8aa20edb15917ed44b8422e5cd15f3dfcddc
|
||||
F src/alter.c e1b6782b85dd758f89e5c588e4e3eb82638c2dafc0c857b79a43bb8ec1746fca
|
||||
F src/analyze.c a3df28274e2565ba5656577d7e3fd262169a213e6eb0bd47890e0f0729a4031c
|
||||
F src/attach.c cc9d00d30da916ff656038211410ccf04ed784b7564639b9b61d1839ed69fd39
|
||||
F src/auth.c 19b7ccacae3dfba23fc6f1d0af68134fa216e9040e53b0681b4715445ea030b4
|
||||
F src/backup.c 5c97e8023aab1ce14a42387eb3ae00ba5a0644569e3476f38661fa6f824c3523
|
||||
F src/bitvec.c 9eac5f42c11914d5ef00a75605bb205e934f435c579687f985f1f8b0995c8645
|
||||
F src/btmutex.c 79a43670447eacc651519a429f6ece9fd638563cf95b469d6891185ddae2b522
|
||||
F src/btree.c 285b493d843e7ba8ef78b6ae7d31238e904901dbc0c484f7904de4cf18fd8802
|
||||
F src/btree.c 71b80e77b255144db47180fda8138740608e382a44231942464029b1a45fc036
|
||||
F src/btree.h 55066f513eb095db935169dab1dc2f7c7a747ef223c533f5d4ad4dfed346cbd0
|
||||
F src/btreeInt.h 98aadb6dcb77b012cab2574d6a728fad56b337fc946839b9898c4b4c969e30b6
|
||||
F src/build.c 7ee3616b8a25577f2fb715d91eaa27f62a34e6ee6d0130cc8b9644c07875b759
|
||||
F src/build.c 02f5b25ca854c83b5015cb02b8c9ab236c60b1795528675aee8a5070e58da52a
|
||||
F src/callback.c db3a45e376deff6a16c0058163fe0ae2b73a2945f3f408ca32cf74960b28d490
|
||||
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
|
||||
F src/ctime.c 23331529e654be40ca97d171cbbffe9b3d4c71cc53b78fe5501230675952da8b
|
||||
F src/date.c 90df32c2d8b2a38dd2e83d32e47802629305c4882fb2ec75c9ecdcd75b68bcb2
|
||||
F src/ctime.c 64e4b1227b4ed123146f0aa2989131d1fbd9b927b11e80c9d58c6a68f9cd5ce3
|
||||
F src/date.c 126ba2ab10aeb2e7ba6e089b5f07b747c0625b8287f78b60da346eda8d23c875
|
||||
F src/dbpage.c 80e46e1df623ec40486da7a5086cb723b0275a6e2a7b01d9f9b5da0f04ba2782
|
||||
F src/dbstat.c 3b677254d512fcafd4d0b341bf267b38b235ccfddbef24f9154e19360fa22e43
|
||||
F src/delete.c cb766727c78e715f9fb7ec8a7d03658ed2a3016343ca687acfcec9083cdca500
|
||||
F src/expr.c 2803f5e7e3458ced24c0de48ec3640cd7a68ec61350d99c9f30b1bcd6640bd61
|
||||
F src/expr.c 005bf7a088a2fb12a50752a2a1d40d423b8942e1920e93c3a1ba76da0bfbe52b
|
||||
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
|
||||
F src/fkey.c 0592046ed7598625234298211cc1fe611efb3fe7870a3f1938038fd9092c82f9
|
||||
F src/func.c 4204c56196847faefef57fa14e43b8e4d65eb8d7e65318abe463472e3fd148cb
|
||||
F src/global.c 765a0656d6cbf043cb272ff0ae38f39cc46713539ffe6793258ed3eb4b188b52
|
||||
F src/fkey.c a47610f0a5c6cb0ad79f8fcef039c01833dec0c751bb695f28dc0ec6a4c3ba00
|
||||
F src/func.c 283d4f3b2751a1d9339fd93a8a013d1948fd5f4474a3cab0955eb4fafd445d0f
|
||||
F src/global.c 61a419dd9e993b9be0f91de4c4ccf322b053eb829868e089f0321dd669be3b90
|
||||
F src/hash.c 9ee4269fb1d6632a6fecfb9479c93a1f29271bddbbaf215dd60420bcb80c7220
|
||||
F src/hash.h 3340ab6e1d13e725571d7cee6d3e3135f0779a7d8e76a9ce0a85971fa3953c51
|
||||
F src/hwtime.h f9c2dfb84dce7acf95ce6d289e46f5f9d3d1afd328e53da8f8e9008e3b3caae6
|
||||
F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
|
||||
F src/insert.c 3f0a94082d978bbdd33c38fefea15346c6c6bffb70bc645a71dc0f1f87dd3276
|
||||
F src/json.c 3b4e2778d95d923d6d77e8a5efd51a6265017b466782d597303f5f094fcd68af
|
||||
F src/insert.c 4bd7c7e54a1062dcd0214b7a6296f7194eb10fb14d3ddca1ed20b01c2a86a18c
|
||||
F src/json.c e2e40760d6689134c3e2ece38c6a496b34ff5e2661a8f238444a119af666fdce
|
||||
F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
|
||||
F src/loadext.c 7432c944ff197046d67a1207790a1b13eec4548c85a9457eb0896bb3641dfb36
|
||||
F src/main.c 438b95162acfa17b7d218f586f5bde11d6ae82bcf030c9611fc537556870ad6b
|
||||
F src/main.c 8a59d297ec77e6b78550433bfccb95a1b26f2fb69aaaf233206e21579a1cfcc1
|
||||
F src/malloc.c 410e570b30c26cc36e3372577df50f7a96ee3eed5b2b161c6b6b48773c650c5e
|
||||
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
|
||||
F src/mem1.c 3bb59158c38e05f6270e761a9f435bf19827a264c13d1631c58b84bdc96d73b2
|
||||
@@ -734,28 +735,28 @@ F src/os.h 1ff5ae51d339d0e30d8a9d814f4b8f8e448169304d83a7ed9db66a65732f3e63
|
||||
F src/os_common.h 6c0eb8dd40ef3e12fe585a13e709710267a258e2c8dd1c40b1948a1d14582e06
|
||||
F src/os_kv.c 4d39e1f1c180b11162c6dc4aa8ad34053873a639bac6baae23272fc03349986a
|
||||
F src/os_setup.h 6011ad7af5db4e05155f385eb3a9b4470688de6f65d6166b8956e58a3d872107
|
||||
F src/os_unix.c 8d7533b3b4d0d2d6ddd34d1ebc92f50a91f04e722a3a9295a000bc3c25128e2f
|
||||
F src/os_unix.c 6227cbc4ac93046f121436886cf3712da6f4e2082af6314f976eeae1d86b794a
|
||||
F src/os_win.c 6ff43bac175bd9ed79e7c0f96840b139f2f51d01689a638fd05128becf94908a
|
||||
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
|
||||
F src/pager.c ff60e98138d2499082ac6230f01ac508aba545315debccfca2fd6042f5f10fcd
|
||||
F src/pager.c 9beb80f6e330dd63c5d8ba0f7a7f3a55fff22067a68d424949c389bfc6fa0c56
|
||||
F src/pager.h 4b1140d691860de0be1347474c51fee07d5420bd7f802d38cbab8ea4ab9f538a
|
||||
F src/parse.y 9a77520c83950ced6e8b981c7826ebfd8e4a5c6e4b5d9743639e357910180c94
|
||||
F src/parse.y 5bcef16094213efcc365a9d4dc4e3131f09251dc8838dce4a9e5f9764bff5b82
|
||||
F src/pcache.c 040b165f30622a21b7a9a77c6f2e4877a32fb7f22d4c7f0d2a6fa6833a156a75
|
||||
F src/pcache.h 1497ce1b823cf00094bb0cf3bac37b345937e6f910890c626b16512316d3abf5
|
||||
F src/pcache1.c 602acb23c471bb8d557a6f0083cc2be641d6cafcafa19e481eba7ef4c9ca0f00
|
||||
F src/pragma.c e8221d6310c9923c80f6fa6d09b7ea7c5263a671f53db8d0894df23efcdb617b
|
||||
F src/pragma.c f8f1845b42df684e9d31c5a1628c989a34939686049d7878bc5394ac1ae9cac4
|
||||
F src/pragma.h e690a356c18e98414d2e870ea791c1be1545a714ba623719deb63f7f226d8bb7
|
||||
F src/prepare.c 371f6115cb69286ebc12c6f2d7511279c2e47d9f54f475d46a554d687a3b312c
|
||||
F src/printf.c 10e8bad30042f8bd6114a013b4afc229ec8ad255ab27518d7d9f52e8cbc5cd0a
|
||||
F src/printf.c 8b250972305e14b365561be5117ed0fd364e4fd58968776df1ce64c6280b90f9
|
||||
F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c
|
||||
F src/resolve.c d77c6160bc8f249c2196fdd3e75f66a1dd70e37aa25c39aedc7b1f93c42b7c6d
|
||||
F src/resolve.c 647edf93729ba124c0a6048982af56c2fa4f841e69d626e4f3caa620f082bb15
|
||||
F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97
|
||||
F src/select.c 43fabfc01bf87addd15e39f112f1e2ade15b19594835ab8a9e5bd50839d4e1b1
|
||||
F src/shell.c.in 2ec564ed3ff0147036be313efeb47b3dbfb8753d5eb5ea0e90636427c6b3a365
|
||||
F src/sqlite.h.in 19a2db3995a699bd7f6dfb423856242bfceb7ec849a93c91d241d19fc28d9f0f
|
||||
F src/select.c 04178566d0188be7de471064ced8cec1d407920726cb49b609486282d78faf56
|
||||
F src/shell.c.in 0354ca51eee5fbf6af394a7ef9f5ef6823ef45b743db65431f6777e4d5be2199
|
||||
F src/sqlite.h.in 32389e0d584551b300d0157881336162c14315a424cbf385c0d65eb7c2e31f7b
|
||||
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
|
||||
F src/sqlite3ext.h 3f046c04ea3595d6bfda99b781926b17e672fd6d27da2ba6d8d8fc39981dcb54
|
||||
F src/sqliteInt.h 532224eec9f53245c8450c662c2a9d06a1aec22cb28e5fc4cdfd0f67239e9049
|
||||
F src/sqliteInt.h 4ca38e206befb3738d8cca97b6c6ee56c10f1c5bdb379ac5442d0f1a71b9fefa
|
||||
F src/sqliteLimit.h 6878ab64bdeb8c24a1d762d45635e34b96da21132179023338c93f820eee6728
|
||||
F src/status.c cb11f8589a6912af2da3bb1ec509a94dd8ef27df4d4c1a97e0bcf2309ece972b
|
||||
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
|
||||
@@ -771,10 +772,10 @@ F src/test9.c 12e5ba554d2d1cbe0158f6ab3f7ffcd7a86ee4e5
|
||||
F src/test_async.c 195ab49da082053fdb0f949c114b806a49ca770a
|
||||
F src/test_autoext.c 915d245e736652a219a907909bb6710f0d587871
|
||||
F src/test_backup.c bf5da90c9926df0a4b941f2d92825a01bbe090a0
|
||||
F src/test_bestindex.c f6af1e41cb7901edafb065a8198e4a0192dd42432b642d038965be5e628dec12
|
||||
F src/test_bestindex.c 1ee3d64b49ca06a9cb8195fab04f1a0585cafc90d25a2a817caa14e7caab22e7
|
||||
F src/test_blob.c ae4a0620b478548afb67963095a7417cd06a4ec0a56adb453542203bfdcb31ce
|
||||
F src/test_btree.c 8b2dc8b8848cf3a4db93f11578f075e82252a274
|
||||
F src/test_config.c f0cc1f517deaa96dd384822ae2bb91534fa56aa458528b439830d709941d3932
|
||||
F src/test_config.c 5fa77ee6064ba546e144c4fea870c5ede2c54314616f81485c6a9c4192100c75
|
||||
F src/test_delete.c e2fe07646dff6300b48d49b2fee2fe192ed389e834dd635e3b3bac0ce0bf9f8f
|
||||
F src/test_demovfs.c 38a459d1c78fd9afa770445b224c485e079018d6ac07332ff9bd07b54d2b8ce9
|
||||
F src/test_devsym.c 649434ed34d0b03fbd5a6b42df80f0f9a7e53f94dd1710aad5dd8831e91c4e86
|
||||
@@ -813,46 +814,46 @@ F src/test_window.c cdae419fdcea5bad6dcd9368c685abdad6deb59e9fc8b84b153de513d394
|
||||
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
|
||||
F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
|
||||
F src/tokenize.c 3f703cacdab728d7741e5a6ac242006d74fe1c2754d4f03ed889d7253259bd68
|
||||
F src/treeview.c c6fc972683fd00f975d8b32a81c1f25d2fb7d4035366bf45c9f5622d3ccd70ee
|
||||
F src/trigger.c 15ca35f491c03197c3ccd5a0b3c5b926719cbe4e185b73da0507dbeb84a52d0e
|
||||
F src/update.c 6904814dd62a7a93bbb86d9f1419c7f134a9119582645854ab02b36b676d9f92
|
||||
F src/upsert.c fa125a8d3410ce9a97b02cb50f7ae68a2476c405c76aa692d3acf6b8586e9242
|
||||
F src/treeview.c a8aa3086c886c6eb2ff2b6354b0f23d251f7219bf08fad52d4f2791e55324f1b
|
||||
F src/trigger.c 0858f75818ed1580332db274f1032bcc5effe567cb132df5c5be8b1d800ca97f
|
||||
F src/update.c 732404a04d1737ef14bb6ec6b84f74edf28b3c102a92ae46b4855438a710efe7
|
||||
F src/upsert.c 2e60567a0e9e8520c18671b30712a88dc73534474304af94f32bb5f3ef65ac65
|
||||
F src/utf.c f23165685a67b4caf8ec08fb274cb3f319103decfb2a980b7cfd55d18dfa855e
|
||||
F src/util.c 0765014847e2a06c952dd64aef0bea5144cd5b335a161eb0768ebe4f63dfe216
|
||||
F src/util.c 4d6d7ebfe6772a1b950c97bbb1d1a72ad4874617ec498ab8aa73b7f5a43e44bb
|
||||
F src/vacuum.c 604fcdaebe76f3497c855afcbf91b8fa5046b32de3045bab89cc008d68e40104
|
||||
F src/vdbe.c 523a88b3df328810fbcbb407738c352dd9d5163b7af4c953e6e9887a4b582859
|
||||
F src/vdbe.c 3b1793c5d2235ae89b01ef051a33d7d2ad3704c71799653b112686735ad401ff
|
||||
F src/vdbe.h c2d78d15112c3fc5ab87f5e8e0b75d2db1c624409de2e858c3d1aafb1650bb4f
|
||||
F src/vdbeInt.h 949669dfd8a41550d27dcb905b494f2ccde9a2e6c1b0b04daa1227e2e74c2b2c
|
||||
F src/vdbeapi.c 8f57d60c89da0b60e6d4e272358c511f6bae4e24330bdb11f8b42f986d1bf21b
|
||||
F src/vdbeaux.c 66161ba75c4a2d86aab124fe3cbcc2a752d8e4b1fc8c1fc6e00625db4798168c
|
||||
F src/vdbeapi.c 80235ac380e9467fec1cb0883354d841f2a771976e766995f7e0c77f845406df
|
||||
F src/vdbeaux.c 6385727adf51a649e4993098870a62c3945fe21dbc0e0fd9013772aff930b8fb
|
||||
F src/vdbeblob.c 13f9287b55b6356b4b1845410382d6bede203ceb29ef69388a4a3d007ffacbe5
|
||||
F src/vdbemem.c 213bf303826c0ef702e3a2a69dab2309d84b8381b822c6787885859fd7cd4c4e
|
||||
F src/vdbemem.c 385c8b89da3b5ef9a468d77a466958aa72ee1212d5cb005f23ec63df1d413054
|
||||
F src/vdbesort.c 237840ca1947511fa59bd4e18b9eeae93f2af2468c34d2427b059f896230a547
|
||||
F src/vdbetrace.c fe0bc29ebd4e02c8bc5c1945f1d2e6be5927ec12c06d89b03ef2a4def34bf823
|
||||
F src/vdbevtab.c 2143db7db0ceed69b21422581f434baffc507a08d831565193a7a02882a1b6a7
|
||||
F src/vtab.c 38fcf63832f7e606755fa47b028c2eb6d6cd5facb40e280d66fbda4ed9a52188
|
||||
F src/vtab.c 4c475fb672a6fe57830561e614dbee21a9a24a6f616d1cfcbe85f356a09f14ad
|
||||
F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
|
||||
F src/wal.c 887fc4ca3f020ebb2e376f222069570834ac63bf50111ef0cbf3ae417048ed89
|
||||
F src/wal.h ba252daaa94f889f4b2c17c027e823d9be47ce39da1d3799886bbd51f0490452
|
||||
F src/walker.c 7c7ea0115345851c3da4e04e2e239a29983b61fb5b038b94eede6aba462640e2
|
||||
F src/where.c 33eaaeef3aef10c2b9e82096e70a174d6636e35cb0b180321b8ddf804590e5cd
|
||||
F src/where.c 0ef9638651b900d64d7e1e877af37cd7900159ff875547ec29b918a1497e5c9c
|
||||
F src/whereInt.h 82a13766f13d1a53b05387c2e60726289ef26404bc7b9b1f7770204d97357fb8
|
||||
F src/wherecode.c 5d77db30a2a3dd532492ae882de114edba2fae672622056b1c7fd61f5917a8f1
|
||||
F src/whereexpr.c dc5096eca5ed503999be3bdee8a90c51361289a678d396a220912e9cb73b3c00
|
||||
F src/window.c 5b1387d59df30d481ed14cceef5f4d1dab1f8752aa106ba72c8b62777bd139d2
|
||||
F src/wherecode.c 1f6940349e92a6e056aecd70163b00f331554c815c362b4cc80906c48151d73d
|
||||
F src/whereexpr.c 67d15caf88a1a9528283d68ff578e024cf9fe810b517bb0343e5aaf695ad97dd
|
||||
F src/window.c 5d95122dd330bfaebd732358c8ef067c5a9394a53ac249470d611d0ce2c52be2
|
||||
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
||||
F test/affinity2.test ce1aafc86e110685b324e9a763eab4f2a73f737842ec3b687bd965867de90627
|
||||
F test/affinity3.test f094773025eddf31135c7ad4cde722b7696f8eb07b97511f98585addf2a510a9
|
||||
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
||||
F test/aggfault.test 777f269d0da5b0c2524c7ff6d99ae9a93db4f1b1839a914dd2a12e3035c29829
|
||||
F test/aggnested.test 4dfdbfab105cec5750a1eeb59284ffffc3b37a32aaaf09143df3f549e28e2081
|
||||
F test/aggorderby.test af1e07766e8f752d54dd317aa1d956e8e896671a70ddb20228e8cdf9391023b1
|
||||
F test/aggnested.test 610b0ce2c3e8f3daee25f9752800ee8d785db10da4aa1fbeea0ea1aabaf1d704
|
||||
F test/aggorderby.test cc3abf5de64d46ff66395ca8c2346b66c2576d5aedb7bffc5b0742508856e3bf
|
||||
F test/alias.test 4529fbc152f190268a15f9384a5651bbbabc9d87
|
||||
F test/all.test 2ecb8bbd52416642e41c9081182a8df05d42c75637afd4488aace78cc4b69e13
|
||||
F test/alter.test 3c00eff1e2036b9f93e9cd0f3d3e63750ac87ecb5bc71b9d7bd07cbf2ac4c494
|
||||
F test/alter2.test 7e3d26ab409df52df887b366a63902c3429b935c41cb962fd58ffc25784f2f19
|
||||
F test/alter3.test 0663df0cb3b9558ccc21abe642b792d4e2e747164156208e2a44ce88c09fe09b
|
||||
F test/alter4.test 0ef8e62259bbc17495456d19e33a97b14cc2f634ef67bfdfb6a3f826eb9cfbc1
|
||||
F test/alter3.test ffc4ab29ce78a3517a66afd69b2730667e3471622509c283b2bd4c46f680fba3
|
||||
F test/alter4.test 716caa071dd8a3c6d57225778d15d3c3cbf5e34b2e84ae44199aeb2bbf50a707
|
||||
F test/alterauth.test 63442ba61ceb0c1eeb63aac1f4f5cebfa509d352276059d27106ae256bafc959
|
||||
F test/alterauth2.test 48967abae0494d9a300d1c92473d99fcb66edfcc23579c89322f033f49410adc
|
||||
F test/altercol.test 29fed774747777fbbaacdd865b4413ed2d0844a4c824f8af531b5c7d4a832087
|
||||
@@ -867,10 +868,10 @@ F test/altermalloc3.test 8040e486368403f2fdd6fc3998258b499bd4cc2f3ddbb5f8f874cd4
|
||||
F test/alterqf.test 8ec03d776de9c391daa0078ea8f838903bdcfb11dfae4ba3576b48436834ccba
|
||||
F test/altertab.test 8a2712f9076da5012a002d0b5cc0a421398a5bf61c25bab41b77c427586a7a27
|
||||
F test/altertab2.test 62597b6fd08feaba1b6bfe7d31dac6117c67e06dc9ce9c478a3abe75b5926de0
|
||||
F test/altertab3.test 6c432fbb9963e0bd6549bf1422f6861d744ee5a80cb3298564e81e556481df16
|
||||
F test/altertab3.test b331ae34e69594e19605e3297805202d6156fcc8f75379dfd972a2e51cae8721
|
||||
F test/altertrig.test aacc980b657354fe2d3d4d3a004f07d04ccc1a93e5ef82d68a79088c274ddc6b
|
||||
F test/amatch1.test b5ae7065f042b7f4c1c922933f4700add50cdb9f
|
||||
F test/analyze.test e8ab7a3fa8b0294dd72c6d0acd822c3b69fd4ab9392789b29dd29daaa8601b4c
|
||||
F test/analyze.test 2fb21d7d64748636384e6cb8998dbf83968caf644c07fcb4f76c18f2e7ede94b
|
||||
F test/analyze3.test 03f4b3d794760cf15da2d85a52df9bae300e51c8fefe9c36cfae1f86dc10d23f
|
||||
F test/analyze4.test 68bd069f3ac7ac1e652ddd9f04f57d5606ddb4208450f5297005db7aa0dd707d
|
||||
F test/analyze5.test fa5131952303ac4146aba101b116b9c8cb89e2637531c334a6df7f7d19dddc0d
|
||||
@@ -898,7 +899,7 @@ F test/attach2.test 6d1e3a457ce260d6fc8e5945c07fba6c76dc2aa90e1c701f067b50ee88f7
|
||||
F test/attach3.test c59d92791070c59272e00183b7353eeb94915976
|
||||
F test/attach4.test 00e754484859998d124d144de6d114d920f2ed6ca2f961e6a7f4183c714f885e
|
||||
F test/attachmalloc.test 67309af95c6b765c13e7d2279d7fccbef78e6eb0565d75d51cefd5dc88784549
|
||||
F test/auth.test 8d4152a8dca10e6dbe15b0c6dfcc183d5e9a7f6f983d9ae6e05f70e947aed7c3
|
||||
F test/auth.test 5b8558a40571ebc55c1581cb7cec3b2348a699542a0a51b83ef21c6a953d95e3
|
||||
F test/auth2.test 9eb7fce9f34bf1f50d3f366fb3e606be5a2000a1
|
||||
F test/auth3.test 76d20a7fa136d63bcfcf8bcb65c0b1455ed71078d81f22bcd0550d3eb18594ab
|
||||
F test/autoanalyze1.test b9cc3f32a990fa56669b668d237c6d53e983554ae80c0604992e18869a0b2dec
|
||||
@@ -911,7 +912,7 @@ F test/autoindex5.test 2ee94f033b87ca0160e08d81034c507aff8e230df2627f0304fa309b2
|
||||
F test/autovacuum.test 00671369bbf96c6a49989a9425f5b78b94075d6a4b031e5e00000c2c32f365df
|
||||
F test/autovacuum2.test 76f7eb4fe6a6bf6d33a196a7141dba98886d2fb53a268d7feca285d5da4759d7
|
||||
F test/autovacuum_ioerr2.test 8a367b224183ad801e0e24dcb7d1501f45f244b4
|
||||
F test/avfs.test 0c3a38e03cccb0fc3127838462dc05dc3f4c1480d770c084b388304c25de3652
|
||||
F test/avfs.test 76f59743dc1f5fa533840d1818b420fe1ee45e21c0fd6bbac7942ba677903128
|
||||
F test/avtrans.test b7dc25459ecbd86c6fa9c606ee3068f59d81e225118617dcf2bbb6ded2ade89e
|
||||
F test/backcompat.test 3e64cedda754c778ef6bbe417b6e7a295e662a4d
|
||||
F test/backup.test 3b08fd4af69f0fa786931103a31f4542b184aba16e239e5f22b18c3c2476697f
|
||||
@@ -931,10 +932,11 @@ F test/bestindex4.test 3039894f2dad50f3a68443dffad1b44c9b067ac03870102df1ce3d9a4
|
||||
F test/bestindex5.test a0c90b2dad7836e80a01379e200e5f8ec9476d49b349af02c0dbff2fb75dc98d
|
||||
F test/bestindex6.test 16942535b551273f3ad9df8d7cc4b7f22b1fcd8882714358859eb049a6f99dd4
|
||||
F test/bestindex7.test f094c669a6400777f4d2ddc3ed28e39169f1adb5be3d59b55f22ccf8c414b71e
|
||||
F test/bestindex8.test 333ad8c6a554b885a49b68c019166eda92b05f493a92b36b0acdf7f766d04dad
|
||||
F test/bestindex8.test b63a4f171a2c83d481bb14c431a8b72e85d27b2ffdaa0435a95d58ca941678f9
|
||||
F test/bestindex9.test 1a4b93db117fd8abe74ae9be982f86aa72f01e60cd4ac541e6ede39673a451a0
|
||||
F test/bestindexA.test e1b5def6b190797cacf008e6815ffb78fb30261999030d60a728d572eef44c7f
|
||||
F test/bestindexB.test 328b97b69cd1a20928d5997f9ecb04d2e00f1d18e19ab27f9e9adb44d7bc51ce
|
||||
F test/bestindexC.test c14a8c8639b6825b0efa1ae693f34ec04f41a46e3056e7063d6e0f46bf4ff692
|
||||
F test/between.test b9a65fb065391980119e8a781a7409d3fcf059d89968279c750e190a9a1d5263
|
||||
F test/bigfile.test aa74f4e5db51c8e54a1d9de9fa65d01d1eb20b59
|
||||
F test/bigfile2.test 1b489a3a39ae90c7f027b79110d6b4e1dbc71bfc
|
||||
@@ -977,6 +979,7 @@ F test/changes2.test 07949edcc732af28cb54276bfb7d99723bccc1e905a423648bf57ac5cb0
|
||||
F test/check.test 56e4ed457e9f8683b9fc56f5b964f461f6e8a8dd5a13f3d495408215d66419ed
|
||||
F test/checkfault.test da6cb3d50247169efcb20bdf57863a3ccfa1d27d9e55cd324f0680096970f014
|
||||
F test/chunksize.test 427d87791743486cbf0c3b8c625002f3255cb3a89c6eba655a98923b1387b760
|
||||
F test/cksumvfs.test 6f05dc95847c06a3dc10eee6b5ab1351d78314a52d0db15717c9388f4cb96646
|
||||
F test/close.test eccbad8ecd611d974cbf47278c3d4e5874faf02d811338d5d348af42d56d647c
|
||||
F test/closure01.test 9905883f1b171a4638f98fc764879f154e214a306d3d8daf412a15e7f3a9b1e0
|
||||
F test/coalesce.test cee0dccb9fbd2d494b77234bccf9dc6c6786eb91
|
||||
@@ -1009,7 +1012,7 @@ F test/corrupt8.test 2399dfe40d2c0c63af86706e30f3e6302a8d0516
|
||||
F test/corrupt9.test 730a3db08d4ab9aa43392ea30d9c2b4879cbff85
|
||||
F test/corruptA.test 112f4b2ae0b95ebf3ea63718642fb969a93acea557ace3a307234d19c245989b
|
||||
F test/corruptB.test 73a8d6c0b9833697ecf16b63e3c5c05c945b5dec
|
||||
F test/corruptC.test 9cf32275dae3ca33f645afe5d1d3f5ba5ac2af2b0833dfb5282f9dccb6fb81bb
|
||||
F test/corruptC.test 7d6d9e907334ea3ccb7111a0656cafa30a28f8a5f2aaf1c45ad712236302856a
|
||||
F test/corruptD.test 614320aa519f6bf6c7dd2f581f9513ff7b6826954180cca1a606d0e25ea084a3
|
||||
F test/corruptE.test 4143791f2dfb443aec5b7fabfa5821e6063eccc3b49b06f212c2f014715fd476
|
||||
F test/corruptF.test be9fde98e4c93648f1ba52b74e5318edc8f59fe4
|
||||
@@ -1018,10 +1021,10 @@ F test/corruptH.test 79801d97ec5c2f9f3c87739aa1ec2eb786f96454
|
||||
F test/corruptI.test 9d8cbf6214e492abe9e822e759b9751ae336cec0a6fe3ff3b37bfbd8ff9c22ca
|
||||
F test/corruptJ.test 4d5ccc4bf959464229a836d60142831ef76a5aa4
|
||||
F test/corruptK.test 5b4212fe346699831c5ad559a62c54e11c0611bdde1ea8423a091f9c01aa32af
|
||||
F test/corruptL.test 504d90502d9993440226edc355d2275524b89064ea3df5ee5c27f7028ec59d07
|
||||
F test/corruptL.test 652fc8ac0763a6fd3eb28b951d481924167b2d9936083bcc68253b2274a0c8fe
|
||||
F test/corruptM.test 7d574320e08c1b36caa3e47262061f186367d593a7e305d35f15289cc2c3e067
|
||||
F test/corruptN.test 7c099d153a554001b4fb829c799b01f2ea6276cbc32479131e0db0da4efd9cc4
|
||||
F test/cost.test b11cdbf9f11ffe8ef99c9881bf390e61fe92baf2182bad1dbe6de59a7295c576
|
||||
F test/cost.test cc434a026b1e9d0d98137a147e24e5daf1b1ad09e9ff7da63b34c83ddd136d92
|
||||
F test/count.test cd4bd531066e8d77ef8fe1e3fc8253d042072e117ccab214b290cf83f1602249
|
||||
F test/countofview.test 4088e461a10ee33e69803c177a69aa1d7bba81a9ffc2df66d76465a22ca7fdfc
|
||||
F test/coveridxscan.test f35c7208dedc4f98e471c569df64c0f95a49f6e072d8dc7c8f99bdee2697de1b
|
||||
@@ -1042,7 +1045,7 @@ F test/ctime.test 340f362f41f92972bbd71f44e10569a5cc694062b692231bd08aa6fe6c1c47
|
||||
F test/cursorhint.test 05cf0febe5c5f8a31f199401fd1c9322249e753950d55f26f9d5aca61408a270
|
||||
F test/cursorhint2.test 6f3aa9cb19e7418967a10ec6905209bcbb5968054da855fc36c8beee9ae9c42f
|
||||
F test/dataversion1.test 6e5e86ac681f0782e766ebcb56c019ae001522d114e0e111e5ebf68ccf2a7bb8
|
||||
F test/date.test b1a5208e6a9c390cf1d1fa4e38a910386b427b0e27046901c6b0fb995d19800e
|
||||
F test/date.test c8ff835023f2107b57ce7a45c92265d51c98a23fc93231e998f12d850831aad6
|
||||
F test/date2.test 7e12ec14aaf4d5e6294b4ba140445b0eca06ea50062a9c3a69c4ee13d0b6f8b1
|
||||
F test/date3.test a1b77abf05c6772fe5ca2337cac1398892f2a41e62bce7e6be0f4a08a0e64ae5
|
||||
F test/date4.test 75dc8401e8c0639a228cd26a6eaa4ff5ea8ccda912b9853d1c9462c476670e17
|
||||
@@ -1056,7 +1059,7 @@ F test/dbpagefault.test 35f06cfb2ef100a9b19d25754e8141b9cba9b7daabd4c60fa5af93fc
|
||||
F test/dbstatus.test 4a4221a883025ffd39696b3d1b3910b928fb097d77e671351acb35f3aed42759
|
||||
F test/dbstatus2.test f5fe0afed3fa45e57cfa70d1147606c20d2ba23feac78e9a172f2fe8ab5b78ef
|
||||
F test/decimal.test ef731887b43ee32ef86e1c8fddb61a40789f988332c029c601dcf2c319277e9e
|
||||
F test/default.test 9687cfb16717e4b8238c191697c98be88c0b16e568dd5368cd9284154097ef50
|
||||
F test/default.test c7124864cded213a3f118bc7e2e26f34b7c36dfa26cf6945cc8b7f5db1191277
|
||||
F test/delete.test 2686e1c98d552ef37d79ad55b17b93fe96fad9737786917ce3839767f734c48f
|
||||
F test/delete2.test 3a03f2cca1f9a67ec469915cb8babd6485db43fa
|
||||
F test/delete3.test 555e84a00a99230b7d049d477a324a631126a6ab
|
||||
@@ -1069,7 +1072,6 @@ F test/diskfull.test 106391384780753ea6896b7b4f005d10e9866b6e
|
||||
F test/distinct.test 691c9e850b0d0b56b66e7e235453198cb4cf0760e324b7403d3c5abbeab0a014
|
||||
F test/distinct2.test bb71cc7b5e58e895787f9910a788c254f679928d324732d063fe9bc202ecbe71
|
||||
F test/distinctagg.test 40d7169ae5846caaf62c6e307d2ca3c333daf9b6f7cde888956a339a97afe85f
|
||||
F test/drop-many.test 30dd091a4fd0a04b1a38e70c93f69c55749e62a3d895ac5e09277cd97caa5bbf
|
||||
F test/e_blobbytes.test 4c01dfe4f12087b92b20705a3fdfded45dc4ed16d5a211fed4e1d2786ba68a52
|
||||
F test/e_blobclose.test 692fc02a058476c2222a63d97e3f3b2b809c1842e5525ded7f854d540ac2e075
|
||||
F test/e_blobopen.test 29f6055ee453b8e679fe9570c4d3acfedbef821622c5dad16875148c5952ef50
|
||||
@@ -1100,7 +1102,8 @@ F test/enc.test 9a7be5479da985381d740b15f432800f65e2c87029ee57a318f42cb2eb43763a
|
||||
F test/enc2.test 848bf05f15b011719f478dddb7b5e9aea35e39e457493cba4c4eef75d849a5ec
|
||||
F test/enc3.test 55ef64416d72975c66167310a51dc9fc544ba3ae4858b8d5ab22f4cb6500b087
|
||||
F test/enc4.test c8f1ce3618508fd0909945beb8b8831feef2c020
|
||||
F test/eqp.test f3f7548d2f3df03e2f23ecaf35c7c2cc7b89848bd7c3606d94a010521b7ea4f6
|
||||
F test/eqp.test 3302598f611220a6c61e29d9b7bb62fd4a43504509b978dbabdb0b3e56ae3bc0
|
||||
F test/eqp2.test 6e8996148de88f0e7670491e92e712a2920a369b4406f21a27c3c9b6a46b68dd
|
||||
F test/errmsg.test eae9f091eb39ce7e20305de45d8e5d115b68fa856fba4ea6757b6ca3705ff7f9
|
||||
F test/eval.test 73969a2d43a511bf44080c44485a8c4d796b6a4f038d19e491867081155692c0
|
||||
F test/exclusive.test 7ff63be7503990921838d5c9f77f6e33e68e48ed1a9d48cd28745bf650bf0747
|
||||
@@ -1120,7 +1123,7 @@ F test/filter1.test 590f8ba9a0cd0823b80d89ac75c5ce72276189cef9225d2436adaf1ee87f
|
||||
F test/filter2.tcl 44e525497ce07382915f01bd29ffd0fa49dab3adb87253b5e5103ba8f93393e8
|
||||
F test/filter2.test 3cc20eaea2ea1ab245197cc4a62468deb460b78f5aa9bd7d5d3353c2fe569bae
|
||||
F test/filterfault.test c08fb491d698e8df6c122c98f7db1c65ffcfcad2c1ab0e07fa8a5be1b34eaa8b
|
||||
F test/fkey1.test 6cf3fb520def0950799499b5bd0c6f22517cf7b6aee07523cbb52c1496aa8d00
|
||||
F test/fkey1.test e563bcb4cb108ce3f40363cda4f84009dc89a39e2973076e5057ba99fca35378
|
||||
F test/fkey2.test 1063d65e5923c054cfb8f0555a92a3ae0fa8c067275a33ee1715bd856cdb304c
|
||||
F test/fkey3.test 76d475c80b84ee7a5d062e56ccb6ea68882e2b49
|
||||
F test/fkey4.test 86446017011273aad8f9a99c1a65019e7bd9ca9d
|
||||
@@ -1199,7 +1202,7 @@ F test/fts3rank.test cd99bc83a3c923c8d52afd90d86979cf05fc41849f892faeac3988055ef
|
||||
F test/fts3rnd.test 1320d8826a845e38a96e769562bf83d7a92a15d0
|
||||
F test/fts3shared.test 57e26a801f21027b7530da77db54286a6fe4997e
|
||||
F test/fts3snippet.test 0887196d67cffbe365edde535b95ecc642a532ce8551ccd9a73aab5999c3ffae
|
||||
F test/fts3snippet2.test e79afeb1f673713f96d7fc5655726081975399d11e659d15553207be43301dc4
|
||||
F test/fts3snippet2.test 03f6738ab3897bea2ba6be424a0613872e167acbf37a66200d655d737b470f65
|
||||
F test/fts3sort.test ed34c716a11cc2009a35210e84ad5f9c102362ca
|
||||
F test/fts3tok1.test a663f4cac22a9505400bc22aacb818d7055240409c28729669ea7d4cc2120d15
|
||||
F test/fts3tok_err.test 52273cd193b9036282f7bacb43da78c6be87418d
|
||||
@@ -1229,10 +1232,10 @@ F test/fts4umlaut.test fcaca4471de7e78c9d1f7e8976e3e8704d7d8ad979d57a739d00f3f75
|
||||
F test/fts4unicode.test 82a9c16b68ba2f358a856226bb2ee02f81583797bc4744061c54401bf1a0f4c9
|
||||
F test/fts4upfrom.test f25835162c989dffd5e2ef91ec24c4848cc9973093e2d492d1c7b32afac1b49d
|
||||
F test/full.test 6b3c8fb43c6beab6b95438c1675374b95fab245d
|
||||
F test/func.test 504d202650c7940b5aa98364dd68f242df87f39f829e51074a55d79fc7bc7414
|
||||
F test/func2.test 772d66227e4e6684b86053302e2d74a2500e1e0f
|
||||
F test/func.test b56905748ce0567c01d60005f3e6ad1af19453d224ba4730ee687d048fd09ef9
|
||||
F test/func2.test 69f6ae3751b4ec765bdc3b803c0a255aa0f693f28f44805bef03e6b4a3fd242f
|
||||
F test/func3.test 600a632c305a88f3946d38f9a51efe145c989b2e13bd2b2a488db47fe76bab6a
|
||||
F test/func4.test e8ef9b2bd6a192a213cbd5cf31a3b35e25cd6ff2fdaeea0b58d63be31b03d220
|
||||
F test/func4.test a3f9062487dbd826776f54f4e0e9517fe8c3cf689af92735308965774d51fac5
|
||||
F test/func5.test 863e6d1bd0013d09c17236f8a13ea34008dd857d87d85a13a673960e4c25d82a
|
||||
F test/func6.test 9cc9b1f43b435af34fe1416eb1e318c8920448ea7a6962f2121972f5215cb9b0
|
||||
F test/func7.test adbfc910385a6ffd15dc47be3c619ef070c542fcb7488964badb17b2d9a4d080
|
||||
@@ -1245,7 +1248,7 @@ F test/fuzz3.test 9c813e6613b837cb7a277b0383cd66bfa07042b4cf0317157c35852f30043c
|
||||
F test/fuzz4.test c229bcdb45518a89e1d208a21343e061503460ac69fae1539320a89f572eb634
|
||||
F test/fuzz_common.tcl b7197de6ed1ee8250a4f82d67876f4561b42ee8cbbfc6160dcb66331bad3f830
|
||||
F test/fuzz_malloc.test f348276e732e814802e39f042b1f6da6362a610af73a528d8f76898fde6b22f2
|
||||
F test/fuzzcheck.c e6a40f53ac5624aa5b7c4f31c385f09ba088d524cecc4512fd3057caeed8f530
|
||||
F test/fuzzcheck.c dc159967609d00b0cfe619e735cbbf8482570aca85711397034b0662b6c18fc7
|
||||
F test/fuzzdata1.db 3e86d9cf5aea68ddb8e27c02d7dfdaa226347426c7eb814918e4d95475bf8517
|
||||
F test/fuzzdata2.db 128b3feeb78918d075c9b14b48610145a0dd4c8d6f1ca7c2870c7e425f5bf31f
|
||||
F test/fuzzdata3.db c6586d3e3cef0fbc18108f9bb649aa77bfc38aba
|
||||
@@ -1257,7 +1260,7 @@ F test/fuzzdata8.db 4a53b6d077c6a5c23b609d8d3ac66996fa55ba3f8d02f9b6efdd0214a767
|
||||
F test/fuzzer1.test 3d4c4b7e547aba5e5511a2991e3e3d07166cfbb8
|
||||
F test/fuzzer2.test a85ef814ce071293bce1ad8dffa217cbbaad4c14
|
||||
F test/fuzzerfault.test f64c4aef4c9e9edf1d6dc0d3f1e65dcc81e67c996403c88d14f09b74807a42bc
|
||||
F test/fuzzinvariants.c b34530e8431f2cf3591eff588fc7684d6fdef466916fb46141c8c5374a3d8099
|
||||
F test/fuzzinvariants.c 0729b9d8ed77ad0f8c5c7601168a707d5803087d2da030ede9057c51c809cc6c
|
||||
F test/gcfault.test 4ea410ac161e685f17b19e1f606f58514a2850e806c65b846d05f60d436c5b0d
|
||||
F test/gencol1.test e169bdfa11c7ed5e9f322a98a7db3afe9e66235750b68c923efee8e1876b46ec
|
||||
F test/genesis.tcl 1e2e2e8e5cc4058549a154ff1892fe5c9de19f98
|
||||
@@ -1266,14 +1269,14 @@ F test/hexlit.test 4a6a5f46e3c65c4bf1fa06f5dd5a9507a5627751
|
||||
F test/hidden.test 23c1393a79e846d68fd902d72c85d5e5dcf98711
|
||||
F test/hook.test 18cae9140fa7f9a6f346e892a3fe3e31b2ca0be1494cd01b918adb74281016a6
|
||||
F test/hook2.test b9ff3b8c6519fb67f33192f1afe86e7782ee4ac8
|
||||
F test/icu.test 716a6b89fbabe5cc63e0cd4c260befb08fd7b9d761f04d43669233292f0753b1
|
||||
F test/icu.test 8da7d52cd9722c82f33b0466ed915460cb03c23a38f18a9a2d3ff97da9a4a8c0
|
||||
F test/ieee754.test b0945d12be7d255f3dfa18e2511b17ca37e0edd2b803231c52d05b86c04ab26e
|
||||
F test/imposter1.test c3f1db2d3db2c24611a6596a3fc0ffc14f1466c8
|
||||
F test/in.test d1cad4ededd425568b2e39fb0c31fa9a3772311dd595801ff13ba3912b69bba6
|
||||
F test/in2.test 5d4c61d17493c832f7d2d32bef785119e87bde75
|
||||
F test/in3.test 3cbf58c87f4052cee3a58b37b6389777505aa0c0
|
||||
F test/in4.test fdd1d8134da8376985c2edba6035a2de1f6c731524d2ffa651419e8fe2cd1c5a
|
||||
F test/in5.test b32ce7f4a93f44c5dee94af16886d922cc16ebe33c8e1765c73d4049d0f4b40f
|
||||
F test/in4.test bb767ec1cfd1730256f0a83219f0acda36bc251b63f8b8bb7d8c7cff17875a4f
|
||||
F test/in5.test 4fd79c70dfa0681313e8cdca07f5ff0400bdc0e20f808a5c59eaef1e4b48082a
|
||||
F test/in6.test f5f40d6816a8bb7c784424b58a10ac38efb76ab29127a2c17399e0cbeeda0e4b
|
||||
F test/incrblob.test c9b96afc292aeff43d6687bcb09b0280aa599822
|
||||
F test/incrblob2.test a494c9e848560039a23974b9119cfc2cf3ad3bd15cc2694ee6367ae537ef8f1f
|
||||
@@ -1326,7 +1329,7 @@ F test/join.test f7abfef3faeaf2800308872e33a57e5b6e4a2b44fb8c6b90c6068412e71a6cf
|
||||
F test/join2.test 8561fe82ce434ac96de91544072e578dc2cadddf2d9bc9cd802f866a9b92502e
|
||||
F test/join3.test 6f0c774ff1ba0489e6c88a3e77b9d3528fb4fda0
|
||||
F test/join4.test 1a352e4e267114444c29266ce79e941af5885916
|
||||
F test/join5.test 7cc3f3595bb41e60f3f96d5cb6dd8cfcbc31212f0136bba6fc081c082994a94a
|
||||
F test/join5.test 380d12a9350f99f0cc681a4f1fea999886f18b3fe0d71a9b3065bcaead1e007f
|
||||
F test/join6.test f809c025fa253f9e150c0e9afd4cef8813257bceeb6f46e04041228c9403cc2c
|
||||
F test/join7.test 2268dcbb54b724391dda3748ea95c60d960607ffeed67885675998e7117697f6
|
||||
F test/join8.test d384d63985e3991c404afccadaf3efd1cdf9cd72680167f80e3cb80b95c18c68
|
||||
@@ -1337,7 +1340,7 @@ F test/joinC.test 1f1a602c2127f55f136e2cbd3bf2d26546614bf8cffe5902ec1ac9c07f87f2
|
||||
F test/joinD.test 2ce62e7353a0702ca5e70008faf319c1d4686aa19fba34275c6d1da0e960be28
|
||||
F test/joinE.test d5d182f3812771e2c0d97c9dcf5dbe4c41c8e21c82560e59358731c4a3981d6b
|
||||
F test/joinF.test 53dd66158806823ea680dd7543b5406af151b5aafa5cd06a7f3231cd94938127
|
||||
F test/joinH.test f69e5b53b7d887914e854b6a131efbed4ea9f5ca52bdab81788bfc3e79299f43
|
||||
F test/joinH.test 55f69e64da74d4eca2235237f3acb657aef181e22e45daa228e35bba865e0255
|
||||
F test/journal1.test c7b768041b7f494471531e17abc2f4f5ebf9e5096984f43ed17c4eb80ba34497
|
||||
F test/journal2.test 9dac6b4ba0ca79c3b21446bbae993a462c2397c4
|
||||
F test/journal3.test 7c3cf23ffc77db06601c1fcfc9743de8441cb77db9d1aa931863d94f5ffa140e
|
||||
@@ -1354,8 +1357,9 @@ F test/json102.test 557a46e16df1aa9bdbc4076a71a45814ea0e7503d6621d87d42a8c04cbc2
|
||||
F test/json103.test 53df87f83a4e5fa0c0a56eb29ff6c94055c6eb919f33316d62161a8880112dbe
|
||||
F test/json104.test 1b844a70cddcfa2e4cd81a5db0657b2e61e7f00868310f24f56a9ba0114348c1
|
||||
F test/json105.test 043838b56e68f3252a0dcf5be1689016f6f3f05056f8dcfcdc9d074f4d932988
|
||||
F test/json106.test 1d46a9294e2ced35c7f87cebbcb9626d01abab04f1969d7ded7b6f6a1d9be0f2
|
||||
F test/json106.test 4aed3afd16549045d198a8d9cea00deea96e1f2ecf55864dce96cac558b8abef
|
||||
F test/json107.test 59054e815c8f6b67d634d44ace421cf975828fb5651c4460aa66015c8e19d562
|
||||
F test/json108.test 0a5f1e2d4b35a1bc33052563d2a5ede03052e2099e58cb424547656c898e0f49
|
||||
F test/json501.test b95e2d14988b682a5cadf079dd6162f0f85fb74cd59c6b1f1624110104a974eb
|
||||
F test/json502.test 84634d3dbb521d2814e43624025b760c6198456c8197bbec6c977c0236648f5b
|
||||
F test/jsonb01.test f4cdfb4cf5a0c940091b17675ed9583f45add0c938f07d65b0de0e19d3a9a101
|
||||
@@ -1425,13 +1429,13 @@ F test/minmax2.test cf9311babb6f0518d04e42fd6a42c619531c4309a9dd790a2c4e9b3bc595
|
||||
F test/minmax3.test cc1e8b010136db0d01a6f2a29ba5a9f321034354
|
||||
F test/minmax4.test 272ca395257f05937dc96441c9dde4bc9fbf116a8d4fa02baeb0d13d50e36c87
|
||||
F test/misc1.test e3e36262aff1bd9b8b9bf1eeb3af04adb3fc1e23f0a92dbff708bba9e939ace1
|
||||
F test/misc2.test 71e746af479119386ac2ed7ab7d81d99970e75b49ffd3e8efffee100b4b5f350
|
||||
F test/misc2.test a1a3573cc02662becd967766021d6f16c54684d56df5f227481c7ef0d9df0bd0
|
||||
F test/misc3.test cf3dda47d5dda3e53fc5804a100d3c82be736c9d
|
||||
F test/misc4.test 10cd6addb2fa9093df4751a1b92b50440175dd5468a6ec84d0386e78f087db0e
|
||||
F test/misc5.test 027cf0ac10314ea534173f335a33bb4059907ddabbac2c16786766d6f26c8923
|
||||
F test/misc6.test 953cc693924d88e6117aeba16f46f0bf5abede91
|
||||
F test/misc7.test d912f3d45c2989191b797504a220ca225d6be80b21acad22ba0d35f4a9ee4579
|
||||
F test/misc8.test 4db9f8be59834cea08c87e9658014080efa02678ef54a088f84fa5647e81fee0
|
||||
F test/misc8.test 08d2380bc435486b12161521f225043ac2be26f02471c2c1ea4cac0b1548edbd
|
||||
F test/misuse.test 9e7f78402005e833af71dcab32d048003869eca5abcaccc985d4f8dc1d86bcc7
|
||||
F test/mjournal.test 28a08d5cb5fb5b5702a46e19176e45e964e0800d1f894677169e79f34030e152
|
||||
F test/mmap1.test 18de3fd7b70a777af6004ca2feecfcdd3d0be17fa04058e808baf530c94b1a1d
|
||||
@@ -1455,7 +1459,7 @@ F test/notify1.test 669b2b743618efdc18ca4b02f45423d5d2304abf
|
||||
F test/notify2.test 2ecabaa1305083856b7c39cf32816b612740c161
|
||||
F test/notify3.test 796c7b7157f55c93b4e672b724e9c923a6fc6aa72ac419379a623e2350472e22
|
||||
F test/notnull.test a37b663d5bb728d66fc182016613fb8e4a0a4bbf3d75b8876a7527f7d4ed3f18
|
||||
F test/notnull2.test 1ee4acbd614d3cf5f1c4a52f5af7fc771b82352f1a51a86afeaa02c9df1d82ef
|
||||
F test/notnull2.test 2ac7b4e04917148c7a1a9ed36df20150175ce942f07f5714375b29acbaca7106
|
||||
F test/notnullfault.test fc4bb7845582a2b3db376001ef49118393b1b11abe0d24adb03db057ee2b73d5
|
||||
F test/null.test b7ff206a1c60fe01aa2abd33ef9ea83c93727d993ca8a613de86e925c9f2bc6f
|
||||
F test/nulls1.test 7a5e4346ee4285034100b4cd20e6784f16a9d6c927e44ecdf10034086bbee9c9
|
||||
@@ -1466,7 +1470,7 @@ F test/openv2.test 0d3040974bf402e19b7df4b783e447289d7ab394
|
||||
F test/optfuzz-db01.c 9f2fa80b8f84ebbf1f2e8b13421a4e0477fe300f6686fbd76cac1d2db66e0fdc
|
||||
F test/optfuzz-db01.txt 21f6bdeadc701cf11528276e2a55c70bfcb846ba42df327f979bd9e7b6ce7041
|
||||
F test/optfuzz.c 690430a0bf0ad047d5a168bf52b05b2ee97aedaad8c14337e9eb5050faa64994
|
||||
F test/orderby1.test 02cfd870127a7342170b829175c5c53e9e7405744451ac1aeb2f7e2b0c18ca76
|
||||
F test/orderby1.test 7d0e4ee692a3e808c1026b3c483594ad1e468b68b50dcefa0d678a8c05274ceb
|
||||
F test/orderby2.test bc11009f7cd99d96b1b11e57b199b00633eb5b04
|
||||
F test/orderby3.test 8619d06a3debdcd80a27c0fdea5c40b468854b99
|
||||
F test/orderby4.test 4d39bfbaaa3ae64d026ca2ff166353d2edca4ba4
|
||||
@@ -1499,16 +1503,16 @@ F test/pg_common.tcl 3b27542224db1e713ae387459b5d117c836a5f6e328846922993b6d2b76
|
||||
F test/pragma.test 8bb6d3992c1c31ff6d5553d1e0693d642f7e19015648c6ae7034cb497d26bbd4
|
||||
F test/pragma2.test e5d5c176360c321344249354c0c16aec46214c9f
|
||||
F test/pragma3.test 92a46bbea12322dd94a404f49edcfbfc913a2c98115f0d030a7459bb4712ef31
|
||||
F test/pragma4.test 9559cf5173864bf47c0431873d158fbeb72f920a59905b1f46069d8543eccdab
|
||||
F test/pragma4.test 22834a228e59b80f5c15b519b710474859d91535002670ddb7cd13ac44b54e9a
|
||||
F test/pragma5.test 7b33fc43e2e41abf17f35fb73f71b49671a380ea92a6c94b6ce530a25f8d9102
|
||||
F test/pragma6.test fc3b670ab8ed985b2e5faa870f0f81aba1bfd5c3877ef3214e2df88592ccd3e5
|
||||
F test/pragma6.test c5ec577ba087954b4dfa619a3cbe97b155b60a0af487527abe89b10fc17e6512
|
||||
F test/pragmafault.test 275edaf3161771d37de60e5c2b412627ac94cef11739236bec12ed1258b240f8
|
||||
F test/prefixes.test b524a1c44bffec225b9aec98bd728480352aa8532ac4c15771fb85e8beef65d9
|
||||
F test/printf.test 685fec5a0c5af2490ab0632775a301554361d674211d690f5bee0a97b05333de
|
||||
F test/printf2.test 3f55c1871a5a65507416076f6eb97e738d5210aeda7595a74ee895f2224cce60
|
||||
F test/progress.test ebab27f670bd0d4eb9d20d49cef96e68141d92fb
|
||||
F test/ptrchng.test ef1aa72d6cf35a2bbd0869a649b744e9d84977fc
|
||||
F test/pushdown.test 1495a09837a1cedfc0adf07ba42dc6b83be05a2c15de331b67c39a0e22078238
|
||||
F test/pushdown.test 3330746a897ea271b1021bc1e7e57c6f8d49bcb8ca7d58a823d01aa64a303cc7
|
||||
F test/queryonly.test 5f653159e0f552f0552d43259890c1089391dcca
|
||||
F test/quick.test 1681febc928d686362d50057c642f77a02c62e57
|
||||
F test/quickcheck.test a4b7e878cd97e46108291c409b0bf8214f29e18fddd68a42bc5c1375ad1fb80a
|
||||
@@ -1520,13 +1524,14 @@ F test/randexpr1.tcl 40dec52119ed3a2b8b2a773bce24b63a3a746459
|
||||
F test/randexpr1.test eda062a97e60f9c38ae8d806b03b0ddf23d796df
|
||||
F test/rbu.test 168573d353cd0fd10196b87b0caa322c144ef736
|
||||
F test/rdonly.test 64e2696c322e3538df0b1ed624e21f9a23ed9ff8
|
||||
F test/recover.test fd5199f928757cb308661b5fdca1abc19398a798ff7f24b57c3071e9f8e0471e
|
||||
F test/readonly.test c1985f0b4ab55041f2ba629dadc6578a3ff0f0e5b0ec7912e85c51f49c3e82fe
|
||||
F test/recover.test 6463509a7404e0c35431dd9b4a1c3b4a29d7a6af8a08462b31670c8a5a616d3a
|
||||
F test/regexp1.test 8f2a8bc1569666e29a4cee6c1a666cd224eb6d50e2470d1dc1df995170f3e0f1
|
||||
F test/regexp2.test 55ed41da802b0e284ac7e2fe944be3948f93ff25abbca0361a609acfed1368b5
|
||||
F test/reindex.test cd9d6021729910ece82267b4f5e1b5ac2911a7566c43b43c176a6a4732e2118d
|
||||
F test/resetdb.test 54c06f18bc832ac6d6319e5ab23d5c8dd49fdbeec7c696d791682a8006bd5fc3
|
||||
F test/resolver01.test f4022acafda7f4d40eca94dbf16bc5fc4ac30ceb
|
||||
F test/returning1.test db532cde29d6aebbc48c6ddc3149b30476f8e69ca7a2c4b53986c7635e6fd8ec
|
||||
F test/returning1.test 2ebfe6e56f3de9b194295620f46a747c26cebdab937defb9afd84b96dd202ccb
|
||||
F test/returningfault.test ae4c4b5e8745813287a359d9ccdb9d5c883c2e68afb18fb0767937d5de5692a4
|
||||
F test/rollback.test 06680159bc6746d0f26276e339e3ae2f951c64812468308838e0a3362d911eaa
|
||||
F test/rollback2.test 3f3a4e20401825017df7e7671e9f31b6de5fae5620c2b9b49917f52f8c160a8f
|
||||
@@ -1534,7 +1539,7 @@ F test/rollbackfault.test 0e646aeab8840c399cfbfa43daab46fd609cf04a
|
||||
F test/round1.test 29c3c9039936ed024d672f003c4d35ee11c14c0acb75c5f7d6188ff16190cfd4
|
||||
F test/rowallock.test 3f88ec6819489d0b2341c7a7528ae17c053ab7cc
|
||||
F test/rowhash.test 0bc1d31415e4575d10cacf31e1a66b5cc0f8be81
|
||||
F test/rowid.test e29025be95baf6b32f0d5edef59a7633028325896a98f1caa8019559ca910350
|
||||
F test/rowid.test d27191b5ce794c05bf61081e8b2c546a1844c1641321dcaf7fb785234256cc8e
|
||||
F test/rowvalue.test baf4fa3ec1a8c1c920c3faa5fd25959cb454bbd99ac8960397c34549d9fc4abe
|
||||
F test/rowvalue2.test 060d238b7e5639a7c5630cb5e63e311b44efef2b
|
||||
F test/rowvalue3.test 1347e25ca11c547c5a6ff0cc5626f95aa9740e9275bfaec096029f57cb2130ce
|
||||
@@ -1557,7 +1562,7 @@ F test/savepoint6.test f41279c5e137139fa5c21485773332c7adb98cd7
|
||||
F test/savepoint7.test cde525ea3075283eb950cdcdefe23ead4f700daa
|
||||
F test/savepointfault.test f044eac64b59f09746c7020ee261734de82bf9b2
|
||||
F test/scanstatus.test b249328caf4d317e71058006872b8012598a5fa045b30bf24a81eeff650ab49e
|
||||
F test/scanstatus2.test 317670daf7f3eef48a9598cb7800ba8eccab51949cf52bca3f7da3b83a0c1c8c
|
||||
F test/scanstatus2.test 688adc0c3ab1ffadead218cbce6446b10aa892004a8ea5e3640d59257fb836f2
|
||||
F test/schema.test 5dd11c96ba64744de955315d2e4f8992e447533690153b93377dffb2a5ef5431
|
||||
F test/schema2.test 906408621ea881fdb496d878b1822572a34e32c5
|
||||
F test/schema3.test 8ed4ae66e082cdd8b1b1f22d8549e1e7a0db4527a8e6ee8b6193053ee1e5c9ce
|
||||
@@ -1577,7 +1582,7 @@ F test/select6.test 9b2fb4ffedf52e1b5703cfcae1212e7a4a063f014c0458d78d29aca3db76
|
||||
F test/select7.test f659f231489349e8c5734e610803d7654207318f
|
||||
F test/select8.test 8c8f5ae43894c891efc5755ed905467d1d67ad5d
|
||||
F test/select9.test f7586b207ce2304ab80dc93d3146469a28fd4403621dd3a82d06644563d3c812
|
||||
F test/selectA.test 6aef8b2136a4ac7a3e2e4161d2b8ca7bc6ebe2779de084f9bb66ca9e2323a937
|
||||
F test/selectA.test 1da8ce3884c326e11d2855baffb76436b0d7e044404af8a2a70d1399a4ff7e29
|
||||
F test/selectB.test 954e4e49cf1f896d61794e440669e03a27ceea25
|
||||
F test/selectC.test 38c530b0cc5728b793c3c11f52b52c70290d39822224acd39011c89c1853bd31
|
||||
F test/selectD.test 6d1909b49970bf92f45ce657505befcef5fc7cbc13544e18103a316d32189bfb
|
||||
@@ -1587,7 +1592,7 @@ F test/selectG.test 089f7d3d7e6db91566f00b036cb353107a2cca6220eb1cb264085a836dae
|
||||
F test/selectH.test 0b54599f1917d99568c9b929df22ec6261ed7b6d2f02a46b5945ef81b7871aac
|
||||
F test/session.test 78fa2365e93d3663a6e933f86e7afc395adf18be
|
||||
F test/sessionfuzz-data1.db 1f8d5def831f19b1c74571037f0d53a588ea49a6c4ca2a028fc0c27ef896dbcb
|
||||
F test/sessionfuzz.c 666b47e177c7b25f01ba645d41fb9131d2d54ae673f0d81c08f5af2b3e6ecbda
|
||||
F test/sessionfuzz.c f693b8827034a3bed7616d89c65fb4fe8b7ff3c0f000c6ea6beda69b7f1aced3
|
||||
F test/shared.test f022874d9d299fe913529dc10f52ad5a386e4e7ff709270b9b1111b3a0f3420a
|
||||
F test/shared2.test 03eb4a8d372e290107d34b6ce1809919a698e879
|
||||
F test/shared3.test f8cd07c1a2b7cdb315c01671a0b2f8e3830b11ef31da6baa9a9cd8da88965403
|
||||
@@ -1600,15 +1605,15 @@ F test/sharedA.test 64bdd21216dda2c6a3bd3475348ccdc108160f34682c97f2f51c19fc0e21
|
||||
F test/sharedB.test 1a84863d7a2204e0d42f2e1606577c5e92e4473fa37ea0f5bdf829e4bf8ee707
|
||||
F test/shared_err.test 32634e404a3317eeb94abc7a099c556a346fdb8fb3858dbe222a4cbb8926a939
|
||||
F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304
|
||||
F test/shell1.test c7127a5e780ffc9e14c476773127fdf292c6db226529c44c1676f37b3793123f
|
||||
F test/shell2.test 35226c070a8c7f64fd016dfac2a0db2a40f709b3131f61daacd9dad61536c9cb
|
||||
F test/shell3.test 91febeac0412812bf6370abb8ed72700e32bf8f9878849414518f662dfd55e8a
|
||||
F test/shell4.test 947029e5a9efae9054d424b309fc0311439c0c3a0866ebfa3b8a771120708220
|
||||
F test/shell5.test c8b6c54f26ec537f8558273d7ed293ca3725ef42e6b12b8f151718628bd1473b
|
||||
F test/shell6.test 1ceb51b2678c472ba6cf1e5da96679ce8347889fe2c3bf93a0e0fa73f00b00d3
|
||||
F test/shell7.test 115132f66d0463417f408562cc2cf534f6bbc6d83a6d50f0072a9eb171bae97f
|
||||
F test/shell8.test 3fd093d481aaa94dc77fb73f1044c1f19c7efe3477a395cc4f7450133bc54915
|
||||
F test/shell9.test f457a96c088344908e0518dbabffd02eda8ac2a8733f278679e5f47c103efbab
|
||||
F test/shell1.test 17a5ca9c6f24f807b2f505b4b38fcbce143d96cd8664c06c34bbbe0672bf7c30
|
||||
F test/shell2.test 56da24128304c9ab67da2964cc80beff7b35761c446ec6e6e98bff2775b15026
|
||||
F test/shell3.test 5ad4b2813717956414f2c0c8a2027895cd98ccf7dd54dbacbde4d4f5591ce5a1
|
||||
F test/shell4.test 522fdc628c55eff697b061504fb0a9e4e6dfc5d9087a633ab0f3dd11bcc4f807
|
||||
F test/shell5.test 5b2ab1c0540217773f939927c24163a56257446da3f564d4724042620bfea762
|
||||
F test/shell6.test e3b883b61d4916b6906678a35f9d19054861123ad91b856461e0a456273bdbb8
|
||||
F test/shell7.test 753c6ece5361df50025a50cadf378ea36db9cc05fb23d7a96cff7fa130626ef9
|
||||
F test/shell8.test 9b71d56a6f6fc62edd9163534ac21eaa328ad95f1b9026e7bd08d5b4621eacf6
|
||||
F test/shell9.test 8742a5b390cdcef6369f5aa223e415aa4255a4129ef249b177887dc635a87209
|
||||
F test/shmlock.test 3dbf017d34ab0c60abe6a44e447d3552154bd0c87b41eaf5ceacd408dd13fda5
|
||||
F test/shortread1.test bb591ef20f0fd9ed26d0d12e80eee6d7ac8897a3
|
||||
F test/show_speedtest1_rtree.tcl 32e6c5f073d7426148a6936a0408f4b5b169aba5
|
||||
@@ -1648,7 +1653,7 @@ F test/spellfix2.test dfc8f519a3fc204cb2dfa8b4f29821ae90f6f8c3
|
||||
F test/spellfix3.test 0f9efaaa502a0e0a09848028518a6fb096c8ad33
|
||||
F test/spellfix4.test 51c7c26514ade169855c66bcf130bd5acfb4d7fd090cc624645ab275ae6a41fb
|
||||
F test/sqldiff1.test 1b7ab4f312442c5cc6b3a5f299fa8ca051416d1dd173cb1126fd51bf64f2c3fb
|
||||
F test/sqllimits1.test 5880a2f107185744ba4d93637f44c78d17706a9899a38b694d50f209735c81cc
|
||||
F test/sqllimits1.test dee96a51b83ef866d06ec3c687d4c951d97b02549facc5be88c9dfcb215b98bf
|
||||
F test/sqllog.test 6af6cb0b09f4e44e1917e06ce85be7670302517a
|
||||
F test/startup.c 1beb5ca66fcc0fce95c3444db9d1674f90fc605499a574ae2434dcfc10d22805
|
||||
F test/stat.test 123212a20ceb496893d5254a5f6c76442ce549fdc08d1702d8288a2bbaac8408
|
||||
@@ -1658,7 +1663,7 @@ F test/stmtvtab1.test 6873dfb24f8e79cbb5b799b95c2e4349060eb7a3b811982749a84b3594
|
||||
F test/strict1.test 4d2b492152b984fd7e8196d23eb88e2ccb0ef9e46ca2f96c2ce7147ceef9d168
|
||||
F test/strict2.test b22c7a98b5000aef937f1990776497f0e979b1a23bc4f63e2d53b00e59b20070
|
||||
F test/subjournal.test 8d4e2572c0ee9a15549f0d8e40863161295107e52f07a3e8012a2e1fdd093c49
|
||||
F test/subquery.test 312c5d26304b0e93a56ba2cb9d4480b8a1c8217e3b2b8f8be2bfb0b2458ac3a7
|
||||
F test/subquery.test 903abf41049f8404256f7be24b3151328304a5b25162e17ab0079460237382fc
|
||||
F test/subquery2.test 90cf944b9de8204569cf656028391e4af1ccc8c0cc02d4ef38ee3be8de1ffb12
|
||||
F test/subselect.test 0966aa8e720224dbd6a5e769a3ec2a723e332303
|
||||
F test/substr.test a673e3763e247e9b5e497a6cacbaf3da2bd8ec8921c0677145c109f2e633f36b
|
||||
@@ -1674,7 +1679,7 @@ F test/sync.test 89539f4973c010eda5638407e71ca7fddbcd8e0594f4c9980229f804d433309
|
||||
F test/sync2.test 8f9f7d4f6d5be8ca8941a8dadcc4299e558cb6a1ff653a9469146c7a76ef2039
|
||||
F test/syscall.test a39d9a36f852ae6e4800f861bc2f2e83f68bbc2112d9399931ecfadeabd2d69d
|
||||
F test/sysfault.test c9f2b0d8d677558f74de750c75e12a5454719d04
|
||||
F test/tabfunc01.test 54f27eacd054aa528a8b6e3331192c484104f30aaee351ad035f2b39a00f87c4
|
||||
F test/tabfunc01.test f150d206294471d20f50029e6b46b76b87a7a010b16dc57eb44245c76dd02802
|
||||
F test/table.test 7862a00b58b5541511a26757ea9c5c7c3f8298766e98aa099deec703d9c0a8e0
|
||||
F test/tableapi.test ecbcc29c4ab62c1912c3717c48ea5c5e59f7d64e4a91034e6148bd2b82f177f4
|
||||
F test/tableopts.test dba698ba97251017b7c80d738c198d39ab747930
|
||||
@@ -1687,8 +1692,8 @@ F test/temptable2.test 76821347810ecc88203e6ef0dd6897b6036ac788e9dd3e6b04fd4d163
|
||||
F test/temptable3.test d11a0974e52b347e45ee54ef1923c91ed91e4637
|
||||
F test/temptrigger.test 38f0ca479b1822d3117069e014daabcaacefffcc
|
||||
F test/tester.tcl fe617b88c7eb08bdf983d2aaa31c20fbf439eee7b8e0d61ca636fcd0c305bbbf
|
||||
F test/testrunner.tcl 8e2a5c7550b78d3283eee6103104ae2bcf56aa1df892dbd1608f27b93ebf4de8
|
||||
F test/testrunner_data.tcl 7ffd951527bbc614e723fd8d123b6834321878530696adecfdf6035100bac64e
|
||||
F test/testrunner.tcl 1386667c04207d0a540ce1a9bc5ee0b734f7a3ba856c14a03943fb4f32de55bb
|
||||
F test/testrunner_data.tcl 3d36660cfd55ea5e20e661e8f94c0520feebcb437848f9b98b33c483cc479c0c
|
||||
F test/thread001.test a0985c117eab62c0c65526e9fa5d1360dd1cac5b03bde223902763274ce21899
|
||||
F test/thread002.test c24c83408e35ba5a952a3638b7ac03ccdf1ce4409289c54a050ac4c5f1de7502
|
||||
F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7
|
||||
@@ -1750,7 +1755,7 @@ F test/tkt-b351d95f9.test d14a503c414c5c58fdde3e80f9a3cfef986498c0
|
||||
F test/tkt-b72787b1.test a95e8cdad0b98af1853ac7f0afd4ab27b77bf5f3
|
||||
F test/tkt-b75a9ca6b0.test dc6a853c242f7d0326564ae32e9e5eb462b5e8d2bc5b01ea3b18fd24f8e5894b
|
||||
F test/tkt-ba7cbfaedc.test b4c0deccc12aeb55cfdb57935b16b5d67c5a9877
|
||||
F test/tkt-bd484a090c.test 60460bf946f79a79712b71f202eda501ca99b898
|
||||
F test/tkt-bd484a090c.test e6af3e3a4242cd8f1c91c736364f09075d8e33e3b86f6492a1ee36278ea71b61
|
||||
F test/tkt-bdc6bbbb38.test fc38bb09bdd440e3513a1f5f98fc60a075182d7d
|
||||
F test/tkt-c48d99d690.test ba61977d62ab612fc515b3c488a6fbd6464a2447
|
||||
F test/tkt-c694113d5.test 82c461924ada5c14866c47e85535b0b0923ba16a2e907e370061a5ca77f65d77
|
||||
@@ -1866,7 +1871,7 @@ F test/trigger5.test 619391a3e9fc194081d22cefd830d811e7badf83
|
||||
F test/trigger6.test 0e411654f122552da6590f0b4e6f781048a4a9b9
|
||||
F test/trigger7.test e7ce54bfda67a88d778aea42544e151c465547a7e617127b6914c2221a6d53c1
|
||||
F test/trigger8.test 30cb0530bd7c4728055420e3f739aa00412eafa4
|
||||
F test/trigger9.test fd49aff8b724ae1a6238989ecf84320d88c0e8f8d9142a891b93f826dfe37b59
|
||||
F test/trigger9.test 1724b595661da3dd3c8d79f0ebae818132a39e65c241bad2049f66952b1dc29d
|
||||
F test/triggerA.test 837be862d8721f903dba3f3ceff05b32e0bee5214cf6ea3da5fadf12d3650e9d
|
||||
F test/triggerB.test 56780c031b454abac2340dbb3b71ac5c56c3d7fe
|
||||
F test/triggerC.test 29f5a28d0fe39e6e2c01f6e1f53f08c0955170ae10a63ad023e33cb0a1682a51
|
||||
@@ -1886,7 +1891,7 @@ F test/types.test bf816ce73c7dfcfe26b700c19f97ef4050d194ff
|
||||
F test/types2.test 1aeb81976841a91eef292723649b5c4fe3bc3cac
|
||||
F test/types3.test c9db8f9e80309edfa4252585cf16bcab7ed31f39eeb904d21e831199a3613fb0
|
||||
F test/unhex.test b7f1b806207cb77fa31c3e434fe92fba524464e3e9356809bfcc28f15af1a8b7
|
||||
F test/unionall.test 5b1c4186a661e4bf762875caf4c61d8fda3dd04a6fa9005187f6ba8900c2913f
|
||||
F test/unionall.test 04d30726c5056f84f92b3a12bf8d8a1dbbe807d1ddc8af95def09e6ef2dd91e3
|
||||
F test/unionall2.test 71e8fa08d5699d50dc9f9dc0c9799c2e7a6bb7931a330d369307a4df7f157fa1
|
||||
F test/unionallfault.test 652bfbb630e6c43135965dc1e8f0a9a791da83aec885d626a632fe1909c56f73
|
||||
F test/unionvtab.test e1704ab1b4c1bb3ffc9da4681f8e85a0b909fd80b937984fc94b27415ac8e5a4
|
||||
@@ -1903,17 +1908,17 @@ F test/upfrom2.test 66f3ebf721b3cebd922faee5c386bf244f816d416b57c000753ff51af623
|
||||
F test/upfrom3.test 6130f24ebf97f5ea865e5d2a14a2d543fe5428a62e87cc60f62d875e45c1f5f0
|
||||
F test/upfrom4.test 78f742a6577c91a7a55c64edb8811004e7c6aa99b8d57b2320f70a918c357807
|
||||
F test/upfromfault.test 3a10075a0043f0c4fad6614b2c371f88a8ba5a4acab68b907438413865d6a8d6
|
||||
F test/upsert1.test a512e2f884d3a36159fce2e45108c236f78ae38e35bda55f4050db580ceb25d3
|
||||
F test/upsert1.test beba4316fbd4b7b9d76784313f6129a548cfe7abea04d46db33e2efce1ab0ac2
|
||||
F test/upsert2.test 720e94d09f7362a282bc69b3c6b83d51daeaaf0440eb4920a08b86518b8c7496
|
||||
F test/upsert3.test 88d7d590a1948a9cb6eac1b54b0642f67a9f35a1fc0f19b200e97d5d39e3179c
|
||||
F test/upsert4.test 25d2a1da92f149331ae0c51ca6e3eee78189577585eab92de149900d62994fa5
|
||||
F test/upsert5.test fff0dcfce73c649204543088d8e5bde01172676063ec9b8f8fc7f195abc386fe
|
||||
F test/upsert5.test 9953b180d02d1369cdbb6c73c900834e5fef8cb78e98e07511c8762ec21cc176
|
||||
F test/upsertfault.test f21ca47740841fdb4d61acfa7b17646d773e67724fe8c185b71c018db8a94b35
|
||||
F test/uri.test c1abaaaa28e9422d61e5f3f9cbc8ef993ec49fe802f581520731708561d49384
|
||||
F test/uri2.test 9d3ba7a53ee167572d53a298ee4a5d38ec4a8fb7
|
||||
F test/userauth01.test e740a2697a7b40d7c5003a7d7edaee16acd349a9
|
||||
F test/utf16align.test 9fde0bb5d3a821594aa68c6829ab9c5453a084384137ebb9f6153e2d678039da
|
||||
F test/vacuum-into.test 35dc6f79b563f91c61822f61797363e97fed1bf28f1f722688b98d43f1980d76
|
||||
F test/vacuum-into.test 77845cee98770c416dae9b0da6bb3229753861f2da65c11b4f9715d081712d8a
|
||||
F test/vacuum.test ce91c39f7f91a4273bf620efad21086b5aa6ef1d
|
||||
F test/vacuum2.test 9fd45ce6ce29f5614c249e03938d3567c06a9e772d4f155949f8eafe2d8af520
|
||||
F test/vacuum3.test d9d9a04ee58c485b94694fd4f68cffaba49c32234fdefe1ac1a622c5e17d4ce3
|
||||
@@ -1921,9 +1926,11 @@ F test/vacuum4.test 7ea76b769fffeb41f925303b04cbcf5a5bbeabe55e4c60ae754ff24eeeb7
|
||||
F test/vacuum5.test 263b144d537e92ad8e9ca8a73cc6e1583f41cfd0dda9432b87f7806174a2f48c
|
||||
F test/vacuum6.test b137b04bf3392d3f5c3b8fda0ce85a6775a70ca112f6559f74ff52dc9ce042fd
|
||||
F test/vacuummem.test 4b30f5b95a9ff86e9d5c20741e50a898b2dc10b0962a3211571eb165357003fb
|
||||
F test/values.test 52102ad9e5068b449429e40a976486a52246041f7cd79d086a2b170e77dec925
|
||||
F test/valuesfault.test 2ef23ed965e3bd08e268cdc38a0d11653390ddbbe1e8e2e98d16f55edd30f6e8
|
||||
F test/varint.test bbce22cda8fc4d135bcc2b589574be8410614e62
|
||||
F test/veryquick.test 57ab846bacf7b90cf4e9a672721ea5c5b669b661
|
||||
F test/view.test d4c4281e1679245829db35597817282f60dc513fc39cc5439078f009bd118487
|
||||
F test/view.test 3c23d7a068e9e4a0c4e6907498042772adea725f0630c3d9638ffd4e5a08b92b
|
||||
F test/view2.test db32c8138b5b556f610b35dfddd38c5a58a292f07fda5281eedb0851b2672679
|
||||
F test/view3.test ad8a8290ee2b55ff6ce66c9ef1ce3f1e47926273a3814e1c425293e128a95456
|
||||
F test/vt02.c 5b44ac67b1a283fedecf2d6e2ceda61e7a157f01d44dcb4490dcb1e87d057060
|
||||
@@ -1946,6 +1953,7 @@ F test/vtabH.test 2efb5a24b0bb50796b21eca23032cfb77abfa4b0c03938e38ce5897abac404
|
||||
F test/vtabI.test 751b07636700dbdea328e4265b6077ccd6811a3f
|
||||
F test/vtabJ.test a6aef49d558af90fae10565b29501f82a95781cb4f797f2d13e2d19f9b6bc77b
|
||||
F test/vtabK.test 13293177528fada1235c0112db0d187d754af1355c5a39371abd365104e3afbf
|
||||
F test/vtabL.test 49ec7342e8bfcb0d6c3d2443c619f430c609c042d5d7e6ddf52def65d6d1812f
|
||||
F test/vtab_alter.test 736e66fb5ec7b4fee58229aa3ada2f27ec58bc58c00edae4836890c3784c6783
|
||||
F test/vtab_err.test dcc8b7b9cb67522b3fe7a272c73856829dae4ab7fdb30399aea1b6981bda2b65
|
||||
F test/vtab_shared.test 5253bff2355a9a3f014c15337da7e177ab0ef8ad
|
||||
@@ -2009,8 +2017,9 @@ F test/whereH.test e4b07f7a3c2f5d31195cd33710054c78667573b2
|
||||
F test/whereI.test c4bb7e2ca56d49bd8ab5c7bd085b8b83e353922b46904d68aefb3c7468643581
|
||||
F test/whereJ.test fc05e374cc9f2dc204148d6c06822c380ad388895fe97a6d335b94a26a08aecf
|
||||
F test/whereK.test 0270ab7f04ba5436fb9156d31d642a1c82727f4c4bfe5ba90d435c78cf44684a
|
||||
F test/whereL.test 9d7c8a9f4e5e82d6859e61cf8758c3856c7e0a7fd8be11c92cac8c3ec39228fd
|
||||
F test/whereL.test 438a397fa883b77bb6361c08a8befa41b52e9cfbe15a2a43715d122f8cfa8649
|
||||
F test/whereM.test 0dbc9998783458ddcf3cc078ca7c2951d8b2677d472ecf0028f449ed327c0250
|
||||
F test/whereN.test 63a3584b71acfb6963416de82f26c6b1644abc5ca6080c76546b9246734c8803
|
||||
F test/wherefault.test 6cf2a9c5712952d463d3f45ebee7f6caf400984df51a195d884cfb7eb0e837a7
|
||||
F test/wherelfault.test 9012e4ef5259058b771606616bd007af5d154e64cc25fa9fd4170f6411db44e3
|
||||
F test/wherelimit.test afb46397c6d7e964e6e294ba3569864a0c570fe3807afc634236c2b752372f31
|
||||
@@ -2088,7 +2097,7 @@ F tool/genfkey.test b6afd7b825d797a1e1274f519ab5695373552ecad5cd373530c63533638a
|
||||
F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce
|
||||
F tool/index_usage.c f62a0c701b2c7ff2f3e21d206f093c123f222dbf07136a10ffd1ca15a5c706c5
|
||||
F tool/kvtest-speed.sh 4761a9c4b3530907562314d7757995787f7aef8f
|
||||
F tool/lemon.c 7f264d5d06450f929a20fa63a1b7e8f2df47dfaa6d7f80e4afef3639157497a4
|
||||
F tool/lemon.c 2eaee61479f9b97056950741c8f671a13281c819b94246698264a322360319a9
|
||||
F tool/lempar.c e6b649778e5c027c8365ff01d7ef39297cd7285fa1f881cce31792689541e79f
|
||||
F tool/libvers.c caafc3b689638a1d88d44bc5f526c2278760d9b9
|
||||
F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862
|
||||
@@ -2097,11 +2106,11 @@ F tool/max-limits.c cbb635fbb37ae4d05f240bfb5b5270bb63c54439
|
||||
F tool/merge-test.tcl de76b62f2de2a92d4c1ca4f976bce0aea6899e0229e250479b229b2a1914b176
|
||||
F tool/mkautoconfamal.sh cbdcf993fa83dccbef7fb77b39cdeb31ef9f77d9d88c9e343b58d35ca3898a6a
|
||||
F tool/mkccode.tcl 86463e68ce9c15d3041610fedd285ce32a5cf7a58fc88b3202b8b76837650dbe x
|
||||
F tool/mkctimec.tcl a16682eae5f01f85e5861b2aa215ca0d46b4230658ee25977e02b4508566fb75 x
|
||||
F tool/mkctimec.tcl 060e9785e9503bf51f8b1b11b542bdeef90fd0ceb0738154f6762acec0c61e5f x
|
||||
F tool/mkkeywordhash.c b9faa0ae7e14e4dbbcd951cddd786bf46b8a65bb07b129ba8c0cfade723aaffd
|
||||
F tool/mkmsvcmin.tcl 8897d515ef7f94772322db95a3b6fce6c614d84fe0bdd06ba5a1c786351d5a1d
|
||||
F tool/mkopcodec.tcl 33d20791e191df43209b77d37f0ff0904620b28465cca6990cf8d60da61a07ef
|
||||
F tool/mkopcodeh.tcl 769d9e6a8b462323150dc13a8539d6064664b72974f7894befe2491cc73e05cd
|
||||
F tool/mkopcodeh.tcl 2b4e6967a670ef21bf53a164964c35c6163277d002a4c6f56fa231d68c88d023
|
||||
F tool/mkopts.tcl 680f785fdb09729fd9ac50632413da4eadbdf9071535e3f26d03795828ab07fa
|
||||
F tool/mkpragmatab.tcl 32e359ccb21011958a821955254bd7a5fa7915d01a8c16fed91ffc8b40cb4adf
|
||||
F tool/mkshellc.tcl b7adf08b82de60811d2cb6af05ff59fc17e5cd6f3e98743c14eaaa3f8971fed0
|
||||
@@ -2177,8 +2186,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||
P 26272590691aee8569a1ea9c233f9b0e55ece63ed167696cc1ecfe3ca2548ba1
|
||||
R ffcb677589cb061417252fbc7f9600de
|
||||
U drh
|
||||
Z 148d8810a6ba162cbd3b9cd95d027cbb
|
||||
P 7d30596496c6a7a37b925f13d8d94d5de224ec31bb86594fa4cc07b10082e776
|
||||
R 9eed5aaa8e26bff88d62db6ed7adfa29
|
||||
U dan
|
||||
Z d168d9476b0b5c157ebfbc91beb1e6fe
|
||||
# Remove this line to create a well-formed Fossil manifest.
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
1a49788afd90fa4415c6aae4b6bbad68f9306c1df1026762a9d88bcb40e4cd8f
|
||||
90e5c8226a695e838e8c1703a9b8598e654d216799e8806c4d1a1f20c28c6486
|
||||
@@ -2262,7 +2262,12 @@ void sqlite3AlterDropColumn(Parse *pParse, SrcList *pSrc, const Token *pName){
|
||||
if( i==pTab->iPKey ){
|
||||
sqlite3VdbeAddOp2(v, OP_Null, 0, regOut);
|
||||
}else{
|
||||
char aff = pTab->aCol[i].affinity;
|
||||
if( aff==SQLITE_AFF_REAL ){
|
||||
pTab->aCol[i].affinity = SQLITE_AFF_NUMERIC;
|
||||
}
|
||||
sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, i, regOut);
|
||||
pTab->aCol[i].affinity = aff;
|
||||
}
|
||||
nField++;
|
||||
}
|
||||
|
||||
+27
-14
@@ -5143,6 +5143,12 @@ static int accessPayload(
|
||||
memset(pCur->aOverflow, 0, nOvfl*sizeof(Pgno));
|
||||
pCur->curFlags |= BTCF_ValidOvfl;
|
||||
}else{
|
||||
/* Sanity check the validity of the overflow page cache */
|
||||
assert( pCur->aOverflow[0]==nextPage
|
||||
|| pCur->aOverflow[0]==0
|
||||
|| CORRUPT_DB );
|
||||
assert( pCur->aOverflow[0]!=0 || pCur->aOverflow[offset/ovflSize]==0 );
|
||||
|
||||
/* If the overflow page-list cache has been allocated and the
|
||||
** entry for the first required overflow page is valid, skip
|
||||
** directly to it.
|
||||
@@ -5624,6 +5630,23 @@ int sqlite3BtreeFirst(BtCursor *pCur, int *pRes){
|
||||
return rc;
|
||||
}
|
||||
|
||||
#ifdef SQLITE_DEBUG
|
||||
/* The cursors is CURSOR_VALID and has BTCF_AtLast set. Verify that
|
||||
** this flags are true for a consistent database.
|
||||
**
|
||||
** This routine is is called from within assert() statements only.
|
||||
** It is an internal verification routine and does not appear in production
|
||||
** builds.
|
||||
*/
|
||||
static int cursorIsAtLastEntry(BtCursor *pCur){
|
||||
int ii;
|
||||
for(ii=0; ii<pCur->iPage; ii++){
|
||||
if( pCur->aiIdx[ii]!=pCur->apPage[ii]->nCell ) return 0;
|
||||
}
|
||||
return pCur->ix==pCur->pPage->nCell-1 && pCur->pPage->leaf!=0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Move the cursor to the last entry in the table. Return SQLITE_OK
|
||||
** on success. Set *pRes to 0 if the cursor actually points to something
|
||||
** or set *pRes to 1 if the table is empty.
|
||||
@@ -5652,18 +5675,7 @@ int sqlite3BtreeLast(BtCursor *pCur, int *pRes){
|
||||
|
||||
/* If the cursor already points to the last entry, this is a no-op. */
|
||||
if( CURSOR_VALID==pCur->eState && (pCur->curFlags & BTCF_AtLast)!=0 ){
|
||||
#ifdef SQLITE_DEBUG
|
||||
/* This block serves to assert() that the cursor really does point
|
||||
** to the last entry in the b-tree. */
|
||||
int ii;
|
||||
for(ii=0; ii<pCur->iPage; ii++){
|
||||
assert( pCur->aiIdx[ii]==pCur->apPage[ii]->nCell );
|
||||
}
|
||||
assert( pCur->ix==pCur->pPage->nCell-1 || CORRUPT_DB );
|
||||
testcase( pCur->ix!=pCur->pPage->nCell-1 );
|
||||
/* ^-- dbsqlfuzz b92b72e4de80b5140c30ab71372ca719b8feb618 */
|
||||
assert( pCur->pPage->leaf );
|
||||
#endif
|
||||
assert( cursorIsAtLastEntry(pCur) || CORRUPT_DB );
|
||||
*pRes = 0;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
@@ -5716,6 +5728,7 @@ int sqlite3BtreeTableMoveto(
|
||||
}
|
||||
if( pCur->info.nKey<intKey ){
|
||||
if( (pCur->curFlags & BTCF_AtLast)!=0 ){
|
||||
assert( cursorIsAtLastEntry(pCur) || CORRUPT_DB );
|
||||
*pRes = -1;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
@@ -9521,7 +9534,7 @@ int sqlite3BtreeInsert(
|
||||
}else if( loc<0 && pPage->nCell>0 ){
|
||||
assert( pPage->leaf );
|
||||
idx = ++pCur->ix;
|
||||
pCur->curFlags &= ~BTCF_ValidNKey;
|
||||
pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
|
||||
}else{
|
||||
assert( pPage->leaf );
|
||||
}
|
||||
@@ -9551,7 +9564,7 @@ int sqlite3BtreeInsert(
|
||||
*/
|
||||
if( pPage->nOverflow ){
|
||||
assert( rc==SQLITE_OK );
|
||||
pCur->curFlags &= ~(BTCF_ValidNKey);
|
||||
pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
|
||||
rc = balance(pCur);
|
||||
|
||||
/* Must make sure nOverflow is reset to zero even if the balance()
|
||||
|
||||
+211
-306
@@ -2828,20 +2828,20 @@ void sqlite3EndTable(
|
||||
int regRowid; /* Rowid of the next row to insert */
|
||||
int addrInsLoop; /* Top of the loop for inserting rows */
|
||||
Table *pSelTab; /* A table that describes the SELECT results */
|
||||
int iCsr; /* Write cursor on the new table */
|
||||
|
||||
if( IN_SPECIAL_PARSE ){
|
||||
pParse->rc = SQLITE_ERROR;
|
||||
pParse->nErr++;
|
||||
return;
|
||||
}
|
||||
iCsr = pParse->nTab++;
|
||||
regYield = ++pParse->nMem;
|
||||
regRec = ++pParse->nMem;
|
||||
regRowid = ++pParse->nMem;
|
||||
assert(pParse->nTab==1);
|
||||
sqlite3MayAbort(pParse);
|
||||
sqlite3VdbeAddOp3(v, OP_OpenWrite, 1, pParse->regRoot, iDb);
|
||||
sqlite3VdbeAddOp3(v, OP_OpenWrite, iCsr, pParse->regRoot, iDb);
|
||||
sqlite3VdbeChangeP5(v, OPFLAG_P2ISREG);
|
||||
pParse->nTab = 2;
|
||||
addrTop = sqlite3VdbeCurrentAddr(v) + 1;
|
||||
sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, addrTop);
|
||||
if( pParse->nErr ) return;
|
||||
@@ -2862,11 +2862,11 @@ void sqlite3EndTable(
|
||||
VdbeCoverage(v);
|
||||
sqlite3VdbeAddOp3(v, OP_MakeRecord, dest.iSdst, dest.nSdst, regRec);
|
||||
sqlite3TableAffinity(v, p, 0);
|
||||
sqlite3VdbeAddOp2(v, OP_NewRowid, 1, regRowid);
|
||||
sqlite3VdbeAddOp3(v, OP_Insert, 1, regRec, regRowid);
|
||||
sqlite3VdbeAddOp2(v, OP_NewRowid, iCsr, regRowid);
|
||||
sqlite3VdbeAddOp3(v, OP_Insert, iCsr, regRec, regRowid);
|
||||
sqlite3VdbeGoto(v, addrInsLoop);
|
||||
sqlite3VdbeJumpHere(v, addrInsLoop);
|
||||
sqlite3VdbeAddOp1(v, OP_Close, 1);
|
||||
sqlite3VdbeAddOp1(v, OP_Close, iCsr);
|
||||
}
|
||||
|
||||
/* Compute the complete text of the CREATE statement */
|
||||
@@ -3006,9 +3006,12 @@ void sqlite3CreateView(
|
||||
** on a view, even though views do not have rowids. The following flag
|
||||
** setting fixes this problem. But the fix can be disabled by compiling
|
||||
** with -DSQLITE_ALLOW_ROWID_IN_VIEW in case there are legacy apps that
|
||||
** depend upon the old buggy behavior. */
|
||||
#ifndef SQLITE_ALLOW_ROWID_IN_VIEW
|
||||
p->tabFlags |= TF_NoVisibleRowid;
|
||||
** depend upon the old buggy behavior. The ability can also be toggled
|
||||
** using sqlite3_config(SQLITE_CONFIG_ROWID_IN_VIEW,...) */
|
||||
#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
|
||||
p->tabFlags |= sqlite3Config.mNoVisibleRowid; /* Optional. Allow by default */
|
||||
#else
|
||||
p->tabFlags |= TF_NoVisibleRowid; /* Never allow rowid in view */
|
||||
#endif
|
||||
|
||||
sqlite3TwoPartName(pParse, pName1, pName2, &pName);
|
||||
@@ -3260,129 +3263,84 @@ void sqlite3RootPageMoved(sqlite3 *db, int iDb, Pgno iFrom, Pgno iTo){
|
||||
#endif
|
||||
|
||||
/*
|
||||
** The RootStack object holds a list (really a Heap) of btree root pages
|
||||
** and schema numbers that need to be deleted using OP_Destroy.
|
||||
**
|
||||
** OP_Destroy opcodes must be issued in order of decreasing root page
|
||||
** numbers in order to avoid having auto-vacuum disrupt subsequent
|
||||
** OP_Destroy opcodes. For that reason, all pending OP_Destroy calls
|
||||
** are accumulated in an instance of this object. Then at the end of
|
||||
** code generation, this object is used to generate the OP_Destroy opcodes
|
||||
** in decreasing order.
|
||||
**
|
||||
** The data structure is a max-heap. Each rootpage/schema-number combo
|
||||
** is stored as a 64-bit integer, with the schema-number in the upper 32
|
||||
** bits and the page number in the lower 32-bits. The root of the heap
|
||||
** (RootStack.a[0]) is the largest entry in the heap. The children of
|
||||
** heap entry i are i*2+1 and i*2+2. The heap always stays balanced by
|
||||
** ensuring that a parent entry is larger than both children.
|
||||
**
|
||||
** Write code to erase the table with root-page iTable from database iDb.
|
||||
** Also write code to modify the sqlite_schema table and internal schema
|
||||
** if a root-page of another table is moved by the btree-layer whilst
|
||||
** erasing iTable (this can happen with an auto-vacuum database).
|
||||
*/
|
||||
typedef struct RootStack RootStack;
|
||||
struct RootStack {
|
||||
u32 nAlloc; /* Slots allocated for a[] */
|
||||
u32 nUsed; /* Slots used for in a[] */
|
||||
u64 *a; /* Sorting heap. Each entry has iDb in the upper 32 bits and
|
||||
** a page number in the lower 32 bits */
|
||||
};
|
||||
|
||||
/*
|
||||
** Add a new Pgno and iDb to the RootStack in question.
|
||||
**
|
||||
** The new entry is inserted at the of the heap (most distant child)
|
||||
** and then the heap is rebalanced.
|
||||
*/
|
||||
static void rootStackPush(Parse *pParse, RootStack *p, Pgno pgno, int iDb){
|
||||
u64 iNew;
|
||||
int i, j;
|
||||
if( p->nAlloc<p->nUsed+1 ){
|
||||
p->nAlloc = p->nAlloc*2 + 12;
|
||||
p->a = sqlite3DbRealloc(pParse->db, p->a, sizeof(Pgno)*p->nAlloc);
|
||||
if( p->a==0 ){
|
||||
p->nAlloc = p->nUsed = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
assert( pgno>0 || CORRUPT_DB );
|
||||
assert( iDb>=0 && iDb<pParse->db->nDb );
|
||||
iNew = (((u64)iDb)<<32) | pgno;
|
||||
i = p->nUsed++;
|
||||
p->a[i] = iNew;
|
||||
while( i>=1 && p->a[j = (i-1)/2]<p->a[i] ){
|
||||
u64 tmp = p->a[i];
|
||||
p->a[i] = p->a[j];
|
||||
p->a[j] = tmp;
|
||||
i = j;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Remove the largest entry from the RootStack heap. Rebalance the
|
||||
** heap and then return that largest entry.
|
||||
*/
|
||||
static u64 rootStackPop(RootStack *p){
|
||||
u64 iMax;
|
||||
int i, j;
|
||||
assert( p->nUsed>0 );
|
||||
assert( p->a!=0 );
|
||||
iMax = p->a[0];
|
||||
p->a[0] = p->a[--p->nUsed];
|
||||
i = 0;
|
||||
while( (j = i*2+1)<p->nUsed ){
|
||||
u64 tmp;
|
||||
if( j+1<p->nUsed && p->a[j+1]>p->a[j] ) j++;
|
||||
if( p->a[i]>p->a[j] ) break;
|
||||
tmp = p->a[i];
|
||||
p->a[i] = p->a[j];
|
||||
p->a[j] = tmp;
|
||||
i = j;
|
||||
}
|
||||
return iMax;
|
||||
}
|
||||
|
||||
/*
|
||||
** Generate OP_Destroy opcodes for every btree named in the given
|
||||
** RootStack object. Issue these OP_Destroy opcodes in order of decreasing
|
||||
** root page number. Then clean up any memory used by the RootStack.
|
||||
*/
|
||||
static void rootStackCode(Parse *pParse, RootStack *p){
|
||||
int iLastDb = -1;
|
||||
static void destroyRootPage(Parse *pParse, int iTable, int iDb){
|
||||
Vdbe *v = sqlite3GetVdbe(pParse);
|
||||
int r1 = sqlite3GetTempReg(pParse);
|
||||
int r2 = sqlite3GetTempReg(pParse);
|
||||
int regReturn = sqlite3GetTempReg(pParse);
|
||||
Vdbe *v = pParse->pVdbe;
|
||||
int addrSub = 0;
|
||||
while( pParse->nErr==0 && p->nUsed>0 ){
|
||||
u64 iNext = rootStackPop(p);
|
||||
Pgno pgno = iNext & 0xffffffff;
|
||||
int iDb = (iNext>>32)&0xffff;
|
||||
if( pgno<2 ) sqlite3ErrorMsg(pParse, "corrupt schema");
|
||||
sqlite3MayAbort(pParse);
|
||||
if( iDb!=iLastDb ){
|
||||
/* Code a subroutine to that will update the schema table when
|
||||
** a root page number changes. The old root page is in register r1.
|
||||
** Root page is moved to the value in register r2. */
|
||||
iLastDb = iDb;
|
||||
sqlite3VdbeAddOp0(v, OP_Goto);
|
||||
addrSub = sqlite3VdbeCurrentAddr(v);
|
||||
sqlite3NestedParse(pParse,
|
||||
"UPDATE %Q." LEGACY_SCHEMA_TABLE
|
||||
" SET rootpage=#%d WHERE rootpage=#%d",
|
||||
pParse->db->aDb[iDb].zDbSName, r2, r1);
|
||||
sqlite3VdbeAddOp1(v, OP_Return, regReturn);
|
||||
sqlite3VdbeJumpHere(v, addrSub-1);
|
||||
if( iTable<2 ) sqlite3ErrorMsg(pParse, "corrupt schema");
|
||||
sqlite3VdbeAddOp3(v, OP_Destroy, iTable, r1, iDb);
|
||||
sqlite3MayAbort(pParse);
|
||||
#ifndef SQLITE_OMIT_AUTOVACUUM
|
||||
/* OP_Destroy stores an in integer r1. If this integer
|
||||
** is non-zero, then it is the root page number of a table moved to
|
||||
** location iTable. The following code modifies the sqlite_schema table to
|
||||
** reflect this.
|
||||
**
|
||||
** The "#NNN" in the SQL is a special constant that means whatever value
|
||||
** is in register NNN. See grammar rules associated with the TK_REGISTER
|
||||
** token for additional information.
|
||||
*/
|
||||
sqlite3NestedParse(pParse,
|
||||
"UPDATE %Q." LEGACY_SCHEMA_TABLE
|
||||
" SET rootpage=%d WHERE #%d AND rootpage=#%d",
|
||||
pParse->db->aDb[iDb].zDbSName, iTable, r1, r1);
|
||||
#endif
|
||||
sqlite3ReleaseTempReg(pParse, r1);
|
||||
}
|
||||
|
||||
/*
|
||||
** Write VDBE code to erase table pTab and all associated indices on disk.
|
||||
** Code to update the sqlite_schema tables and internal schema definitions
|
||||
** in case a root-page belonging to another table is moved by the btree layer
|
||||
** is also added (this can happen with an auto-vacuum database).
|
||||
*/
|
||||
static void destroyTable(Parse *pParse, Table *pTab){
|
||||
/* If the database may be auto-vacuum capable (if SQLITE_OMIT_AUTOVACUUM
|
||||
** is not defined), then it is important to call OP_Destroy on the
|
||||
** table and index root-pages in order, starting with the numerically
|
||||
** largest root-page number. This guarantees that none of the root-pages
|
||||
** to be destroyed is relocated by an earlier OP_Destroy. i.e. if the
|
||||
** following were coded:
|
||||
**
|
||||
** OP_Destroy 4 0
|
||||
** ...
|
||||
** OP_Destroy 5 0
|
||||
**
|
||||
** and root page 5 happened to be the largest root-page number in the
|
||||
** database, then root page 5 would be moved to page 4 by the
|
||||
** "OP_Destroy 4 0" opcode. The subsequent "OP_Destroy 5 0" would hit
|
||||
** a free-list page.
|
||||
*/
|
||||
Pgno iTab = pTab->tnum;
|
||||
Pgno iDestroyed = 0;
|
||||
|
||||
while( 1 ){
|
||||
Index *pIdx;
|
||||
Pgno iLargest = 0;
|
||||
|
||||
if( iDestroyed==0 || iTab<iDestroyed ){
|
||||
iLargest = iTab;
|
||||
}
|
||||
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
|
||||
Pgno iIdx = pIdx->tnum;
|
||||
assert( pIdx->pSchema==pTab->pSchema );
|
||||
if( (iDestroyed==0 || (iIdx<iDestroyed)) && iIdx>iLargest ){
|
||||
iLargest = iIdx;
|
||||
}
|
||||
}
|
||||
if( iLargest==0 ){
|
||||
return;
|
||||
}else{
|
||||
int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
|
||||
assert( iDb>=0 && iDb<pParse->db->nDb );
|
||||
destroyRootPage(pParse, iLargest, iDb);
|
||||
iDestroyed = iLargest;
|
||||
}
|
||||
sqlite3VdbeAddOp3(v, OP_Destroy, pgno, r1, iDb);
|
||||
sqlite3VdbeAddOp2(v, OP_IfNot, r1, sqlite3VdbeCurrentAddr(v)+3);
|
||||
VdbeCoverage(v);
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, pgno, r2);
|
||||
sqlite3VdbeAddOp2(v, OP_Gosub, regReturn, addrSub);
|
||||
}
|
||||
if( pParse->nErr==0 ){
|
||||
sqlite3ReleaseTempReg(pParse, r1);
|
||||
sqlite3ReleaseTempReg(pParse, regReturn);
|
||||
}
|
||||
sqlite3DbFree(pParse->db, p->a);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3412,12 +3370,7 @@ static void sqlite3ClearStatTables(
|
||||
/*
|
||||
** Generate code to drop a table.
|
||||
*/
|
||||
static void sqlite3CodeDropTable(
|
||||
Parse *pParse, /* Parsing context */
|
||||
RootStack *pStack, /* List of pending OP_Destroys */
|
||||
Table *pTab, /* Table to be dropped */
|
||||
int iDb /* Schema holding pTab */
|
||||
){
|
||||
void sqlite3CodeDropTable(Parse *pParse, Table *pTab, int iDb, int isView){
|
||||
Vdbe *v;
|
||||
sqlite3 *db = pParse->db;
|
||||
Trigger *pTrigger;
|
||||
@@ -3470,13 +3423,8 @@ static void sqlite3CodeDropTable(
|
||||
"DELETE FROM %Q." LEGACY_SCHEMA_TABLE
|
||||
" WHERE tbl_name=%Q and type!='trigger'",
|
||||
pDb->zDbSName, pTab->zName);
|
||||
if( IsOrdinaryTable(pTab) ){
|
||||
Index *pIdx;
|
||||
rootStackPush(pParse, pStack, pTab->tnum, iDb);
|
||||
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
|
||||
if( pIdx->tnum==pTab->tnum ) continue;
|
||||
rootStackPush(pParse, pStack, pIdx->tnum, iDb);
|
||||
}
|
||||
if( !isView && !IsVirtual(pTab) ){
|
||||
destroyTable(pParse, pTab);
|
||||
}
|
||||
|
||||
/* Remove the table entry from SQLite's internal schema and modify
|
||||
@@ -3532,134 +3480,106 @@ static int tableMayNotBeDropped(sqlite3 *db, Table *pTab){
|
||||
*/
|
||||
void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView, int noErr){
|
||||
Table *pTab;
|
||||
Vdbe *v;
|
||||
sqlite3 *db = pParse->db;
|
||||
int iDb;
|
||||
int ii, jj;
|
||||
RootStack rootStack;
|
||||
|
||||
memset(&rootStack, 0, sizeof(rootStack));
|
||||
(void)sqlite3GetVdbe(pParse);
|
||||
sqlite3ReadSchema(pParse);
|
||||
assert( pName!=0 || pParse->nErr!=0 );
|
||||
for(ii=0; pParse->nErr==0 && ii<pName->nSrc; ii++){
|
||||
if( noErr ) db->suppressErr++;
|
||||
assert( isView==0 || isView==LOCATE_VIEW );
|
||||
pTab = sqlite3LocateTableItem(pParse, isView, &pName->a[ii]);
|
||||
if( noErr ) db->suppressErr--;
|
||||
if( db->mallocFailed ){
|
||||
goto exit_drop_table;
|
||||
}
|
||||
assert( pParse->nErr==0 );
|
||||
assert( pName->nSrc==1 );
|
||||
if( sqlite3ReadSchema(pParse) ) goto exit_drop_table;
|
||||
if( noErr ) db->suppressErr++;
|
||||
assert( isView==0 || isView==LOCATE_VIEW );
|
||||
pTab = sqlite3LocateTableItem(pParse, isView, &pName->a[0]);
|
||||
if( noErr ) db->suppressErr--;
|
||||
|
||||
if( pTab==0 ){
|
||||
if( noErr ){
|
||||
sqlite3CodeVerifyNamedSchema(pParse, pName->a[ii].zDatabase);
|
||||
sqlite3ForceNotReadOnly(pParse);
|
||||
}
|
||||
testcase( ii+1<pName->nSrc );
|
||||
continue;
|
||||
if( pTab==0 ){
|
||||
if( noErr ){
|
||||
sqlite3CodeVerifyNamedSchema(pParse, pName->a[0].zDatabase);
|
||||
sqlite3ForceNotReadOnly(pParse);
|
||||
}
|
||||
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
|
||||
assert( iDb>=0 && iDb<db->nDb );
|
||||
goto exit_drop_table;
|
||||
}
|
||||
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
|
||||
assert( iDb>=0 && iDb<db->nDb );
|
||||
|
||||
/* If pTab is a virtual table, call ViewGetColumnNames() to ensure
|
||||
** it is initialized.
|
||||
*/
|
||||
if( IsVirtual(pTab) && sqlite3ViewGetColumnNames(pParse, pTab) ){
|
||||
break;
|
||||
}
|
||||
/* If pTab is a virtual table, call ViewGetColumnNames() to ensure
|
||||
** it is initialized.
|
||||
*/
|
||||
if( IsVirtual(pTab) && sqlite3ViewGetColumnNames(pParse, pTab) ){
|
||||
goto exit_drop_table;
|
||||
}
|
||||
#ifndef SQLITE_OMIT_AUTHORIZATION
|
||||
{
|
||||
int code;
|
||||
const char *zTab = SCHEMA_TABLE(iDb);
|
||||
const char *zDb = db->aDb[iDb].zDbSName;
|
||||
const char *zArg2 = 0;
|
||||
if( sqlite3AuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb)){
|
||||
testcase( ii>0 );
|
||||
testcase( ii+1<pName->nSrc );
|
||||
break;
|
||||
}
|
||||
if( isView ){
|
||||
if( !OMIT_TEMPDB && iDb==1 ){
|
||||
code = SQLITE_DROP_TEMP_VIEW;
|
||||
}else{
|
||||
code = SQLITE_DROP_VIEW;
|
||||
}
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
}else if( IsVirtual(pTab) ){
|
||||
code = SQLITE_DROP_VTABLE;
|
||||
zArg2 = sqlite3GetVTable(db, pTab)->pMod->zName;
|
||||
#endif
|
||||
{
|
||||
int code;
|
||||
const char *zTab = SCHEMA_TABLE(iDb);
|
||||
const char *zDb = db->aDb[iDb].zDbSName;
|
||||
const char *zArg2 = 0;
|
||||
if( sqlite3AuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb)){
|
||||
goto exit_drop_table;
|
||||
}
|
||||
if( isView ){
|
||||
if( !OMIT_TEMPDB && iDb==1 ){
|
||||
code = SQLITE_DROP_TEMP_VIEW;
|
||||
}else{
|
||||
if( !OMIT_TEMPDB && iDb==1 ){
|
||||
code = SQLITE_DROP_TEMP_TABLE;
|
||||
}else{
|
||||
code = SQLITE_DROP_TABLE;
|
||||
}
|
||||
code = SQLITE_DROP_VIEW;
|
||||
}
|
||||
if( sqlite3AuthCheck(pParse, code, pTab->zName, zArg2, zDb) ){
|
||||
testcase( ii>0 );
|
||||
testcase( ii+1<pName->nSrc );
|
||||
break;
|
||||
}
|
||||
if( sqlite3AuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0, zDb) ){
|
||||
testcase( ii>0 );
|
||||
testcase( ii+1<pName->nSrc );
|
||||
break;
|
||||
}
|
||||
}
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
}else if( IsVirtual(pTab) ){
|
||||
code = SQLITE_DROP_VTABLE;
|
||||
zArg2 = sqlite3GetVTable(db, pTab)->pMod->zName;
|
||||
#endif
|
||||
if( tableMayNotBeDropped(db, pTab) ){
|
||||
testcase( ii>0 );
|
||||
testcase( ii+1<pName->nSrc );
|
||||
sqlite3ErrorMsg(pParse, "table %s may not be dropped", pTab->zName);
|
||||
break;
|
||||
}else{
|
||||
if( !OMIT_TEMPDB && iDb==1 ){
|
||||
code = SQLITE_DROP_TEMP_TABLE;
|
||||
}else{
|
||||
code = SQLITE_DROP_TABLE;
|
||||
}
|
||||
}
|
||||
if( sqlite3AuthCheck(pParse, code, pTab->zName, zArg2, zDb) ){
|
||||
goto exit_drop_table;
|
||||
}
|
||||
if( sqlite3AuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0, zDb) ){
|
||||
goto exit_drop_table;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if( tableMayNotBeDropped(db, pTab) ){
|
||||
sqlite3ErrorMsg(pParse, "table %s may not be dropped", pTab->zName);
|
||||
goto exit_drop_table;
|
||||
}
|
||||
|
||||
#ifndef SQLITE_OMIT_VIEW
|
||||
/* Ensure DROP TABLE is not used on a view, and DROP VIEW is not used
|
||||
** on a table.
|
||||
*/
|
||||
if( isView && !IsView(pTab) ){
|
||||
testcase( ii>0 );
|
||||
testcase( ii+1<pName->nSrc );
|
||||
sqlite3ErrorMsg(pParse, "use DROP TABLE to delete table %s", pTab->zName);
|
||||
break;
|
||||
}
|
||||
if( !isView && IsView(pTab) ){
|
||||
testcase( ii>0 );
|
||||
testcase( ii+1<pName->nSrc );
|
||||
sqlite3ErrorMsg(pParse, "use DROP VIEW to delete view %s", pTab->zName);
|
||||
break;
|
||||
}
|
||||
/* Ensure DROP TABLE is not used on a view, and DROP VIEW is not used
|
||||
** on a table.
|
||||
*/
|
||||
if( isView && !IsView(pTab) ){
|
||||
sqlite3ErrorMsg(pParse, "use DROP TABLE to delete table %s", pTab->zName);
|
||||
goto exit_drop_table;
|
||||
}
|
||||
if( !isView && IsView(pTab) ){
|
||||
sqlite3ErrorMsg(pParse, "use DROP VIEW to delete view %s", pTab->zName);
|
||||
goto exit_drop_table;
|
||||
}
|
||||
#endif
|
||||
/* If this table or view has appeared previously in the list of tables
|
||||
** or views to be dropped, then the prior appearance is sufficient so
|
||||
** skip this one. */
|
||||
for(jj=ii-1; jj>=0 && pName->a[jj].pTab!=pTab; jj--){}
|
||||
if( jj>=0 ) continue;
|
||||
|
||||
/* Remember the table for use in the second pass */
|
||||
pName->a[ii].pTab = pTab;
|
||||
pTab->nTabRef++;
|
||||
|
||||
/* Generate code to clear this table from sqlite_statN and to
|
||||
** cascade foreign key constraints.
|
||||
*/
|
||||
/* Generate code to remove the table from the schema table
|
||||
** on disk.
|
||||
*/
|
||||
v = sqlite3GetVdbe(pParse);
|
||||
if( v ){
|
||||
sqlite3BeginWriteOperation(pParse, 1, iDb);
|
||||
if( IsOrdinaryTable(pTab) ){
|
||||
if( !isView ){
|
||||
sqlite3ClearStatTables(pParse, iDb, "tbl", pTab->zName);
|
||||
sqlite3FkDropTable(pParse, pName, pTab);
|
||||
}
|
||||
sqlite3CodeDropTable(pParse, pTab, iDb, isView);
|
||||
}
|
||||
|
||||
/* Generate code to actually delete the tables/views in a second pass.
|
||||
** Btrees must be deleted largest root page first, to avoid problems
|
||||
** caused by autovacuum page reordering. */
|
||||
for(ii=0; pParse->nErr==0 && ii<pName->nSrc; ii++){
|
||||
pTab = pName->a[ii].pTab;
|
||||
if( pTab==0 ) continue;
|
||||
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
|
||||
sqlite3CodeDropTable(pParse, &rootStack, pTab, iDb);
|
||||
}
|
||||
exit_drop_table:
|
||||
sqlite3SrcListDelete(db, pName);
|
||||
rootStackCode(pParse, &rootStack);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -4659,82 +4579,67 @@ void sqlite3DefaultRowEst(Index *pIdx){
|
||||
*/
|
||||
void sqlite3DropIndex(Parse *pParse, SrcList *pName, int ifExists){
|
||||
Index *pIndex;
|
||||
sqlite3 *db = pParse->db;
|
||||
Vdbe *v;
|
||||
sqlite3 *db = pParse->db;
|
||||
int iDb;
|
||||
int ii, jj;
|
||||
RootStack rootStack;
|
||||
|
||||
memset(&rootStack, 0, sizeof(rootStack));
|
||||
v = sqlite3GetVdbe(pParse);
|
||||
sqlite3ReadSchema(pParse);
|
||||
assert( pName!=0 || pParse->nErr!=0 );
|
||||
for(ii=0; pParse->nErr==0 && ii<pName->nSrc; ii++){
|
||||
pName->a[ii].regReturn = 0;
|
||||
pIndex = sqlite3FindIndex(db, pName->a[ii].zName, pName->a[ii].zDatabase);
|
||||
if( pIndex==0 ){
|
||||
if( !ifExists ){
|
||||
sqlite3ErrorMsg(pParse, "no such index: %S", pName->a+ii);
|
||||
}else{
|
||||
sqlite3CodeVerifyNamedSchema(pParse, pName->a[ii].zDatabase);
|
||||
sqlite3ForceNotReadOnly(pParse);
|
||||
testcase( ii>0 );
|
||||
testcase( ii+1<pName->nSrc );
|
||||
}
|
||||
pParse->checkSchema = 1;
|
||||
continue;
|
||||
if( db->mallocFailed ){
|
||||
goto exit_drop_index;
|
||||
}
|
||||
assert( pParse->nErr==0 ); /* Never called with prior non-OOM errors */
|
||||
assert( pName->nSrc==1 );
|
||||
if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){
|
||||
goto exit_drop_index;
|
||||
}
|
||||
pIndex = sqlite3FindIndex(db, pName->a[0].zName, pName->a[0].zDatabase);
|
||||
if( pIndex==0 ){
|
||||
if( !ifExists ){
|
||||
sqlite3ErrorMsg(pParse, "no such index: %S", pName->a);
|
||||
}else{
|
||||
sqlite3CodeVerifyNamedSchema(pParse, pName->a[0].zDatabase);
|
||||
sqlite3ForceNotReadOnly(pParse);
|
||||
}
|
||||
if( pIndex->idxType!=SQLITE_IDXTYPE_APPDEF ){
|
||||
sqlite3ErrorMsg(pParse, "index associated with UNIQUE "
|
||||
"or PRIMARY KEY constraint cannot be dropped", 0);
|
||||
testcase( ii>0 );
|
||||
testcase( ii+1<pName->nSrc );
|
||||
break;
|
||||
}
|
||||
iDb = sqlite3SchemaToIndex(db, pIndex->pSchema);
|
||||
pParse->checkSchema = 1;
|
||||
goto exit_drop_index;
|
||||
}
|
||||
if( pIndex->idxType!=SQLITE_IDXTYPE_APPDEF ){
|
||||
sqlite3ErrorMsg(pParse, "index associated with UNIQUE "
|
||||
"or PRIMARY KEY constraint cannot be dropped", 0);
|
||||
goto exit_drop_index;
|
||||
}
|
||||
iDb = sqlite3SchemaToIndex(db, pIndex->pSchema);
|
||||
#ifndef SQLITE_OMIT_AUTHORIZATION
|
||||
{
|
||||
int code = SQLITE_DROP_INDEX;
|
||||
Table *pTab = pIndex->pTable;
|
||||
const char *zDb = db->aDb[iDb].zDbSName;
|
||||
const char *zTab = SCHEMA_TABLE(iDb);
|
||||
if( sqlite3AuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb) ){
|
||||
testcase( ii>0 );
|
||||
testcase( ii+1<pName->nSrc );
|
||||
break;
|
||||
}
|
||||
if( !OMIT_TEMPDB && iDb==1 ) code = SQLITE_DROP_TEMP_INDEX;
|
||||
if( sqlite3AuthCheck(pParse, code, pIndex->zName, pTab->zName, zDb) ){
|
||||
testcase( ii>0 );
|
||||
testcase( ii+1<pName->nSrc );
|
||||
break;
|
||||
}
|
||||
{
|
||||
int code = SQLITE_DROP_INDEX;
|
||||
Table *pTab = pIndex->pTable;
|
||||
const char *zDb = db->aDb[iDb].zDbSName;
|
||||
const char *zTab = SCHEMA_TABLE(iDb);
|
||||
if( sqlite3AuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb) ){
|
||||
goto exit_drop_index;
|
||||
}
|
||||
if( !OMIT_TEMPDB && iDb==1 ) code = SQLITE_DROP_TEMP_INDEX;
|
||||
if( sqlite3AuthCheck(pParse, code, pIndex->zName, pTab->zName, zDb) ){
|
||||
goto exit_drop_index;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Skip over redundant DROP INDEXes */
|
||||
for(jj=ii-1; jj>=0 && pName->a[jj].u2.pIdx!=pIndex; jj--){}
|
||||
if( jj>=0 ) continue;
|
||||
|
||||
/* Record that this index needs to be dropped. */
|
||||
pName->a[ii].u2.pIdx = pIndex;
|
||||
|
||||
/* Generate code to remove the index and from the schema table and
|
||||
** from sqlite_statN tables */
|
||||
/* Generate code to remove the index and from the schema table */
|
||||
v = sqlite3GetVdbe(pParse);
|
||||
if( v ){
|
||||
sqlite3BeginWriteOperation(pParse, 1, iDb);
|
||||
sqlite3NestedParse(pParse,
|
||||
"DELETE FROM %Q." LEGACY_SCHEMA_TABLE
|
||||
" WHERE name=%Q AND type='index'",
|
||||
"DELETE FROM %Q." LEGACY_SCHEMA_TABLE " WHERE name=%Q AND type='index'",
|
||||
db->aDb[iDb].zDbSName, pIndex->zName
|
||||
);
|
||||
sqlite3ClearStatTables(pParse, iDb, "idx", pIndex->zName);
|
||||
|
||||
rootStackPush(pParse, &rootStack, pIndex->tnum, iDb);
|
||||
sqlite3ChangeCookie(pParse, iDb);
|
||||
destroyRootPage(pParse, pIndex->tnum, iDb);
|
||||
sqlite3VdbeAddOp4(v, OP_DropIndex, iDb, 0, 0, pIndex->zName, 0);
|
||||
}
|
||||
|
||||
exit_drop_index:
|
||||
sqlite3SrcListDelete(db, pName);
|
||||
rootStackCode(pParse, &rootStack);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -65,6 +65,9 @@ static const char * const sqlite3azCompileOpt[] = {
|
||||
"ALLOW_COVERING_INDEX_SCAN=" CTIMEOPT_VAL(SQLITE_ALLOW_COVERING_INDEX_SCAN),
|
||||
# endif
|
||||
#endif
|
||||
#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
|
||||
"ALLOW_ROWID_IN_VIEW",
|
||||
#endif
|
||||
#ifdef SQLITE_ALLOW_URI_AUTHORITY
|
||||
"ALLOW_URI_AUTHORITY",
|
||||
#endif
|
||||
|
||||
+138
-29
@@ -71,13 +71,14 @@ struct DateTime {
|
||||
int tz; /* Timezone offset in minutes */
|
||||
double s; /* Seconds */
|
||||
char validJD; /* True (1) if iJD is valid */
|
||||
char rawS; /* Raw numeric value stored in s */
|
||||
char validYMD; /* True (1) if Y,M,D are valid */
|
||||
char validHMS; /* True (1) if h,m,s are valid */
|
||||
char validTZ; /* True (1) if tz is valid */
|
||||
char tzSet; /* Timezone was set explicitly */
|
||||
char isError; /* An overflow has occurred */
|
||||
char useSubsec; /* Display subsecond precision */
|
||||
char nFloor; /* Days to implement "floor" */
|
||||
unsigned rawS : 1; /* Raw numeric value stored in s */
|
||||
unsigned isError : 1; /* An overflow has occurred */
|
||||
unsigned useSubsec : 1; /* Display subsecond precision */
|
||||
unsigned isUtc : 1; /* Time is known to be UTC */
|
||||
unsigned isLocal : 1; /* Time is known to be localtime */
|
||||
};
|
||||
|
||||
|
||||
@@ -175,6 +176,8 @@ static int parseTimezone(const char *zDate, DateTime *p){
|
||||
sgn = +1;
|
||||
}else if( c=='Z' || c=='z' ){
|
||||
zDate++;
|
||||
p->isLocal = 0;
|
||||
p->isUtc = 1;
|
||||
goto zulu_time;
|
||||
}else{
|
||||
return c!=0;
|
||||
@@ -187,7 +190,6 @@ static int parseTimezone(const char *zDate, DateTime *p){
|
||||
p->tz = sgn*(nMn + nHr*60);
|
||||
zulu_time:
|
||||
while( sqlite3Isspace(*zDate) ){ zDate++; }
|
||||
p->tzSet = 1;
|
||||
return *zDate!=0;
|
||||
}
|
||||
|
||||
@@ -231,7 +233,6 @@ static int parseHhMmSs(const char *zDate, DateTime *p){
|
||||
p->m = m;
|
||||
p->s = s + ms;
|
||||
if( parseTimezone(zDate, p) ) return 1;
|
||||
p->validTZ = (p->tz!=0)?1:0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -278,15 +279,40 @@ static void computeJD(DateTime *p){
|
||||
p->validJD = 1;
|
||||
if( p->validHMS ){
|
||||
p->iJD += p->h*3600000 + p->m*60000 + (sqlite3_int64)(p->s*1000 + 0.5);
|
||||
if( p->validTZ ){
|
||||
if( p->tz ){
|
||||
p->iJD -= p->tz*60000;
|
||||
p->validYMD = 0;
|
||||
p->validHMS = 0;
|
||||
p->validTZ = 0;
|
||||
p->tz = 0;
|
||||
p->isUtc = 1;
|
||||
p->isLocal = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Given the YYYY-MM-DD information current in p, determine if there
|
||||
** is day-of-month overflow and set nFloor to the number of days that
|
||||
** would need to be subtracted from the date in order to bring the
|
||||
** date back to the end of the month.
|
||||
*/
|
||||
static void computeFloor(DateTime *p){
|
||||
assert( p->validYMD || p->isError );
|
||||
assert( p->D>=0 && p->D<=31 );
|
||||
assert( p->M>=0 && p->M<=12 );
|
||||
if( p->D<=28 ){
|
||||
p->nFloor = 0;
|
||||
}else if( (1<<p->M) & 0x15aa ){
|
||||
p->nFloor = 0;
|
||||
}else if( p->M!=2 ){
|
||||
p->nFloor = (p->D==31);
|
||||
}else if( p->Y%4!=0 || (p->Y%100==0 && p->Y%400!=0) ){
|
||||
p->nFloor = p->D - 28;
|
||||
}else{
|
||||
p->nFloor = p->D - 29;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Parse dates of the form
|
||||
**
|
||||
@@ -325,12 +351,16 @@ static int parseYyyyMmDd(const char *zDate, DateTime *p){
|
||||
p->Y = neg ? -Y : Y;
|
||||
p->M = M;
|
||||
p->D = D;
|
||||
if( p->validTZ ){
|
||||
computeFloor(p);
|
||||
if( p->tz ){
|
||||
computeJD(p);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void clearYMD_HMS_TZ(DateTime *p); /* Forward declaration */
|
||||
|
||||
/*
|
||||
** Set the time to the current time reported by the VFS.
|
||||
**
|
||||
@@ -340,6 +370,9 @@ static int setDateTimeToCurrent(sqlite3_context *context, DateTime *p){
|
||||
p->iJD = sqlite3StmtCurrentTime(context);
|
||||
if( p->iJD>0 ){
|
||||
p->validJD = 1;
|
||||
p->isUtc = 1;
|
||||
p->isLocal = 0;
|
||||
clearYMD_HMS_TZ(p);
|
||||
return 0;
|
||||
}else{
|
||||
return 1;
|
||||
@@ -478,7 +511,7 @@ static void computeYMD_HMS(DateTime *p){
|
||||
static void clearYMD_HMS_TZ(DateTime *p){
|
||||
p->validYMD = 0;
|
||||
p->validHMS = 0;
|
||||
p->validTZ = 0;
|
||||
p->tz = 0;
|
||||
}
|
||||
|
||||
#ifndef SQLITE_OMIT_LOCALTIME
|
||||
@@ -610,7 +643,7 @@ static int toLocaltime(
|
||||
p->validHMS = 1;
|
||||
p->validJD = 0;
|
||||
p->rawS = 0;
|
||||
p->validTZ = 0;
|
||||
p->tz = 0;
|
||||
p->isError = 0;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
@@ -630,12 +663,12 @@ static const struct {
|
||||
float rLimit; /* Maximum NNN value for this transform */
|
||||
float rXform; /* Constant used for this transform */
|
||||
} aXformType[] = {
|
||||
{ 6, "second", 4.6427e+14, 1.0 },
|
||||
{ 6, "minute", 7.7379e+12, 60.0 },
|
||||
{ 4, "hour", 1.2897e+11, 3600.0 },
|
||||
{ 3, "day", 5373485.0, 86400.0 },
|
||||
{ 5, "month", 176546.0, 2592000.0 },
|
||||
{ 4, "year", 14713.0, 31536000.0 },
|
||||
/* 0 */ { 6, "second", 4.6427e+14, 1.0 },
|
||||
/* 1 */ { 6, "minute", 7.7379e+12, 60.0 },
|
||||
/* 2 */ { 4, "hour", 1.2897e+11, 3600.0 },
|
||||
/* 3 */ { 3, "day", 5373485.0, 86400.0 },
|
||||
/* 4 */ { 5, "month", 176546.0, 30.0*86400.0 },
|
||||
/* 5 */ { 4, "year", 14713.0, 365.0*86400.0 },
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -667,14 +700,20 @@ static void autoAdjustDate(DateTime *p){
|
||||
** NNN.NNNN seconds
|
||||
** NNN months
|
||||
** NNN years
|
||||
** +/-YYYY-MM-DD HH:MM:SS.SSS
|
||||
** ceiling
|
||||
** floor
|
||||
** start of month
|
||||
** start of year
|
||||
** start of week
|
||||
** start of day
|
||||
** weekday N
|
||||
** unixepoch
|
||||
** auto
|
||||
** localtime
|
||||
** utc
|
||||
** subsec
|
||||
** subsecond
|
||||
**
|
||||
** Return 0 on success and 1 if there is any kind of error. If the error
|
||||
** is in a system call (i.e. localtime()), then an error message is written
|
||||
@@ -705,6 +744,37 @@ static int parseModifier(
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'c': {
|
||||
/*
|
||||
** ceiling
|
||||
**
|
||||
** Resolve day-of-month overflow by rolling forward into the next
|
||||
** month. As this is the default action, this modifier is really
|
||||
** a no-op that is only included for symmetry. See "floor".
|
||||
*/
|
||||
if( sqlite3_stricmp(z, "ceiling")==0 ){
|
||||
computeJD(p);
|
||||
clearYMD_HMS_TZ(p);
|
||||
rc = 0;
|
||||
p->nFloor = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'f': {
|
||||
/*
|
||||
** floor
|
||||
**
|
||||
** Resolve day-of-month overflow by rolling back to the end of the
|
||||
** previous month.
|
||||
*/
|
||||
if( sqlite3_stricmp(z, "floor")==0 ){
|
||||
computeJD(p);
|
||||
p->iJD -= p->nFloor*86400000;
|
||||
clearYMD_HMS_TZ(p);
|
||||
rc = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'j': {
|
||||
/*
|
||||
** julianday
|
||||
@@ -731,7 +801,9 @@ static int parseModifier(
|
||||
** show local time.
|
||||
*/
|
||||
if( sqlite3_stricmp(z, "localtime")==0 && sqlite3NotPureFunc(pCtx) ){
|
||||
rc = toLocaltime(p, pCtx);
|
||||
rc = p->isLocal ? SQLITE_OK : toLocaltime(p, pCtx);
|
||||
p->isUtc = 0;
|
||||
p->isLocal = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -756,7 +828,7 @@ static int parseModifier(
|
||||
}
|
||||
#ifndef SQLITE_OMIT_LOCALTIME
|
||||
else if( sqlite3_stricmp(z, "utc")==0 && sqlite3NotPureFunc(pCtx) ){
|
||||
if( p->tzSet==0 ){
|
||||
if( p->isUtc==0 ){
|
||||
i64 iOrigJD; /* Original localtime */
|
||||
i64 iGuess; /* Guess at the corresponding utc time */
|
||||
int cnt = 0; /* Safety to prevent infinite loop */
|
||||
@@ -779,7 +851,8 @@ static int parseModifier(
|
||||
memset(p, 0, sizeof(*p));
|
||||
p->iJD = iGuess;
|
||||
p->validJD = 1;
|
||||
p->tzSet = 1;
|
||||
p->isUtc = 1;
|
||||
p->isLocal = 0;
|
||||
}
|
||||
rc = SQLITE_OK;
|
||||
}
|
||||
@@ -799,7 +872,7 @@ static int parseModifier(
|
||||
&& r>=0.0 && r<7.0 && (n=(int)r)==r ){
|
||||
sqlite3_int64 Z;
|
||||
computeYMD_HMS(p);
|
||||
p->validTZ = 0;
|
||||
p->tz = 0;
|
||||
p->validJD = 0;
|
||||
computeJD(p);
|
||||
Z = ((p->iJD + 129600000)/86400000) % 7;
|
||||
@@ -839,7 +912,7 @@ static int parseModifier(
|
||||
p->h = p->m = 0;
|
||||
p->s = 0.0;
|
||||
p->rawS = 0;
|
||||
p->validTZ = 0;
|
||||
p->tz = 0;
|
||||
p->validJD = 0;
|
||||
if( sqlite3_stricmp(z,"month")==0 ){
|
||||
p->D = 1;
|
||||
@@ -910,6 +983,7 @@ static int parseModifier(
|
||||
x = p->M>0 ? (p->M-1)/12 : (p->M-12)/12;
|
||||
p->Y += x;
|
||||
p->M -= x*12;
|
||||
computeFloor(p);
|
||||
computeJD(p);
|
||||
p->validHMS = 0;
|
||||
p->validYMD = 0;
|
||||
@@ -956,11 +1030,12 @@ static int parseModifier(
|
||||
z += n;
|
||||
while( sqlite3Isspace(*z) ) z++;
|
||||
n = sqlite3Strlen30(z);
|
||||
if( n>10 || n<3 ) break;
|
||||
if( n<3 || n>10 ) break;
|
||||
if( sqlite3UpperToLower[(u8)z[n-1]]=='s' ) n--;
|
||||
computeJD(p);
|
||||
assert( rc==1 );
|
||||
rRounder = r<0 ? -0.5 : +0.5;
|
||||
p->nFloor = 0;
|
||||
for(i=0; i<ArraySize(aXformType); i++){
|
||||
if( aXformType[i].nName==n
|
||||
&& sqlite3_strnicmp(aXformType[i].zName, z, n)==0
|
||||
@@ -968,21 +1043,24 @@ static int parseModifier(
|
||||
){
|
||||
switch( i ){
|
||||
case 4: { /* Special processing to add months */
|
||||
assert( strcmp(aXformType[i].zName,"month")==0 );
|
||||
assert( strcmp(aXformType[4].zName,"month")==0 );
|
||||
computeYMD_HMS(p);
|
||||
p->M += (int)r;
|
||||
x = p->M>0 ? (p->M-1)/12 : (p->M-12)/12;
|
||||
p->Y += x;
|
||||
p->M -= x*12;
|
||||
computeFloor(p);
|
||||
p->validJD = 0;
|
||||
r -= (int)r;
|
||||
break;
|
||||
}
|
||||
case 5: { /* Special processing to add years */
|
||||
int y = (int)r;
|
||||
assert( strcmp(aXformType[i].zName,"year")==0 );
|
||||
assert( strcmp(aXformType[5].zName,"year")==0 );
|
||||
computeYMD_HMS(p);
|
||||
assert( p->M>=0 && p->M<=12 );
|
||||
p->Y += y;
|
||||
computeFloor(p);
|
||||
p->validJD = 0;
|
||||
r -= (int)r;
|
||||
break;
|
||||
@@ -1607,9 +1685,7 @@ static void timediffFunc(
|
||||
d1.iJD = d2.iJD - d1.iJD;
|
||||
d1.iJD += (u64)1486995408 * (u64)100000;
|
||||
}
|
||||
d1.validYMD = 0;
|
||||
d1.validHMS = 0;
|
||||
d1.validTZ = 0;
|
||||
clearYMD_HMS_TZ(&d1);
|
||||
computeYMD_HMS(&d1);
|
||||
sqlite3StrAccumInit(&sRes, 0, 0, 0, 100);
|
||||
sqlite3_str_appendf(&sRes, "%c%04d-%02d-%02d %02d:%02d:%06.3f",
|
||||
@@ -1678,6 +1754,36 @@ static void currentTimeFunc(
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(SQLITE_OMIT_DATETIME_FUNCS) && defined(SQLITE_DEBUG)
|
||||
/*
|
||||
** datedebug(...)
|
||||
**
|
||||
** This routine returns JSON that describes the internal DateTime object.
|
||||
** Used for debugging and testing only. Subject to change.
|
||||
*/
|
||||
static void datedebugFunc(
|
||||
sqlite3_context *context,
|
||||
int argc,
|
||||
sqlite3_value **argv
|
||||
){
|
||||
DateTime x;
|
||||
if( isDate(context, argc, argv, &x)==0 ){
|
||||
char *zJson;
|
||||
zJson = sqlite3_mprintf(
|
||||
"{iJD:%lld,Y:%d,M:%d,D:%d,h:%d,m:%d,tz:%d,"
|
||||
"s:%.3f,validJD:%d,validYMS:%d,validHMS:%d,"
|
||||
"nFloor:%d,rawS:%d,isError:%d,useSubsec:%d,"
|
||||
"isUtc:%d,isLocal:%d}",
|
||||
x.iJD, x.Y, x.M, x.D, x.h, x.m, x.tz,
|
||||
x.s, x.validJD, x.validYMD, x.validHMS,
|
||||
x.nFloor, x.rawS, x.isError, x.useSubsec,
|
||||
x.isUtc, x.isLocal);
|
||||
sqlite3_result_text(context, zJson, -1, sqlite3_free);
|
||||
}
|
||||
}
|
||||
#endif /* !SQLITE_OMIT_DATETIME_FUNCS && SQLITE_DEBUG */
|
||||
|
||||
|
||||
/*
|
||||
** This function registered all of the above C functions as SQL
|
||||
** functions. This should be the only routine in this file with
|
||||
@@ -1693,6 +1799,9 @@ void sqlite3RegisterDateTimeFunctions(void){
|
||||
PURE_DATE(datetime, -1, 0, 0, datetimeFunc ),
|
||||
PURE_DATE(strftime, -1, 0, 0, strftimeFunc ),
|
||||
PURE_DATE(timediff, 2, 0, 0, timediffFunc ),
|
||||
#ifdef SQLITE_DEBUG
|
||||
PURE_DATE(datedebug, -1, 0, 0, datedebugFunc ),
|
||||
#endif
|
||||
DFUNCTION(current_time, 0, 0, 0, ctimeFunc ),
|
||||
DFUNCTION(current_timestamp, 0, 0, 0, ctimestampFunc),
|
||||
DFUNCTION(current_date, 0, 0, 0, cdateFunc ),
|
||||
|
||||
+138
-38
@@ -218,9 +218,10 @@ Expr *sqlite3ExprSkipCollateAndLikely(Expr *pExpr){
|
||||
assert( pExpr->x.pList->nExpr>0 );
|
||||
assert( pExpr->op==TK_FUNCTION );
|
||||
pExpr = pExpr->x.pList->a[0].pExpr;
|
||||
}else{
|
||||
assert( pExpr->op==TK_COLLATE );
|
||||
}else if( pExpr->op==TK_COLLATE ){
|
||||
pExpr = pExpr->pLeft;
|
||||
}else{
|
||||
break;
|
||||
}
|
||||
}
|
||||
return pExpr;
|
||||
@@ -1869,17 +1870,19 @@ SrcList *sqlite3SrcListDup(sqlite3 *db, const SrcList *p, int flags){
|
||||
pNewItem->iCursor = pOldItem->iCursor;
|
||||
pNewItem->addrFillSub = pOldItem->addrFillSub;
|
||||
pNewItem->regReturn = pOldItem->regReturn;
|
||||
pNewItem->regResult = pOldItem->regResult;
|
||||
if( pNewItem->fg.isIndexedBy ){
|
||||
pNewItem->u1.zIndexedBy = sqlite3DbStrDup(db, pOldItem->u1.zIndexedBy);
|
||||
}else if( pNewItem->fg.isTabFunc ){
|
||||
pNewItem->u1.pFuncArg =
|
||||
sqlite3ExprListDup(db, pOldItem->u1.pFuncArg, flags);
|
||||
}else{
|
||||
pNewItem->u1.nRow = pOldItem->u1.nRow;
|
||||
}
|
||||
pNewItem->u2 = pOldItem->u2;
|
||||
if( pNewItem->fg.isCte ){
|
||||
pNewItem->u2.pCteUse->nUse++;
|
||||
}
|
||||
if( pNewItem->fg.isTabFunc ){
|
||||
pNewItem->u1.pFuncArg =
|
||||
sqlite3ExprListDup(db, pOldItem->u1.pFuncArg, flags);
|
||||
}
|
||||
pTab = pNewItem->pTab = pOldItem->pTab;
|
||||
if( pTab ){
|
||||
pTab->nTabRef++;
|
||||
@@ -2345,6 +2348,54 @@ Expr *sqlite3ExprSimplifiedAndOr(Expr *pExpr){
|
||||
return pExpr;
|
||||
}
|
||||
|
||||
/*
|
||||
** pExpr is a TK_FUNCTION node. Try to determine whether or not the
|
||||
** function is a constant function. A function is constant if all of
|
||||
** the following are true:
|
||||
**
|
||||
** (1) It is a scalar function (not an aggregate or window function)
|
||||
** (2) It has either the SQLITE_FUNC_CONSTANT or SQLITE_FUNC_SLOCHNG
|
||||
** property.
|
||||
** (3) All of its arguments are constants
|
||||
**
|
||||
** This routine sets pWalker->eCode to 0 if pExpr is not a constant.
|
||||
** It makes no changes to pWalker->eCode if pExpr is constant. In
|
||||
** every case, it returns WRC_Abort.
|
||||
**
|
||||
** Called as a service subroutine from exprNodeIsConstant().
|
||||
*/
|
||||
static SQLITE_NOINLINE int exprNodeIsConstantFunction(
|
||||
Walker *pWalker,
|
||||
Expr *pExpr
|
||||
){
|
||||
int n; /* Number of arguments */
|
||||
ExprList *pList; /* List of arguments */
|
||||
FuncDef *pDef; /* The function */
|
||||
sqlite3 *db; /* The database */
|
||||
|
||||
assert( pExpr->op==TK_FUNCTION );
|
||||
if( ExprHasProperty(pExpr, EP_TokenOnly)
|
||||
|| (pList = pExpr->x.pList)==0
|
||||
){;
|
||||
n = 0;
|
||||
}else{
|
||||
n = pList->nExpr;
|
||||
sqlite3WalkExprList(pWalker, pList);
|
||||
if( pWalker->eCode==0 ) return WRC_Abort;
|
||||
}
|
||||
db = pWalker->pParse->db;
|
||||
pDef = sqlite3FindFunction(db, pExpr->u.zToken, n, ENC(db), 0);
|
||||
if( pDef==0
|
||||
|| pDef->xFinalize!=0
|
||||
|| (pDef->funcFlags & (SQLITE_FUNC_CONSTANT|SQLITE_FUNC_SLOCHNG))==0
|
||||
|| ExprHasProperty(pExpr, EP_WinFunc)
|
||||
){
|
||||
pWalker->eCode = 0;
|
||||
return WRC_Abort;
|
||||
}
|
||||
return WRC_Prune;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** These routines are Walker callbacks used to check expressions to
|
||||
@@ -2373,6 +2424,7 @@ Expr *sqlite3ExprSimplifiedAndOr(Expr *pExpr){
|
||||
** malformed schema error.
|
||||
*/
|
||||
static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){
|
||||
assert( pWalker->eCode>0 );
|
||||
|
||||
/* If pWalker->eCode is 2 then any term of the expression that comes from
|
||||
** the ON or USING clauses of an outer join disqualifies the expression
|
||||
@@ -2392,6 +2444,8 @@ static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){
|
||||
){
|
||||
if( pWalker->eCode==5 ) ExprSetProperty(pExpr, EP_FromDDL);
|
||||
return WRC_Continue;
|
||||
}else if( pWalker->pParse ){
|
||||
return exprNodeIsConstantFunction(pWalker, pExpr);
|
||||
}else{
|
||||
pWalker->eCode = 0;
|
||||
return WRC_Abort;
|
||||
@@ -2420,9 +2474,11 @@ static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){
|
||||
case TK_IF_NULL_ROW:
|
||||
case TK_REGISTER:
|
||||
case TK_DOT:
|
||||
case TK_RAISE:
|
||||
testcase( pExpr->op==TK_REGISTER );
|
||||
testcase( pExpr->op==TK_IF_NULL_ROW );
|
||||
testcase( pExpr->op==TK_DOT );
|
||||
testcase( pExpr->op==TK_RAISE );
|
||||
pWalker->eCode = 0;
|
||||
return WRC_Abort;
|
||||
case TK_VARIABLE:
|
||||
@@ -2444,15 +2500,15 @@ static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){
|
||||
return WRC_Continue;
|
||||
}
|
||||
}
|
||||
static int exprIsConst(Expr *p, int initFlag, int iCur){
|
||||
static int exprIsConst(Parse *pParse, Expr *p, int initFlag){
|
||||
Walker w;
|
||||
w.eCode = initFlag;
|
||||
w.pParse = pParse;
|
||||
w.xExprCallback = exprNodeIsConstant;
|
||||
w.xSelectCallback = sqlite3SelectWalkFail;
|
||||
#ifdef SQLITE_DEBUG
|
||||
w.xSelectCallback2 = sqlite3SelectWalkAssert2;
|
||||
#endif
|
||||
w.u.iCur = iCur;
|
||||
sqlite3WalkExpr(&w, p);
|
||||
return w.eCode;
|
||||
}
|
||||
@@ -2464,9 +2520,15 @@ static int exprIsConst(Expr *p, int initFlag, int iCur){
|
||||
** For the purposes of this function, a double-quoted string (ex: "abc")
|
||||
** is considered a variable but a single-quoted string (ex: 'abc') is
|
||||
** a constant.
|
||||
**
|
||||
** The pParse parameter may be NULL. But if it is NULL, there is no way
|
||||
** to determine if function calls are constant or not, and hence all
|
||||
** function calls will be considered to be non-constant. If pParse is
|
||||
** not NULL, then a function call might be constant, depending on the
|
||||
** function and on its parameters.
|
||||
*/
|
||||
int sqlite3ExprIsConstant(Expr *p){
|
||||
return exprIsConst(p, 1, 0);
|
||||
int sqlite3ExprIsConstant(Parse *pParse, Expr *p){
|
||||
return exprIsConst(pParse, p, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2482,8 +2544,24 @@ int sqlite3ExprIsConstant(Expr *p){
|
||||
** can be added to the pParse->pConstExpr list and evaluated once when
|
||||
** the prepared statement starts up. See sqlite3ExprCodeRunJustOnce().
|
||||
*/
|
||||
int sqlite3ExprIsConstantNotJoin(Expr *p){
|
||||
return exprIsConst(p, 2, 0);
|
||||
static int sqlite3ExprIsConstantNotJoin(Parse *pParse, Expr *p){
|
||||
return exprIsConst(pParse, p, 2);
|
||||
}
|
||||
|
||||
/*
|
||||
** This routine examines sub-SELECT statements as an expression is being
|
||||
** walked as part of sqlite3ExprIsTableConstant(). Sub-SELECTs are considered
|
||||
** constant as long as they are uncorrelated - meaning that they do not
|
||||
** contain any terms from outer contexts.
|
||||
*/
|
||||
static int exprSelectWalkTableConstant(Walker *pWalker, Select *pSelect){
|
||||
assert( pSelect!=0 );
|
||||
assert( pWalker->eCode==3 || pWalker->eCode==0 );
|
||||
if( (pSelect->selFlags & SF_Correlated)!=0 ){
|
||||
pWalker->eCode = 0;
|
||||
return WRC_Abort;
|
||||
}
|
||||
return WRC_Prune;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2491,9 +2569,26 @@ int sqlite3ExprIsConstantNotJoin(Expr *p){
|
||||
** for any single row of the table with cursor iCur. In other words, the
|
||||
** expression must not refer to any non-deterministic function nor any
|
||||
** table other than iCur.
|
||||
**
|
||||
** Consider uncorrelated subqueries to be constants if the bAllowSubq
|
||||
** parameter is true.
|
||||
*/
|
||||
int sqlite3ExprIsTableConstant(Expr *p, int iCur){
|
||||
return exprIsConst(p, 3, iCur);
|
||||
static int sqlite3ExprIsTableConstant(Expr *p, int iCur, int bAllowSubq){
|
||||
Walker w;
|
||||
w.eCode = 3;
|
||||
w.pParse = 0;
|
||||
w.xExprCallback = exprNodeIsConstant;
|
||||
if( bAllowSubq ){
|
||||
w.xSelectCallback = exprSelectWalkTableConstant;
|
||||
}else{
|
||||
w.xSelectCallback = sqlite3SelectWalkFail;
|
||||
#ifdef SQLITE_DEBUG
|
||||
w.xSelectCallback2 = sqlite3SelectWalkAssert2;
|
||||
#endif
|
||||
}
|
||||
w.u.iCur = iCur;
|
||||
sqlite3WalkExpr(&w, p);
|
||||
return w.eCode;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2511,7 +2606,10 @@ int sqlite3ExprIsTableConstant(Expr *p, int iCur){
|
||||
**
|
||||
** (1) pExpr cannot refer to any table other than pSrc->iCursor.
|
||||
**
|
||||
** (2) pExpr cannot use subqueries or non-deterministic functions.
|
||||
** (2a) pExpr cannot use subqueries unless the bAllowSubq parameter is
|
||||
** true and the subquery is non-correlated
|
||||
**
|
||||
** (2b) pExpr cannot use non-deterministic functions.
|
||||
**
|
||||
** (3) pSrc cannot be part of the left operand for a RIGHT JOIN.
|
||||
** (Is there some way to relax this constraint?)
|
||||
@@ -2540,7 +2638,8 @@ int sqlite3ExprIsTableConstant(Expr *p, int iCur){
|
||||
int sqlite3ExprIsSingleTableConstraint(
|
||||
Expr *pExpr, /* The constraint */
|
||||
const SrcList *pSrcList, /* Complete FROM clause */
|
||||
int iSrc /* Which element of pSrcList to use */
|
||||
int iSrc, /* Which element of pSrcList to use */
|
||||
int bAllowSubq /* Allow non-correlated subqueries */
|
||||
){
|
||||
const SrcItem *pSrc = &pSrcList->a[iSrc];
|
||||
if( pSrc->fg.jointype & JT_LTORJ ){
|
||||
@@ -2565,7 +2664,8 @@ int sqlite3ExprIsSingleTableConstraint(
|
||||
}
|
||||
}
|
||||
}
|
||||
return sqlite3ExprIsTableConstant(pExpr, pSrc->iCursor); /* rules (1), (2) */
|
||||
/* Rules (1), (2a), and (2b) handled by the following: */
|
||||
return sqlite3ExprIsTableConstant(pExpr, pSrc->iCursor, bAllowSubq);
|
||||
}
|
||||
|
||||
|
||||
@@ -2650,7 +2750,7 @@ int sqlite3ExprIsConstantOrGroupBy(Parse *pParse, Expr *p, ExprList *pGroupBy){
|
||||
*/
|
||||
int sqlite3ExprIsConstantOrFunction(Expr *p, u8 isInit){
|
||||
assert( isInit==0 || isInit==1 );
|
||||
return exprIsConst(p, 4+isInit, 0);
|
||||
return exprIsConst(0, p, 4+isInit);
|
||||
}
|
||||
|
||||
#ifdef SQLITE_ENABLE_CURSOR_HINTS
|
||||
@@ -2740,9 +2840,12 @@ int sqlite3ExprCanBeNull(const Expr *p){
|
||||
return 0;
|
||||
case TK_COLUMN:
|
||||
assert( ExprUseYTab(p) );
|
||||
return ExprHasProperty(p, EP_CanBeNull) ||
|
||||
NEVER(p->y.pTab==0) || /* Reference to column of index on expr */
|
||||
(p->iColumn>=0
|
||||
return ExprHasProperty(p, EP_CanBeNull)
|
||||
|| NEVER(p->y.pTab==0) /* Reference to column of index on expr */
|
||||
#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
|
||||
|| (p->iColumn==XN_ROWID && IsView(p->y.pTab))
|
||||
#endif
|
||||
|| (p->iColumn>=0
|
||||
&& p->y.pTab->aCol!=0 /* Possible due to prior error */
|
||||
&& ALWAYS(p->iColumn<p->y.pTab->nCol)
|
||||
&& p->y.pTab->aCol[p->iColumn].notNull==0);
|
||||
@@ -2895,13 +2998,13 @@ static void sqlite3SetHasNullFlag(Vdbe *v, int iCur, int regHasNull){
|
||||
** The argument is an IN operator with a list (not a subquery) on the
|
||||
** right-hand side. Return TRUE if that list is constant.
|
||||
*/
|
||||
static int sqlite3InRhsIsConstant(Expr *pIn){
|
||||
static int sqlite3InRhsIsConstant(Parse *pParse, Expr *pIn){
|
||||
Expr *pLHS;
|
||||
int res;
|
||||
assert( !ExprHasProperty(pIn, EP_xIsSelect) );
|
||||
pLHS = pIn->pLeft;
|
||||
pIn->pLeft = 0;
|
||||
res = sqlite3ExprIsConstant(pIn);
|
||||
res = sqlite3ExprIsConstant(pParse, pIn);
|
||||
pIn->pLeft = pLHS;
|
||||
return res;
|
||||
}
|
||||
@@ -3170,7 +3273,7 @@ int sqlite3FindInIndex(
|
||||
if( eType==0
|
||||
&& (inFlags & IN_INDEX_NOOP_OK)
|
||||
&& ExprUseXList(pX)
|
||||
&& (!sqlite3InRhsIsConstant(pX) || pX->x.pList->nExpr<=2)
|
||||
&& (!sqlite3InRhsIsConstant(pParse,pX) || pX->x.pList->nExpr<=2)
|
||||
){
|
||||
pParse->nTab--; /* Back out the allocation of the unused cursor */
|
||||
iTab = -1; /* Cursor is not allocated */
|
||||
@@ -3453,7 +3556,7 @@ void sqlite3CodeRhsOfIN(
|
||||
** this code only executes once. Because for a non-constant
|
||||
** expression we need to rerun this code each time.
|
||||
*/
|
||||
if( addrOnce && !sqlite3ExprIsConstant(pE2) ){
|
||||
if( addrOnce && !sqlite3ExprIsConstant(pParse, pE2) ){
|
||||
sqlite3VdbeChangeToNoop(v, addrOnce-1);
|
||||
sqlite3VdbeChangeToNoop(v, addrOnce);
|
||||
ExprClearProperty(pExpr, EP_Subrtn);
|
||||
@@ -4617,12 +4720,6 @@ expr_code_doover:
|
||||
assert( pExpr->u.zToken!=0 );
|
||||
assert( pExpr->u.zToken[0]!=0 );
|
||||
sqlite3VdbeAddOp2(v, OP_Variable, pExpr->iColumn, target);
|
||||
if( pExpr->u.zToken[1]!=0 ){
|
||||
const char *z = sqlite3VListNumToName(pParse->pVList, pExpr->iColumn);
|
||||
assert( pExpr->u.zToken[0]=='?' || (z && !strcmp(pExpr->u.zToken, z)) );
|
||||
pParse->pVList[0] = 0; /* Indicate VList may no longer be enlarged */
|
||||
sqlite3VdbeAppendP4(v, (char*)z, P4_STATIC);
|
||||
}
|
||||
return target;
|
||||
}
|
||||
case TK_REGISTER: {
|
||||
@@ -4796,7 +4893,9 @@ expr_code_doover:
|
||||
}
|
||||
#endif
|
||||
|
||||
if( ConstFactorOk(pParse) && sqlite3ExprIsConstantNotJoin(pExpr) ){
|
||||
if( ConstFactorOk(pParse)
|
||||
&& sqlite3ExprIsConstantNotJoin(pParse,pExpr)
|
||||
){
|
||||
/* SQL functions can be expensive. So try to avoid running them
|
||||
** multiple times if we know they always give the same result */
|
||||
return sqlite3ExprCodeRunJustOnce(pParse, pExpr, -1);
|
||||
@@ -4827,7 +4926,7 @@ expr_code_doover:
|
||||
}
|
||||
|
||||
for(i=0; i<nFarg; i++){
|
||||
if( i<32 && sqlite3ExprIsConstant(pFarg->a[i].pExpr) ){
|
||||
if( i<32 && sqlite3ExprIsConstant(pParse, pFarg->a[i].pExpr) ){
|
||||
testcase( i==31 );
|
||||
constMask |= MASKBIT32(i);
|
||||
}
|
||||
@@ -4969,8 +5068,9 @@ expr_code_doover:
|
||||
if( !ExprHasProperty(pExpr, EP_Collate) ){
|
||||
/* A TK_COLLATE Expr node without the EP_Collate tag is a so-called
|
||||
** "SOFT-COLLATE" that is added to constraints that are pushed down
|
||||
** from outer queries into sub-queries by the push-down optimization.
|
||||
** Clear subtypes as subtypes may not cross a subquery boundary.
|
||||
** from outer queries into sub-queries by the WHERE-clause push-down
|
||||
** optimization. Clear subtypes as subtypes may not cross a subquery
|
||||
** boundary.
|
||||
*/
|
||||
assert( pExpr->pLeft );
|
||||
sqlite3ExprCode(pParse, pExpr->pLeft, target);
|
||||
@@ -5294,7 +5394,7 @@ int sqlite3ExprCodeTemp(Parse *pParse, Expr *pExpr, int *pReg){
|
||||
if( ConstFactorOk(pParse)
|
||||
&& ALWAYS(pExpr!=0)
|
||||
&& pExpr->op!=TK_REGISTER
|
||||
&& sqlite3ExprIsConstantNotJoin(pExpr)
|
||||
&& sqlite3ExprIsConstantNotJoin(pParse, pExpr)
|
||||
){
|
||||
*pReg = 0;
|
||||
r2 = sqlite3ExprCodeRunJustOnce(pParse, pExpr, -1);
|
||||
@@ -5358,7 +5458,7 @@ void sqlite3ExprCodeCopy(Parse *pParse, Expr *pExpr, int target){
|
||||
** might choose to code the expression at initialization time.
|
||||
*/
|
||||
void sqlite3ExprCodeFactorable(Parse *pParse, Expr *pExpr, int target){
|
||||
if( pParse->okConstFactor && sqlite3ExprIsConstantNotJoin(pExpr) ){
|
||||
if( pParse->okConstFactor && sqlite3ExprIsConstantNotJoin(pParse,pExpr) ){
|
||||
sqlite3ExprCodeRunJustOnce(pParse, pExpr, target);
|
||||
}else{
|
||||
sqlite3ExprCodeCopy(pParse, pExpr, target);
|
||||
@@ -5417,7 +5517,7 @@ int sqlite3ExprCodeExprList(
|
||||
sqlite3VdbeAddOp2(v, copyOp, j+srcReg-1, target+i);
|
||||
}
|
||||
}else if( (flags & SQLITE_ECEL_FACTOR)!=0
|
||||
&& sqlite3ExprIsConstantNotJoin(pExpr)
|
||||
&& sqlite3ExprIsConstantNotJoin(pParse,pExpr)
|
||||
){
|
||||
sqlite3ExprCodeRunJustOnce(pParse, pExpr, target+i);
|
||||
}else{
|
||||
|
||||
+6
-25
@@ -718,9 +718,8 @@ void sqlite3FkClearTriggerCache(sqlite3 *db, int iDb){
|
||||
/*
|
||||
** This function is called to generate code that runs when table pTab is
|
||||
** being dropped from the database. The SrcList passed as the second argument
|
||||
** to this function contains entries for every table that is being dropped,
|
||||
** with the SrcItem.pTab line being set to the table being dropped. pTab
|
||||
** will be one of those tables.
|
||||
** to this function contains a single entry guaranteed to resolve to
|
||||
** table pTab.
|
||||
**
|
||||
** Normally, no code is required. However, if either
|
||||
**
|
||||
@@ -729,23 +728,15 @@ void sqlite3FkClearTriggerCache(sqlite3 *db, int iDb){
|
||||
** determined at runtime that there are outstanding deferred FK
|
||||
** constraint violations in the database,
|
||||
**
|
||||
** then the equivalent of "DELETE FROM <tbl>" is executed for every table
|
||||
** being dropped, in the order specified in the DROP TABLE statement, which
|
||||
** is the same as the order in which these tables appear in pName.
|
||||
** Triggers are disabled while running these DELETEs, but foreign key
|
||||
** actions are not.
|
||||
**
|
||||
** This routine sets the SrcList.addrFillSub value for all pName entries
|
||||
** for which DELETE FROM has been run. This prevents the DELETE FROM
|
||||
** from being run multiple times.
|
||||
** then the equivalent of "DELETE FROM <tbl>" is executed before dropping
|
||||
** the table from the database. Triggers are disabled while running this
|
||||
** DELETE, but foreign key actions are not.
|
||||
*/
|
||||
void sqlite3FkDropTable(Parse *pParse, SrcList *pName, Table *pTab){
|
||||
sqlite3 *db = pParse->db;
|
||||
if( (db->flags&SQLITE_ForeignKeys) && IsOrdinaryTable(pTab) ){
|
||||
int iSkip = 0;
|
||||
Vdbe *v = sqlite3GetVdbe(pParse);
|
||||
SrcList *pSrc;
|
||||
int ii;
|
||||
|
||||
assert( v ); /* VDBE has already been allocated */
|
||||
assert( IsOrdinaryTable(pTab) );
|
||||
@@ -765,17 +756,7 @@ void sqlite3FkDropTable(Parse *pParse, SrcList *pName, Table *pTab){
|
||||
}
|
||||
|
||||
pParse->disableTriggers = 1;
|
||||
for(ii=0; ii<pName->nSrc; ii++){
|
||||
if( pName->a[ii].pTab==0 ) continue;
|
||||
if( pName->a[ii].addrFillSub ) continue;
|
||||
pName->a[ii].addrFillSub = 1;
|
||||
pSrc = sqlite3SrcListAppend(pParse, 0, 0, 0);
|
||||
if( pSrc ){
|
||||
pSrc->a[0].zDatabase = sqlite3DbStrDup(db, pName->a[ii].zDatabase);
|
||||
pSrc->a[0].zName = sqlite3DbStrDup(db, pName->a[ii].zName);
|
||||
sqlite3DeleteFrom(pParse, pSrc, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
sqlite3DeleteFrom(pParse, sqlite3SrcListDup(db, pName, 0), 0, 0, 0);
|
||||
pParse->disableTriggers = 0;
|
||||
|
||||
/* If the DELETE has generated immediate foreign key constraint
|
||||
|
||||
+3
-3
@@ -1892,7 +1892,7 @@ static void sumFinalize(sqlite3_context *context){
|
||||
if( p->approx ){
|
||||
if( p->ovrfl ){
|
||||
sqlite3_result_error(context,"integer overflow",-1);
|
||||
}else if( !sqlite3IsNaN(p->rErr) ){
|
||||
}else if( !sqlite3IsOverflow(p->rErr) ){
|
||||
sqlite3_result_double(context, p->rSum+p->rErr);
|
||||
}else{
|
||||
sqlite3_result_double(context, p->rSum);
|
||||
@@ -1909,7 +1909,7 @@ static void avgFinalize(sqlite3_context *context){
|
||||
double r;
|
||||
if( p->approx ){
|
||||
r = p->rSum;
|
||||
if( !sqlite3IsNaN(p->rErr) ) r += p->rErr;
|
||||
if( !sqlite3IsOverflow(p->rErr) ) r += p->rErr;
|
||||
}else{
|
||||
r = (double)(p->iSum);
|
||||
}
|
||||
@@ -1923,7 +1923,7 @@ static void totalFinalize(sqlite3_context *context){
|
||||
if( p ){
|
||||
if( p->approx ){
|
||||
r = p->rSum;
|
||||
if( !sqlite3IsNaN(p->rErr) ) r += p->rErr;
|
||||
if( !sqlite3IsOverflow(p->rErr) ) r += p->rErr;
|
||||
}else{
|
||||
r = (double)(p->iSum);
|
||||
}
|
||||
|
||||
@@ -288,6 +288,9 @@ SQLITE_WSD struct Sqlite3Config sqlite3Config = {
|
||||
#endif
|
||||
#ifndef SQLITE_UNTESTABLE
|
||||
0, /* xTestCallback */
|
||||
#endif
|
||||
#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
|
||||
0, /* mNoVisibleRowid. 0 == allow rowid-in-view */
|
||||
#endif
|
||||
0, /* bLocaltimeFault */
|
||||
0, /* xAltLocaltime */
|
||||
|
||||
+226
-19
@@ -577,6 +577,195 @@ void sqlite3AutoincrementEnd(Parse *pParse){
|
||||
# define autoIncStep(A,B,C)
|
||||
#endif /* SQLITE_OMIT_AUTOINCREMENT */
|
||||
|
||||
/*
|
||||
** If argument pVal is a Select object returned by an sqlite3MultiValues()
|
||||
** that was able to use the co-routine optimization, finish coding the
|
||||
** co-routine.
|
||||
*/
|
||||
void sqlite3MultiValuesEnd(Parse *pParse, Select *pVal){
|
||||
if( ALWAYS(pVal) && pVal->pSrc->nSrc>0 ){
|
||||
SrcItem *pItem = &pVal->pSrc->a[0];
|
||||
sqlite3VdbeEndCoroutine(pParse->pVdbe, pItem->regReturn);
|
||||
sqlite3VdbeJumpHere(pParse->pVdbe, pItem->addrFillSub - 1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Return true if all expressions in the expression-list passed as the
|
||||
** only argument are constant.
|
||||
*/
|
||||
static int exprListIsConstant(Parse *pParse, ExprList *pRow){
|
||||
int ii;
|
||||
for(ii=0; ii<pRow->nExpr; ii++){
|
||||
if( 0==sqlite3ExprIsConstant(pParse, pRow->a[ii].pExpr) ) return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return true if all expressions in the expression-list passed as the
|
||||
** only argument are both constant and have no affinity.
|
||||
*/
|
||||
static int exprListIsNoAffinity(Parse *pParse, ExprList *pRow){
|
||||
int ii;
|
||||
if( exprListIsConstant(pParse,pRow)==0 ) return 0;
|
||||
for(ii=0; ii<pRow->nExpr; ii++){
|
||||
Expr *pExpr = pRow->a[ii].pExpr;
|
||||
assert( pExpr->op!=TK_RAISE );
|
||||
assert( pExpr->affExpr==0 );
|
||||
if( 0!=sqlite3ExprAffinity(pExpr) ) return 0;
|
||||
}
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
** This function is called by the parser for the second and subsequent
|
||||
** rows of a multi-row VALUES clause. Argument pLeft is the part of
|
||||
** the VALUES clause already parsed, argument pRow is the vector of values
|
||||
** for the new row. The Select object returned represents the complete
|
||||
** VALUES clause, including the new row.
|
||||
**
|
||||
** There are two ways in which this may be achieved - by incremental
|
||||
** coding of a co-routine (the "co-routine" method) or by returning a
|
||||
** Select object equivalent to the following (the "UNION ALL" method):
|
||||
**
|
||||
** "pLeft UNION ALL SELECT pRow"
|
||||
**
|
||||
** If the VALUES clause contains a lot of rows, this compound Select
|
||||
** object may consume a lot of memory.
|
||||
**
|
||||
** When the co-routine method is used, each row that will be returned
|
||||
** by the VALUES clause is coded into part of a co-routine as it is
|
||||
** passed to this function. The returned Select object is equivalent to:
|
||||
**
|
||||
** SELECT * FROM (
|
||||
** Select object to read co-routine
|
||||
** )
|
||||
**
|
||||
** The co-routine method is used in most cases. Exceptions are:
|
||||
**
|
||||
** a) If the current statement has a WITH clause. This is to avoid
|
||||
** statements like:
|
||||
**
|
||||
** WITH cte AS ( VALUES('x'), ('y') ... )
|
||||
** SELECT * FROM cte AS a, cte AS b;
|
||||
**
|
||||
** This will not work, as the co-routine uses a hard-coded register
|
||||
** for its OP_Yield instructions, and so it is not possible for two
|
||||
** cursors to iterate through it concurrently.
|
||||
**
|
||||
** b) The schema is currently being parsed (i.e. the VALUES clause is part
|
||||
** of a schema item like a VIEW or TRIGGER). In this case there is no VM
|
||||
** being generated when parsing is taking place, and so generating
|
||||
** a co-routine is not possible.
|
||||
**
|
||||
** c) There are non-constant expressions in the VALUES clause (e.g.
|
||||
** the VALUES clause is part of a correlated sub-query).
|
||||
**
|
||||
** d) One or more of the values in the first row of the VALUES clause
|
||||
** has an affinity (i.e. is a CAST expression). This causes problems
|
||||
** because the complex rules SQLite uses (see function
|
||||
** sqlite3SubqueryColumnTypes() in select.c) to determine the effective
|
||||
** affinity of such a column for all rows require access to all values in
|
||||
** the column simultaneously.
|
||||
*/
|
||||
Select *sqlite3MultiValues(Parse *pParse, Select *pLeft, ExprList *pRow){
|
||||
|
||||
if( pParse->bHasWith /* condition (a) above */
|
||||
|| pParse->db->init.busy /* condition (b) above */
|
||||
|| exprListIsConstant(pParse,pRow)==0 /* condition (c) above */
|
||||
|| (pLeft->pSrc->nSrc==0 &&
|
||||
exprListIsNoAffinity(pParse,pLeft->pEList)==0) /* condition (d) above */
|
||||
|| IN_SPECIAL_PARSE
|
||||
){
|
||||
/* The co-routine method cannot be used. Fall back to UNION ALL. */
|
||||
Select *pSelect = 0;
|
||||
int f = SF_Values | SF_MultiValue;
|
||||
if( pLeft->pSrc->nSrc ){
|
||||
sqlite3MultiValuesEnd(pParse, pLeft);
|
||||
f = SF_Values;
|
||||
}else if( pLeft->pPrior ){
|
||||
/* In this case set the SF_MultiValue flag only if it was set on pLeft */
|
||||
f = (f & pLeft->selFlags);
|
||||
}
|
||||
pSelect = sqlite3SelectNew(pParse, pRow, 0, 0, 0, 0, 0, f, 0);
|
||||
pLeft->selFlags &= ~SF_MultiValue;
|
||||
if( pSelect ){
|
||||
pSelect->op = TK_ALL;
|
||||
pSelect->pPrior = pLeft;
|
||||
pLeft = pSelect;
|
||||
}
|
||||
}else{
|
||||
SrcItem *p = 0; /* SrcItem that reads from co-routine */
|
||||
|
||||
if( pLeft->pSrc->nSrc==0 ){
|
||||
/* Co-routine has not yet been started and the special Select object
|
||||
** that accesses the co-routine has not yet been created. This block
|
||||
** does both those things. */
|
||||
Vdbe *v = sqlite3GetVdbe(pParse);
|
||||
Select *pRet = sqlite3SelectNew(pParse, 0, 0, 0, 0, 0, 0, 0, 0);
|
||||
|
||||
/* Ensure the database schema has been read. This is to ensure we have
|
||||
** the correct text encoding. */
|
||||
if( (pParse->db->mDbFlags & DBFLAG_SchemaKnownOk)==0 ){
|
||||
sqlite3ReadSchema(pParse);
|
||||
}
|
||||
|
||||
if( pRet ){
|
||||
SelectDest dest;
|
||||
pRet->pSrc->nSrc = 1;
|
||||
pRet->pPrior = pLeft->pPrior;
|
||||
pRet->op = pLeft->op;
|
||||
pLeft->pPrior = 0;
|
||||
pLeft->op = TK_SELECT;
|
||||
assert( pLeft->pNext==0 );
|
||||
assert( pRet->pNext==0 );
|
||||
p = &pRet->pSrc->a[0];
|
||||
p->pSelect = pLeft;
|
||||
p->fg.viaCoroutine = 1;
|
||||
p->addrFillSub = sqlite3VdbeCurrentAddr(v) + 1;
|
||||
p->regReturn = ++pParse->nMem;
|
||||
p->iCursor = -1;
|
||||
p->u1.nRow = 2;
|
||||
sqlite3VdbeAddOp3(v,OP_InitCoroutine,p->regReturn,0,p->addrFillSub);
|
||||
sqlite3SelectDestInit(&dest, SRT_Coroutine, p->regReturn);
|
||||
|
||||
/* Allocate registers for the output of the co-routine. Do so so
|
||||
** that there are two unused registers immediately before those
|
||||
** used by the co-routine. This allows the code in sqlite3Insert()
|
||||
** to use these registers directly, instead of copying the output
|
||||
** of the co-routine to a separate array for processing. */
|
||||
dest.iSdst = pParse->nMem + 3;
|
||||
dest.nSdst = pLeft->pEList->nExpr;
|
||||
pParse->nMem += 2 + dest.nSdst;
|
||||
|
||||
pLeft->selFlags |= SF_MultiValue;
|
||||
sqlite3Select(pParse, pLeft, &dest);
|
||||
p->regResult = dest.iSdst;
|
||||
assert( pParse->nErr || dest.iSdst>0 );
|
||||
pLeft = pRet;
|
||||
}
|
||||
}else{
|
||||
p = &pLeft->pSrc->a[0];
|
||||
assert( !p->fg.isTabFunc && !p->fg.isIndexedBy );
|
||||
p->u1.nRow++;
|
||||
}
|
||||
|
||||
if( pParse->nErr==0 ){
|
||||
assert( p!=0 );
|
||||
if( p->pSelect->pEList->nExpr!=pRow->nExpr ){
|
||||
sqlite3SelectWrongNumTermsError(pParse, p->pSelect);
|
||||
}else{
|
||||
sqlite3ExprCodeExprList(pParse, pRow, p->regResult, 0, 0);
|
||||
sqlite3VdbeAddOp1(pParse->pVdbe, OP_Yield, p->regReturn);
|
||||
}
|
||||
}
|
||||
sqlite3ExprListDelete(pParse->db, pRow);
|
||||
}
|
||||
|
||||
return pLeft;
|
||||
}
|
||||
|
||||
/* Forward declaration */
|
||||
static int xferOptimization(
|
||||
@@ -913,25 +1102,40 @@ void sqlite3Insert(
|
||||
if( pSelect ){
|
||||
/* Data is coming from a SELECT or from a multi-row VALUES clause.
|
||||
** Generate a co-routine to run the SELECT. */
|
||||
int regYield; /* Register holding co-routine entry-point */
|
||||
int addrTop; /* Top of the co-routine */
|
||||
int rc; /* Result code */
|
||||
|
||||
regYield = ++pParse->nMem;
|
||||
addrTop = sqlite3VdbeCurrentAddr(v) + 1;
|
||||
sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, addrTop);
|
||||
sqlite3SelectDestInit(&dest, SRT_Coroutine, regYield);
|
||||
dest.iSdst = bIdListInOrder ? regData : 0;
|
||||
dest.nSdst = pTab->nCol;
|
||||
rc = sqlite3Select(pParse, pSelect, &dest);
|
||||
regFromSelect = dest.iSdst;
|
||||
assert( db->pParse==pParse );
|
||||
if( rc || pParse->nErr ) goto insert_cleanup;
|
||||
assert( db->mallocFailed==0 );
|
||||
sqlite3VdbeEndCoroutine(v, regYield);
|
||||
sqlite3VdbeJumpHere(v, addrTop - 1); /* label B: */
|
||||
assert( pSelect->pEList );
|
||||
nColumn = pSelect->pEList->nExpr;
|
||||
if( pSelect->pSrc->nSrc==1
|
||||
&& pSelect->pSrc->a[0].fg.viaCoroutine
|
||||
&& pSelect->pPrior==0
|
||||
){
|
||||
SrcItem *pItem = &pSelect->pSrc->a[0];
|
||||
dest.iSDParm = pItem->regReturn;
|
||||
regFromSelect = pItem->regResult;
|
||||
nColumn = pItem->pSelect->pEList->nExpr;
|
||||
ExplainQueryPlan((pParse, 0, "SCAN %S", pItem));
|
||||
if( bIdListInOrder && nColumn==pTab->nCol ){
|
||||
regData = regFromSelect;
|
||||
regRowid = regData - 1;
|
||||
regIns = regRowid - (IsVirtual(pTab) ? 1 : 0);
|
||||
}
|
||||
}else{
|
||||
int addrTop; /* Top of the co-routine */
|
||||
int regYield = ++pParse->nMem;
|
||||
addrTop = sqlite3VdbeCurrentAddr(v) + 1;
|
||||
sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, addrTop);
|
||||
sqlite3SelectDestInit(&dest, SRT_Coroutine, regYield);
|
||||
dest.iSdst = bIdListInOrder ? regData : 0;
|
||||
dest.nSdst = pTab->nCol;
|
||||
rc = sqlite3Select(pParse, pSelect, &dest);
|
||||
regFromSelect = dest.iSdst;
|
||||
assert( db->pParse==pParse );
|
||||
if( rc || pParse->nErr ) goto insert_cleanup;
|
||||
assert( db->mallocFailed==0 );
|
||||
sqlite3VdbeEndCoroutine(v, regYield);
|
||||
sqlite3VdbeJumpHere(v, addrTop - 1); /* label B: */
|
||||
assert( pSelect->pEList );
|
||||
nColumn = pSelect->pEList->nExpr;
|
||||
}
|
||||
|
||||
/* Set useTempTable to TRUE if the result of the SELECT statement
|
||||
** should be written into a temporary table (template 4). Set to
|
||||
@@ -1086,7 +1290,7 @@ void sqlite3Insert(
|
||||
pNx->iDataCur = iDataCur;
|
||||
pNx->iIdxCur = iIdxCur;
|
||||
if( pNx->pUpsertTarget ){
|
||||
if( sqlite3UpsertAnalyzeTarget(pParse, pTabList, pNx) ){
|
||||
if( sqlite3UpsertAnalyzeTarget(pParse, pTabList, pNx, pUpsert) ){
|
||||
goto insert_cleanup;
|
||||
}
|
||||
}
|
||||
@@ -2978,7 +3182,10 @@ static int xferOptimization(
|
||||
}
|
||||
}
|
||||
#ifndef SQLITE_OMIT_CHECK
|
||||
if( pDest->pCheck && sqlite3ExprListCompare(pSrc->pCheck,pDest->pCheck,-1) ){
|
||||
if( pDest->pCheck
|
||||
&& (db->mDbFlags & DBFLAG_Vacuum)==0
|
||||
&& sqlite3ExprListCompare(pSrc->pCheck,pDest->pCheck,-1)
|
||||
){
|
||||
return 0; /* Tables have different CHECK constraints. Ticket #2252 */
|
||||
}
|
||||
#endif
|
||||
|
||||
+144
-3
@@ -563,7 +563,6 @@ static void jsonAppendRawNZ(JsonString *p, const char *zIn, u32 N){
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Append formatted text (not to exceed N bytes) to the JsonString.
|
||||
*/
|
||||
static void jsonPrintf(int N, JsonString *p, const char *zFormat, ...){
|
||||
@@ -2336,6 +2335,112 @@ static u32 jsonTranslateBlobToText(
|
||||
return i+n+sz;
|
||||
}
|
||||
|
||||
/* Context for recursion of json_pretty()
|
||||
*/
|
||||
typedef struct JsonPretty JsonPretty;
|
||||
struct JsonPretty {
|
||||
JsonParse *pParse; /* The BLOB being rendered */
|
||||
JsonString *pOut; /* Generate pretty output into this string */
|
||||
const char *zIndent; /* Use this text for indentation */
|
||||
u32 szIndent; /* Bytes in zIndent[] */
|
||||
u32 nIndent; /* Current level of indentation */
|
||||
};
|
||||
|
||||
/* Append indentation to the pretty JSON under construction */
|
||||
static void jsonPrettyIndent(JsonPretty *pPretty){
|
||||
u32 jj;
|
||||
for(jj=0; jj<pPretty->nIndent; jj++){
|
||||
jsonAppendRaw(pPretty->pOut, pPretty->zIndent, pPretty->szIndent);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Translate the binary JSONB representation of JSON beginning at
|
||||
** pParse->aBlob[i] into a JSON text string. Append the JSON
|
||||
** text onto the end of pOut. Return the index in pParse->aBlob[]
|
||||
** of the first byte past the end of the element that is translated.
|
||||
**
|
||||
** This is a variant of jsonTranslateBlobToText() that "pretty-prints"
|
||||
** the output. Extra whitespace is inserted to make the JSON easier
|
||||
** for humans to read.
|
||||
**
|
||||
** If an error is detected in the BLOB input, the pOut->eErr flag
|
||||
** might get set to JSTRING_MALFORMED. But not all BLOB input errors
|
||||
** are detected. So a malformed JSONB input might either result
|
||||
** in an error, or in incorrect JSON.
|
||||
**
|
||||
** The pOut->eErr JSTRING_OOM flag is set on a OOM.
|
||||
*/
|
||||
static u32 jsonTranslateBlobToPrettyText(
|
||||
JsonPretty *pPretty, /* Pretty-printing context */
|
||||
u32 i /* Start rendering at this index */
|
||||
){
|
||||
u32 sz, n, j, iEnd;
|
||||
const JsonParse *pParse = pPretty->pParse;
|
||||
JsonString *pOut = pPretty->pOut;
|
||||
n = jsonbPayloadSize(pParse, i, &sz);
|
||||
if( n==0 ){
|
||||
pOut->eErr |= JSTRING_MALFORMED;
|
||||
return pParse->nBlob+1;
|
||||
}
|
||||
switch( pParse->aBlob[i] & 0x0f ){
|
||||
case JSONB_ARRAY: {
|
||||
j = i+n;
|
||||
iEnd = j+sz;
|
||||
jsonAppendChar(pOut, '[');
|
||||
if( j<iEnd ){
|
||||
jsonAppendChar(pOut, '\n');
|
||||
pPretty->nIndent++;
|
||||
while( pOut->eErr==0 ){
|
||||
jsonPrettyIndent(pPretty);
|
||||
j = jsonTranslateBlobToPrettyText(pPretty, j);
|
||||
if( j>=iEnd ) break;
|
||||
jsonAppendRawNZ(pOut, ",\n", 2);
|
||||
}
|
||||
jsonAppendChar(pOut, '\n');
|
||||
pPretty->nIndent--;
|
||||
jsonPrettyIndent(pPretty);
|
||||
}
|
||||
jsonAppendChar(pOut, ']');
|
||||
i = iEnd;
|
||||
break;
|
||||
}
|
||||
case JSONB_OBJECT: {
|
||||
j = i+n;
|
||||
iEnd = j+sz;
|
||||
jsonAppendChar(pOut, '{');
|
||||
if( j<iEnd ){
|
||||
jsonAppendChar(pOut, '\n');
|
||||
pPretty->nIndent++;
|
||||
while( pOut->eErr==0 ){
|
||||
jsonPrettyIndent(pPretty);
|
||||
j = jsonTranslateBlobToText(pParse, j, pOut);
|
||||
if( j>iEnd ){
|
||||
pOut->eErr |= JSTRING_MALFORMED;
|
||||
break;
|
||||
}
|
||||
jsonAppendRawNZ(pOut, ": ", 2);
|
||||
j = jsonTranslateBlobToPrettyText(pPretty, j);
|
||||
if( j>=iEnd ) break;
|
||||
jsonAppendRawNZ(pOut, ",\n", 2);
|
||||
}
|
||||
jsonAppendChar(pOut, '\n');
|
||||
pPretty->nIndent--;
|
||||
jsonPrettyIndent(pPretty);
|
||||
}
|
||||
jsonAppendChar(pOut, '}');
|
||||
i = iEnd;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
i = jsonTranslateBlobToText(pParse, i, pOut);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
/* Return true if the input pJson
|
||||
**
|
||||
** For performance reasons, this routine does not do a detailed check of the
|
||||
@@ -4255,6 +4360,40 @@ json_type_done:
|
||||
jsonParseFree(p);
|
||||
}
|
||||
|
||||
/*
|
||||
** json_pretty(JSON)
|
||||
** json_pretty(JSON, INDENT)
|
||||
**
|
||||
** Return text that is a pretty-printed rendering of the input JSON.
|
||||
** If the argument is not valid JSON, return NULL.
|
||||
**
|
||||
** The INDENT argument is text that is used for indentation. If omitted,
|
||||
** it defaults to four spaces (the same as PostgreSQL).
|
||||
*/
|
||||
static void jsonPrettyFunc(
|
||||
sqlite3_context *ctx,
|
||||
int argc,
|
||||
sqlite3_value **argv
|
||||
){
|
||||
JsonString s; /* The output string */
|
||||
JsonPretty x; /* Pretty printing context */
|
||||
|
||||
memset(&x, 0, sizeof(x));
|
||||
x.pParse = jsonParseFuncArg(ctx, argv[0], 0);
|
||||
if( x.pParse==0 ) return;
|
||||
x.pOut = &s;
|
||||
jsonStringInit(&s, ctx);
|
||||
if( argc==1 || (x.zIndent = (const char*)sqlite3_value_text(argv[1]))==0 ){
|
||||
x.zIndent = " ";
|
||||
x.szIndent = 4;
|
||||
}else{
|
||||
x.szIndent = (u32)strlen(x.zIndent);
|
||||
}
|
||||
jsonTranslateBlobToPrettyText(&x, 0);
|
||||
jsonReturnString(&s, 0, 0);
|
||||
jsonParseFree(x.pParse);
|
||||
}
|
||||
|
||||
/*
|
||||
** json_valid(JSON)
|
||||
** json_valid(JSON, FLAGS)
|
||||
@@ -4993,9 +5132,9 @@ static int jsonEachColumn(
|
||||
case JEACH_JSON: {
|
||||
if( p->sParse.zJson==0 ){
|
||||
sqlite3_result_blob(ctx, p->sParse.aBlob, p->sParse.nBlob,
|
||||
SQLITE_STATIC);
|
||||
SQLITE_TRANSIENT);
|
||||
}else{
|
||||
sqlite3_result_text(ctx, p->sParse.zJson, -1, SQLITE_STATIC);
|
||||
sqlite3_result_text(ctx, p->sParse.zJson, -1, SQLITE_TRANSIENT);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -5269,6 +5408,8 @@ void sqlite3RegisterJsonFunctions(void){
|
||||
JFUNCTION(jsonb_object, -1,0,1, 1,1,0, jsonObjectFunc),
|
||||
JFUNCTION(json_patch, 2,1,1, 0,0,0, jsonPatchFunc),
|
||||
JFUNCTION(jsonb_patch, 2,1,0, 0,1,0, jsonPatchFunc),
|
||||
JFUNCTION(json_pretty, 1,1,0, 0,0,0, jsonPrettyFunc),
|
||||
JFUNCTION(json_pretty, 2,1,0, 0,0,0, jsonPrettyFunc),
|
||||
JFUNCTION(json_quote, 1,0,1, 1,0,0, jsonQuoteFunc),
|
||||
JFUNCTION(json_remove, -1,1,1, 0,0,0, jsonRemoveFunc),
|
||||
JFUNCTION(jsonb_remove, -1,1,0, 0,1,0, jsonRemoveFunc),
|
||||
|
||||
+12
@@ -765,6 +765,18 @@ int sqlite3_config(int op, ...){
|
||||
}
|
||||
#endif /* SQLITE_OMIT_DESERIALIZE */
|
||||
|
||||
case SQLITE_CONFIG_ROWID_IN_VIEW: {
|
||||
int *pVal = va_arg(ap,int*);
|
||||
#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
|
||||
if( 0==*pVal ) sqlite3GlobalConfig.mNoVisibleRowid = TF_NoVisibleRowid;
|
||||
if( 1==*pVal ) sqlite3GlobalConfig.mNoVisibleRowid = 0;
|
||||
*pVal = (sqlite3GlobalConfig.mNoVisibleRowid==0);
|
||||
#else
|
||||
*pVal = 0;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
rc = SQLITE_ERROR;
|
||||
break;
|
||||
|
||||
+8
-1
@@ -6398,12 +6398,19 @@ static int unixOpen(
|
||||
rc = SQLITE_READONLY_DIRECTORY;
|
||||
}else if( errno!=EISDIR && isReadWrite ){
|
||||
/* Failed to open the file for read/write access. Try read-only. */
|
||||
UnixUnusedFd *pReadonly = 0;
|
||||
flags &= ~(SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE);
|
||||
openFlags &= ~(O_RDWR|O_CREAT);
|
||||
flags |= SQLITE_OPEN_READONLY;
|
||||
openFlags |= O_RDONLY;
|
||||
isReadonly = 1;
|
||||
fd = robust_open(zName, openFlags, openMode);
|
||||
pReadonly = findReusableFd(zName, flags);
|
||||
if( pReadonly ){
|
||||
fd = pReadonly->fd;
|
||||
sqlite3_free(pReadonly);
|
||||
}else{
|
||||
fd = robust_open(zName, openFlags, openMode);
|
||||
}
|
||||
}
|
||||
}
|
||||
if( fd<0 ){
|
||||
|
||||
+1
-1
@@ -7087,7 +7087,7 @@ sqlite3_file *sqlite3PagerFile(Pager *pPager){
|
||||
** This will be either the rollback journal or the WAL file.
|
||||
*/
|
||||
sqlite3_file *sqlite3PagerJrnlFile(Pager *pPager){
|
||||
#if SQLITE_OMIT_WAL
|
||||
#ifdef SQLITE_OMIT_WAL
|
||||
return pPager->jfd;
|
||||
#else
|
||||
return pPager->pWal ? sqlite3WalFile(pPager->pWal) : pPager->jfd;
|
||||
|
||||
+24
-31
@@ -471,7 +471,7 @@ resolvetype(A) ::= REPLACE. {A = OE_Replace;}
|
||||
|
||||
////////////////////////// The DROP TABLE /////////////////////////////////////
|
||||
//
|
||||
cmd ::= DROP TABLE ifexists(E) fullnamelist(X). {
|
||||
cmd ::= DROP TABLE ifexists(E) fullname(X). {
|
||||
sqlite3DropTable(pParse, X, 0, E);
|
||||
}
|
||||
%type ifexists {int}
|
||||
@@ -485,7 +485,7 @@ cmd ::= createkw(X) temp(T) VIEW ifnotexists(E) nm(Y) dbnm(Z) eidlist_opt(C)
|
||||
AS select(S). {
|
||||
sqlite3CreateView(pParse, &X, &Y, &Z, C, S, T, E);
|
||||
}
|
||||
cmd ::= DROP VIEW ifexists(E) fullnamelist(X). {
|
||||
cmd ::= DROP VIEW ifexists(E) fullname(X). {
|
||||
sqlite3DropTable(pParse, X, 1, E);
|
||||
}
|
||||
%endif SQLITE_OMIT_VIEW
|
||||
@@ -565,6 +565,7 @@ cmd ::= select(X). {
|
||||
select(A) ::= WITH wqlist(W) selectnowith(X). {A = attachWithToSelect(pParse,X,W);}
|
||||
select(A) ::= WITH RECURSIVE wqlist(W) selectnowith(X).
|
||||
{A = attachWithToSelect(pParse,X,W);}
|
||||
|
||||
%endif /* SQLITE_OMIT_CTE */
|
||||
select(A) ::= selectnowith(A). {
|
||||
Select *p = A;
|
||||
@@ -622,24 +623,27 @@ oneselect(A) ::= SELECT distinct(D) selcollist(W) from(X) where_opt(Y)
|
||||
%endif
|
||||
|
||||
|
||||
oneselect(A) ::= values(A).
|
||||
|
||||
// Single row VALUES clause.
|
||||
//
|
||||
%type values {Select*}
|
||||
oneselect(A) ::= values(A).
|
||||
%destructor values {sqlite3SelectDelete(pParse->db, $$);}
|
||||
values(A) ::= VALUES LP nexprlist(X) RP. {
|
||||
A = sqlite3SelectNew(pParse,X,0,0,0,0,0,SF_Values,0);
|
||||
}
|
||||
values(A) ::= values(A) COMMA LP nexprlist(Y) RP. {
|
||||
Select *pRight, *pLeft = A;
|
||||
pRight = sqlite3SelectNew(pParse,Y,0,0,0,0,0,SF_Values|SF_MultiValue,0);
|
||||
if( ALWAYS(pLeft) ) pLeft->selFlags &= ~SF_MultiValue;
|
||||
if( pRight ){
|
||||
pRight->op = TK_ALL;
|
||||
pRight->pPrior = pLeft;
|
||||
A = pRight;
|
||||
}else{
|
||||
A = pLeft;
|
||||
}
|
||||
|
||||
// Multiple row VALUES clause.
|
||||
//
|
||||
%type mvalues {Select*}
|
||||
oneselect(A) ::= mvalues(A). {
|
||||
sqlite3MultiValuesEnd(pParse, A);
|
||||
}
|
||||
%destructor mvalues {sqlite3SelectDelete(pParse->db, $$);}
|
||||
mvalues(A) ::= values(A) COMMA LP nexprlist(Y) RP. {
|
||||
A = sqlite3MultiValues(pParse, A, Y);
|
||||
}
|
||||
mvalues(A) ::= mvalues(A) COMMA LP nexprlist(Y) RP. {
|
||||
A = sqlite3MultiValues(pParse, A, Y);
|
||||
}
|
||||
|
||||
// The "distinct" nonterminal is true (1) if the DISTINCT keyword is
|
||||
@@ -774,18 +778,6 @@ fullname(A) ::= nm(X) DOT nm(Y). {
|
||||
if( IN_RENAME_OBJECT && A ) sqlite3RenameTokenMap(pParse, A->a[0].zName, &Y);
|
||||
}
|
||||
|
||||
%type fullnamelist {SrcList*}
|
||||
%destructor fullnamelist {sqlite3SrcListDelete(pParse->db, $$);}
|
||||
fullnamelist(A) ::= fullname(A).
|
||||
fullnamelist(A) ::= fullnamelist(L) COMMA nm(X). {
|
||||
A = sqlite3SrcListAppend(pParse,L,&X,0);
|
||||
assert( !IN_RENAME_OBJECT ); /* Used only by DROP, which cannot be part of schema */
|
||||
}
|
||||
fullnamelist(A) ::= fullnamelist(L) COMMA nm(X) DOT nm(Y). {
|
||||
A = sqlite3SrcListAppend(pParse,L,&X,&Y);
|
||||
assert( !IN_RENAME_OBJECT ); /* Used only by DROP, which cannot be part of schema */
|
||||
}
|
||||
|
||||
%type xfullname {SrcList*}
|
||||
%destructor xfullname {sqlite3SrcListDelete(pParse->db, $$);}
|
||||
xfullname(A) ::= nm(X).
|
||||
@@ -1333,7 +1325,7 @@ expr(A) ::= expr(A) between_op(N) expr(X) AND expr(Y). [BETWEEN] {
|
||||
if( A ) sqlite3ExprIdToTrueFalse(A);
|
||||
}else{
|
||||
Expr *pRHS = Y->a[0].pExpr;
|
||||
if( Y->nExpr==1 && sqlite3ExprIsConstant(pRHS) && A->op!=TK_VECTOR ){
|
||||
if( Y->nExpr==1 && sqlite3ExprIsConstant(pParse,pRHS) && A->op!=TK_VECTOR ){
|
||||
Y->a[0].pExpr = 0;
|
||||
sqlite3ExprListDelete(pParse->db, Y);
|
||||
pRHS = sqlite3PExpr(pParse, TK_UPLUS, pRHS, 0);
|
||||
@@ -1516,7 +1508,7 @@ collate(C) ::= COLLATE ids. {C = 1;}
|
||||
|
||||
///////////////////////////// The DROP INDEX command /////////////////////////
|
||||
//
|
||||
cmd ::= DROP INDEX ifexists(E) fullnamelist(X). {sqlite3DropIndex(pParse, X, E);}
|
||||
cmd ::= DROP INDEX ifexists(E) fullname(X). {sqlite3DropIndex(pParse, X, E);}
|
||||
|
||||
///////////////////////////// The VACUUM command /////////////////////////////
|
||||
//
|
||||
@@ -1673,7 +1665,7 @@ raisetype(A) ::= FAIL. {A = OE_Fail;}
|
||||
|
||||
//////////////////////// DROP TRIGGER statement //////////////////////////////
|
||||
%ifndef SQLITE_OMIT_TRIGGER
|
||||
cmd ::= DROP TRIGGER ifexists(NOERR) fullnamelist(X). {
|
||||
cmd ::= DROP TRIGGER ifexists(NOERR) fullname(X). {
|
||||
sqlite3DropTrigger(pParse,X,NOERR);
|
||||
}
|
||||
%endif !SQLITE_OMIT_TRIGGER
|
||||
@@ -1773,9 +1765,10 @@ with ::= WITH RECURSIVE wqlist(W). { sqlite3WithPush(pParse, W, 1); }
|
||||
wqas(A) ::= AS. {A = M10d_Any;}
|
||||
wqas(A) ::= AS MATERIALIZED. {A = M10d_Yes;}
|
||||
wqas(A) ::= AS NOT MATERIALIZED. {A = M10d_No;}
|
||||
wqitem(A) ::= nm(X) eidlist_opt(Y) wqas(M) LP select(Z) RP. {
|
||||
wqitem(A) ::= withnm(X) eidlist_opt(Y) wqas(M) LP select(Z) RP. {
|
||||
A = sqlite3CteNew(pParse, &X, Y, Z, M); /*A-overwrites-X*/
|
||||
}
|
||||
withnm(A) ::= nm(A). {pParse->bHasWith = 1;}
|
||||
wqlist(A) ::= wqitem(X). {
|
||||
A = sqlite3WithAdd(pParse, 0, X); /*A-overwrites-X*/
|
||||
}
|
||||
|
||||
+7
-6
@@ -2870,9 +2870,9 @@ static int pragmaVtabBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
|
||||
seen[0] = 0;
|
||||
seen[1] = 0;
|
||||
for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
|
||||
if( pConstraint->usable==0 ) continue;
|
||||
if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
|
||||
if( pConstraint->iColumn < pTab->iHidden ) continue;
|
||||
if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
|
||||
if( pConstraint->usable==0 ) return SQLITE_CONSTRAINT;
|
||||
j = pConstraint->iColumn - pTab->iHidden;
|
||||
assert( j < 2 );
|
||||
seen[j] = i+1;
|
||||
@@ -2885,12 +2885,13 @@ static int pragmaVtabBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
|
||||
j = seen[0]-1;
|
||||
pIdxInfo->aConstraintUsage[j].argvIndex = 1;
|
||||
pIdxInfo->aConstraintUsage[j].omit = 1;
|
||||
if( seen[1]==0 ) return SQLITE_OK;
|
||||
pIdxInfo->estimatedCost = (double)20;
|
||||
pIdxInfo->estimatedRows = 20;
|
||||
j = seen[1]-1;
|
||||
pIdxInfo->aConstraintUsage[j].argvIndex = 2;
|
||||
pIdxInfo->aConstraintUsage[j].omit = 1;
|
||||
if( seen[1] ){
|
||||
j = seen[1]-1;
|
||||
pIdxInfo->aConstraintUsage[j].argvIndex = 2;
|
||||
pIdxInfo->aConstraintUsage[j].omit = 1;
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
|
||||
+5
-1
@@ -857,9 +857,13 @@ void sqlite3_str_vappendf(
|
||||
sqlite3_str_appendall(pAccum, pItem->zAlias);
|
||||
}else{
|
||||
Select *pSel = pItem->pSelect;
|
||||
assert( pSel!=0 );
|
||||
assert( pSel!=0 ); /* Because of tag-20240424-1 */
|
||||
if( pSel->selFlags & SF_NestedFrom ){
|
||||
sqlite3_str_appendf(pAccum, "(join-%u)", pSel->selId);
|
||||
}else if( pSel->selFlags & SF_MultiValue ){
|
||||
assert( !pItem->fg.isTabFunc && !pItem->fg.isIndexedBy );
|
||||
sqlite3_str_appendf(pAccum, "%u-ROW VALUES CLAUSE",
|
||||
pItem->u1.nRow);
|
||||
}else{
|
||||
sqlite3_str_appendf(pAccum, "(subquery-%u)", pSel->selId);
|
||||
}
|
||||
|
||||
+83
-14
@@ -469,8 +469,37 @@ static int lookupName(
|
||||
}
|
||||
}
|
||||
if( 0==cnt && VisibleRowid(pTab) ){
|
||||
/* pTab is a potential ROWID match. Keep track of it and match
|
||||
** the ROWID later if that seems appropriate. (Search for "cntTab"
|
||||
** to find related code.) Only allow a ROWID match if there is
|
||||
** a single ROWID match candidate.
|
||||
*/
|
||||
#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
|
||||
/* In SQLITE_ALLOW_ROWID_IN_VIEW mode, allow a ROWID match
|
||||
** if there is a single VIEW candidate or if there is a single
|
||||
** non-VIEW candidate plus multiple VIEW candidates. In other
|
||||
** words non-VIEW candidate terms take precedence over VIEWs.
|
||||
*/
|
||||
if( cntTab==0
|
||||
|| (cntTab==1
|
||||
&& ALWAYS(pMatch!=0)
|
||||
&& ALWAYS(pMatch->pTab!=0)
|
||||
&& (pMatch->pTab->tabFlags & TF_Ephemeral)!=0
|
||||
&& (pTab->tabFlags & TF_Ephemeral)==0)
|
||||
){
|
||||
cntTab = 1;
|
||||
pMatch = pItem;
|
||||
}else{
|
||||
cntTab++;
|
||||
}
|
||||
#else
|
||||
/* The (much more common) non-SQLITE_ALLOW_ROWID_IN_VIEW case is
|
||||
** simpler since we require exactly one candidate, which will
|
||||
** always be a non-VIEW
|
||||
*/
|
||||
cntTab++;
|
||||
pMatch = pItem;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
if( pMatch ){
|
||||
@@ -596,13 +625,18 @@ static int lookupName(
|
||||
** Perhaps the name is a reference to the ROWID
|
||||
*/
|
||||
if( cnt==0
|
||||
&& cntTab==1
|
||||
&& cntTab>=1
|
||||
&& pMatch
|
||||
&& (pNC->ncFlags & (NC_IdxExpr|NC_GenCol))==0
|
||||
&& sqlite3IsRowid(zCol)
|
||||
&& ALWAYS(VisibleRowid(pMatch->pTab) || pMatch->fg.isNestedFrom)
|
||||
){
|
||||
cnt = 1;
|
||||
cnt = cntTab;
|
||||
#if SQLITE_ALLOW_ROWID_IN_VIEW+0==2
|
||||
if( pMatch->pTab!=0 && IsView(pMatch->pTab) ){
|
||||
eNewExprOp = TK_NULL;
|
||||
}
|
||||
#endif
|
||||
if( pMatch->fg.isNestedFrom==0 ) pExpr->iColumn = -1;
|
||||
pExpr->affExpr = SQLITE_AFF_INTEGER;
|
||||
}
|
||||
@@ -971,6 +1005,19 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
|
||||
** resolved. This prevents "column" from being counted as having been
|
||||
** referenced, which might prevent a SELECT from being erroneously
|
||||
** marked as correlated.
|
||||
**
|
||||
** 2024-03-28: Beware of aggregates. A bare column of aggregated table
|
||||
** can still evaluate to NULL even though it is marked as NOT NULL.
|
||||
** Example:
|
||||
**
|
||||
** CREATE TABLE t1(a INT NOT NULL);
|
||||
** SELECT a, a IS NULL, a IS NOT NULL, count(*) FROM t1;
|
||||
**
|
||||
** The "a IS NULL" and "a IS NOT NULL" expressions cannot be optimized
|
||||
** here because at the time this case is hit, we do not yet know whether
|
||||
** or not t1 is being aggregated. We have to assume the worst and omit
|
||||
** the optimization. The only time it is safe to apply this optimization
|
||||
** is within the WHERE clause.
|
||||
*/
|
||||
case TK_NOTNULL:
|
||||
case TK_ISNULL: {
|
||||
@@ -981,19 +1028,36 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
|
||||
anRef[i] = p->nRef;
|
||||
}
|
||||
sqlite3WalkExpr(pWalker, pExpr->pLeft);
|
||||
if( 0==sqlite3ExprCanBeNull(pExpr->pLeft) && !IN_RENAME_OBJECT ){
|
||||
testcase( ExprHasProperty(pExpr, EP_OuterON) );
|
||||
assert( !ExprHasProperty(pExpr, EP_IntValue) );
|
||||
pExpr->u.iValue = (pExpr->op==TK_NOTNULL);
|
||||
pExpr->flags |= EP_IntValue;
|
||||
pExpr->op = TK_INTEGER;
|
||||
|
||||
for(i=0, p=pNC; p && i<ArraySize(anRef); p=p->pNext, i++){
|
||||
p->nRef = anRef[i];
|
||||
}
|
||||
sqlite3ExprDelete(pParse->db, pExpr->pLeft);
|
||||
pExpr->pLeft = 0;
|
||||
if( IN_RENAME_OBJECT ) return WRC_Prune;
|
||||
if( sqlite3ExprCanBeNull(pExpr->pLeft) ){
|
||||
/* The expression can be NULL. So the optimization does not apply */
|
||||
return WRC_Prune;
|
||||
}
|
||||
|
||||
for(i=0, p=pNC; p; p=p->pNext, i++){
|
||||
if( (p->ncFlags & NC_Where)==0 ){
|
||||
return WRC_Prune; /* Not in a WHERE clause. Unsafe to optimize. */
|
||||
}
|
||||
}
|
||||
testcase( ExprHasProperty(pExpr, EP_OuterON) );
|
||||
assert( !ExprHasProperty(pExpr, EP_IntValue) );
|
||||
#if TREETRACE_ENABLED
|
||||
if( sqlite3TreeTrace & 0x80000 ){
|
||||
sqlite3DebugPrintf(
|
||||
"NOT NULL strength reduction converts the following to %d:\n",
|
||||
pExpr->op==TK_NOTNULL
|
||||
);
|
||||
sqlite3ShowExpr(pExpr);
|
||||
}
|
||||
#endif /* TREETRACE_ENABLED */
|
||||
pExpr->u.iValue = (pExpr->op==TK_NOTNULL);
|
||||
pExpr->flags |= EP_IntValue;
|
||||
pExpr->op = TK_INTEGER;
|
||||
for(i=0, p=pNC; p && i<ArraySize(anRef); p=p->pNext, i++){
|
||||
p->nRef = anRef[i];
|
||||
}
|
||||
sqlite3ExprDelete(pParse->db, pExpr->pLeft);
|
||||
pExpr->pLeft = 0;
|
||||
return WRC_Prune;
|
||||
}
|
||||
|
||||
@@ -1290,6 +1354,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
|
||||
testcase( pNC->ncFlags & NC_PartIdx );
|
||||
testcase( pNC->ncFlags & NC_IdxExpr );
|
||||
testcase( pNC->ncFlags & NC_GenCol );
|
||||
assert( pExpr->x.pSelect );
|
||||
if( pNC->ncFlags & NC_SelfRef ){
|
||||
notValidImpl(pParse, pNC, "subqueries", pExpr, pExpr);
|
||||
}else{
|
||||
@@ -1298,6 +1363,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
|
||||
assert( pNC->nRef>=nRef );
|
||||
if( nRef!=pNC->nRef ){
|
||||
ExprSetProperty(pExpr, EP_VarSelect);
|
||||
pExpr->x.pSelect->selFlags |= SF_Correlated;
|
||||
}
|
||||
pNC->ncFlags |= NC_Subquery;
|
||||
}
|
||||
@@ -1823,6 +1889,7 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
|
||||
if( pOuterNC ) pOuterNC->nNestedSelect++;
|
||||
for(i=0; i<p->pSrc->nSrc; i++){
|
||||
SrcItem *pItem = &p->pSrc->a[i];
|
||||
assert( pItem->zName!=0 || pItem->pSelect!=0 );/* Test of tag-20240424-1*/
|
||||
if( pItem->pSelect && (pItem->pSelect->selFlags & SF_Resolved)==0 ){
|
||||
int nRef = pOuterNC ? pOuterNC->nRef : 0;
|
||||
const char *zSavedContext = pParse->zAuthContext;
|
||||
@@ -1891,7 +1958,9 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
|
||||
}
|
||||
if( sqlite3ResolveExprNames(&sNC, p->pHaving) ) return WRC_Abort;
|
||||
}
|
||||
sNC.ncFlags |= NC_Where;
|
||||
if( sqlite3ResolveExprNames(&sNC, p->pWhere) ) return WRC_Abort;
|
||||
sNC.ncFlags &= ~NC_Where;
|
||||
|
||||
/* Resolve names in table-valued-function arguments */
|
||||
for(i=0; i<p->pSrc->nSrc; i++){
|
||||
|
||||
+66
-27
@@ -1673,9 +1673,16 @@ static void generateSortTail(
|
||||
int addrExplain; /* Address of OP_Explain instruction */
|
||||
#endif
|
||||
|
||||
ExplainQueryPlan2(addrExplain, (pParse, 0,
|
||||
"USE TEMP B-TREE FOR %sORDER BY", pSort->nOBSat>0?"RIGHT PART OF ":"")
|
||||
);
|
||||
nKey = pOrderBy->nExpr - pSort->nOBSat;
|
||||
if( pSort->nOBSat==0 || nKey==1 ){
|
||||
ExplainQueryPlan2(addrExplain, (pParse, 0,
|
||||
"USE TEMP B-TREE FOR %sORDER BY", pSort->nOBSat?"LAST TERM OF ":""
|
||||
));
|
||||
}else{
|
||||
ExplainQueryPlan2(addrExplain, (pParse, 0,
|
||||
"USE TEMP B-TREE FOR LAST %d TERMS OF ORDER BY", nKey
|
||||
));
|
||||
}
|
||||
sqlite3VdbeScanStatusRange(v, addrExplain,pSort->addrPush,pSort->addrPushEnd);
|
||||
sqlite3VdbeScanStatusCounters(v, addrExplain, addrExplain, pSort->addrPush);
|
||||
|
||||
@@ -1713,7 +1720,6 @@ static void generateSortTail(
|
||||
regRow = sqlite3GetTempRange(pParse, nColumn);
|
||||
}
|
||||
}
|
||||
nKey = pOrderBy->nExpr - pSort->nOBSat;
|
||||
if( pSort->sortFlags & SORTFLAG_UseSorter ){
|
||||
int regSortOut = ++pParse->nMem;
|
||||
iSortTab = pParse->nTab++;
|
||||
@@ -1953,11 +1959,7 @@ static const char *columnTypeImpl(
|
||||
** data for the result-set column of the sub-select.
|
||||
*/
|
||||
if( iCol<pS->pEList->nExpr
|
||||
#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
|
||||
&& iCol>=0
|
||||
#else
|
||||
&& ALWAYS(iCol>=0)
|
||||
#endif
|
||||
&& (!ViewCanHaveRowid || iCol>=0)
|
||||
){
|
||||
/* If iCol is less than zero, then the expression requests the
|
||||
** rowid of the sub-select or view. This expression is legal (see
|
||||
@@ -2334,17 +2336,22 @@ void sqlite3SubqueryColumnTypes(
|
||||
for(i=0, pCol=pTab->aCol; i<pTab->nCol; i++, pCol++){
|
||||
const char *zType;
|
||||
i64 n;
|
||||
int m = 0;
|
||||
Select *pS2 = pSelect;
|
||||
pTab->tabFlags |= (pCol->colFlags & COLFLAG_NOINSERT);
|
||||
p = a[i].pExpr;
|
||||
/* pCol->szEst = ... // Column size est for SELECT tables never used */
|
||||
pCol->affinity = sqlite3ExprAffinity(p);
|
||||
while( pCol->affinity<=SQLITE_AFF_NONE && pS2->pNext!=0 ){
|
||||
m |= sqlite3ExprDataType(pS2->pEList->a[i].pExpr);
|
||||
pS2 = pS2->pNext;
|
||||
pCol->affinity = sqlite3ExprAffinity(pS2->pEList->a[i].pExpr);
|
||||
}
|
||||
if( pCol->affinity<=SQLITE_AFF_NONE ){
|
||||
pCol->affinity = aff;
|
||||
}
|
||||
if( pCol->affinity>=SQLITE_AFF_TEXT && pSelect->pNext ){
|
||||
int m = 0;
|
||||
Select *pS2;
|
||||
for(m=0, pS2=pSelect->pNext; pS2; pS2=pS2->pNext){
|
||||
if( pCol->affinity>=SQLITE_AFF_TEXT && (pS2->pNext || pS2!=pSelect) ){
|
||||
for(pS2=pS2->pNext; pS2; pS2=pS2->pNext){
|
||||
m |= sqlite3ExprDataType(pS2->pEList->a[i].pExpr);
|
||||
}
|
||||
if( pCol->affinity==SQLITE_AFF_TEXT && (m&0x01)!=0 ){
|
||||
@@ -4776,7 +4783,7 @@ static void constInsert(
|
||||
){
|
||||
int i;
|
||||
assert( pColumn->op==TK_COLUMN );
|
||||
assert( sqlite3ExprIsConstant(pValue) );
|
||||
assert( sqlite3ExprIsConstant(pConst->pParse, pValue) );
|
||||
|
||||
if( ExprHasProperty(pColumn, EP_FixedCol) ) return;
|
||||
if( sqlite3ExprAffinity(pValue)!=0 ) return;
|
||||
@@ -4834,10 +4841,10 @@ static void findConstInWhere(WhereConst *pConst, Expr *pExpr){
|
||||
pLeft = pExpr->pLeft;
|
||||
assert( pRight!=0 );
|
||||
assert( pLeft!=0 );
|
||||
if( pRight->op==TK_COLUMN && sqlite3ExprIsConstant(pLeft) ){
|
||||
if( pRight->op==TK_COLUMN && sqlite3ExprIsConstant(pConst->pParse, pLeft) ){
|
||||
constInsert(pConst,pRight,pLeft,pExpr);
|
||||
}
|
||||
if( pLeft->op==TK_COLUMN && sqlite3ExprIsConstant(pRight) ){
|
||||
if( pLeft->op==TK_COLUMN && sqlite3ExprIsConstant(pConst->pParse, pRight) ){
|
||||
constInsert(pConst,pLeft,pRight,pExpr);
|
||||
}
|
||||
}
|
||||
@@ -5058,6 +5065,18 @@ static int pushDownWindowCheck(Parse *pParse, Select *pSubq, Expr *pExpr){
|
||||
** The hope is that the terms added to the inner query will make it more
|
||||
** efficient.
|
||||
**
|
||||
** NAME AMBIGUITY
|
||||
**
|
||||
** This optimization is called the "WHERE-clause push-down optimization".
|
||||
**
|
||||
** Do not confuse this optimization with another unrelated optimization
|
||||
** with a similar name: The "MySQL push-down optimization" causes WHERE
|
||||
** clause terms that can be evaluated using only the index and without
|
||||
** reference to the table are run first, so that if they are false,
|
||||
** unnecessary table seeks are avoided.
|
||||
**
|
||||
** RULES
|
||||
**
|
||||
** Do not attempt this optimization if:
|
||||
**
|
||||
** (1) (** This restriction was removed on 2017-09-29. We used to
|
||||
@@ -5123,15 +5142,19 @@ static int pushDownWindowCheck(Parse *pParse, Select *pSubq, Expr *pExpr){
|
||||
** (9c) There is a RIGHT JOIN (or FULL JOIN) in between the ON/USING
|
||||
** clause and the subquery.
|
||||
**
|
||||
** Without this restriction, the push-down optimization might move
|
||||
** the ON/USING filter expression from the left side of a RIGHT JOIN
|
||||
** over to the right side, which leads to incorrect answers. See
|
||||
** also restriction (6) in sqlite3ExprIsSingleTableConstraint().
|
||||
** Without this restriction, the WHERE-clause push-down optimization
|
||||
** might move the ON/USING filter expression from the left side of a
|
||||
** RIGHT JOIN over to the right side, which leads to incorrect answers.
|
||||
** See also restriction (6) in sqlite3ExprIsSingleTableConstraint().
|
||||
**
|
||||
** (10) The inner query is not the right-hand table of a RIGHT JOIN.
|
||||
**
|
||||
** (11) The subquery is not a VALUES clause
|
||||
**
|
||||
** (12) The WHERE clause is not "rowid ISNULL" or the equivalent. This
|
||||
** case only comes up if SQLite is compiled using
|
||||
** SQLITE_ALLOW_ROWID_IN_VIEW.
|
||||
**
|
||||
** Return 0 if no changes are made and non-zero if one or more WHERE clause
|
||||
** terms are duplicated into the subquery.
|
||||
*/
|
||||
@@ -5242,7 +5265,19 @@ static int pushDownWhereTerms(
|
||||
}
|
||||
#endif
|
||||
|
||||
if( sqlite3ExprIsSingleTableConstraint(pWhere, pSrcList, iSrc) ){
|
||||
#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
|
||||
if( ViewCanHaveRowid && (pWhere->op==TK_ISNULL || pWhere->op==TK_NOTNULL) ){
|
||||
Expr *pLeft = pWhere->pLeft;
|
||||
if( ALWAYS(pLeft)
|
||||
&& pLeft->op==TK_COLUMN
|
||||
&& pLeft->iColumn < 0
|
||||
){
|
||||
return 0; /* Restriction (12) */
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if( sqlite3ExprIsSingleTableConstraint(pWhere, pSrcList, iSrc, 1) ){
|
||||
nChng++;
|
||||
pSubq->selFlags |= SF_PushDown;
|
||||
while( pSubq ){
|
||||
@@ -5869,12 +5904,14 @@ int sqlite3ExpandSubquery(Parse *pParse, SrcItem *pFrom){
|
||||
while( pSel->pPrior ){ pSel = pSel->pPrior; }
|
||||
sqlite3ColumnsFromExprList(pParse, pSel->pEList,&pTab->nCol,&pTab->aCol);
|
||||
pTab->iPKey = -1;
|
||||
pTab->eTabType = TABTYP_VIEW;
|
||||
pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) );
|
||||
#ifndef SQLITE_ALLOW_ROWID_IN_VIEW
|
||||
/* The usual case - do not allow ROWID on a subquery */
|
||||
pTab->tabFlags |= TF_Ephemeral | TF_NoVisibleRowid;
|
||||
#else
|
||||
pTab->tabFlags |= TF_Ephemeral; /* Legacy compatibility mode */
|
||||
/* Legacy compatibility mode */
|
||||
pTab->tabFlags |= TF_Ephemeral | sqlite3Config.mNoVisibleRowid;
|
||||
#endif
|
||||
return pParse->nErr ? SQLITE_ERROR : SQLITE_OK;
|
||||
}
|
||||
@@ -6142,7 +6179,7 @@ static int selectExpander(Walker *pWalker, Select *p){
|
||||
pNestedFrom = pFrom->pSelect->pEList;
|
||||
assert( pNestedFrom!=0 );
|
||||
assert( pNestedFrom->nExpr==pTab->nCol );
|
||||
assert( VisibleRowid(pTab)==0 );
|
||||
assert( VisibleRowid(pTab)==0 || ViewCanHaveRowid );
|
||||
}else{
|
||||
if( zTName && sqlite3StrICmp(zTName, zTabName)!=0 ){
|
||||
continue;
|
||||
@@ -6174,7 +6211,8 @@ static int selectExpander(Walker *pWalker, Select *p){
|
||||
pUsing = 0;
|
||||
}
|
||||
|
||||
nAdd = pTab->nCol + (VisibleRowid(pTab) && (selFlags&SF_NestedFrom));
|
||||
nAdd = pTab->nCol;
|
||||
if( VisibleRowid(pTab) && (selFlags & SF_NestedFrom)!=0 ) nAdd++;
|
||||
for(j=0; j<nAdd; j++){
|
||||
const char *zName;
|
||||
struct ExprList_item *pX; /* Newly added ExprList term */
|
||||
@@ -6256,7 +6294,8 @@ static int selectExpander(Walker *pWalker, Select *p){
|
||||
pX = &pNew->a[pNew->nExpr-1];
|
||||
assert( pX->zEName==0 );
|
||||
if( (selFlags & SF_NestedFrom)!=0 && !IN_RENAME_OBJECT ){
|
||||
if( pNestedFrom ){
|
||||
if( pNestedFrom && (!ViewCanHaveRowid || j<pNestedFrom->nExpr) ){
|
||||
assert( j<pNestedFrom->nExpr );
|
||||
pX->zEName = sqlite3DbStrDup(db, pNestedFrom->a[j].zEName);
|
||||
testcase( pX->zEName==0 );
|
||||
}else{
|
||||
@@ -7636,7 +7675,7 @@ int sqlite3Select(
|
||||
/* Generate code for all sub-queries in the FROM clause
|
||||
*/
|
||||
pSub = pItem->pSelect;
|
||||
if( pSub==0 ) continue;
|
||||
if( pSub==0 || pItem->addrFillSub!=0 ) continue;
|
||||
|
||||
/* The code for a subquery should only be generated once. */
|
||||
assert( pItem->addrFillSub==0 );
|
||||
@@ -7667,7 +7706,7 @@ int sqlite3Select(
|
||||
#endif
|
||||
assert( pItem->pSelect && (pItem->pSelect->selFlags & SF_PushDown)!=0 );
|
||||
}else{
|
||||
TREETRACE(0x4000,pParse,p,("Push-down not possible\n"));
|
||||
TREETRACE(0x4000,pParse,p,("WHERE-lcause push-down not possible\n"));
|
||||
}
|
||||
|
||||
/* Convert unused result columns of the subquery into simple NULL
|
||||
|
||||
+73
-39
@@ -3776,6 +3776,7 @@ static void exec_prepared_stmt_columnar(
|
||||
rc = sqlite3_step(pStmt);
|
||||
if( rc!=SQLITE_ROW ) return;
|
||||
nColumn = sqlite3_column_count(pStmt);
|
||||
if( nColumn==0 ) goto columnar_end;
|
||||
nAlloc = nColumn*4;
|
||||
if( nAlloc<=0 ) nAlloc = 1;
|
||||
azData = sqlite3_malloc64( nAlloc*sizeof(char*) );
|
||||
@@ -3861,7 +3862,6 @@ static void exec_prepared_stmt_columnar(
|
||||
if( n>p->actualWidth[j] ) p->actualWidth[j] = n;
|
||||
}
|
||||
if( seenInterrupt ) goto columnar_end;
|
||||
if( nColumn==0 ) goto columnar_end;
|
||||
switch( p->cMode ){
|
||||
case MODE_Column: {
|
||||
colSep = " ";
|
||||
@@ -8778,16 +8778,15 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
#ifndef SQLITE_SHELL_FIDDLE
|
||||
if( c=='i' && cli_strncmp(azArg[0], "import", n)==0 ){
|
||||
char *zTable = 0; /* Insert data into this table */
|
||||
char *zSchema = 0; /* within this schema (may default to "main") */
|
||||
char *zSchema = 0; /* Schema of zTable */
|
||||
char *zFile = 0; /* Name of file to extra content from */
|
||||
sqlite3_stmt *pStmt = NULL; /* A statement */
|
||||
int nCol; /* Number of columns in the table */
|
||||
int nByte; /* Number of bytes in an SQL string */
|
||||
i64 nByte; /* Number of bytes in an SQL string */
|
||||
int i, j; /* Loop counters */
|
||||
int needCommit; /* True to COMMIT or ROLLBACK at end */
|
||||
int nSep; /* Number of bytes in p->colSeparator[] */
|
||||
char *zSql; /* An SQL statement */
|
||||
char *zFullTabName; /* Table name with schema if applicable */
|
||||
char *zSql = 0; /* An SQL statement */
|
||||
ImportCtx sCtx; /* Reader context */
|
||||
char *(SQLITE_CDECL *xRead)(ImportCtx*); /* Func to read one value */
|
||||
int eVerbose = 0; /* Larger for more console output */
|
||||
@@ -8921,24 +8920,14 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
while( (nSkip--)>0 ){
|
||||
while( xRead(&sCtx) && sCtx.cTerm==sCtx.cColSep ){}
|
||||
}
|
||||
if( zSchema!=0 ){
|
||||
zFullTabName = sqlite3_mprintf("\"%w\".\"%w\"", zSchema, zTable);
|
||||
}else{
|
||||
zFullTabName = sqlite3_mprintf("\"%w\"", zTable);
|
||||
}
|
||||
zSql = sqlite3_mprintf("SELECT * FROM %s", zFullTabName);
|
||||
if( zSql==0 || zFullTabName==0 ){
|
||||
import_cleanup(&sCtx);
|
||||
shell_out_of_memory();
|
||||
}
|
||||
nByte = strlen30(zSql);
|
||||
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
|
||||
import_append_char(&sCtx, 0); /* To ensure sCtx.z is allocated */
|
||||
if( rc && sqlite3_strglob("no such table: *", sqlite3_errmsg(p->db))==0 ){
|
||||
if( sqlite3_table_column_metadata(p->db, zSchema, zTable,0,0,0,0,0,0) ){
|
||||
/* Table does not exist. Create it. */
|
||||
sqlite3 *dbCols = 0;
|
||||
char *zRenames = 0;
|
||||
char *zColDefs;
|
||||
zCreate = sqlite3_mprintf("CREATE TABLE %s", zFullTabName);
|
||||
zCreate = sqlite3_mprintf("CREATE TABLE \"%w\".\"%w\"",
|
||||
zSchema ? zSchema : "main", zTable);
|
||||
while( xRead(&sCtx) ){
|
||||
zAutoColumn(sCtx.z, &dbCols, 0);
|
||||
if( sCtx.cTerm!=sCtx.cColSep ) break;
|
||||
@@ -8953,34 +8942,50 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
assert(dbCols==0);
|
||||
if( zColDefs==0 ){
|
||||
eputf("%s: empty file\n", sCtx.zFile);
|
||||
import_fail:
|
||||
sqlite3_free(zCreate);
|
||||
sqlite3_free(zSql);
|
||||
sqlite3_free(zFullTabName);
|
||||
import_cleanup(&sCtx);
|
||||
rc = 1;
|
||||
goto meta_command_exit;
|
||||
}
|
||||
zCreate = sqlite3_mprintf("%z%z\n", zCreate, zColDefs);
|
||||
if( zCreate==0 ){
|
||||
import_cleanup(&sCtx);
|
||||
shell_out_of_memory();
|
||||
}
|
||||
if( eVerbose>=1 ){
|
||||
oputf("%s\n", zCreate);
|
||||
}
|
||||
rc = sqlite3_exec(p->db, zCreate, 0, 0, 0);
|
||||
if( rc ){
|
||||
eputf("%s failed:\n%s\n", zCreate, sqlite3_errmsg(p->db));
|
||||
goto import_fail;
|
||||
}
|
||||
sqlite3_free(zCreate);
|
||||
zCreate = 0;
|
||||
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
|
||||
if( rc ){
|
||||
eputf("%s failed:\n%s\n", zCreate, sqlite3_errmsg(p->db));
|
||||
import_cleanup(&sCtx);
|
||||
rc = 1;
|
||||
goto meta_command_exit;
|
||||
}
|
||||
}
|
||||
zSql = sqlite3_mprintf("SELECT count(*) FROM pragma_table_info(%Q,%Q);",
|
||||
zTable, zSchema);
|
||||
if( zSql==0 ){
|
||||
import_cleanup(&sCtx);
|
||||
shell_out_of_memory();
|
||||
}
|
||||
nByte = strlen(zSql);
|
||||
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
|
||||
sqlite3_free(zSql);
|
||||
zSql = 0;
|
||||
if( rc ){
|
||||
if (pStmt) sqlite3_finalize(pStmt);
|
||||
eputf("Error: %s\n", sqlite3_errmsg(p->db));
|
||||
goto import_fail;
|
||||
import_cleanup(&sCtx);
|
||||
rc = 1;
|
||||
goto meta_command_exit;
|
||||
}
|
||||
if( sqlite3_step(pStmt)==SQLITE_ROW ){
|
||||
nCol = sqlite3_column_int(pStmt, 0);
|
||||
}else{
|
||||
nCol = 0;
|
||||
}
|
||||
sqlite3_free(zSql);
|
||||
nCol = sqlite3_column_count(pStmt);
|
||||
sqlite3_finalize(pStmt);
|
||||
pStmt = 0;
|
||||
if( nCol==0 ) return 0; /* no columns, no error */
|
||||
@@ -8989,7 +8994,12 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
import_cleanup(&sCtx);
|
||||
shell_out_of_memory();
|
||||
}
|
||||
sqlite3_snprintf(nByte+20, zSql, "INSERT INTO %s VALUES(?", zFullTabName);
|
||||
if( zSchema ){
|
||||
sqlite3_snprintf(nByte+20, zSql, "INSERT INTO \"%w\".\"%w\" VALUES(?",
|
||||
zSchema, zTable);
|
||||
}else{
|
||||
sqlite3_snprintf(nByte+20, zSql, "INSERT INTO \"%w\" VALUES(?", zTable);
|
||||
}
|
||||
j = strlen30(zSql);
|
||||
for(i=1; i<nCol; i++){
|
||||
zSql[j++] = ',';
|
||||
@@ -9001,13 +9011,15 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
oputf("Insert using: %s\n", zSql);
|
||||
}
|
||||
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
|
||||
sqlite3_free(zSql);
|
||||
zSql = 0;
|
||||
if( rc ){
|
||||
eputf("Error: %s\n", sqlite3_errmsg(p->db));
|
||||
if (pStmt) sqlite3_finalize(pStmt);
|
||||
goto import_fail;
|
||||
import_cleanup(&sCtx);
|
||||
rc = 1;
|
||||
goto meta_command_exit;
|
||||
}
|
||||
sqlite3_free(zSql);
|
||||
sqlite3_free(zFullTabName);
|
||||
needCommit = sqlite3_get_autocommit(p->db);
|
||||
if( needCommit ) sqlite3_exec(p->db, "BEGIN", 0, 0, 0);
|
||||
do{
|
||||
@@ -12046,6 +12058,7 @@ static const char zOptions[] =
|
||||
" -newline SEP set output row separator. Default: '\\n'\n"
|
||||
" -nofollow refuse to open symbolic links to database files\n"
|
||||
" -nonce STRING set the safe-mode escape nonce\n"
|
||||
" -no-rowid-in-view Disable rowid-in-view using sqlite3_config()\n"
|
||||
" -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"
|
||||
" -pcachetrace trace all page cache operations\n"
|
||||
@@ -12336,6 +12349,10 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
|
||||
stdin_is_interactive = 0;
|
||||
}else if( cli_strcmp(z,"-utf8")==0 ){
|
||||
}else if( cli_strcmp(z,"-no-utf8")==0 ){
|
||||
}else if( cli_strcmp(z,"-no-rowid-in-view")==0 ){
|
||||
int val = 0;
|
||||
sqlite3_config(SQLITE_CONFIG_ROWID_IN_VIEW, &val);
|
||||
assert( val==0 );
|
||||
}else if( cli_strcmp(z,"-heap")==0 ){
|
||||
#if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5)
|
||||
const char *zSize;
|
||||
@@ -12611,6 +12628,8 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
|
||||
/* already handled */
|
||||
}else if( cli_strcmp(z,"-no-utf8")==0 ){
|
||||
/* already handled */
|
||||
}else if( cli_strcmp(z,"-no-rowid-in-view")==0 ){
|
||||
/* already handled */
|
||||
}else if( cli_strcmp(z,"-heap")==0 ){
|
||||
i++;
|
||||
}else if( cli_strcmp(z,"-pagecache")==0 ){
|
||||
@@ -12772,6 +12791,11 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
|
||||
#ifndef SQLITE_SHELL_FIDDLE
|
||||
/* In WASM mode we have to leave the db state in place so that
|
||||
** client code can "push" SQL into it after this call returns. */
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
if( data.expert.pExpert ){
|
||||
expertFinish(&data, 1, 0);
|
||||
}
|
||||
#endif
|
||||
free(azCmd);
|
||||
set_table_name(&data, 0);
|
||||
if( data.db ){
|
||||
@@ -12838,7 +12862,7 @@ sqlite3_vfs * fiddle_db_vfs(const char *zDbName){
|
||||
|
||||
/* Only for emcc experimentation purposes. */
|
||||
sqlite3 * fiddle_db_arg(sqlite3 *arg){
|
||||
printf("fiddle_db_arg(%p)\n", (const void*)arg);
|
||||
oputf("fiddle_db_arg(%p)\n", (const void*)arg);
|
||||
return arg;
|
||||
}
|
||||
|
||||
@@ -12864,12 +12888,22 @@ const char * fiddle_db_filename(const char * zDbName){
|
||||
|
||||
/*
|
||||
** Completely wipes out the contents of the currently-opened database
|
||||
** but leaves its storage intact for reuse.
|
||||
** but leaves its storage intact for reuse. If any transactions are
|
||||
** active, they are forcibly rolled back.
|
||||
*/
|
||||
void fiddle_reset_db(void){
|
||||
if( globalDb ){
|
||||
int rc = sqlite3_db_config(globalDb, SQLITE_DBCONFIG_RESET_DATABASE, 1, 0);
|
||||
if( 0==rc ) rc = sqlite3_exec(globalDb, "VACUUM", 0, 0, 0);
|
||||
int rc;
|
||||
while( sqlite3_txn_state(globalDb,0)>0 ){
|
||||
/*
|
||||
** Resolve problem reported in
|
||||
** https://sqlite.org/forum/forumpost/0b41a25d65
|
||||
*/
|
||||
oputz("Rolling back in-progress transaction.\n");
|
||||
sqlite3_exec(globalDb,"ROLLBACK", 0, 0, 0);
|
||||
}
|
||||
rc = sqlite3_db_config(globalDb, SQLITE_DBCONFIG_RESET_DATABASE, 1, 0);
|
||||
if( 0==rc ) sqlite3_exec(globalDb, "VACUUM", 0, 0, 0);
|
||||
sqlite3_db_config(globalDb, SQLITE_DBCONFIG_RESET_DATABASE, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
+26
-3
@@ -2143,6 +2143,22 @@ struct sqlite3_mem_methods {
|
||||
** configuration setting is never used, then the default maximum is determined
|
||||
** by the [SQLITE_MEMDB_DEFAULT_MAXSIZE] compile-time option. If that
|
||||
** compile-time option is not set, then the default maximum is 1073741824.
|
||||
**
|
||||
** [[SQLITE_CONFIG_ROWID_IN_VIEW]]
|
||||
** <dt>SQLITE_CONFIG_ROWID_IN_VIEW
|
||||
** <dd>The SQLITE_CONFIG_ROWID_IN_VIEW option enables or disables the ability
|
||||
** for VIEWs to have a ROWID. The capability can only be enabled if SQLite is
|
||||
** compiled with -DSQLITE_ALLOW_ROWID_IN_VIEW, in which case the capability
|
||||
** defaults to on. This configuration option queries the current setting or
|
||||
** changes the setting to off or on. The argument is a pointer to an integer.
|
||||
** If that integer initially holds a value of 1, then the ability for VIEWs to
|
||||
** have ROWIDs is activated. If the integer initially holds zero, then the
|
||||
** ability is deactivated. Any other initial value for the integer leaves the
|
||||
** setting unchanged. After changes, if any, the integer is written with
|
||||
** a 1 or 0, if the ability for VIEWs to have ROWIDs is on or off. If SQLite
|
||||
** is compiled without -DSQLITE_ALLOW_ROWID_IN_VIEW (which is the usual and
|
||||
** recommended case) then the integer is always filled with zero, regardless
|
||||
** if its initial value.
|
||||
** </dl>
|
||||
*/
|
||||
#define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */
|
||||
@@ -2174,6 +2190,7 @@ struct sqlite3_mem_methods {
|
||||
#define SQLITE_CONFIG_SMALL_MALLOC 27 /* boolean */
|
||||
#define SQLITE_CONFIG_SORTERREF_SIZE 28 /* int nByte */
|
||||
#define SQLITE_CONFIG_MEMDB_MAXSIZE 29 /* sqlite3_int64 */
|
||||
#define SQLITE_CONFIG_ROWID_IN_VIEW 30 /* int* */
|
||||
|
||||
/*
|
||||
** CAPI3REF: Database Connection Configuration Options
|
||||
@@ -3288,8 +3305,8 @@ int sqlite3_set_authorizer(
|
||||
#define SQLITE_RECURSIVE 33 /* NULL NULL */
|
||||
|
||||
/*
|
||||
** CAPI3REF: Tracing And Profiling Functions
|
||||
** METHOD: sqlite3
|
||||
** CAPI3REF: Deprecated Tracing And Profiling Functions
|
||||
** DEPRECATED
|
||||
**
|
||||
** These routines are deprecated. Use the [sqlite3_trace_v2()] interface
|
||||
** instead of the routines described here.
|
||||
@@ -6870,6 +6887,12 @@ int sqlite3_autovacuum_pages(
|
||||
** The exceptions defined in this paragraph might change in a future
|
||||
** release of SQLite.
|
||||
**
|
||||
** Whether the update hook is invoked before or after the
|
||||
** corresponding change is currently unspecified and may differ
|
||||
** depending on the type of change. Do not rely on the order of the
|
||||
** hook call with regards to the final result of the operation which
|
||||
** triggers the hook.
|
||||
**
|
||||
** The update hook implementation must not do anything that will modify
|
||||
** the database connection that invoked the update hook. Any actions
|
||||
** to modify the database connection must be deferred until after the
|
||||
@@ -8340,7 +8363,7 @@ int sqlite3_test_control(int op, ...);
|
||||
** The sqlite3_keyword_count() interface returns the number of distinct
|
||||
** keywords understood by SQLite.
|
||||
**
|
||||
** The sqlite3_keyword_name(N,Z,L) interface finds the N-th keyword and
|
||||
** The sqlite3_keyword_name(N,Z,L) interface finds the 0-based N-th keyword and
|
||||
** makes *Z point to that keyword expressed as UTF8 and writes the number
|
||||
** of bytes in the keyword into *L. The string that *Z points to is not
|
||||
** zero-terminated. The sqlite3_keyword_name(N,Z,L) routine returns
|
||||
|
||||
+42
-17
@@ -1125,6 +1125,7 @@ extern u32 sqlite3TreeTrace;
|
||||
** 0x00010000 Beginning of DELETE/INSERT/UPDATE processing
|
||||
** 0x00020000 Transform DISTINCT into GROUP BY
|
||||
** 0x00040000 SELECT tree dump after all code has been generated
|
||||
** 0x00080000 NOT NULL strength reduction
|
||||
*/
|
||||
|
||||
/*
|
||||
@@ -1155,7 +1156,7 @@ extern u32 sqlite3WhereTrace;
|
||||
** 0x00000010 Display sqlite3_index_info xBestIndex calls
|
||||
** 0x00000020 Range an equality scan metrics
|
||||
** 0x00000040 IN operator decisions
|
||||
** 0x00000080 WhereLoop cost adjustements
|
||||
** 0x00000080 WhereLoop cost adjustments
|
||||
** 0x00000100
|
||||
** 0x00000200 Covering index decisions
|
||||
** 0x00000400 OR optimization
|
||||
@@ -1905,7 +1906,7 @@ struct sqlite3 {
|
||||
#define SQLITE_CursorHints 0x00000400 /* Add OP_CursorHint opcodes */
|
||||
#define SQLITE_Stat4 0x00000800 /* Use STAT4 data */
|
||||
/* TH3 expects this value ^^^^^^^^^^ to be 0x0000800. Don't change it */
|
||||
#define SQLITE_PushDown 0x00001000 /* The push-down optimization */
|
||||
#define SQLITE_PushDown 0x00001000 /* WHERE-clause push-down opt */
|
||||
#define SQLITE_SimplifyJoin 0x00002000 /* Convert LEFT JOIN to JOIN */
|
||||
#define SQLITE_SkipScan 0x00004000 /* Skip-scans */
|
||||
#define SQLITE_PropagateConst 0x00008000 /* The constant propagation opt */
|
||||
@@ -2534,6 +2535,15 @@ struct Table {
|
||||
#define HasRowid(X) (((X)->tabFlags & TF_WithoutRowid)==0)
|
||||
#define VisibleRowid(X) (((X)->tabFlags & TF_NoVisibleRowid)==0)
|
||||
|
||||
/* Macro is true if the SQLITE_ALLOW_ROWID_IN_VIEW (mis-)feature is
|
||||
** available. By default, this macro is false
|
||||
*/
|
||||
#ifndef SQLITE_ALLOW_ROWID_IN_VIEW
|
||||
# define ViewCanHaveRowid 0
|
||||
#else
|
||||
# define ViewCanHaveRowid (sqlite3Config.mNoVisibleRowid==0)
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Each foreign key constraint is an instance of the following structure.
|
||||
**
|
||||
@@ -3269,10 +3279,12 @@ struct IdList {
|
||||
**
|
||||
** Union member validity:
|
||||
**
|
||||
** u1.zIndexedBy fg.isIndexedBy && !fg.isTabFunc
|
||||
** u1.pFuncArg fg.isTabFunc && !fg.isIndexedBy
|
||||
** u2.pIBIndex fg.isIndexedBy && !fg.isCte
|
||||
** u2.pCteUse fg.isCte && !fg.isIndexedBy
|
||||
** u1.zIndexedBy fg.isIndexedBy && !fg.isTabFunc
|
||||
** u1.pFuncArg fg.isTabFunc && !fg.isIndexedBy
|
||||
** u1.nRow !fg.isTabFunc && !fg.isIndexedBy
|
||||
**
|
||||
** u2.pIBIndex fg.isIndexedBy && !fg.isCte
|
||||
** u2.pCteUse fg.isCte && !fg.isIndexedBy
|
||||
*/
|
||||
struct SrcItem {
|
||||
Schema *pSchema; /* Schema to which this item is fixed */
|
||||
@@ -3310,12 +3322,11 @@ struct SrcItem {
|
||||
union {
|
||||
char *zIndexedBy; /* Identifier from "INDEXED BY <zIndex>" clause */
|
||||
ExprList *pFuncArg; /* Arguments to table-valued-function */
|
||||
u32 nRow; /* Number of rows in a VALUES clause */
|
||||
} u1;
|
||||
union {
|
||||
Index *pIBIndex; /* Index structure corresponding to u1.zIndexedBy */
|
||||
CteUse *pCteUse; /* CTE Usage info when fg.isCte is true */
|
||||
Trigger *pTrig; /* Trigger in argument list of DROP TRIGGER */
|
||||
Index *pIdx; /* Index in argument list to DROP INDEX */
|
||||
} u2;
|
||||
};
|
||||
|
||||
@@ -3455,6 +3466,7 @@ struct NameContext {
|
||||
#define NC_InAggFunc 0x020000 /* True if analyzing arguments to an agg func */
|
||||
#define NC_FromDDL 0x040000 /* SQL text comes from sqlite_schema */
|
||||
#define NC_NoSelect 0x080000 /* Do not descend into sub-selects */
|
||||
#define NC_Where 0x100000 /* Processing WHERE clause of a SELECT */
|
||||
#define NC_OrderAgg 0x8000000 /* Has an aggregate other than count/min/max */
|
||||
|
||||
/*
|
||||
@@ -3478,6 +3490,7 @@ struct Upsert {
|
||||
Expr *pUpsertWhere; /* WHERE clause for the ON CONFLICT UPDATE */
|
||||
Upsert *pNextUpsert; /* Next ON CONFLICT clause in the list */
|
||||
u8 isDoUpdate; /* True for DO UPDATE. False for DO NOTHING */
|
||||
u8 isDup; /* True if 2nd or later with same pUpsertIdx */
|
||||
/* Above this point is the parse tree for the ON CONFLICT clauses.
|
||||
** The next group of fields stores intermediate data. */
|
||||
void *pToFree; /* Free memory when deleting the Upsert object */
|
||||
@@ -3567,11 +3580,12 @@ struct Select {
|
||||
#define SF_View 0x0200000 /* SELECT statement is a view */
|
||||
#define SF_NoopOrderBy 0x0400000 /* ORDER BY is ignored for this query */
|
||||
#define SF_UFSrcCheck 0x0800000 /* Check pSrc as required by UPDATE...FROM */
|
||||
#define SF_PushDown 0x1000000 /* SELECT has be modified by push-down opt */
|
||||
#define SF_PushDown 0x1000000 /* Modified by WHERE-clause push-down opt */
|
||||
#define SF_MultiPart 0x2000000 /* Has multiple incompatible PARTITIONs */
|
||||
#define SF_CopyCte 0x4000000 /* SELECT statement is a copy of a CTE */
|
||||
#define SF_OrderByReqd 0x8000000 /* The ORDER BY clause may not be omitted */
|
||||
#define SF_UpdateFrom 0x10000000 /* Query originates with UPDATE FROM */
|
||||
#define SF_Correlated 0x20000000 /* True if references the outer context */
|
||||
|
||||
/* True if S exists and has SF_NestedFrom */
|
||||
#define IsNestedFrom(S) ((S)!=0 && ((S)->selFlags&SF_NestedFrom)!=0)
|
||||
@@ -3811,6 +3825,7 @@ struct Parse {
|
||||
u8 disableLookaside; /* Number of times lookaside has been disabled */
|
||||
u8 prepFlags; /* SQLITE_PREPARE_* flags */
|
||||
u8 withinRJSubrtn; /* Nesting level for RIGHT JOIN body subroutines */
|
||||
u8 bHasWith; /* True if statement contains WITH */
|
||||
#if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST)
|
||||
u8 earlyCleanup; /* OOM inside sqlite3ParserAddCleanup() */
|
||||
#endif
|
||||
@@ -4248,6 +4263,11 @@ struct Sqlite3Config {
|
||||
#endif
|
||||
#ifndef SQLITE_UNTESTABLE
|
||||
int (*xTestCallback)(int); /* Invoked by sqlite3FaultSim() */
|
||||
#endif
|
||||
#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
|
||||
u32 mNoVisibleRowid; /* TF_NoVisibleRowid if the ROWID_IN_VIEW
|
||||
** feature is disabled. 0 if rowids can
|
||||
** occur in views. */
|
||||
#endif
|
||||
int bLocaltimeFault; /* True to fail localtime() calls */
|
||||
int (*xAltLocaltime)(const void*,void*); /* Alternative localtime() routine */
|
||||
@@ -4485,6 +4505,9 @@ struct Window {
|
||||
** due to the SQLITE_SUBTYPE flag */
|
||||
};
|
||||
|
||||
Select *sqlite3MultiValues(Parse *pParse, Select *pLeft, ExprList *pRow);
|
||||
void sqlite3MultiValuesEnd(Parse *pParse, Select *pVal);
|
||||
|
||||
#ifndef SQLITE_OMIT_WINDOWFUNC
|
||||
void sqlite3WindowDelete(sqlite3*, Window*);
|
||||
void sqlite3WindowUnlinkFromSelect(Window*);
|
||||
@@ -4704,10 +4727,13 @@ void sqlite3MutexWarnOnContention(sqlite3_mutex*);
|
||||
# define EXP754 (((u64)0x7ff)<<52)
|
||||
# define MAN754 ((((u64)1)<<52)-1)
|
||||
# define IsNaN(X) (((X)&EXP754)==EXP754 && ((X)&MAN754)!=0)
|
||||
# define IsOvfl(X) (((X)&EXP754)==EXP754)
|
||||
int sqlite3IsNaN(double);
|
||||
int sqlite3IsOverflow(double);
|
||||
#else
|
||||
# define IsNaN(X) 0
|
||||
# define sqlite3IsNaN(X) 0
|
||||
# define IsNaN(X) 0
|
||||
# define sqlite3IsNaN(X) 0
|
||||
# define sqlite3IsOVerflow(X) 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -4928,6 +4954,7 @@ void sqlite3CreateView(Parse*,Token*,Token*,Token*,ExprList*,Select*,int,int);
|
||||
int sqlite3DbMaskAllZero(yDbMask);
|
||||
#endif
|
||||
void sqlite3DropTable(Parse*, SrcList*, int, int);
|
||||
void sqlite3CodeDropTable(Parse*, Table*, int, int);
|
||||
void sqlite3DeleteTable(sqlite3*, Table*);
|
||||
void sqlite3DeleteTableGeneric(sqlite3*, void*);
|
||||
void sqlite3FreeIndex(sqlite3*, Index*);
|
||||
@@ -5052,12 +5079,10 @@ void sqlite3LeaveMutexAndCloseZombie(sqlite3*);
|
||||
u32 sqlite3IsTrueOrFalse(const char*);
|
||||
int sqlite3ExprIdToTrueFalse(Expr*);
|
||||
int sqlite3ExprTruthValue(const Expr*);
|
||||
int sqlite3ExprIsConstant(Expr*);
|
||||
int sqlite3ExprIsConstantNotJoin(Expr*);
|
||||
int sqlite3ExprIsConstant(Parse*,Expr*);
|
||||
int sqlite3ExprIsConstantOrFunction(Expr*, u8);
|
||||
int sqlite3ExprIsConstantOrGroupBy(Parse*, Expr*, ExprList*);
|
||||
int sqlite3ExprIsTableConstant(Expr*,int);
|
||||
int sqlite3ExprIsSingleTableConstraint(Expr*,const SrcList*,int);
|
||||
int sqlite3ExprIsSingleTableConstraint(Expr*,const SrcList*,int,int);
|
||||
#ifdef SQLITE_ENABLE_CURSOR_HINTS
|
||||
int sqlite3ExprContainsSubquery(Expr*);
|
||||
#endif
|
||||
@@ -5553,7 +5578,7 @@ const char *sqlite3JournalModename(int);
|
||||
Upsert *sqlite3UpsertNew(sqlite3*,ExprList*,Expr*,ExprList*,Expr*,Upsert*);
|
||||
void sqlite3UpsertDelete(sqlite3*,Upsert*);
|
||||
Upsert *sqlite3UpsertDup(sqlite3*,Upsert*);
|
||||
int sqlite3UpsertAnalyzeTarget(Parse*,SrcList*,Upsert*);
|
||||
int sqlite3UpsertAnalyzeTarget(Parse*,SrcList*,Upsert*,Upsert*);
|
||||
void sqlite3UpsertDoUpdate(Parse*,Upsert*,Table*,Index*,int);
|
||||
Upsert *sqlite3UpsertOfIndex(Upsert*,Index*);
|
||||
int sqlite3UpsertNextIsIPK(Upsert*);
|
||||
@@ -5575,7 +5600,7 @@ const char *sqlite3JournalModename(int);
|
||||
*/
|
||||
#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
|
||||
void sqlite3FkCheck(Parse*, Table*, int, int, int*, int);
|
||||
void sqlite3FkDropTable(Parse*, SrcList*, Table*);
|
||||
void sqlite3FkDropTable(Parse*, SrcList *, Table*);
|
||||
void sqlite3FkActions(Parse*, Table*, ExprList*, int, int*, int);
|
||||
int sqlite3FkRequired(Parse*, Table*, int*, int);
|
||||
u32 sqlite3FkOldmask(Parse*, Table*);
|
||||
|
||||
@@ -226,7 +226,7 @@ static int tclConnect(
|
||||
}
|
||||
|
||||
sqlite3_free(zCmd);
|
||||
*ppVtab = &pTab->base;
|
||||
*ppVtab = pTab ? &pTab->base : 0;
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
@@ -59,6 +59,14 @@ static void set_options(Tcl_Interp *interp){
|
||||
Tcl_SetVar2(interp, "sqlite_options", "rowid32", "0", TCL_GLOBAL_ONLY);
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
|
||||
Tcl_SetVar2(
|
||||
interp, "sqlite_options", "allow_rowid_in_view", "1", TCL_GLOBAL_ONLY);
|
||||
#else
|
||||
Tcl_SetVar2(
|
||||
interp, "sqlite_options", "allow_rowid_in_view", "0", TCL_GLOBAL_ONLY);
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_CASE_SENSITIVE_LIKE
|
||||
Tcl_SetVar2(interp, "sqlite_options","casesensitivelike","1",TCL_GLOBAL_ONLY);
|
||||
#else
|
||||
|
||||
@@ -235,12 +235,14 @@ void sqlite3TreeViewSrcList(TreeView *pView, const SrcList *pSrc){
|
||||
sqlite3TreeViewIdList(pView, pItem->u3.pUsing, (--n)>0, "USING");
|
||||
}
|
||||
if( pItem->pSelect ){
|
||||
sqlite3TreeViewPush(&pView, i+1<pSrc->nSrc);
|
||||
if( pItem->pTab ){
|
||||
Table *pTab = pItem->pTab;
|
||||
sqlite3TreeViewColumnList(pView, pTab->aCol, pTab->nCol, 1);
|
||||
}
|
||||
assert( (int)pItem->fg.isNestedFrom == IsNestedFrom(pItem->pSelect) );
|
||||
sqlite3TreeViewSelect(pView, pItem->pSelect, (--n)>0);
|
||||
sqlite3TreeViewPop(&pView);
|
||||
}
|
||||
if( pItem->fg.isTabFunc ){
|
||||
sqlite3TreeViewExprList(pView, pItem->u1.pFuncArg, 0, "func-args:");
|
||||
|
||||
+95
-31
@@ -624,39 +624,35 @@ void sqlite3DropTrigger(Parse *pParse, SrcList *pName, int noErr){
|
||||
const char *zDb;
|
||||
const char *zName;
|
||||
sqlite3 *db = pParse->db;
|
||||
int ii, jj;
|
||||
|
||||
sqlite3ReadSchema(pParse);
|
||||
assert( pName!=0 || pParse->nErr!=0 );
|
||||
for(ii=0; pParse->nErr==0 && ii<pName->nSrc; ii++){
|
||||
zDb = pName->a[ii].zDatabase;
|
||||
zName = pName->a[ii].zName;
|
||||
assert( zDb!=0 || sqlite3BtreeHoldsAllMutexes(db) );
|
||||
for(i=OMIT_TEMPDB; i<db->nDb; i++){
|
||||
int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */
|
||||
if( zDb && sqlite3DbIsNamed(db, j, zDb)==0 ) continue;
|
||||
assert( sqlite3SchemaMutexHeld(db, j, 0) );
|
||||
pTrigger = sqlite3HashFind(&(db->aDb[j].pSchema->trigHash), zName);
|
||||
if( pTrigger ) break;
|
||||
}
|
||||
pName->a[ii].u2.pTrig = pTrigger;
|
||||
if( !pTrigger ){
|
||||
if( !noErr ){
|
||||
sqlite3ErrorMsg(pParse, "no such trigger: %S", pName->a+ii);
|
||||
}else{
|
||||
sqlite3CodeVerifyNamedSchema(pParse, zDb);
|
||||
}
|
||||
testcase( ii>0 );
|
||||
testcase( ii+1<pName->nSrc );
|
||||
pParse->checkSchema = 1;
|
||||
continue;
|
||||
}
|
||||
for(jj=ii-1; jj>=0; jj--){
|
||||
if( pName->a[jj].u2.pTrig==pTrigger ) break;
|
||||
}
|
||||
if( jj>=0 ) continue;
|
||||
sqlite3DropTriggerPtr(pParse, pTrigger);
|
||||
if( db->mallocFailed ) goto drop_trigger_cleanup;
|
||||
if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){
|
||||
goto drop_trigger_cleanup;
|
||||
}
|
||||
|
||||
assert( pName->nSrc==1 );
|
||||
zDb = pName->a[0].zDatabase;
|
||||
zName = pName->a[0].zName;
|
||||
assert( zDb!=0 || sqlite3BtreeHoldsAllMutexes(db) );
|
||||
for(i=OMIT_TEMPDB; i<db->nDb; i++){
|
||||
int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */
|
||||
if( zDb && sqlite3DbIsNamed(db, j, zDb)==0 ) continue;
|
||||
assert( sqlite3SchemaMutexHeld(db, j, 0) );
|
||||
pTrigger = sqlite3HashFind(&(db->aDb[j].pSchema->trigHash), zName);
|
||||
if( pTrigger ) break;
|
||||
}
|
||||
if( !pTrigger ){
|
||||
if( !noErr ){
|
||||
sqlite3ErrorMsg(pParse, "no such trigger: %S", pName->a);
|
||||
}else{
|
||||
sqlite3CodeVerifyNamedSchema(pParse, zDb);
|
||||
}
|
||||
pParse->checkSchema = 1;
|
||||
goto drop_trigger_cleanup;
|
||||
}
|
||||
sqlite3DropTriggerPtr(pParse, pTrigger);
|
||||
|
||||
drop_trigger_cleanup:
|
||||
sqlite3SrcListDelete(db, pName);
|
||||
}
|
||||
|
||||
@@ -955,6 +951,72 @@ static ExprList *sqlite3ExpandReturning(
|
||||
return pNew;
|
||||
}
|
||||
|
||||
/* If the Expr node is a subquery or an EXISTS operator or an IN operator that
|
||||
** uses a subquery, and if the subquery is SF_Correlated, then mark the
|
||||
** expression as EP_VarSelect.
|
||||
*/
|
||||
static int sqlite3ReturningSubqueryVarSelect(Walker *NotUsed, Expr *pExpr){
|
||||
UNUSED_PARAMETER(NotUsed);
|
||||
if( ExprUseXSelect(pExpr)
|
||||
&& (pExpr->x.pSelect->selFlags & SF_Correlated)!=0
|
||||
){
|
||||
testcase( ExprHasProperty(pExpr, EP_VarSelect) );
|
||||
ExprSetProperty(pExpr, EP_VarSelect);
|
||||
}
|
||||
return WRC_Continue;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** If the SELECT references the table pWalker->u.pTab, then do two things:
|
||||
**
|
||||
** (1) Mark the SELECT as as SF_Correlated.
|
||||
** (2) Set pWalker->eCode to non-zero so that the caller will know
|
||||
** that (1) has happened.
|
||||
*/
|
||||
static int sqlite3ReturningSubqueryCorrelated(Walker *pWalker, Select *pSelect){
|
||||
int i;
|
||||
SrcList *pSrc;
|
||||
assert( pSelect!=0 );
|
||||
pSrc = pSelect->pSrc;
|
||||
assert( pSrc!=0 );
|
||||
for(i=0; i<pSrc->nSrc; i++){
|
||||
if( pSrc->a[i].pTab==pWalker->u.pTab ){
|
||||
testcase( pSelect->selFlags & SF_Correlated );
|
||||
pSelect->selFlags |= SF_Correlated;
|
||||
pWalker->eCode = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return WRC_Continue;
|
||||
}
|
||||
|
||||
/*
|
||||
** Scan the expression list that is the argument to RETURNING looking
|
||||
** for subqueries that depend on the table which is being modified in the
|
||||
** statement that is hosting the RETURNING clause (pTab). Mark all such
|
||||
** subqueries as SF_Correlated. If the subqueries are part of an
|
||||
** expression, mark the expression as EP_VarSelect.
|
||||
**
|
||||
** https://sqlite.org/forum/forumpost/2c83569ce8945d39
|
||||
*/
|
||||
static void sqlite3ProcessReturningSubqueries(
|
||||
ExprList *pEList,
|
||||
Table *pTab
|
||||
){
|
||||
Walker w;
|
||||
memset(&w, 0, sizeof(w));
|
||||
w.xExprCallback = sqlite3ExprWalkNoop;
|
||||
w.xSelectCallback = sqlite3ReturningSubqueryCorrelated;
|
||||
w.u.pTab = pTab;
|
||||
sqlite3WalkExprList(&w, pEList);
|
||||
if( w.eCode ){
|
||||
w.xExprCallback = sqlite3ReturningSubqueryVarSelect;
|
||||
w.xSelectCallback = sqlite3SelectWalkNoop;
|
||||
sqlite3WalkExprList(&w, pEList);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Generate code for the RETURNING trigger. Unlike other triggers
|
||||
** that invoke a subprogram in the bytecode, the code for RETURNING
|
||||
@@ -991,6 +1053,7 @@ static void codeReturningTrigger(
|
||||
sSelect.pSrc = &sFrom;
|
||||
sFrom.nSrc = 1;
|
||||
sFrom.a[0].pTab = pTab;
|
||||
sFrom.a[0].zName = pTab->zName; /* tag-20240424-1 */
|
||||
sFrom.a[0].iCursor = -1;
|
||||
sqlite3SelectPrep(pParse, &sSelect, 0);
|
||||
if( pParse->nErr==0 ){
|
||||
@@ -1017,6 +1080,7 @@ static void codeReturningTrigger(
|
||||
int i;
|
||||
int nCol = pNew->nExpr;
|
||||
int reg = pParse->nMem+1;
|
||||
sqlite3ProcessReturningSubqueries(pNew, pTab);
|
||||
pParse->nMem += nCol+2;
|
||||
pReturning->iRetReg = reg;
|
||||
for(i=0; i<nCol; i++){
|
||||
|
||||
@@ -921,6 +921,9 @@ void sqlite3Update(
|
||||
}
|
||||
}
|
||||
if( chngRowid==0 && pPk==0 ){
|
||||
#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
|
||||
if( isView ) sqlite3VdbeAddOp2(v, OP_Null, 0, regOldRowid);
|
||||
#endif
|
||||
sqlite3VdbeAddOp2(v, OP_Copy, regOldRowid, regNewRowid);
|
||||
}
|
||||
}
|
||||
|
||||
+17
-4
@@ -90,7 +90,8 @@ Upsert *sqlite3UpsertNew(
|
||||
int sqlite3UpsertAnalyzeTarget(
|
||||
Parse *pParse, /* The parsing context */
|
||||
SrcList *pTabList, /* Table into which we are inserting */
|
||||
Upsert *pUpsert /* The ON CONFLICT clauses */
|
||||
Upsert *pUpsert, /* The ON CONFLICT clauses */
|
||||
Upsert *pAll /* Complete list of all ON CONFLICT clauses */
|
||||
){
|
||||
Table *pTab; /* That table into which we are inserting */
|
||||
int rc; /* Result code */
|
||||
@@ -193,6 +194,14 @@ int sqlite3UpsertAnalyzeTarget(
|
||||
continue;
|
||||
}
|
||||
pUpsert->pUpsertIdx = pIdx;
|
||||
if( sqlite3UpsertOfIndex(pAll,pIdx)!=pUpsert ){
|
||||
/* Really this should be an error. The isDup ON CONFLICT clause will
|
||||
** never fire. But this problem was not discovered until three years
|
||||
** after multi-CONFLICT upsert was added, and so we silently ignore
|
||||
** the problem to prevent breaking applications that might actually
|
||||
** have redundant ON CONFLICT clauses. */
|
||||
pUpsert->isDup = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if( pUpsert->pUpsertIdx==0 ){
|
||||
@@ -219,9 +228,13 @@ int sqlite3UpsertNextIsIPK(Upsert *pUpsert){
|
||||
Upsert *pNext;
|
||||
if( NEVER(pUpsert==0) ) return 0;
|
||||
pNext = pUpsert->pNextUpsert;
|
||||
if( pNext==0 ) return 1;
|
||||
if( pNext->pUpsertTarget==0 ) return 1;
|
||||
if( pNext->pUpsertIdx==0 ) return 1;
|
||||
while( 1 /*exit-by-return*/ ){
|
||||
if( pNext==0 ) return 1;
|
||||
if( pNext->pUpsertTarget==0 ) return 1;
|
||||
if( pNext->pUpsertIdx==0 ) return 1;
|
||||
if( !pNext->isDup ) return 0;
|
||||
pNext = pNext->pNextUpsert;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
+16
@@ -68,6 +68,19 @@ int sqlite3IsNaN(double x){
|
||||
}
|
||||
#endif /* SQLITE_OMIT_FLOATING_POINT */
|
||||
|
||||
#ifndef SQLITE_OMIT_FLOATING_POINT
|
||||
/*
|
||||
** Return true if the floating point value is NaN or +Inf or -Inf.
|
||||
*/
|
||||
int sqlite3IsOverflow(double x){
|
||||
int rc; /* The value return */
|
||||
u64 y;
|
||||
memcpy(&y,&x,sizeof(y));
|
||||
rc = IsOvfl(y);
|
||||
return rc;
|
||||
}
|
||||
#endif /* SQLITE_OMIT_FLOATING_POINT */
|
||||
|
||||
/*
|
||||
** Compute a string length that is limited to what can be stored in
|
||||
** lower 30 bits of a 32-bit signed integer.
|
||||
@@ -665,6 +678,9 @@ do_atof_calc:
|
||||
u64 s2;
|
||||
rr[0] = (double)s;
|
||||
s2 = (u64)rr[0];
|
||||
#if defined(_MSC_VER) && _MSC_VER<1700
|
||||
if( s2==0x8000000000000000LL ){ s2 = 2*(u64)(0.5*rr[0]); }
|
||||
#endif
|
||||
rr[1] = s>=s2 ? (double)(s - s2) : -(double)(s2 - s);
|
||||
if( e>0 ){
|
||||
while( e>=100 ){
|
||||
|
||||
+27
-25
@@ -1129,7 +1129,7 @@ case OP_Return: { /* in1 */
|
||||
**
|
||||
** See also: EndCoroutine
|
||||
*/
|
||||
case OP_InitCoroutine: { /* jump */
|
||||
case OP_InitCoroutine: { /* jump0 */
|
||||
assert( pOp->p1>0 && pOp->p1<=(p->nMem+1 - p->nCursor) );
|
||||
assert( pOp->p2>=0 && pOp->p2<p->nOp );
|
||||
assert( pOp->p3>=0 && pOp->p3<p->nOp );
|
||||
@@ -1152,7 +1152,9 @@ jump_to_p2:
|
||||
**
|
||||
** The instruction at the address in register P1 is a Yield.
|
||||
** Jump to the P2 parameter of that Yield.
|
||||
** After the jump, register P1 becomes undefined.
|
||||
** After the jump, the value register P1 is left with a value
|
||||
** such that subsequent OP_Yields go back to the this same
|
||||
** OP_EndCoroutine instruction.
|
||||
**
|
||||
** See also: InitCoroutine
|
||||
*/
|
||||
@@ -1164,8 +1166,8 @@ case OP_EndCoroutine: { /* in1 */
|
||||
pCaller = &aOp[pIn1->u.i];
|
||||
assert( pCaller->opcode==OP_Yield );
|
||||
assert( pCaller->p2>=0 && pCaller->p2<p->nOp );
|
||||
pIn1->u.i = (int)(pOp - p->aOp) - 1;
|
||||
pOp = &aOp[pCaller->p2 - 1];
|
||||
pIn1->flags = MEM_Undefined;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1182,7 +1184,7 @@ case OP_EndCoroutine: { /* in1 */
|
||||
**
|
||||
** See also: InitCoroutine
|
||||
*/
|
||||
case OP_Yield: { /* in1, jump */
|
||||
case OP_Yield: { /* in1, jump0 */
|
||||
int pcDest;
|
||||
pIn1 = &aMem[pOp->p1];
|
||||
assert( VdbeMemDynamic(pIn1)==0 );
|
||||
@@ -1512,19 +1514,15 @@ case OP_Blob: { /* out2 */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Opcode: Variable P1 P2 * P4 *
|
||||
** Synopsis: r[P2]=parameter(P1,P4)
|
||||
/* Opcode: Variable P1 P2 * * *
|
||||
** Synopsis: r[P2]=parameter(P1)
|
||||
**
|
||||
** Transfer the values of bound parameter P1 into register P2
|
||||
**
|
||||
** If the parameter is named, then its name appears in P4.
|
||||
** The P4 value is used by sqlite3_bind_parameter_name().
|
||||
*/
|
||||
case OP_Variable: { /* out2 */
|
||||
Mem *pVar; /* Value being transferred */
|
||||
|
||||
assert( pOp->p1>0 && pOp->p1<=p->nVar );
|
||||
assert( pOp->p4.z==0 || pOp->p4.z==sqlite3VListNumToName(p->pVList,pOp->p1) );
|
||||
pVar = &p->aVar[pOp->p1 - 1];
|
||||
if( sqlite3VdbeMemTooBig(pVar) ){
|
||||
goto too_big;
|
||||
@@ -2045,7 +2043,7 @@ case OP_AddImm: { /* in1 */
|
||||
** without data loss, then jump immediately to P2, or if P2==0
|
||||
** raise an SQLITE_MISMATCH exception.
|
||||
*/
|
||||
case OP_MustBeInt: { /* jump, in1 */
|
||||
case OP_MustBeInt: { /* jump0, in1 */
|
||||
pIn1 = &aMem[pOp->p1];
|
||||
if( (pIn1->flags & MEM_Int)==0 ){
|
||||
applyAffinity(pIn1, SQLITE_AFF_NUMERIC, encoding);
|
||||
@@ -4586,7 +4584,8 @@ case OP_SequenceTest: {
|
||||
** is the only cursor opcode that works with a pseudo-table.
|
||||
**
|
||||
** P3 is the number of fields in the records that will be stored by
|
||||
** the pseudo-table.
|
||||
** the pseudo-table. If P2 is 0 or negative then the pseudo-cursor
|
||||
** will return NULL for every column.
|
||||
*/
|
||||
case OP_OpenPseudo: {
|
||||
VdbeCursor *pCx;
|
||||
@@ -4729,10 +4728,10 @@ case OP_ColumnsUsed: {
|
||||
**
|
||||
** See also: Found, NotFound, SeekGt, SeekGe, SeekLt
|
||||
*/
|
||||
case OP_SeekLT: /* jump, in3, group, ncycle */
|
||||
case OP_SeekLE: /* jump, in3, group, ncycle */
|
||||
case OP_SeekGE: /* jump, in3, group, ncycle */
|
||||
case OP_SeekGT: { /* jump, in3, group, ncycle */
|
||||
case OP_SeekLT: /* jump0, in3, group, ncycle */
|
||||
case OP_SeekLE: /* jump0, in3, group, ncycle */
|
||||
case OP_SeekGE: /* jump0, in3, group, ncycle */
|
||||
case OP_SeekGT: { /* jump0, in3, group, ncycle */
|
||||
int res; /* Comparison result */
|
||||
int oc; /* Opcode */
|
||||
VdbeCursor *pC; /* The cursor to seek */
|
||||
@@ -5399,7 +5398,7 @@ case OP_Found: { /* jump, in3, ncycle */
|
||||
**
|
||||
** See also: Found, NotFound, NoConflict, SeekRowid
|
||||
*/
|
||||
case OP_SeekRowid: { /* jump, in3, ncycle */
|
||||
case OP_SeekRowid: { /* jump0, in3, ncycle */
|
||||
VdbeCursor *pC;
|
||||
BtCursor *pCrsr;
|
||||
int res;
|
||||
@@ -6158,7 +6157,7 @@ case OP_NullRow: {
|
||||
** configured to use Prev, not Next.
|
||||
*/
|
||||
case OP_SeekEnd: /* ncycle */
|
||||
case OP_Last: { /* jump, ncycle */
|
||||
case OP_Last: { /* jump0, ncycle */
|
||||
VdbeCursor *pC;
|
||||
BtCursor *pCrsr;
|
||||
int res;
|
||||
@@ -6196,7 +6195,8 @@ case OP_Last: { /* jump, ncycle */
|
||||
**
|
||||
** Let N be the approximate number of rows in the table or index
|
||||
** with cursor P1 and let X be 10*log2(N) if N is positive or -1
|
||||
** if N is zero. Thus X will be within the range of -1 to 640, inclusive
|
||||
** if N is zero.
|
||||
**
|
||||
** Jump to P2 if X is in between P3 and P4, inclusive.
|
||||
*/
|
||||
case OP_IfSizeBetween: { /* jump */
|
||||
@@ -6207,8 +6207,8 @@ case OP_IfSizeBetween: { /* jump */
|
||||
|
||||
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
|
||||
assert( pOp->p4type==P4_INT32 );
|
||||
assert( pOp->p3>=-1 && pOp->p3<=640 );
|
||||
assert( pOp->p4.i>=-1 && pOp->p4.i<=640 );
|
||||
assert( pOp->p3>=-1 && pOp->p3<=640*2 );
|
||||
assert( pOp->p4.i>=-1 && pOp->p4.i<=640*2 );
|
||||
pC = p->apCsr[pOp->p1];
|
||||
assert( pC!=0 );
|
||||
pCrsr = pC->uc.pCursor;
|
||||
@@ -6275,7 +6275,7 @@ case OP_Sort: { /* jump ncycle */
|
||||
** from the beginning toward the end. In other words, the cursor is
|
||||
** configured to use Next, not Prev.
|
||||
*/
|
||||
case OP_Rewind: { /* jump, ncycle */
|
||||
case OP_Rewind: { /* jump0, ncycle */
|
||||
VdbeCursor *pC;
|
||||
BtCursor *pCrsr;
|
||||
int res;
|
||||
@@ -7283,7 +7283,9 @@ case OP_RowSetTest: { /* jump, in1, in3 */
|
||||
** P1 contains the address of the memory cell that contains the first memory
|
||||
** cell in an array of values used as arguments to the sub-program. P2
|
||||
** contains the address to jump to if the sub-program throws an IGNORE
|
||||
** exception using the RAISE() function. Register P3 contains the address
|
||||
** exception using the RAISE() function. P2 might be zero, if there is
|
||||
** no possibility that an IGNORE exception will be raised.
|
||||
** Register P3 contains the address
|
||||
** of a memory cell in this (the parent) VM that is used to allocate the
|
||||
** memory required by the sub-vdbe at runtime.
|
||||
**
|
||||
@@ -7291,7 +7293,7 @@ case OP_RowSetTest: { /* jump, in1, in3 */
|
||||
**
|
||||
** If P5 is non-zero, then recursive program invocation is enabled.
|
||||
*/
|
||||
case OP_Program: { /* jump */
|
||||
case OP_Program: { /* jump0 */
|
||||
int nMem; /* Number of memory registers for sub-program */
|
||||
int nByte; /* Bytes of runtime space required for sub-program */
|
||||
Mem *pRt; /* Register to allocate runtime space */
|
||||
@@ -8840,7 +8842,7 @@ case OP_Filter: { /* jump */
|
||||
** error is encountered.
|
||||
*/
|
||||
case OP_Trace:
|
||||
case OP_Init: { /* jump */
|
||||
case OP_Init: { /* jump0 */
|
||||
int i;
|
||||
#ifndef SQLITE_OMIT_TRACE
|
||||
char *zTrace;
|
||||
|
||||
+2
-1
@@ -2404,7 +2404,6 @@ int sqlite3_stmt_scanstatus_v2(
|
||||
}
|
||||
if( flags & SQLITE_SCANSTAT_COMPLEX ){
|
||||
idx = iScan;
|
||||
pScan = &p->aScan[idx];
|
||||
}else{
|
||||
/* If the COMPLEX flag is clear, then this function must ignore any
|
||||
** ScanStatus structures with ScanStatus.addrLoop set to 0. */
|
||||
@@ -2417,6 +2416,8 @@ int sqlite3_stmt_scanstatus_v2(
|
||||
}
|
||||
}
|
||||
if( idx>=p->nScan ) return 1;
|
||||
assert( pScan==0 || pScan==&p->aScan[idx] );
|
||||
pScan = &p->aScan[idx];
|
||||
|
||||
switch( iScanStatusOp ){
|
||||
case SQLITE_SCANSTAT_NLOOP: {
|
||||
|
||||
@@ -939,6 +939,15 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){
|
||||
assert( aLabel!=0 ); /* True because of tag-20230419-1 */
|
||||
pOp->p2 = aLabel[ADDR(pOp->p2)];
|
||||
}
|
||||
|
||||
/* OPFLG_JUMP opcodes never have P2==0, though OPFLG_JUMP0 opcodes
|
||||
** might */
|
||||
assert( pOp->p2>0
|
||||
|| (sqlite3OpcodeProperty[pOp->opcode] & OPFLG_JUMP0)!=0 );
|
||||
|
||||
/* Jumps never go off the end of the bytecode array */
|
||||
assert( pOp->p2<p->nOp
|
||||
|| (sqlite3OpcodeProperty[pOp->opcode] & OPFLG_JUMP)==0 );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
+4
-4
@@ -1949,10 +1949,10 @@ int sqlite3Stat4Column(
|
||||
sqlite3_value **ppVal /* OUT: Extracted value */
|
||||
){
|
||||
u32 t = 0; /* a column type code */
|
||||
int nHdr; /* Size of the header in the record */
|
||||
int iHdr; /* Next unread header byte */
|
||||
int iField; /* Next unread data byte */
|
||||
int szField = 0; /* Size of the current data field */
|
||||
u32 nHdr; /* Size of the header in the record */
|
||||
u32 iHdr; /* Next unread header byte */
|
||||
i64 iField; /* Next unread data byte */
|
||||
u32 szField = 0; /* Size of the current data field */
|
||||
int i; /* Column index */
|
||||
u8 *a = (u8*)pRec; /* Typecast byte array */
|
||||
Mem *pMem = *ppVal; /* Write result into this Mem object */
|
||||
|
||||
+20
-5
@@ -813,12 +813,27 @@ int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){
|
||||
Table *pTab;
|
||||
Parse sParse;
|
||||
int initBusy;
|
||||
int i;
|
||||
const unsigned char *z;
|
||||
static const u8 aKeyword[] = { TK_CREATE, TK_TABLE, 0 };
|
||||
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( !sqlite3SafetyCheckOk(db) || zCreateTable==0 ){
|
||||
return SQLITE_MISUSE_BKPT;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Verify that the first two keywords in the CREATE TABLE statement
|
||||
** really are "CREATE" and "TABLE". If this is not the case, then
|
||||
** sqlite3_declare_vtab() is being misused.
|
||||
*/
|
||||
z = (const unsigned char*)zCreateTable;
|
||||
for(i=0; aKeyword[i]; i++){
|
||||
int tokenType = 0;
|
||||
do{ z += sqlite3GetToken(z, &tokenType); }while( tokenType==TK_SPACE );
|
||||
if( tokenType!=aKeyword[i] ) return SQLITE_MISUSE_BKPT;
|
||||
}
|
||||
|
||||
sqlite3_mutex_enter(db->mutex);
|
||||
pCtx = db->pVtabCtx;
|
||||
if( !pCtx || pCtx->bDeclared ){
|
||||
@@ -826,6 +841,7 @@ int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){
|
||||
sqlite3_mutex_leave(db->mutex);
|
||||
return SQLITE_MISUSE_BKPT;
|
||||
}
|
||||
|
||||
pTab = pCtx->pTab;
|
||||
assert( IsVirtual(pTab) );
|
||||
|
||||
@@ -839,11 +855,10 @@ int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){
|
||||
initBusy = db->init.busy;
|
||||
db->init.busy = 0;
|
||||
sParse.nQueryLoop = 1;
|
||||
if( SQLITE_OK==sqlite3RunParser(&sParse, zCreateTable)
|
||||
&& ALWAYS(sParse.pNewTable!=0)
|
||||
&& ALWAYS(!db->mallocFailed)
|
||||
&& IsOrdinaryTable(sParse.pNewTable)
|
||||
){
|
||||
if( SQLITE_OK==sqlite3RunParser(&sParse, zCreateTable) ){
|
||||
assert( sParse.pNewTable!=0 );
|
||||
assert( !db->mallocFailed );
|
||||
assert( IsOrdinaryTable(sParse.pNewTable) );
|
||||
assert( sParse.zErrMsg==0 );
|
||||
if( !pTab->aCol ){
|
||||
Table *pNew = sParse.pNewTable;
|
||||
|
||||
+209
-40
@@ -302,6 +302,42 @@ static Expr *whereRightSubexprIsColumn(Expr *p){
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Term pTerm is guaranteed to be a WO_IN term. It may be a component term
|
||||
** of a vector IN expression of the form "(x, y, ...) IN (SELECT ...)".
|
||||
** This function checks to see if the term is compatible with an index
|
||||
** column with affinity idxaff (one of the SQLITE_AFF_XYZ values). If so,
|
||||
** it returns a pointer to the name of the collation sequence (e.g. "BINARY"
|
||||
** or "NOCASE") used by the comparison in pTerm. If it is not compatible
|
||||
** with affinity idxaff, NULL is returned.
|
||||
*/
|
||||
static SQLITE_NOINLINE const char *indexInAffinityOk(
|
||||
Parse *pParse,
|
||||
WhereTerm *pTerm,
|
||||
u8 idxaff
|
||||
){
|
||||
Expr *pX = pTerm->pExpr;
|
||||
Expr inexpr;
|
||||
|
||||
assert( pTerm->eOperator & WO_IN );
|
||||
|
||||
if( sqlite3ExprIsVector(pX->pLeft) ){
|
||||
int iField = pTerm->u.x.iField - 1;
|
||||
inexpr.flags = 0;
|
||||
inexpr.op = TK_EQ;
|
||||
inexpr.pLeft = pX->pLeft->x.pList->a[iField].pExpr;
|
||||
assert( ExprUseXSelect(pX) );
|
||||
inexpr.pRight = pX->x.pSelect->pEList->a[iField].pExpr;
|
||||
pX = &inexpr;
|
||||
}
|
||||
|
||||
if( sqlite3IndexAffinityOk(pX, idxaff) ){
|
||||
CollSeq *pRet = sqlite3ExprCompareCollSeq(pParse, pX);
|
||||
return pRet ? pRet->zName : sqlite3StrBINARY;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Advance to the next WhereTerm that matches according to the criteria
|
||||
** established when the pScan object was initialized by whereScanInit().
|
||||
@@ -352,16 +388,24 @@ static WhereTerm *whereScanNext(WhereScan *pScan){
|
||||
if( (pTerm->eOperator & pScan->opMask)!=0 ){
|
||||
/* Verify the affinity and collating sequence match */
|
||||
if( pScan->zCollName && (pTerm->eOperator & WO_ISNULL)==0 ){
|
||||
CollSeq *pColl;
|
||||
const char *zCollName;
|
||||
Parse *pParse = pWC->pWInfo->pParse;
|
||||
pX = pTerm->pExpr;
|
||||
if( !sqlite3IndexAffinityOk(pX, pScan->idxaff) ){
|
||||
continue;
|
||||
|
||||
if( (pTerm->eOperator & WO_IN) ){
|
||||
zCollName = indexInAffinityOk(pParse, pTerm, pScan->idxaff);
|
||||
if( !zCollName ) continue;
|
||||
}else{
|
||||
CollSeq *pColl;
|
||||
if( !sqlite3IndexAffinityOk(pX, pScan->idxaff) ){
|
||||
continue;
|
||||
}
|
||||
assert(pX->pLeft);
|
||||
pColl = sqlite3ExprCompareCollSeq(pParse, pX);
|
||||
zCollName = pColl ? pColl->zName : sqlite3StrBINARY;
|
||||
}
|
||||
assert(pX->pLeft);
|
||||
pColl = sqlite3ExprCompareCollSeq(pParse, pX);
|
||||
if( pColl==0 ) pColl = pParse->db->pDfltColl;
|
||||
if( sqlite3StrICmp(pColl->zName, pScan->zCollName) ){
|
||||
|
||||
if( sqlite3StrICmp(zCollName, pScan->zCollName) ){
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -713,9 +757,13 @@ static void translateColumnToCopy(
|
||||
** are no-ops.
|
||||
*/
|
||||
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(WHERETRACE_ENABLED)
|
||||
static void whereTraceIndexInfoInputs(sqlite3_index_info *p){
|
||||
static void whereTraceIndexInfoInputs(
|
||||
sqlite3_index_info *p, /* The IndexInfo object */
|
||||
Table *pTab /* The TABLE that is the virtual table */
|
||||
){
|
||||
int i;
|
||||
if( (sqlite3WhereTrace & 0x10)==0 ) return;
|
||||
sqlite3DebugPrintf("sqlite3_index_info inputs for %s:\n", pTab->zName);
|
||||
for(i=0; i<p->nConstraint; i++){
|
||||
sqlite3DebugPrintf(
|
||||
" constraint[%d]: col=%d termid=%d op=%d usabled=%d collseq=%s\n",
|
||||
@@ -733,9 +781,13 @@ static void whereTraceIndexInfoInputs(sqlite3_index_info *p){
|
||||
p->aOrderBy[i].desc);
|
||||
}
|
||||
}
|
||||
static void whereTraceIndexInfoOutputs(sqlite3_index_info *p){
|
||||
static void whereTraceIndexInfoOutputs(
|
||||
sqlite3_index_info *p, /* The IndexInfo object */
|
||||
Table *pTab /* The TABLE that is the virtual table */
|
||||
){
|
||||
int i;
|
||||
if( (sqlite3WhereTrace & 0x10)==0 ) return;
|
||||
sqlite3DebugPrintf("sqlite3_index_info outputs for %s:\n", pTab->zName);
|
||||
for(i=0; i<p->nConstraint; i++){
|
||||
sqlite3DebugPrintf(" usage[%d]: argvIdx=%d omit=%d\n",
|
||||
i,
|
||||
@@ -749,8 +801,8 @@ static void whereTraceIndexInfoOutputs(sqlite3_index_info *p){
|
||||
sqlite3DebugPrintf(" estimatedRows=%lld\n", p->estimatedRows);
|
||||
}
|
||||
#else
|
||||
#define whereTraceIndexInfoInputs(A)
|
||||
#define whereTraceIndexInfoOutputs(A)
|
||||
#define whereTraceIndexInfoInputs(A,B)
|
||||
#define whereTraceIndexInfoOutputs(A,B)
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -934,7 +986,7 @@ static SQLITE_NOINLINE void constructAutomaticIndex(
|
||||
** WHERE clause (or the ON clause of a LEFT join) that constrain which
|
||||
** rows of the target table (pSrc) that can be used. */
|
||||
if( (pTerm->wtFlags & TERM_VIRTUAL)==0
|
||||
&& sqlite3ExprIsSingleTableConstraint(pExpr, pTabList, pLevel->iFrom)
|
||||
&& sqlite3ExprIsSingleTableConstraint(pExpr, pTabList, pLevel->iFrom, 0)
|
||||
){
|
||||
pPartial = sqlite3ExprAnd(pParse, pPartial,
|
||||
sqlite3ExprDup(pParse->db, pExpr, 0));
|
||||
@@ -976,7 +1028,7 @@ static SQLITE_NOINLINE void constructAutomaticIndex(
|
||||
** if they go out of sync.
|
||||
*/
|
||||
if( IsView(pTable) ){
|
||||
extraCols = ALLBITS;
|
||||
extraCols = ALLBITS & ~idxCols;
|
||||
}else{
|
||||
extraCols = pSrc->colUsed & (~idxCols | MASKBIT(BMS-1));
|
||||
}
|
||||
@@ -1203,7 +1255,7 @@ static SQLITE_NOINLINE void sqlite3ConstructBloomFilter(
|
||||
for(pTerm=pWInfo->sWC.a; pTerm<pWCEnd; pTerm++){
|
||||
Expr *pExpr = pTerm->pExpr;
|
||||
if( (pTerm->wtFlags & TERM_VIRTUAL)==0
|
||||
&& sqlite3ExprIsSingleTableConstraint(pExpr, pTabList, iSrc)
|
||||
&& sqlite3ExprIsSingleTableConstraint(pExpr, pTabList, iSrc, 0)
|
||||
){
|
||||
sqlite3ExprIfFalse(pParse, pTerm->pExpr, addrCont, SQLITE_JUMPIFNULL);
|
||||
}
|
||||
@@ -1329,7 +1381,7 @@ static sqlite3_index_info *allocateIndexInfo(
|
||||
Expr *pE2;
|
||||
|
||||
/* Skip over constant terms in the ORDER BY clause */
|
||||
if( sqlite3ExprIsConstant(pExpr) ){
|
||||
if( sqlite3ExprIsConstant(0, pExpr) ){
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1441,7 +1493,7 @@ static sqlite3_index_info *allocateIndexInfo(
|
||||
pIdxInfo->nConstraint = j;
|
||||
for(i=j=0; i<nOrderBy; i++){
|
||||
Expr *pExpr = pOrderBy->a[i].pExpr;
|
||||
if( sqlite3ExprIsConstant(pExpr) ) continue;
|
||||
if( sqlite3ExprIsConstant(0, pExpr) ) continue;
|
||||
assert( pExpr->op==TK_COLUMN
|
||||
|| (pExpr->op==TK_COLLATE && pExpr->pLeft->op==TK_COLUMN
|
||||
&& pExpr->iColumn==pExpr->pLeft->iColumn) );
|
||||
@@ -1493,11 +1545,11 @@ static int vtabBestIndex(Parse *pParse, Table *pTab, sqlite3_index_info *p){
|
||||
sqlite3_vtab *pVtab = sqlite3GetVTable(pParse->db, pTab)->pVtab;
|
||||
int rc;
|
||||
|
||||
whereTraceIndexInfoInputs(p);
|
||||
whereTraceIndexInfoInputs(p, pTab);
|
||||
pParse->db->nSchemaLock++;
|
||||
rc = pVtab->pModule->xBestIndex(pVtab, p);
|
||||
pParse->db->nSchemaLock--;
|
||||
whereTraceIndexInfoOutputs(p);
|
||||
whereTraceIndexInfoOutputs(p, pTab);
|
||||
|
||||
if( rc!=SQLITE_OK && rc!=SQLITE_CONSTRAINT ){
|
||||
if( rc==SQLITE_NOMEM ){
|
||||
@@ -3244,10 +3296,13 @@ static int whereLoopAddBtreeIndex(
|
||||
}
|
||||
}
|
||||
|
||||
/* Set rCostIdx to the cost of visiting selected rows in index. Add
|
||||
** it to pNew->rRun, which is currently set to the cost of the index
|
||||
** seek only. Then, if this is a non-covering index, add the cost of
|
||||
** visiting the rows in the main table. */
|
||||
/* Set rCostIdx to the estimated cost of visiting selected rows in the
|
||||
** index. The estimate is the sum of two values:
|
||||
** 1. The cost of doing one search-by-key to find the first matching
|
||||
** entry
|
||||
** 2. Stepping forward in the index pNew->nOut times to find all
|
||||
** additional matching entries.
|
||||
*/
|
||||
assert( pSrc->pTab->szTabRow>0 );
|
||||
if( pProbe->idxType==SQLITE_IDXTYPE_IPK ){
|
||||
/* The pProbe->szIdxRow is low for an IPK table since the interior
|
||||
@@ -3258,7 +3313,15 @@ static int whereLoopAddBtreeIndex(
|
||||
}else{
|
||||
rCostIdx = pNew->nOut + 1 + (15*pProbe->szIdxRow)/pSrc->pTab->szTabRow;
|
||||
}
|
||||
pNew->rRun = sqlite3LogEstAdd(rLogSize, rCostIdx);
|
||||
rCostIdx = sqlite3LogEstAdd(rLogSize, rCostIdx);
|
||||
|
||||
/* Estimate the cost of running the loop. If all data is coming
|
||||
** from the index, then this is just the cost of doing the index
|
||||
** lookup and scan. But if some data is coming out of the main table,
|
||||
** we also have to add in the cost of doing pNew->nOut searches to
|
||||
** locate the row in the main table that corresponds to the index entry.
|
||||
*/
|
||||
pNew->rRun = rCostIdx;
|
||||
if( (pNew->wsFlags & (WHERE_IDX_ONLY|WHERE_IPK|WHERE_EXPRIDX))==0 ){
|
||||
pNew->rRun = sqlite3LogEstAdd(pNew->rRun, pNew->nOut + 16);
|
||||
}
|
||||
@@ -3623,7 +3686,7 @@ static void wherePartIdxExpr(
|
||||
u8 aff;
|
||||
|
||||
if( pLeft->op!=TK_COLUMN ) return;
|
||||
if( !sqlite3ExprIsConstant(pRight) ) return;
|
||||
if( !sqlite3ExprIsConstant(0, pRight) ) return;
|
||||
if( !sqlite3IsBinary(sqlite3ExprCompareCollSeq(pParse, pPart)) ) return;
|
||||
if( pLeft->iColumn<0 ) return;
|
||||
aff = pIdx->pTable->aCol[pLeft->iColumn].affinity;
|
||||
@@ -3994,6 +4057,21 @@ static int isLimitTerm(WhereTerm *pTerm){
|
||||
&& pTerm->eMatchOp<=SQLITE_INDEX_CONSTRAINT_OFFSET;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return true if the first nCons constraints in the pUsage array are
|
||||
** marked as in-use (have argvIndex>0). False otherwise.
|
||||
*/
|
||||
static int allConstraintsUsed(
|
||||
struct sqlite3_index_constraint_usage *aUsage,
|
||||
int nCons
|
||||
){
|
||||
int ii;
|
||||
for(ii=0; ii<nCons; ii++){
|
||||
if( aUsage[ii].argvIndex<=0 ) return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
** Argument pIdxInfo is already populated with all constraints that may
|
||||
** be used by the virtual table identified by pBuilder->pNew->iTab. This
|
||||
@@ -4134,13 +4212,20 @@ static int whereLoopAddVirtualOne(
|
||||
*pbIn = 1; assert( (mExclude & WO_IN)==0 );
|
||||
}
|
||||
|
||||
/* Unless pbRetryLimit is non-NULL, there should be no LIMIT/OFFSET
|
||||
** terms. And if there are any, they should follow all other terms. */
|
||||
assert( pbRetryLimit || !isLimitTerm(pTerm) );
|
||||
if( isLimitTerm(pTerm) && *pbIn ){
|
||||
assert( !isLimitTerm(pTerm) || i>=nConstraint-2 );
|
||||
assert( !isLimitTerm(pTerm) || i==nConstraint-1 || isLimitTerm(pTerm+1) );
|
||||
|
||||
if( isLimitTerm(pTerm) && (*pbIn || !allConstraintsUsed(pUsage, i)) ){
|
||||
/* If there is an IN(...) term handled as an == (separate call to
|
||||
** xFilter for each value on the RHS of the IN) and a LIMIT or
|
||||
** OFFSET term handled as well, the plan is unusable. Set output
|
||||
** variable *pbRetryLimit to true to tell the caller to retry with
|
||||
** LIMIT and OFFSET disabled. */
|
||||
** OFFSET term handled as well, the plan is unusable. Similarly,
|
||||
** if there is a LIMIT/OFFSET and there are other unused terms,
|
||||
** the plan cannot be used. In these cases set variable *pbRetryLimit
|
||||
** to true to tell the caller to retry with LIMIT and OFFSET
|
||||
** disabled. */
|
||||
if( pIdxInfo->needToFreeIdxStr ){
|
||||
sqlite3_free(pIdxInfo->idxStr);
|
||||
pIdxInfo->idxStr = 0;
|
||||
@@ -4997,7 +5082,7 @@ static i8 wherePathSatisfiesOrderBy(
|
||||
if( MASKBIT(i) & obSat ) continue;
|
||||
p = pOrderBy->a[i].pExpr;
|
||||
mTerm = sqlite3WhereExprUsage(&pWInfo->sMaskSet,p);
|
||||
if( mTerm==0 && !sqlite3ExprIsConstant(p) ) continue;
|
||||
if( mTerm==0 && !sqlite3ExprIsConstant(0,p) ) continue;
|
||||
if( (mTerm&~orderDistinctMask)==0 ){
|
||||
obSat |= MASKBIT(i);
|
||||
}
|
||||
@@ -5511,7 +5596,6 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pWInfo->nRowOut = pFrom->nRow;
|
||||
|
||||
/* Free temporary memory and return success */
|
||||
@@ -5519,6 +5603,83 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** This routine implements a heuristic designed to improve query planning.
|
||||
** This routine is called in between the first and second call to
|
||||
** wherePathSolver(). Hence the name "Interstage" "Heuristic".
|
||||
**
|
||||
** The first call to wherePathSolver() (hereafter just "solver()") computes
|
||||
** the best path without regard to the order of the outputs. The second call
|
||||
** to the solver() builds upon the first call to try to find an alternative
|
||||
** path that satisfies the ORDER BY clause.
|
||||
**
|
||||
** This routine looks at the results of the first solver() run, and for
|
||||
** every FROM clause term in the resulting query plan that uses an equality
|
||||
** constraint against an index, disable other WhereLoops for that same
|
||||
** FROM clause term that would try to do a full-table scan. This prevents
|
||||
** an index search from being converted into a full-table scan in order to
|
||||
** satisfy an ORDER BY clause, since even though we might get slightly better
|
||||
** performance using the full-scan without sorting if the output size
|
||||
** estimates are very precise, we might also get severe performance
|
||||
** degradation using the full-scan if the output size estimate is too large.
|
||||
** It is better to err on the side of caution.
|
||||
**
|
||||
** Except, if the first solver() call generated a full-table scan in an outer
|
||||
** loop then stop this analysis at the first full-scan, since the second
|
||||
** solver() run might try to swap that full-scan for another in order to
|
||||
** get the output into the correct order. In other words, we allow a
|
||||
** rewrite like this:
|
||||
**
|
||||
** First Solver() Second Solver()
|
||||
** |-- SCAN t1 |-- SCAN t2
|
||||
** |-- SEARCH t2 `-- SEARCH t1
|
||||
** `-- SORT USING B-TREE
|
||||
**
|
||||
** The purpose of this routine is to disallow rewrites such as:
|
||||
**
|
||||
** First Solver() Second Solver()
|
||||
** |-- SEARCH t1 |-- SCAN t2 <--- bad!
|
||||
** |-- SEARCH t2 `-- SEARCH t1
|
||||
** `-- SORT USING B-TREE
|
||||
**
|
||||
** See test cases in test/whereN.test for the real-world query that
|
||||
** originally provoked this heuristic.
|
||||
*/
|
||||
static SQLITE_NOINLINE void whereInterstageHeuristic(WhereInfo *pWInfo){
|
||||
int i;
|
||||
#ifdef WHERETRACE_ENABLED
|
||||
int once = 0;
|
||||
#endif
|
||||
for(i=0; i<pWInfo->nLevel; i++){
|
||||
WhereLoop *p = pWInfo->a[i].pWLoop;
|
||||
if( p==0 ) break;
|
||||
if( (p->wsFlags & WHERE_VIRTUALTABLE)!=0 ) continue;
|
||||
if( (p->wsFlags & (WHERE_COLUMN_EQ|WHERE_COLUMN_NULL|WHERE_COLUMN_IN))!=0 ){
|
||||
u8 iTab = p->iTab;
|
||||
WhereLoop *pLoop;
|
||||
for(pLoop=pWInfo->pLoops; pLoop; pLoop=pLoop->pNextLoop){
|
||||
if( pLoop->iTab!=iTab ) continue;
|
||||
if( (pLoop->wsFlags & (WHERE_CONSTRAINT|WHERE_AUTO_INDEX))!=0 ){
|
||||
/* Auto-index and index-constrained loops allowed to remain */
|
||||
continue;
|
||||
}
|
||||
#ifdef WHERETRACE_ENABLED
|
||||
if( sqlite3WhereTrace & 0x80 ){
|
||||
if( once==0 ){
|
||||
sqlite3DebugPrintf("Loops disabled by interstage heuristic:\n");
|
||||
once = 1;
|
||||
}
|
||||
sqlite3WhereLoopPrint(pLoop, &pWInfo->sWC);
|
||||
}
|
||||
#endif /* WHERETRACE_ENABLED */
|
||||
pLoop->prereq = ALLBITS; /* Prevent 2nd solver() from using this one */
|
||||
}
|
||||
}else{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Most queries use only a single table (they are not joins) and have
|
||||
** simple == constraints against indexed fields. This routine attempts
|
||||
@@ -5853,20 +6014,14 @@ static SQLITE_NOINLINE void whereAddIndexedExpr(
|
||||
for(i=0; i<pIdx->nColumn; i++){
|
||||
Expr *pExpr;
|
||||
int j = pIdx->aiColumn[i];
|
||||
int bMaybeNullRow;
|
||||
if( j==XN_EXPR ){
|
||||
pExpr = pIdx->aColExpr->a[i].pExpr;
|
||||
testcase( pTabItem->fg.jointype & JT_LEFT );
|
||||
testcase( pTabItem->fg.jointype & JT_RIGHT );
|
||||
testcase( pTabItem->fg.jointype & JT_LTORJ );
|
||||
bMaybeNullRow = (pTabItem->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))!=0;
|
||||
}else if( j>=0 && (pTab->aCol[j].colFlags & COLFLAG_VIRTUAL)!=0 ){
|
||||
pExpr = sqlite3ColumnExpr(pTab, &pTab->aCol[j]);
|
||||
bMaybeNullRow = 0;
|
||||
}else{
|
||||
continue;
|
||||
}
|
||||
if( sqlite3ExprIsConstant(pExpr) ) continue;
|
||||
if( sqlite3ExprIsConstant(0,pExpr) ) continue;
|
||||
if( pExpr->op==TK_FUNCTION ){
|
||||
/* Functions that might set a subtype should not be replaced by the
|
||||
** value taken from an expression index since the index omits the
|
||||
@@ -5894,7 +6049,7 @@ static SQLITE_NOINLINE void whereAddIndexedExpr(
|
||||
p->iDataCur = pTabItem->iCursor;
|
||||
p->iIdxCur = iIdxCur;
|
||||
p->iIdxCol = i;
|
||||
p->bMaybeNullRow = bMaybeNullRow;
|
||||
p->bMaybeNullRow = (pTabItem->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))!=0;
|
||||
if( sqlite3IndexAffinityStr(pParse->db, pIdx) ){
|
||||
p->aff = pIdx->zColAff[i];
|
||||
}
|
||||
@@ -6144,7 +6299,11 @@ WhereInfo *sqlite3WhereBegin(
|
||||
){
|
||||
pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE;
|
||||
}
|
||||
ExplainQueryPlan((pParse, 0, "SCAN CONSTANT ROW"));
|
||||
if( ALWAYS(pWInfo->pSelect)
|
||||
&& (pWInfo->pSelect->selFlags & SF_MultiValue)==0
|
||||
){
|
||||
ExplainQueryPlan((pParse, 0, "SCAN CONSTANT ROW"));
|
||||
}
|
||||
}else{
|
||||
/* Assign a bit from the bitmask to every term in the FROM clause.
|
||||
**
|
||||
@@ -6297,6 +6456,7 @@ WhereInfo *sqlite3WhereBegin(
|
||||
wherePathSolver(pWInfo, 0);
|
||||
if( db->mallocFailed ) goto whereBeginError;
|
||||
if( pWInfo->pOrderBy ){
|
||||
whereInterstageHeuristic(pWInfo);
|
||||
wherePathSolver(pWInfo, pWInfo->nRowOut+1);
|
||||
if( db->mallocFailed ) goto whereBeginError;
|
||||
}
|
||||
@@ -6846,7 +7006,15 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
|
||||
addr = sqlite3VdbeAddOp1(v, OP_IfPos, pLevel->iLeftJoin); VdbeCoverage(v);
|
||||
assert( (ws & WHERE_IDX_ONLY)==0 || (ws & WHERE_INDEXED)!=0 );
|
||||
if( (ws & WHERE_IDX_ONLY)==0 ){
|
||||
assert( pLevel->iTabCur==pTabList->a[pLevel->iFrom].iCursor );
|
||||
SrcItem *pSrc = &pTabList->a[pLevel->iFrom];
|
||||
assert( pLevel->iTabCur==pSrc->iCursor );
|
||||
if( pSrc->fg.viaCoroutine ){
|
||||
int m, n;
|
||||
n = pSrc->regResult;
|
||||
assert( pSrc->pTab!=0 );
|
||||
m = pSrc->pTab->nCol;
|
||||
sqlite3VdbeAddOp3(v, OP_Null, 0, n, n+m-1);
|
||||
}
|
||||
sqlite3VdbeAddOp1(v, OP_NullRow, pLevel->iTabCur);
|
||||
}
|
||||
if( (ws & WHERE_INDEXED)
|
||||
@@ -6896,6 +7064,7 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
|
||||
*/
|
||||
if( pTabItem->fg.viaCoroutine ){
|
||||
testcase( pParse->db->mallocFailed );
|
||||
assert( pTabItem->regResult>=0 );
|
||||
translateColumnToCopy(pParse, pLevel->addrBody, pLevel->iTabCur,
|
||||
pTabItem->regResult, 0);
|
||||
continue;
|
||||
|
||||
@@ -2474,6 +2474,12 @@ Bitmask sqlite3WhereCodeOneLoopStart(
|
||||
** iLoop==3: Code all remaining expressions.
|
||||
**
|
||||
** An effort is made to skip unnecessary iterations of the loop.
|
||||
**
|
||||
** This optimization of causing simple query restrictions to occur before
|
||||
** more complex one is call the "push-down" optimization in MySQL. Here
|
||||
** in SQLite, the name is "MySQL push-down", since there is also another
|
||||
** totally unrelated optimization called "WHERE-clause push-down".
|
||||
** Sometimes the qualifier is omitted, resulting in an ambiguity, so beware.
|
||||
*/
|
||||
iLoop = (pIdx ? 1 : 2);
|
||||
do{
|
||||
@@ -2724,7 +2730,16 @@ SQLITE_NOINLINE void sqlite3WhereRightJoinLoop(
|
||||
pRJ->regReturn);
|
||||
for(k=0; k<iLevel; k++){
|
||||
int iIdxCur;
|
||||
SrcItem *pRight;
|
||||
assert( pWInfo->a[k].pWLoop->iTab == pWInfo->a[k].iFrom );
|
||||
pRight = &pWInfo->pTabList->a[pWInfo->a[k].iFrom];
|
||||
mAll |= pWInfo->a[k].pWLoop->maskSelf;
|
||||
if( pRight->fg.viaCoroutine ){
|
||||
sqlite3VdbeAddOp3(
|
||||
v, OP_Null, 0, pRight->regResult,
|
||||
pRight->regResult + pRight->pSelect->pEList->nExpr-1
|
||||
);
|
||||
}
|
||||
sqlite3VdbeAddOp1(v, OP_NullRow, pWInfo->a[k].iTabCur);
|
||||
iIdxCur = pWInfo->a[k].iIdxCur;
|
||||
if( iIdxCur ){
|
||||
|
||||
+7
-4
@@ -989,7 +989,7 @@ static SQLITE_NOINLINE int exprMightBeIndexed2(
|
||||
if( pIdx->aiColumn[i]!=XN_EXPR ) continue;
|
||||
assert( pIdx->bHasExpr );
|
||||
if( sqlite3ExprCompareSkip(pExpr,pIdx->aColExpr->a[i].pExpr,iCur)==0
|
||||
&& pExpr->op!=TK_STRING
|
||||
&& !sqlite3ExprIsConstant(0,pIdx->aColExpr->a[i].pExpr)
|
||||
){
|
||||
aiCurCol[0] = iCur;
|
||||
aiCurCol[1] = XN_EXPR;
|
||||
@@ -1638,6 +1638,7 @@ void SQLITE_NOINLINE sqlite3WhereAddLimit(WhereClause *pWC, Select *p){
|
||||
continue;
|
||||
}
|
||||
if( pWC->a[ii].leftCursor!=iCsr ) return;
|
||||
if( pWC->a[ii].prereqRight!=0 ) return;
|
||||
}
|
||||
|
||||
/* Check condition (5). Return early if it is not met. */
|
||||
@@ -1652,12 +1653,14 @@ void SQLITE_NOINLINE sqlite3WhereAddLimit(WhereClause *pWC, Select *p){
|
||||
|
||||
/* All conditions are met. Add the terms to the where-clause object. */
|
||||
assert( p->pLimit->op==TK_LIMIT );
|
||||
whereAddLimitExpr(pWC, p->iLimit, p->pLimit->pLeft,
|
||||
iCsr, SQLITE_INDEX_CONSTRAINT_LIMIT);
|
||||
if( p->iOffset>0 ){
|
||||
if( p->iOffset!=0 && (p->selFlags & SF_Compound)==0 ){
|
||||
whereAddLimitExpr(pWC, p->iOffset, p->pLimit->pRight,
|
||||
iCsr, SQLITE_INDEX_CONSTRAINT_OFFSET);
|
||||
}
|
||||
if( p->iOffset==0 || (p->selFlags & SF_Compound)==0 ){
|
||||
whereAddLimitExpr(pWC, p->iLimit, p->pLimit->pLeft,
|
||||
iCsr, SQLITE_INDEX_CONSTRAINT_LIMIT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -1164,7 +1164,7 @@ void sqlite3WindowListDelete(sqlite3 *db, Window *p){
|
||||
** variable values in the expression tree.
|
||||
*/
|
||||
static Expr *sqlite3WindowOffsetExpr(Parse *pParse, Expr *pExpr){
|
||||
if( 0==sqlite3ExprIsConstant(pExpr) ){
|
||||
if( 0==sqlite3ExprIsConstant(0,pExpr) ){
|
||||
if( IN_RENAME_OBJECT ) sqlite3RenameExprUnmap(pParse, pExpr);
|
||||
sqlite3ExprDelete(pParse->db, pExpr);
|
||||
pExpr = sqlite3ExprAlloc(pParse->db, TK_NULL, 0, 0);
|
||||
|
||||
+12
-6
@@ -117,7 +117,8 @@ do_test aggnested-3.0 {
|
||||
#
|
||||
do_test aggnested-3.1 {
|
||||
db eval {
|
||||
DROP TABLE IF EXISTS t1, t2;
|
||||
DROP TABLE IF EXISTS t1;
|
||||
DROP TABLE IF EXISTS t2;
|
||||
CREATE TABLE t1 (
|
||||
id1 INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
value1 INTEGER
|
||||
@@ -149,7 +150,8 @@ do_test aggnested-3.1-rj {
|
||||
|
||||
do_test aggnested-3.2 {
|
||||
db eval {
|
||||
DROP TABLE IF EXISTS t1, t2;
|
||||
DROP TABLE IF EXISTS t1;
|
||||
DROP TABLE IF EXISTS t2;
|
||||
CREATE TABLE t1 (
|
||||
id1 INTEGER,
|
||||
value1 INTEGER,
|
||||
@@ -176,7 +178,8 @@ do_test aggnested-3.2 {
|
||||
} {1 0}
|
||||
do_test aggnested-3.3 {
|
||||
db eval {
|
||||
DROP TABLE IF EXISTS t1, t2;
|
||||
DROP TABLE IF EXISTS t1;
|
||||
DROP TABLE IF EXISTS t2;
|
||||
CREATE TABLE t1(id1, value1);
|
||||
INSERT INTO t1 VALUES(4469,2),(4469,1);
|
||||
CREATE TABLE t2 (value2);
|
||||
@@ -246,7 +249,8 @@ do_test aggnested-3.16 {
|
||||
# Problem found by dbsqlfuzz
|
||||
#
|
||||
do_execsql_test aggnested-4.1 {
|
||||
DROP TABLE IF EXISTS aa, bb;
|
||||
DROP TABLE IF EXISTS aa;
|
||||
DROP TABLE IF EXISTS bb;
|
||||
CREATE TABLE aa(x INT); INSERT INTO aa(x) VALUES(123);
|
||||
CREATE TABLE bb(y INT); INSERT INTO bb(y) VALUES(456);
|
||||
SELECT (SELECT sum(x+(SELECT y)) FROM bb) FROM aa;
|
||||
@@ -255,7 +259,8 @@ do_execsql_test aggnested-4.2 {
|
||||
SELECT (SELECT sum(x+y) FROM bb) FROM aa;
|
||||
} {579}
|
||||
do_execsql_test aggnested-4.3 {
|
||||
DROP TABLE IF EXISTS tx, ty;
|
||||
DROP TABLE IF EXISTS tx;
|
||||
DROP TABLE IF EXISTS ty;
|
||||
CREATE TABLE tx(x INT);
|
||||
INSERT INTO tx VALUES(1),(2),(3),(4),(5);
|
||||
CREATE TABLE ty(y INT);
|
||||
@@ -472,7 +477,8 @@ do_execsql_test 9.5 {
|
||||
# https://bugs.chromium.org/p/chromium/issues/detail?id=1511689
|
||||
#
|
||||
do_execsql_test 10.1 {
|
||||
DROP TABLE IF EXISTS t0, t1;
|
||||
DROP TABLE IF EXISTS t0;
|
||||
DROP TABLE IF EXISTS t1;
|
||||
CREATE TABLE t0(c1, c2); INSERT INTO t0 VALUES(1,2);
|
||||
CREATE TABLE t1(c3, c4); INSERT INTO t1 VALUES(3,4);
|
||||
SELECT * FROM t0 WHERE EXISTS (SELECT 1 FROM t1 GROUP BY c3 HAVING ( SELECT count(*) FROM (SELECT 1 UNION ALL SELECT sum(DISTINCT c1) ) ) ) BETWEEN 1 AND 1;
|
||||
|
||||
@@ -60,7 +60,8 @@ do_execsql_test aggorderby-4.1 {
|
||||
|
||||
|
||||
do_execsql_test aggorderby-5.0 {
|
||||
DROP TABLE IF EXISTS t1, t3;
|
||||
DROP TABLE IF EXISTS t1;
|
||||
DROP TABLE IF EXISTS t3;
|
||||
CREATE TABLE t1(a TEXT); INSERT INTO t1 VALUES('aaa'),('bbb');
|
||||
CREATE TABLE t3(d TEXT); INSERT INTO t3 VALUES('/'),('-');
|
||||
SELECT (SELECT string_agg(a,d) FROM t3) FROM t1;
|
||||
|
||||
+5
-2
@@ -105,7 +105,9 @@ do_test alter3-1.99 {
|
||||
DROP TABLE t2;
|
||||
}
|
||||
execsql {
|
||||
DROP TABLE abc, t1, t3;
|
||||
DROP TABLE abc;
|
||||
DROP TABLE t1;
|
||||
DROP TABLE t3;
|
||||
}
|
||||
} {}
|
||||
|
||||
@@ -294,7 +296,8 @@ ifcapable attach {
|
||||
} {1 one 2 two}
|
||||
do_test alter3-5.99 {
|
||||
execsql {
|
||||
DROP TABLE aux.t1, main.t1;
|
||||
DROP TABLE aux.t1;
|
||||
DROP TABLE t1;
|
||||
}
|
||||
} {}
|
||||
}
|
||||
|
||||
+3
-1
@@ -114,7 +114,9 @@ do_test alter4-1.99 {
|
||||
DROP TABLE t2;
|
||||
}
|
||||
execsql {
|
||||
DROP TABLE abc, t1, t3;
|
||||
DROP TABLE abc;
|
||||
DROP TABLE t1;
|
||||
DROP TABLE t3;
|
||||
}
|
||||
} {}
|
||||
|
||||
|
||||
@@ -736,4 +736,54 @@ do_execsql_test 29.7 {
|
||||
END}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_execsql_test 30.0 {
|
||||
CREATE TABLE t1(a, b);
|
||||
CREATE VIEW v1 AS
|
||||
SELECT ( VALUES(a), (b) ) FROM (
|
||||
SELECT a, b FROM t1
|
||||
)
|
||||
;
|
||||
}
|
||||
|
||||
do_execsql_test 30.1 {
|
||||
SELECT * FROM v1
|
||||
}
|
||||
|
||||
do_execsql_test 30.1 {
|
||||
ALTER TABLE t1 RENAME TO t2;
|
||||
}
|
||||
do_execsql_test 30.2 {
|
||||
SELECT sql FROM sqlite_schema WHERE type='view'
|
||||
} {
|
||||
{CREATE VIEW v1 AS
|
||||
SELECT ( VALUES(a), (b) ) FROM (
|
||||
SELECT a, b FROM "t2"
|
||||
)}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_execsql_test 31.0 {
|
||||
CREATE TABLE t1(ii INTEGER PRIMARY KEY, tt INTEGER, rr REAL);
|
||||
WITH s(i) AS (
|
||||
SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<50000
|
||||
)
|
||||
INSERT INTO t1 SELECT NULL, i, 5.0 FROM s;
|
||||
}
|
||||
|
||||
do_test 31.1 {
|
||||
set pg [db one {PRAGMA page_count}]
|
||||
execsql {
|
||||
ALTER TABLE t1 DROP COLUMN tt;
|
||||
}
|
||||
set pg2 [db one {PRAGMA page_count}]
|
||||
expr $pg==$pg2
|
||||
} {1}
|
||||
|
||||
do_execsql_test 31.2 {
|
||||
SELECT rr FROM t1 LIMIT 1
|
||||
} {5.0}
|
||||
|
||||
finish_test
|
||||
|
||||
+2
-1
@@ -195,7 +195,8 @@ do_test analyze-3.8 {
|
||||
CREATE INDEX t3i1 ON t3(a);
|
||||
CREATE INDEX t3i2 ON t3(a,b,c,d);
|
||||
CREATE INDEX t3i3 ON t3(d,b,c,a);
|
||||
DROP TABLE t1, t2;
|
||||
DROP TABLE t1;
|
||||
DROP TABLE t2;
|
||||
SELECT idx, stat FROM sqlite_stat1 ORDER BY idx;
|
||||
}
|
||||
} {}
|
||||
|
||||
+5
-5
@@ -216,7 +216,7 @@ do_test auth-1.21.1 {
|
||||
}
|
||||
return SQLITE_OK
|
||||
}
|
||||
catchsql {DROP TABLE IF EXISTS none1, none2, t2, none3}
|
||||
catchsql {DROP TABLE t2}
|
||||
} {1 {not authorized}}
|
||||
do_test auth-1.21.2 {
|
||||
set ::authargs
|
||||
@@ -483,7 +483,7 @@ do_test auth-1.63 {
|
||||
}
|
||||
return SQLITE_OK
|
||||
}
|
||||
catchsql {DROP TABLE IF EXISTS none1, t2, none2}
|
||||
catchsql {DROP TABLE t2}
|
||||
} {1 {not authorized}}
|
||||
do_test auth-1.64 {
|
||||
execsql {SELECT name FROM sqlite_master}
|
||||
@@ -726,7 +726,7 @@ do_test auth-1.101 {
|
||||
}
|
||||
return SQLITE_OK
|
||||
}
|
||||
catchsql {DROP VIEW IF EXISTS none1, v2, none2}
|
||||
catchsql {DROP VIEW v2}
|
||||
} {1 {not authorized}}
|
||||
do_test auth-1.102 {
|
||||
set ::authargs
|
||||
@@ -1090,7 +1090,7 @@ do_test auth-1.153 {
|
||||
}
|
||||
return SQLITE_OK
|
||||
}
|
||||
catchsql {DROP TRIGGER IF EXISTS none1, r2, none2}
|
||||
catchsql {DROP TRIGGER r2}
|
||||
} {1 {not authorized}}
|
||||
do_test auth-1.154 {
|
||||
set ::authargs
|
||||
@@ -1389,7 +1389,7 @@ do_test auth-1.205 {
|
||||
}
|
||||
return SQLITE_OK
|
||||
}
|
||||
catchsql {DROP INDEX IF EXISTS none1, i2, none2}
|
||||
catchsql {DROP INDEX i2}
|
||||
} {1 {not authorized}}
|
||||
do_test auth-1.205a {
|
||||
set ::authargs
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
# TESTRUNNER: shell
|
||||
#
|
||||
# This file implements tests for the appendvfs extension.
|
||||
#
|
||||
|
||||
@@ -158,7 +158,7 @@ do_test 2.2 {
|
||||
set ::lFilterArgs [list]
|
||||
execsql { SELECT * FROM vt1 LIMIT 5 OFFSET 50 }
|
||||
set ::lFilterArgs
|
||||
} {{5 50}}
|
||||
} {{50 5}}
|
||||
|
||||
do_test 2.3 {
|
||||
set ::lFilterArgs [list]
|
||||
|
||||
@@ -0,0 +1,178 @@
|
||||
# 2024-04-26
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix bestindexC
|
||||
|
||||
ifcapable !vtab {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
register_tcl_module db
|
||||
|
||||
proc vtab_command {lVal method args} {
|
||||
switch -- $method {
|
||||
xConnect {
|
||||
return "CREATE TABLE t1(a)"
|
||||
}
|
||||
|
||||
xBestIndex {
|
||||
set hdl [lindex $args 0]
|
||||
set clist [$hdl constraints]
|
||||
set orderby [$hdl orderby]
|
||||
|
||||
set idxstr [list]
|
||||
set res [list]
|
||||
|
||||
set idx 0
|
||||
foreach c $clist {
|
||||
array set a $c
|
||||
if {$a(usable)==0} continue
|
||||
if {$a(op)=="limit" && ![info exists ::do_not_use_limit]} {
|
||||
lappend idxstr limit
|
||||
lappend res omit $idx
|
||||
}
|
||||
if {$a(op)=="offset" && ![info exists ::do_not_use_offset]} {
|
||||
lappend idxstr offset
|
||||
lappend res omit $idx
|
||||
}
|
||||
incr idx
|
||||
}
|
||||
|
||||
return "cost 1000000 rows 1000000 idxnum 0 idxstr {$idxstr} $res"
|
||||
}
|
||||
|
||||
xFilter {
|
||||
set idxstr [lindex $args 1]
|
||||
set LIMIT ""
|
||||
foreach a $idxstr b [lindex $args 2] {
|
||||
set x($a) $b
|
||||
}
|
||||
|
||||
if {![info exists x(limit)]} { set x(limit) -1 }
|
||||
if {![info exists x(offset)]} { set x(offset) -1 }
|
||||
set LIMIT " LIMIT $x(limit) OFFSET $x(offset)"
|
||||
|
||||
set idx 1
|
||||
foreach v $lVal {
|
||||
lappend lRow "($idx, '$v')"
|
||||
incr idx
|
||||
}
|
||||
|
||||
return [list sql "
|
||||
SELECT * FROM ( VALUES [join $lRow ,]) $LIMIT
|
||||
"]
|
||||
}
|
||||
}
|
||||
|
||||
return {}
|
||||
}
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE VIRTUAL TABLE x1 USING tcl(vtab_command "a b c d e f");
|
||||
CREATE VIRTUAL TABLE x2 USING tcl(vtab_command "A B C D E F a b");
|
||||
} {}
|
||||
|
||||
do_execsql_test 1.1 {
|
||||
CREATE TEMP TABLE t_unionall AS
|
||||
SELECT * FROM x1 UNION ALL SELECT * FROM x2;
|
||||
|
||||
CREATE TEMP TABLE t_intersect AS
|
||||
SELECT * FROM x1 INTERSECT SELECT * FROM x2;
|
||||
|
||||
CREATE TEMP TABLE t_union AS
|
||||
SELECT * FROM x1 UNION SELECT * FROM x2;
|
||||
|
||||
CREATE TEMP TABLE t_except AS
|
||||
SELECT * FROM x1 EXCEPT SELECT * FROM x2;
|
||||
}
|
||||
|
||||
foreach {tn limit} {
|
||||
1 "LIMIT 8"
|
||||
2 "LIMIT 4"
|
||||
3 "LIMIT 4 OFFSET 2"
|
||||
4 "LIMIT 8 OFFSET 4"
|
||||
} {
|
||||
|
||||
foreach {op tbl} {
|
||||
"UNION ALL" t_unionall
|
||||
"UNION" t_union
|
||||
"INTERSECT" t_intersect
|
||||
"EXCEPT" t_except
|
||||
} {
|
||||
|
||||
set expect [execsql "SELECT * FROM $tbl $limit"]
|
||||
do_execsql_test 1.2.$tbl.$tn "SELECT * FROM (
|
||||
SELECT * FROM x1 $op SELECT * FROM x2
|
||||
) $limit" $expect
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
register_tcl_module db
|
||||
|
||||
do_execsql_test 2.0 {
|
||||
CREATE VIRTUAL TABLE x1 USING tcl(vtab_command "a b c d e f");
|
||||
CREATE VIRTUAL TABLE x2 USING tcl(vtab_command "a b e f");
|
||||
} {}
|
||||
|
||||
do_execsql_test 2.1 {
|
||||
SELECT * FROM x1
|
||||
EXCEPT
|
||||
SELECT * FROM x2
|
||||
LIMIT 3
|
||||
} {c d}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
register_tcl_module db
|
||||
do_execsql_test 3.0 {
|
||||
CREATE VIRTUAL TABLE y1 USING tcl(vtab_command "1 2 3 4 5 6 7 8 9 10");
|
||||
} {}
|
||||
|
||||
do_execsql_test 3.1 {
|
||||
SELECT * FROM y1 WHERE a = COALESCE('8', a) LIMIT 3
|
||||
} {8}
|
||||
|
||||
do_execsql_test 3.2 {
|
||||
SELECT * FROM y1 WHERE a = '2' LIMIT 3
|
||||
} {2}
|
||||
|
||||
load_static_extension db series
|
||||
do_execsql_test 3.3 {
|
||||
SELECT * FROM generate_series(1, 5) WHERE value = (value & 14) LIMIT 3
|
||||
} {2 4}
|
||||
|
||||
do_execsql_test 3.4 {
|
||||
SELECT value FROM generate_series(1,10) WHERE value>2 LIMIT 4 OFFSET 1;
|
||||
} {4 5 6 7}
|
||||
|
||||
set ::do_not_use_limit 1
|
||||
do_execsql_test 3.5 {
|
||||
SELECT * FROM y1 LIMIT 5 OFFSET 3
|
||||
} {4 5 6 7 8}
|
||||
unset ::do_not_use_limit
|
||||
set ::do_not_use_offset 1
|
||||
do_execsql_test 3.6 {
|
||||
SELECT * FROM y1 LIMIT 5 OFFSET 3
|
||||
} {4 5 6 7 8}
|
||||
unset ::do_not_use_offset
|
||||
|
||||
|
||||
|
||||
finish_test
|
||||
@@ -0,0 +1,33 @@
|
||||
# 2024 March 19
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix cksumvfs
|
||||
|
||||
sqlite3_register_cksumvfs
|
||||
db close
|
||||
sqlite3 db test.db
|
||||
file_control_reservebytes db 8
|
||||
|
||||
set text [db one "SELECT hex(randomblob(5000))"]
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
|
||||
INSERT INTO t1 VALUES(1, $text);
|
||||
}
|
||||
|
||||
do_execsql_test 1.1 {
|
||||
SELECT * FROM t1;
|
||||
} [list 1 $text]
|
||||
|
||||
finish_test
|
||||
+1
-1
@@ -98,7 +98,7 @@ do_test corruptC-2.1 {
|
||||
sqlite3 db test.db
|
||||
catchsql {PRAGMA integrity_check}
|
||||
} {0 {{*** in database main ***
|
||||
Tree 3 page 3: free space corruption}}}
|
||||
Tree 3 page 3: free space corruption} {wrong # of entries in index t1i1}}}
|
||||
|
||||
# test that a corrupt content offset size is handled (seed 5649)
|
||||
#
|
||||
|
||||
@@ -1505,4 +1505,89 @@ do_catchsql_test 19.4 {
|
||||
PRAGMA integrity_check;
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_test 18.0 {
|
||||
sqlite3 db {}
|
||||
db deserialize [decode_hexdb {
|
||||
.open --hexdb
|
||||
| size 20480 pagesize 4096 filename crash-a4150b729051e4.db
|
||||
| page 1 offset 0
|
||||
| 0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00 SQLite format 3.
|
||||
| 16: 10 00 01 01 00 40 20 20 00 00 00 00 00 00 00 05 .....@ ........
|
||||
| 32: 00 00 00 00 00 00 00 00 00 00 00 04 00 00 00 04 ................
|
||||
| 48: 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 ................
|
||||
| 64: 00 00 00 00 00 00 00 00 00 00 ff f0 00 00 00 00 ................
|
||||
| 96: 00 00 00 00 0d 00 00 00 04 0e e5 00 0f c2 0f 75 ...............u
|
||||
| 112: 0f 19 0e e5 00 00 00 00 00 00 00 01 00 00 00 00 ................
|
||||
| 3808: 00 00 00 00 00 32 04 06 17 17 11 01 4b 69 6e 64 .....2......Kind
|
||||
| 3824: 65 78 74 31 61 62 63 74 31 05 43 52 45 41 54 45 ext1abct1.CREATE
|
||||
| 3840: 20 49 4e 44 45 58 20 74 31 61 62 63 20 4f 4e 20 INDEX t1abc ON
|
||||
| 3856: 74 31 28 61 2c 62 2c 63 29 5a 03 06 17 25 25 01 t1(a,b,c)Z...%%.
|
||||
| 3872: 79 74 61 62 6c 65 73 71 6c 69 74 65 5f 73 74 61 ytablesqlite_sta
|
||||
| 3888: 74 34 73 71 6c 69 74 65 5f 73 74 61 74 34 04 43 t4sqlite_stat4.C
|
||||
| 3904: 52 45 41 54 45 20 54 41 42 4c 45 20 73 71 6c 69 REATE TABLE sqli
|
||||
| 3920: 74 65 5f 73 74 61 74 34 28 74 62 6c 2c 69 64 78 te_stat4(tbl,idx
|
||||
| 3936: 2c 6e 65 71 2c 6e 6c 74 2c 6e 64 6c 74 2c 73 61 ,neq,nlt,ndlt,sa
|
||||
| 3952: 6d 70 6c 65 29 4b 02 06 17 25 25 01 5b 74 61 62 mple)K...%%.[tab
|
||||
| 3968: 6c 65 73 71 6c 69 74 65 5f 73 74 61 74 31 73 71 lesqlite_stat1sq
|
||||
| 3984: 6c 69 74 65 5f 73 74 61 74 31 03 43 52 45 41 54 lite_stat1.CREAT
|
||||
| 4000: 45 20 54 41 42 4c 45 20 73 71 6c 69 74 65 5f 73 E TABLE sqlite_s
|
||||
| 4016: 74 61 74 31 28 74 62 6c 2c 69 64 78 2c 73 74 61 tat1(tbl,idx,sta
|
||||
| 4032: 74 29 3c 01 06 17 11 11 01 65 74 61 62 6c 65 74 t)<......etablet
|
||||
| 4048: 31 74 31 02 43 52 45 41 54 45 20 54 41 42 4c 45 1t1.CREATE TABLE
|
||||
| 4064: 20 74 31 28 61 20 54 45 58 54 2c 20 62 20 49 4e t1(a TEXT, b IN
|
||||
| 4080: 54 2c 20 63 20 49 4e 54 2c 20 64 20 49 4e 54 29 T, c INT, d INT)
|
||||
| page 2 offset 4096
|
||||
| 0: 0d 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
|
||||
| 4000: 0b 07 05 13 01 01 01 62 63 64 64 06 0b 0c 06 05 .......bcdd.....
|
||||
| 4016: 13 02 01 01 64 65 66 01 59 09 0a 0c 05 05 13 03 ....def.Y.......
|
||||
| 4032: 01 01 64 65 66 02 6f 08 09 0c 04 05 13 02 01 01 ..def.o.........
|
||||
| 4048: 61 62 63 01 59 07 08 0c 03 05 13 02 01 01 87 62 abc.Y..........b
|
||||
| 4064: 63 00 ea 06 07 0c 02 05 13 02 01 01 61 62 63 00 c...........abc.
|
||||
| 4080: ea 06 06 0b 01 05 13 01 01 01 61 62 63 7b 04 04 ..........abc...
|
||||
| page 3 offset 8192
|
||||
| 0: 0d 00 00 00 01 0f e0 00 0f e1 00 00 00 00 00 00 ................
|
||||
| 4064: 00 1d 01 04 11 17 31 74 31 74 31 61 62 63 31 30 ......1t1t1abc10
|
||||
| 4080: 30 30 30 20 35 30 30 30 20 32 30 30 30 20 31 30 000 5000 2000 10
|
||||
| page 4 offset 12288
|
||||
| 0: 0d 00 00 00 07 0e ac 00 0f d1 0f a0 0f 6f 0f 3e .............o.>
|
||||
| 16: 0f 0e 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
|
||||
| 3744: 00 00 00 00 00 00 00 00 00 00 00 00 2f 07 07 11 ............/...
|
||||
| 3760: 17 1b 1b 1b 24 74 31 74 31 61 62 63 32 20 31 20 ....$t1t1abc2 1
|
||||
| 3776: 31 20 31 35 20 36 20 36 20 36 32 20 35 20 36 20 1 15 6 6 62 5 6
|
||||
| 3792: 36 05 13 02 01 01 64 65 66 02 37 08 05 2f 06 07 6.....def.7../..
|
||||
| 3808: 11 17 1b 1b 1b 24 74 41 74 31 61 62 63 32 20 31 .....$tAt1abc2 1
|
||||
| 3824: 20 31 20 31 35 20 35 20 55 20 35 32 20 34 20 35 1 15 5 U 52 4 5
|
||||
| 3840: 20 35 05 13 02 01 01 64 65 66 01 59 09 06 2e 05 5.....def.Y....
|
||||
| 3856: 07 11 17 1b 1b 1b 22 74 31 74 31 61 62 63 31 20 .......t1t1abc1
|
||||
| 3872: 31 20 31 20 31 34 20 34 20 34 20 34 31 20 33 20 1 1 14 4 4 41 3
|
||||
| 3888: 34 20 34 08 b3 cd f0 f1 62 63 64 64 06 07 2f 05 4 4.....bcdd../.
|
||||
| 3904: 07 11 17 1b 1b 1b 24 74 37 74 31 61 62 63 34 20 ......$t7t1abc4
|
||||
| 3920: 31 20 31 20 31 30 20 33 20 33 20 33 30 20 32 20 1 1 10 3 3 30 2
|
||||
| 3936: 33 20 33 05 13 02 01 01 61 62 63 01 59 07 04 2f 3 3.....abc.Y../
|
||||
| 3952: 03 07 11 17 1b 1b 1b 24 74 31 74 31 61 62 63 34 .......$t1t1abc4
|
||||
| 3968: 20 32 20 31 20 31 30 20 31 20 32 20 32 30 20 31 2 1 10 1 2 20 1
|
||||
| 3984: 20 32 20 32 05 13 02 01 01 61 62 63 00 ea 06 03 2 2.....abc....
|
||||
| 4000: 2f 02 07 11 17 1b 1b 1b 24 74 31 74 31 61 62 63 /.......$t1t1abc
|
||||
| 4016: 34 20 32 20 31 20 31 30 20 31 20 31 20 31 30 20 4 2 1 10 1 1 10
|
||||
| 4032: 31 20 31 20 31 05 13 02 01 01 61 62 63 00 ea 05 1 1 1.....abc...
|
||||
| 4048: 02 2d 01 07 11 17 1b 1b 1b 20 74 31 74 31 61 62 .-....... t1t1ab
|
||||
| 4064: 63 34 20 31 20 31 20 31 30 20 30 20 30 1f 30 30 c4 1 1 10 0 0.00
|
||||
| 4080: 20 30 20 30 20 30 05 13 01 01 09 61 62 63 7b 04 0 0 0.....abc..
|
||||
| page 5 offset 16384
|
||||
| 0: 0a 00 00 00 07 0f a8 00 0f f5 00 00 00 00 00 00 ................
|
||||
| 4000: 00 00 00 00 00 00 00 00 0c 05 13 02 01 01 64 65 ..............de
|
||||
| 4016: 66 02 37 08 05 0c 05 13 02 01 01 64 65 66 01 59 f.7........def.Y
|
||||
| 4032: 09 06 0b 05 12 01 01 01 62 63 64 64 06 07 0c 05 ........bcdd....
|
||||
| 4048: 13 02 01 01 61 62 63 01 59 07 01 2c 05 13 02 01 ....abc.Y..,....
|
||||
| 4064: 01 61 62 63 00 ea 06 03 0c 05 13 02 01 01 61 62 .abc..........ab
|
||||
| 4080: 63 00 ea 05 00 00 00 00 00 00 00 00 00 00 00 00 c...............
|
||||
| end crash-a4150b729051e4.db
|
||||
}]} {}
|
||||
|
||||
do_catchsql_test 18.1 {
|
||||
SELECT a FROM t1 WHERE b GLOB b AND b GLOB '0^x]␅6␚xz]';
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
finish_test
|
||||
|
||||
+1
-1
@@ -103,7 +103,7 @@ do_eqp_test 5.2 {
|
||||
} {
|
||||
QUERY PLAN
|
||||
|--SCAN t2 USING INDEX t2i1
|
||||
`--USE TEMP B-TREE FOR RIGHT PART OF ORDER BY
|
||||
`--USE TEMP B-TREE FOR LAST TERM OF ORDER BY
|
||||
}
|
||||
|
||||
do_eqp_test 5.3 {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user