Compare commits
189 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a81eb93bba | |||
| 2acd24d90c | |||
| 97258194a2 | |||
| 559656196b | |||
| 2def2f7e0a | |||
| 3df6c3b1c5 | |||
| a19543fe70 | |||
| 154896e8d2 | |||
| 3ed0f1c936 | |||
| 629ec14abc | |||
| 263a8b660f | |||
| bb6896226f | |||
| 4c08735732 | |||
| d33bcb8a3c | |||
| 74588ceb31 | |||
| 77187faf5a | |||
| bf60baa985 | |||
| 702948edbe | |||
| ca90eced28 | |||
| 3ba18adde5 | |||
| b9772e7fe8 | |||
| 3e1e14d818 | |||
| 68262d85ec | |||
| fa7b471c35 | |||
| 303a69b5ad | |||
| 33892c11a7 | |||
| 09ccaf72d1 | |||
| 9ecd7086c1 | |||
| c2c6fd18dd | |||
| 226cef4ef1 | |||
| d03024d814 | |||
| d351e7643f | |||
| 2158a0c7ac | |||
| 7834551c1e | |||
| 05f1ba0ef8 | |||
| 3841372350 | |||
| 1273f8dafe | |||
| f21124f251 | |||
| 88a7973057 | |||
| 050dc5cff4 | |||
| 7e6f980bd4 | |||
| 70739addc2 | |||
| 3908fe90b1 | |||
| dfcdc663f2 | |||
| f0dae6d0a2 | |||
| 38688b0b1d | |||
| 9c1cf3235c | |||
| 617b7b42e3 | |||
| 52fb8e1945 | |||
| 83bebddbd9 | |||
| 52df6f5e5c | |||
| b2a0f75c06 | |||
| b3c4523c58 | |||
| 20554381d9 | |||
| f49759bf03 | |||
| 36494b8bc6 | |||
| 83e8ca54d1 | |||
| 6034846eb6 | |||
| 95b46c85e2 | |||
| 1c305122a2 | |||
| daaae7b9d1 | |||
| 9c6e07d2fa | |||
| 09e16491f6 | |||
| 526740b1b9 | |||
| 87d63c900d | |||
| 5e398e4cbd | |||
| 5e27e1dc49 | |||
| 489a224bea | |||
| 0a02c72e79 | |||
| 48b9a6dd6b | |||
| c9aed7f891 | |||
| a172254742 | |||
| f39e0ed4de | |||
| 2e2338101a | |||
| b40f06c62d | |||
| b32c18bf42 | |||
| c84ddf14c5 | |||
| 251866d07c | |||
| 56520ab848 | |||
| c68886bb9e | |||
| 0f3f7664f0 | |||
| 62f6f51ae1 | |||
| ceb4b1dbdd | |||
| dceed86d07 | |||
| 6f7fbcf0bb | |||
| efaffb64fd | |||
| 6362bbe68d | |||
| 967f8f9e07 | |||
| 865c3c58ab | |||
| dc6b41ed47 | |||
| fe0cf7a18c | |||
| 1f613c4df3 | |||
| 95b225a46d | |||
| 6cd8c8c57a | |||
| 352a35abf5 | |||
| f38dd3b68f | |||
| 44548e7218 | |||
| f0357d8b2c | |||
| 4dd89d5a24 | |||
| 1112cc797b | |||
| 3c77a1e9f1 | |||
| dccf4f2b15 | |||
| 3f18e6d7a9 | |||
| 8abc80b294 | |||
| b7f4b6ccca | |||
| 140efc90ea | |||
| cb96d2a79c | |||
| 037a2bacb0 | |||
| f41a8d3d9a | |||
| 21f6b626f5 | |||
| 7c3ca3611c | |||
| 5b156b2bb4 | |||
| 09fc79bd6f | |||
| 4dd176eaab | |||
| e3740f272b | |||
| 6fa9375c01 | |||
| 7524b613c5 | |||
| 73e00cf056 | |||
| 2e27d28fec | |||
| ca03bdaf6e | |||
| b8313cc998 | |||
| 4f57352937 | |||
| b46dfdb81c | |||
| e35395a45a | |||
| 089df50687 | |||
| 010a016ac9 | |||
| 43c1e622cd | |||
| 54640de156 | |||
| 969012e534 | |||
| 226744d11b | |||
| eabb67fb61 | |||
| 7d90417733 | |||
| 1451778a88 | |||
| a5aed4b10b | |||
| d83e082524 | |||
| 0ff2217035 | |||
| f12228fa23 | |||
| f5f0e43a6d | |||
| a64d1fbc23 | |||
| f48d4ef8bc | |||
| 0c2e5cfda5 | |||
| 5859636fb1 | |||
| a485ad191f | |||
| 63331b1af3 | |||
| 754ee285fa | |||
| 59533aa5e0 | |||
| 60172a5a93 | |||
| 85ef630fde | |||
| 57498ae9cf | |||
| 13aa88d956 | |||
| 6a8700b97b | |||
| a02860511d | |||
| 59c435a015 | |||
| 0019881e08 | |||
| 6903bf6d49 | |||
| 86b40dfd33 | |||
| b7673ede37 | |||
| e9e1074d27 | |||
| 334d163e41 | |||
| 5b54259873 | |||
| ab2eca0965 | |||
| 93bbfbe539 | |||
| c644980c4d | |||
| ea2844f153 | |||
| df94966c8b | |||
| ce00d05a7b | |||
| f35f2f92ed | |||
| 7751deb3e2 | |||
| f6285fab68 | |||
| 1d42ea71c2 | |||
| 01d837df9c | |||
| 2036833a66 | |||
| 761decbb50 | |||
| 05cccc2848 | |||
| 34fcf36d62 | |||
| a0024e6c99 | |||
| 22930062d5 | |||
| 8257aa8dbe | |||
| cf201488a5 | |||
| 61ffb2cda6 | |||
| 1fc376bfd1 | |||
| e8cf1ab9aa | |||
| b67abfc463 | |||
| fb920e7eb0 | |||
| e8e0eda95d | |||
| 1d8536bc0f | |||
| caf8cc1b4b | |||
| 07c3a1a358 | |||
| 5acc3bdbdf |
+17
-4
@@ -181,7 +181,7 @@ LIBOBJS0 = alter.lo analyze.lo attach.lo auth.lo \
|
||||
notify.lo opcodes.lo os.lo os_unix.lo os_win.lo \
|
||||
pager.lo parse.lo pcache.lo pcache1.lo pragma.lo prepare.lo printf.lo \
|
||||
random.lo resolve.lo rowset.lo rtree.lo \
|
||||
sqlite3session.lo select.lo sqlite3rbu.lo status.lo \
|
||||
sqlite3session.lo select.lo sqlite3rbu.lo status.lo stmt.lo \
|
||||
table.lo threads.lo tokenize.lo treeview.lo trigger.lo \
|
||||
update.lo util.lo vacuum.lo \
|
||||
vdbe.lo vdbeapi.lo vdbeaux.lo vdbeblob.lo vdbemem.lo vdbesort.lo \
|
||||
@@ -350,7 +350,8 @@ SRC += \
|
||||
$(TOP)/ext/rbu/sqlite3rbu.h \
|
||||
$(TOP)/ext/rbu/sqlite3rbu.c
|
||||
SRC += \
|
||||
$(TOP)/ext/misc/json1.c
|
||||
$(TOP)/ext/misc/json1.c \
|
||||
$(TOP)/ext/misc/stmt.c
|
||||
|
||||
# Generated source code files
|
||||
#
|
||||
@@ -434,6 +435,7 @@ TESTSRC += \
|
||||
$(TOP)/ext/misc/series.c \
|
||||
$(TOP)/ext/misc/spellfix.c \
|
||||
$(TOP)/ext/misc/totype.c \
|
||||
$(TOP)/ext/misc/unionvtab.c \
|
||||
$(TOP)/ext/misc/wholenumber.c
|
||||
|
||||
# Source code to the library files needed by the test fixture
|
||||
@@ -483,7 +485,8 @@ TESTSRC2 = \
|
||||
$(TOP)/ext/fts3/fts3_tokenizer.c \
|
||||
$(TOP)/ext/fts3/fts3_write.c \
|
||||
$(TOP)/ext/async/sqlite3async.c \
|
||||
$(TOP)/ext/session/sqlite3session.c
|
||||
$(TOP)/ext/session/sqlite3session.c \
|
||||
$(TOP)/ext/misc/stmt.c
|
||||
|
||||
# Header files used by all library source files.
|
||||
#
|
||||
@@ -564,6 +567,7 @@ SHELL_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS4
|
||||
# SHELL_OPT += -DSQLITE_ENABLE_FTS5
|
||||
SHELL_OPT += -DSQLITE_ENABLE_EXPLAIN_COMMENTS
|
||||
SHELL_OPT += -DSQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
|
||||
SHELL_OPT += -DSQLITE_ENABLE_STMTVTAB
|
||||
FUZZERSHELL_OPT = -DSQLITE_ENABLE_JSON1
|
||||
FUZZCHECK_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5 -DSQLITE_OSS_FUZZ
|
||||
FUZZCHECK_OPT += -DSQLITE_MAX_MEMORY=50000000
|
||||
@@ -689,6 +693,11 @@ lemon$(BEXE): $(TOP)/tool/lemon.c $(TOP)/tool/lempar.c
|
||||
$(BCC) -o $@ $(TOP)/tool/lemon.c
|
||||
cp $(TOP)/tool/lempar.c .
|
||||
|
||||
# Rules to build the program that generates the source-id
|
||||
#
|
||||
mksourceid$(BEXE): $(TOP)/tool/mksourceid.c
|
||||
$(BCC) -o $@ $(TOP)/tool/mksourceid.c
|
||||
|
||||
# Rules to build individual *.o files from generated *.c files. This
|
||||
# applies to:
|
||||
#
|
||||
@@ -954,7 +963,7 @@ parse.c: $(TOP)/src/parse.y lemon$(BEXE) $(TOP)/tool/addopcodes.tcl
|
||||
mv parse.h parse.h.temp
|
||||
$(TCLSH_CMD) $(TOP)/tool/addopcodes.tcl parse.h.temp >parse.h
|
||||
|
||||
sqlite3.h: $(TOP)/src/sqlite.h.in $(TOP)/manifest.uuid $(TOP)/VERSION
|
||||
sqlite3.h: $(TOP)/src/sqlite.h.in $(TOP)/manifest mksourceid$(BEXE) $(TOP)/VERSION
|
||||
$(TCLSH_CMD) $(TOP)/tool/mksqlite3h.tcl $(TOP) >sqlite3.h
|
||||
|
||||
keywordhash.h: $(TOP)/tool/mkkeywordhash.c
|
||||
@@ -1034,6 +1043,9 @@ sqlite3session.lo: $(TOP)/ext/session/sqlite3session.c $(HDR) $(EXTHDR)
|
||||
json1.lo: $(TOP)/ext/misc/json1.c
|
||||
$(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/misc/json1.c
|
||||
|
||||
stmt.lo: $(TOP)/ext/misc/stmt.c
|
||||
$(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/misc/stmt.c
|
||||
|
||||
# FTS5 things
|
||||
#
|
||||
FTS5_SRC = \
|
||||
@@ -1083,6 +1095,7 @@ TESTFIXTURE_FLAGS += -DSQLITE_SERVER=1 -DSQLITE_PRIVATE="" -DSQLITE_CORE
|
||||
TESTFIXTURE_FLAGS += -DBUILD_sqlite
|
||||
TESTFIXTURE_FLAGS += -DSQLITE_SERIES_CONSTRAINT_VERIFY=1
|
||||
TESTFIXTURE_FLAGS += -DSQLITE_DEFAULT_PAGE_SIZE=1024
|
||||
TESTFIXTURE_FLAGS += -DSQLITE_ENABLE_STMTVTAB
|
||||
|
||||
TESTFIXTURE_SRC0 = $(TESTSRC2) libsqlite3.la
|
||||
TESTFIXTURE_SRC1 = sqlite3.c
|
||||
|
||||
+17
-4
@@ -1294,7 +1294,8 @@ SRC07 = \
|
||||
$(TOP)\ext\rtree\rtree.c \
|
||||
$(TOP)\ext\session\sqlite3session.c \
|
||||
$(TOP)\ext\rbu\sqlite3rbu.c \
|
||||
$(TOP)\ext\misc\json1.c
|
||||
$(TOP)\ext\misc\json1.c \
|
||||
$(TOP)\ext\misc\stmt.c
|
||||
|
||||
# Extension header files, part 1.
|
||||
#
|
||||
@@ -1417,6 +1418,7 @@ TESTEXT = \
|
||||
$(TOP)\ext\misc\series.c \
|
||||
$(TOP)\ext\misc\spellfix.c \
|
||||
$(TOP)\ext\misc\totype.c \
|
||||
$(TOP)\ext\misc\unionvtab.c \
|
||||
$(TOP)\ext\misc\wholenumber.c
|
||||
|
||||
# Source code to the library files needed by the test fixture
|
||||
@@ -1505,7 +1507,7 @@ FUZZDATA = \
|
||||
# when the shell is not being dynamically linked.
|
||||
#
|
||||
!IF $(DYNAMIC_SHELL)==0 && $(FOR_WIN10)==0
|
||||
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_SHELL_JSON1 -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS
|
||||
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_SHELL_JSON1 -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_STMTVTAB
|
||||
!ENDIF
|
||||
|
||||
# <<mark>>
|
||||
@@ -1668,6 +1670,12 @@ lemon.exe: $(TOP)\tool\lemon.c lempar.c
|
||||
$(BCC) $(NO_WARN) -Daccess=_access \
|
||||
-Fe$@ $(TOP)\tool\lemon.c /link $(LDFLAGS) $(NLTLINKOPTS) $(NLTLIBPATHS)
|
||||
|
||||
# <<mark>>
|
||||
# Rules to build the source-id generator tool
|
||||
#
|
||||
mksourceid.exe: $(TOP)\tool\mksourceid.c
|
||||
$(BCC) $(NO_WARN) -Fe$@ $(TOP)\tool\mksourceid.c /link $(LDFLAGS) $(NLTLINKOPTS) $(NLTLIBPATHS)
|
||||
|
||||
# Rules to build individual *.lo files from generated *.c files. This
|
||||
# applies to:
|
||||
#
|
||||
@@ -1946,7 +1954,7 @@ parse.c: $(TOP)\src\parse.y lemon.exe $(TOP)\tool\addopcodes.tcl
|
||||
move parse.h parse.h.temp
|
||||
$(TCLSH_CMD) $(TOP)\tool\addopcodes.tcl parse.h.temp > parse.h
|
||||
|
||||
$(SQLITE3H): $(TOP)\src\sqlite.h.in $(TOP)\manifest.uuid $(TOP)\VERSION
|
||||
$(SQLITE3H): $(TOP)\src\sqlite.h.in $(TOP)\manifest mksourceid.exe $(TOP)\VERSION
|
||||
$(TCLSH_CMD) $(TOP)\tool\mksqlite3h.tcl $(TOP:\=/) > $(SQLITE3H) $(MKSQLITE3H_ARGS)
|
||||
|
||||
sqlite3ext.h: .target_source
|
||||
@@ -2089,6 +2097,7 @@ TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_SERVER=1 -DSQLITE_PRIVATE=""
|
||||
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_CORE $(NO_WARN)
|
||||
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_SERIES_CONSTRAINT_VERIFY=1
|
||||
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_DEFAULT_PAGE_SIZE=1024
|
||||
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_ENABLE_STMTVTAB
|
||||
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) $(TEST_CCONV_OPTS)
|
||||
|
||||
TESTFIXTURE_SRC0 = $(TESTEXT) $(TESTSRC2)
|
||||
@@ -2242,6 +2251,9 @@ rbu.exe: $(TOP)\ext\rbu\rbu.c $(TOP)\ext\rbu\sqlite3rbu.c $(SQLITE3C) $(SQLITE3H
|
||||
$(LTLINK) $(NO_WARN) -DSQLITE_ENABLE_RBU \
|
||||
$(TOP)\ext\rbu\rbu.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
||||
|
||||
LSMDIR=$(TOP)\ext\lsm1
|
||||
!INCLUDE $(LSMDIR)\Makefile.msc
|
||||
|
||||
moreclean: clean
|
||||
del /Q $(SQLITE3C) $(SQLITE3H) 2>NUL
|
||||
# <</mark>>
|
||||
@@ -2254,13 +2266,14 @@ clean:
|
||||
del /Q sqlite3.c sqlite3.h 2>NUL
|
||||
del /Q opcodes.c opcodes.h 2>NUL
|
||||
del /Q lemon.* lempar.c parse.* 2>NUL
|
||||
del /Q mkkeywordhash.* keywordhash.h 2>NUL
|
||||
del /Q mksourceid.* mkkeywordhash.* keywordhash.h 2>NUL
|
||||
del /Q notasharedlib.* 2>NUL
|
||||
-rmdir /Q/S .deps 2>NUL
|
||||
-rmdir /Q/S .libs 2>NUL
|
||||
-rmdir /Q/S tsrc 2>NUL
|
||||
del /Q .target_source 2>NUL
|
||||
del /Q tclsqlite3.exe $(SQLITETCLH) $(SQLITETCLDECLSH) 2>NUL
|
||||
del /Q lsm.dll lsmtest.exe 2>NUL
|
||||
del /Q testloadext.dll 2>NUL
|
||||
del /Q testfixture.exe test.db 2>NUL
|
||||
del /Q LogEst.exe fts3view.exe rollback-test.exe showdb.exe dbdump.exe 2>NUL
|
||||
|
||||
@@ -34,7 +34,9 @@ archives as follows:
|
||||
If you do want to use Fossil to check out the source tree,
|
||||
first install Fossil version 2.0 or later.
|
||||
(Source tarballs and precompiled binaries available
|
||||
[here](https://www.fossil-scm.org/fossil/uv/download.html).)
|
||||
[here](https://www.fossil-scm.org/fossil/uv/download.html). Fossil is
|
||||
a stand-alone program. To install, simply download or build the single
|
||||
executable file and put that file someplace on your $PATH.)
|
||||
Then run commands like this:
|
||||
|
||||
mkdir ~/sqlite
|
||||
@@ -106,19 +108,22 @@ The makefiles also require AWK.
|
||||
|
||||
## Source Code Tour
|
||||
|
||||
Most of the core source files are in the **src/** subdirectory. But
|
||||
src/ also contains files used to build the "testfixture" test harness;
|
||||
those file all begin with "test". And src/ contains the "shell.c" file
|
||||
which is the main program for the "sqlite3.exe" command-line shell and
|
||||
the "tclsqlite.c" file which implements the bindings to SQLite from the
|
||||
Tcl programming language. (Historical note: SQLite began as a Tcl
|
||||
Most of the core source files are in the **src/** subdirectory. The
|
||||
**src/** folder also contains files used to build the "testfixture" test
|
||||
harness. The names of the source files used by "testfixture" all begin
|
||||
with "test".
|
||||
The **src/** also contains the "shell.c" file
|
||||
which is the main program for the "sqlite3.exe"
|
||||
[command-line shell](https://sqlite.org/cli.html) and
|
||||
the "tclsqlite.c" file which implements the
|
||||
[TCL bindings](https://sqlite.org/tclsqlite.html) for SQLite.
|
||||
(Historical note: SQLite began as a Tcl
|
||||
extension and only later escaped to the wild as an independent library.)
|
||||
|
||||
Test scripts and programs are found in the **test/** subdirectory.
|
||||
There are other test suites for SQLite (see
|
||||
[How SQLite Is Tested](http://www.sqlite.org/testing.html))
|
||||
but those other test suites are
|
||||
in separate source repositories.
|
||||
Addtional test code is found in other source repositories.
|
||||
See [How SQLite Is Tested](http://www.sqlite.org/testing.html) for
|
||||
additional information.
|
||||
|
||||
The **ext/** subdirectory contains code for extensions. The
|
||||
Full-text search engine is in **ext/fts3**. The R-Tree engine is in
|
||||
@@ -142,7 +147,7 @@ manually-edited files and automatically-generated files.
|
||||
The SQLite interface is defined by the **sqlite3.h** header file, which is
|
||||
generated from src/sqlite.h.in, ./manifest.uuid, and ./VERSION. The
|
||||
[Tcl script](http://www.tcl.tk) at tool/mksqlite3h.tcl does the conversion.
|
||||
The manifest.uuid file contains the SHA1 hash of the particular check-in
|
||||
The manifest.uuid file contains the SHA3 hash of the particular check-in
|
||||
and is used to generate the SQLITE\_SOURCE\_ID macro. The VERSION file
|
||||
contains the current SQLite version number. The sqlite3.h header is really
|
||||
just a copy of src/sqlite.h.in with the source-id and version number inserted
|
||||
@@ -153,9 +158,8 @@ used to generate that documentation are in a separate source repository.
|
||||
The SQL language parser is **parse.c** which is generate from a grammar in
|
||||
the src/parse.y file. The conversion of "parse.y" into "parse.c" is done
|
||||
by the [lemon](./doc/lemon.html) LALR(1) parser generator. The source code
|
||||
for lemon is at tool/lemon.c. Lemon uses a
|
||||
template for generating its parser. A generic template is in tool/lempar.c,
|
||||
but SQLite uses a slightly modified template found in src/lempar.c.
|
||||
for lemon is at tool/lemon.c. Lemon uses the tool/lempar.c file as a
|
||||
template for generating its parser.
|
||||
|
||||
Lemon also generates the **parse.h** header file, at the same time it
|
||||
generates parse.c. But the parse.h header file is
|
||||
@@ -175,6 +179,13 @@ that maps SQL language keywords (ex: "CREATE", "SELECT", "INDEX", etc.) into
|
||||
the numeric codes used by the parse.c parser. The keywordhash.h file is
|
||||
generated by a C-language program at tool mkkeywordhash.c.
|
||||
|
||||
The **pragma.h** header file contains various definitions used to parse
|
||||
and implement the PRAGMA statements. The header is generated by a
|
||||
script **tool/mkpragmatab.tcl**. If you want to add a new PRAGMA, edit
|
||||
the **tool/mkpragmatab.tcl** file to insert the information needed by the
|
||||
parser for your new PRAGMA, then run the script to regenerate the
|
||||
**pragma.h** header file.
|
||||
|
||||
### The Amalgamation
|
||||
|
||||
All of the individual C source code and header files (both manually-edited
|
||||
@@ -192,7 +203,7 @@ subdirectory (using the equivalent of "make target_source") then the
|
||||
tool/mksqlite3c.tcl script is run to copy them all together in just the
|
||||
right order while resolving internal "#include" references.
|
||||
|
||||
The amalgamation source file is more than 100K lines long. Some symbolic
|
||||
The amalgamation source file is more than 200K lines long. Some symbolic
|
||||
debuggers (most notably MSVC) are unable to deal with files longer than 64K
|
||||
lines. To work around this, a separate Tcl script, tool/split-sqlite3c.tcl,
|
||||
can be run on the amalgamation to break it up into a single small C file
|
||||
@@ -209,14 +220,15 @@ See the [architectural description](http://www.sqlite.org/arch.html)
|
||||
for details. Other documents that are useful in
|
||||
(helping to understand how SQLite works include the
|
||||
[file format](http://www.sqlite.org/fileformat2.html) description,
|
||||
the [virtual machine](http://www.sqlite.org/vdbe.html) that runs
|
||||
the [virtual machine](http://www.sqlite.org/opcode.html) that runs
|
||||
prepared statements, the description of
|
||||
[how transactions work](http://www.sqlite.org/atomiccommit.html), and
|
||||
the [overview of the query planner](http://www.sqlite.org/optoverview.html).
|
||||
|
||||
Unfortunately, years of effort have gone into optimizating SQLite, both
|
||||
Years of effort have gone into optimizating SQLite, both
|
||||
for small size and high performance. And optimizations tend to result in
|
||||
complex code. So there is a lot of complexity in the SQLite implementation.
|
||||
complex code. So there is a lot of complexity in the current SQLite
|
||||
implementation. It will not be the easiest library in the world to hack.
|
||||
|
||||
Key files:
|
||||
|
||||
@@ -227,7 +239,7 @@ Key files:
|
||||
* **sqliteInt.h** - this header file defines many of the data objects
|
||||
used internally by SQLite.
|
||||
|
||||
* **parse.y** - This file describes the LALR(1) grammer that SQLite uses
|
||||
* **parse.y** - This file describes the LALR(1) grammar that SQLite uses
|
||||
to parse SQL statements, and the actions that are taken at each step
|
||||
in the parsing process.
|
||||
|
||||
@@ -260,13 +272,13 @@ Key files:
|
||||
is not part of the core SQLite library. But as most of the tests in this
|
||||
repository are written in Tcl, the Tcl language bindings are important.
|
||||
|
||||
There are many other source files. Each has a suscinct header comment that
|
||||
There are many other source files. Each has a succinct header comment that
|
||||
describes its purpose and role within the larger system.
|
||||
|
||||
|
||||
## Contacts
|
||||
|
||||
The main SQLite webpage is [http://www.sqlite.org/](http://www.sqlite.org/)
|
||||
with geographically distributed backup servers at
|
||||
with geographically distributed backups at
|
||||
[http://www2.sqlite.org/](http://www2.sqlite.org) and
|
||||
[http://www3.sqlite.org/](http://www3.sqlite.org).
|
||||
|
||||
@@ -12,7 +12,7 @@ sqlite3_LDADD = @EXTRA_SHELL_OBJ@ @READLINE_LIBS@
|
||||
sqlite3_DEPENDENCIES = @EXTRA_SHELL_OBJ@
|
||||
sqlite3_CFLAGS = $(AM_CFLAGS) -DSQLITE_ENABLE_EXPLAIN_COMMENTS
|
||||
|
||||
include_HEADERS = sqlite3.h sqlite3ext.h msvc.h
|
||||
include_HEADERS = sqlite3.h sqlite3ext.h
|
||||
|
||||
EXTRA_DIST = sqlite3.1 tea Makefile.msc sqlite3.rc README.txt Replace.cs
|
||||
pkgconfigdir = ${libdir}/pkgconfig
|
||||
|
||||
@@ -927,7 +927,7 @@ LIBRESOBJS =
|
||||
# when the shell is not being dynamically linked.
|
||||
#
|
||||
!IF $(DYNAMIC_SHELL)==0 && $(FOR_WIN10)==0
|
||||
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_SHELL_JSON1 -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS
|
||||
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_SHELL_JSON1 -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_STMTVTAB
|
||||
!ENDIF
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#! /bin/sh
|
||||
# Guess values for system-dependent variables and create Makefiles.
|
||||
# Generated by GNU Autoconf 2.69 for sqlite 3.19.4.
|
||||
# Generated by GNU Autoconf 2.69 for sqlite 3.21.0.
|
||||
#
|
||||
#
|
||||
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
|
||||
@@ -726,8 +726,8 @@ MAKEFLAGS=
|
||||
# Identity of this package.
|
||||
PACKAGE_NAME='sqlite'
|
||||
PACKAGE_TARNAME='sqlite'
|
||||
PACKAGE_VERSION='3.19.4'
|
||||
PACKAGE_STRING='sqlite 3.19.4'
|
||||
PACKAGE_VERSION='3.21.0'
|
||||
PACKAGE_STRING='sqlite 3.21.0'
|
||||
PACKAGE_BUGREPORT=''
|
||||
PACKAGE_URL=''
|
||||
|
||||
@@ -909,6 +909,7 @@ enable_fts3
|
||||
enable_fts4
|
||||
enable_fts5
|
||||
enable_json1
|
||||
enable_update_limit
|
||||
enable_rtree
|
||||
enable_session
|
||||
enable_gcov
|
||||
@@ -1463,7 +1464,7 @@ if test "$ac_init_help" = "long"; then
|
||||
# Omit some internal or obsolete options to make the list less imposing.
|
||||
# This message is too long to be a string in the A/UX 3.1 sh.
|
||||
cat <<_ACEOF
|
||||
\`configure' configures sqlite 3.19.4 to adapt to many kinds of systems.
|
||||
\`configure' configures sqlite 3.21.0 to adapt to many kinds of systems.
|
||||
|
||||
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||
|
||||
@@ -1528,7 +1529,7 @@ fi
|
||||
|
||||
if test -n "$ac_init_help"; then
|
||||
case $ac_init_help in
|
||||
short | recursive ) echo "Configuration of sqlite 3.19.4:";;
|
||||
short | recursive ) echo "Configuration of sqlite 3.21.0:";;
|
||||
esac
|
||||
cat <<\_ACEOF
|
||||
|
||||
@@ -1560,6 +1561,7 @@ Optional Features:
|
||||
--enable-fts4 Enable the FTS4 extension
|
||||
--enable-fts5 Enable the FTS5 extension
|
||||
--enable-json1 Enable the JSON1 extension
|
||||
--enable-update-limit Enable the UPDATE/DELETE LIMIT clause
|
||||
--enable-rtree Enable the RTREE extension
|
||||
--enable-session Enable the SESSION extension
|
||||
--enable-gcov Enable coverage testing using gcov
|
||||
@@ -1652,7 +1654,7 @@ fi
|
||||
test -n "$ac_init_help" && exit $ac_status
|
||||
if $ac_init_version; then
|
||||
cat <<\_ACEOF
|
||||
sqlite configure 3.19.4
|
||||
sqlite configure 3.21.0
|
||||
generated by GNU Autoconf 2.69
|
||||
|
||||
Copyright (C) 2012 Free Software Foundation, Inc.
|
||||
@@ -2071,7 +2073,7 @@ cat >config.log <<_ACEOF
|
||||
This file contains any messages produced by compilers while
|
||||
running configure, to aid debugging if configure makes a mistake.
|
||||
|
||||
It was created by sqlite $as_me 3.19.4, which was
|
||||
It was created by sqlite $as_me 3.21.0, which was
|
||||
generated by GNU Autoconf 2.69. Invocation command line was
|
||||
|
||||
$ $0 $@
|
||||
@@ -3929,13 +3931,13 @@ if ${lt_cv_nm_interface+:} false; then :
|
||||
else
|
||||
lt_cv_nm_interface="BSD nm"
|
||||
echo "int some_variable = 0;" > conftest.$ac_ext
|
||||
(eval echo "\"\$as_me:3932: $ac_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:3934: $ac_compile\"" >&5)
|
||||
(eval "$ac_compile" 2>conftest.err)
|
||||
cat conftest.err >&5
|
||||
(eval echo "\"\$as_me:3935: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
|
||||
(eval echo "\"\$as_me:3937: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
|
||||
(eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
|
||||
cat conftest.err >&5
|
||||
(eval echo "\"\$as_me:3938: output\"" >&5)
|
||||
(eval echo "\"\$as_me:3940: output\"" >&5)
|
||||
cat conftest.out >&5
|
||||
if $GREP 'External.*some_variable' conftest.out > /dev/null; then
|
||||
lt_cv_nm_interface="MS dumpbin"
|
||||
@@ -5141,7 +5143,7 @@ ia64-*-hpux*)
|
||||
;;
|
||||
*-*-irix6*)
|
||||
# Find out which ABI we are using.
|
||||
echo '#line 5144 "configure"' > conftest.$ac_ext
|
||||
echo '#line 5146 "configure"' > conftest.$ac_ext
|
||||
if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
|
||||
(eval $ac_compile) 2>&5
|
||||
ac_status=$?
|
||||
@@ -6666,11 +6668,11 @@ else
|
||||
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
|
||||
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
|
||||
-e 's:$: $lt_compiler_flag:'`
|
||||
(eval echo "\"\$as_me:6669: $lt_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:6671: $lt_compile\"" >&5)
|
||||
(eval "$lt_compile" 2>conftest.err)
|
||||
ac_status=$?
|
||||
cat conftest.err >&5
|
||||
echo "$as_me:6673: \$? = $ac_status" >&5
|
||||
echo "$as_me:6675: \$? = $ac_status" >&5
|
||||
if (exit $ac_status) && test -s "$ac_outfile"; then
|
||||
# The compiler can only warn and ignore the option if not recognized
|
||||
# So say no if there are warnings other than the usual output.
|
||||
@@ -7005,11 +7007,11 @@ else
|
||||
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
|
||||
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
|
||||
-e 's:$: $lt_compiler_flag:'`
|
||||
(eval echo "\"\$as_me:7008: $lt_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:7010: $lt_compile\"" >&5)
|
||||
(eval "$lt_compile" 2>conftest.err)
|
||||
ac_status=$?
|
||||
cat conftest.err >&5
|
||||
echo "$as_me:7012: \$? = $ac_status" >&5
|
||||
echo "$as_me:7014: \$? = $ac_status" >&5
|
||||
if (exit $ac_status) && test -s "$ac_outfile"; then
|
||||
# The compiler can only warn and ignore the option if not recognized
|
||||
# So say no if there are warnings other than the usual output.
|
||||
@@ -7110,11 +7112,11 @@ else
|
||||
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
|
||||
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
|
||||
-e 's:$: $lt_compiler_flag:'`
|
||||
(eval echo "\"\$as_me:7113: $lt_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:7115: $lt_compile\"" >&5)
|
||||
(eval "$lt_compile" 2>out/conftest.err)
|
||||
ac_status=$?
|
||||
cat out/conftest.err >&5
|
||||
echo "$as_me:7117: \$? = $ac_status" >&5
|
||||
echo "$as_me:7119: \$? = $ac_status" >&5
|
||||
if (exit $ac_status) && test -s out/conftest2.$ac_objext
|
||||
then
|
||||
# The compiler can only warn and ignore the option if not recognized
|
||||
@@ -7165,11 +7167,11 @@ else
|
||||
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
|
||||
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
|
||||
-e 's:$: $lt_compiler_flag:'`
|
||||
(eval echo "\"\$as_me:7168: $lt_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:7170: $lt_compile\"" >&5)
|
||||
(eval "$lt_compile" 2>out/conftest.err)
|
||||
ac_status=$?
|
||||
cat out/conftest.err >&5
|
||||
echo "$as_me:7172: \$? = $ac_status" >&5
|
||||
echo "$as_me:7174: \$? = $ac_status" >&5
|
||||
if (exit $ac_status) && test -s out/conftest2.$ac_objext
|
||||
then
|
||||
# The compiler can only warn and ignore the option if not recognized
|
||||
@@ -9545,7 +9547,7 @@ else
|
||||
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
|
||||
lt_status=$lt_dlunknown
|
||||
cat > conftest.$ac_ext <<_LT_EOF
|
||||
#line 9548 "configure"
|
||||
#line 9550 "configure"
|
||||
#include "confdefs.h"
|
||||
|
||||
#if HAVE_DLFCN_H
|
||||
@@ -9641,7 +9643,7 @@ else
|
||||
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
|
||||
lt_status=$lt_dlunknown
|
||||
cat > conftest.$ac_ext <<_LT_EOF
|
||||
#line 9644 "configure"
|
||||
#line 9646 "configure"
|
||||
#include "confdefs.h"
|
||||
|
||||
#if HAVE_DLFCN_H
|
||||
@@ -11539,6 +11541,20 @@ if test "${enable_json1}" = "yes" ; then
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_JSON1"
|
||||
fi
|
||||
|
||||
#########
|
||||
# See whether we should enable the LIMIT clause on UPDATE and DELETE
|
||||
# statements.
|
||||
# Check whether --enable-update-limit was given.
|
||||
if test "${enable_update_limit+set}" = set; then :
|
||||
enableval=$enable_update_limit; enable_udlimit=yes
|
||||
else
|
||||
enable_udlimit=no
|
||||
fi
|
||||
|
||||
if test "${enable_udlimit}" = "yes" ; then
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_UPDATE_DELETE_LIMIT"
|
||||
fi
|
||||
|
||||
#########
|
||||
# See whether we should enable RTREE
|
||||
# Check whether --enable-rtree was given.
|
||||
@@ -12151,7 +12167,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
|
||||
# report actual input values of CONFIG_FILES etc. instead of their
|
||||
# values after options handling.
|
||||
ac_log="
|
||||
This file was extended by sqlite $as_me 3.19.4, which was
|
||||
This file was extended by sqlite $as_me 3.21.0, which was
|
||||
generated by GNU Autoconf 2.69. Invocation command line was
|
||||
|
||||
CONFIG_FILES = $CONFIG_FILES
|
||||
@@ -12217,7 +12233,7 @@ _ACEOF
|
||||
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
||||
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
|
||||
ac_cs_version="\\
|
||||
sqlite config.status 3.19.4
|
||||
sqlite config.status 3.21.0
|
||||
configured by $0, generated by GNU Autoconf 2.69,
|
||||
with options \\"\$ac_cs_config\\"
|
||||
|
||||
|
||||
@@ -644,6 +644,16 @@ if test "${enable_json1}" = "yes" ; then
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_JSON1"
|
||||
fi
|
||||
|
||||
#########
|
||||
# See whether we should enable the LIMIT clause on UPDATE and DELETE
|
||||
# statements.
|
||||
AC_ARG_ENABLE(update-limit, AC_HELP_STRING([--enable-update-limit],
|
||||
[Enable the UPDATE/DELETE LIMIT clause]),
|
||||
[enable_udlimit=yes],[enable_udlimit=no])
|
||||
if test "${enable_udlimit}" = "yes" ; then
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_UPDATE_DELETE_LIMIT"
|
||||
fi
|
||||
|
||||
#########
|
||||
# See whether we should enable RTREE
|
||||
AC_ARG_ENABLE(rtree, AC_HELP_STRING([--enable-rtree],
|
||||
|
||||
@@ -23,6 +23,26 @@ or embedded controllers.</p>
|
||||
<p>This document is an introduction to the Lemon
|
||||
parser generator.</p>
|
||||
|
||||
<h2>Security Note</h2>
|
||||
|
||||
<p>The language parser code created by Lemon is very robust and
|
||||
is well-suited for use in internet-facing applications that need to
|
||||
safely process maliciously crafted inputs.
|
||||
|
||||
<p>The "lemon.exe" command-line tool itself works great when given a valid
|
||||
input grammar file and almost always gives helpful
|
||||
error messages for malformed inputs. However, it is possible for
|
||||
a malicious user to craft a grammar file that will cause
|
||||
lemon.exe to crash.
|
||||
We do not see this as a problem, as lemon.exe is not intended to be used
|
||||
with hostile inputs.
|
||||
To summarize:</p>
|
||||
|
||||
<ul>
|
||||
<li>Parser code generated by lemon → Robust and secure
|
||||
<li>The "lemon.exe" command line tool itself → Not so much
|
||||
</ul>
|
||||
|
||||
<h2>Theory of Operation</h2>
|
||||
|
||||
<p>The main goal of Lemon is to translate a context free grammar (CFG)
|
||||
|
||||
+28
-18
@@ -1707,6 +1707,19 @@ static void fts3CursorFinalizeStmt(Fts3Cursor *pCsr){
|
||||
sqlite3_finalize(pCsr->pStmt);
|
||||
}
|
||||
|
||||
/*
|
||||
** Free all resources currently held by the cursor passed as the only
|
||||
** argument.
|
||||
*/
|
||||
static void fts3ClearCursor(Fts3Cursor *pCsr){
|
||||
fts3CursorFinalizeStmt(pCsr);
|
||||
sqlite3Fts3FreeDeferredTokens(pCsr);
|
||||
sqlite3_free(pCsr->aDoclist);
|
||||
sqlite3Fts3MIBufferFree(pCsr->pMIBuffer);
|
||||
sqlite3Fts3ExprFree(pCsr->pExpr);
|
||||
memset(&(&pCsr->base)[1], 0, sizeof(Fts3Cursor)-sizeof(sqlite3_vtab_cursor));
|
||||
}
|
||||
|
||||
/*
|
||||
** Close the cursor. For additional information see the documentation
|
||||
** on the xClose method of the virtual table interface.
|
||||
@@ -1714,11 +1727,7 @@ static void fts3CursorFinalizeStmt(Fts3Cursor *pCsr){
|
||||
static int fts3CloseMethod(sqlite3_vtab_cursor *pCursor){
|
||||
Fts3Cursor *pCsr = (Fts3Cursor *)pCursor;
|
||||
assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 );
|
||||
fts3CursorFinalizeStmt(pCsr);
|
||||
sqlite3Fts3ExprFree(pCsr->pExpr);
|
||||
sqlite3Fts3FreeDeferredTokens(pCsr);
|
||||
sqlite3_free(pCsr->aDoclist);
|
||||
sqlite3Fts3MIBufferFree(pCsr->pMIBuffer);
|
||||
fts3ClearCursor(pCsr);
|
||||
assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 );
|
||||
sqlite3_free(pCsr);
|
||||
return SQLITE_OK;
|
||||
@@ -1744,7 +1753,7 @@ static int fts3CursorSeekStmt(Fts3Cursor *pCsr){
|
||||
}else{
|
||||
zSql = sqlite3_mprintf("SELECT %s WHERE rowid = ?", p->zReadExprlist);
|
||||
if( !zSql ) return SQLITE_NOMEM;
|
||||
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pCsr->pStmt, 0);
|
||||
rc = sqlite3_prepare_v3(p->db, zSql,-1,SQLITE_PREPARE_PERSISTENT,&pCsr->pStmt,0);
|
||||
sqlite3_free(zSql);
|
||||
}
|
||||
if( rc==SQLITE_OK ) pCsr->bSeekStmt = 1;
|
||||
@@ -3219,11 +3228,7 @@ static int fts3FilterMethod(
|
||||
assert( iIdx==nVal );
|
||||
|
||||
/* In case the cursor has been used before, clear it now. */
|
||||
fts3CursorFinalizeStmt(pCsr);
|
||||
sqlite3_free(pCsr->aDoclist);
|
||||
sqlite3Fts3MIBufferFree(pCsr->pMIBuffer);
|
||||
sqlite3Fts3ExprFree(pCsr->pExpr);
|
||||
memset(&pCursor[1], 0, sizeof(Fts3Cursor)-sizeof(sqlite3_vtab_cursor));
|
||||
fts3ClearCursor(pCsr);
|
||||
|
||||
/* Set the lower and upper bounds on docids to return */
|
||||
pCsr->iMinDocid = fts3DocidRange(pDocidGe, SMALLEST_INT64);
|
||||
@@ -3281,7 +3286,7 @@ static int fts3FilterMethod(
|
||||
);
|
||||
}
|
||||
if( zSql ){
|
||||
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pCsr->pStmt, 0);
|
||||
rc = sqlite3_prepare_v3(p->db,zSql,-1,SQLITE_PREPARE_PERSISTENT,&pCsr->pStmt,0);
|
||||
sqlite3_free(zSql);
|
||||
}else{
|
||||
rc = SQLITE_NOMEM;
|
||||
@@ -3302,7 +3307,12 @@ static int fts3FilterMethod(
|
||||
** routine to find out if it has reached the end of a result set.
|
||||
*/
|
||||
static int fts3EofMethod(sqlite3_vtab_cursor *pCursor){
|
||||
return ((Fts3Cursor *)pCursor)->isEof;
|
||||
Fts3Cursor *pCsr = (Fts3Cursor*)pCursor;
|
||||
if( pCsr->isEof ){
|
||||
fts3ClearCursor(pCsr);
|
||||
pCsr->isEof = 1;
|
||||
}
|
||||
return pCsr->isEof;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3343,8 +3353,7 @@ static int fts3ColumnMethod(
|
||||
switch( iCol-p->nColumn ){
|
||||
case 0:
|
||||
/* The special 'table-name' column */
|
||||
sqlite3_result_blob(pCtx, &pCsr, sizeof(Fts3Cursor*), SQLITE_TRANSIENT);
|
||||
sqlite3_result_subtype(pCtx, SQLITE_BLOB);
|
||||
sqlite3_result_pointer(pCtx, pCsr, "fts3cursor", 0);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
@@ -3562,9 +3571,10 @@ static int fts3FunctionArg(
|
||||
sqlite3_value *pVal, /* argv[0] passed to function */
|
||||
Fts3Cursor **ppCsr /* OUT: Store cursor handle here */
|
||||
){
|
||||
int rc = SQLITE_OK;
|
||||
if( sqlite3_value_subtype(pVal)==SQLITE_BLOB ){
|
||||
*ppCsr = *(Fts3Cursor**)sqlite3_value_blob(pVal);
|
||||
int rc;
|
||||
*ppCsr = (Fts3Cursor*)sqlite3_value_pointer(pVal, "fts3cursor");
|
||||
if( (*ppCsr)!=0 ){
|
||||
rc = SQLITE_OK;
|
||||
}else{
|
||||
char *zErr = sqlite3_mprintf("illegal first argument to %s", zFunc);
|
||||
sqlite3_result_error(pContext, zErr, -1);
|
||||
|
||||
@@ -407,7 +407,8 @@ static int fts3SqlStmt(
|
||||
if( !zSql ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, NULL);
|
||||
rc = sqlite3_prepare_v3(p->db, zSql, -1, SQLITE_PREPARE_PERSISTENT,
|
||||
&pStmt, NULL);
|
||||
sqlite3_free(zSql);
|
||||
assert( rc==SQLITE_OK || pStmt==0 );
|
||||
p->aStmt[eStmt] = pStmt;
|
||||
|
||||
@@ -171,10 +171,11 @@ static int fts5HashResize(Fts5Hash *pHash){
|
||||
|
||||
for(i=0; i<pHash->nSlot; i++){
|
||||
while( apOld[i] ){
|
||||
int iHash;
|
||||
unsigned int iHash;
|
||||
Fts5HashEntry *p = apOld[i];
|
||||
apOld[i] = p->pHashNext;
|
||||
iHash = fts5HashKey(nNew, (u8*)fts5EntryKey(p), strlen(fts5EntryKey(p)));
|
||||
iHash = fts5HashKey(nNew, (u8*)fts5EntryKey(p),
|
||||
(int)strlen(fts5EntryKey(p)));
|
||||
p->pHashNext = apNew[iHash];
|
||||
apNew[iHash] = p;
|
||||
}
|
||||
@@ -477,7 +478,7 @@ int sqlite3Fts5HashQuery(
|
||||
int *pnDoclist /* OUT: Size of doclist in bytes */
|
||||
){
|
||||
unsigned int iHash = fts5HashKey(pHash->nSlot, (const u8*)pTerm, nTerm);
|
||||
char *zKey;
|
||||
char *zKey = 0;
|
||||
Fts5HashEntry *p;
|
||||
|
||||
for(p=pHash->aSlot[iHash]; p; p=p->pHashNext){
|
||||
|
||||
@@ -728,7 +728,8 @@ static int fts5IndexPrepareStmt(
|
||||
){
|
||||
if( p->rc==SQLITE_OK ){
|
||||
if( zSql ){
|
||||
p->rc = sqlite3_prepare_v2(p->pConfig->db, zSql, -1, ppStmt, 0);
|
||||
p->rc = sqlite3_prepare_v3(p->pConfig->db, zSql, -1,
|
||||
SQLITE_PREPARE_PERSISTENT, ppStmt, 0);
|
||||
}else{
|
||||
p->rc = SQLITE_NOMEM;
|
||||
}
|
||||
@@ -777,7 +778,8 @@ static void fts5DataDelete(Fts5Index *p, i64 iFirst, i64 iLast){
|
||||
if( zSql==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
rc = sqlite3_prepare_v2(pConfig->db, zSql, -1, &p->pDeleter, 0);
|
||||
rc = sqlite3_prepare_v3(pConfig->db, zSql, -1,
|
||||
SQLITE_PREPARE_PERSISTENT, &p->pDeleter, 0);
|
||||
sqlite3_free(zSql);
|
||||
}
|
||||
if( rc!=SQLITE_OK ){
|
||||
|
||||
+11
-10
@@ -883,7 +883,8 @@ static int fts5PrepareStatement(
|
||||
if( zSql==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
rc = sqlite3_prepare_v2(pConfig->db, zSql, -1, &pRet, 0);
|
||||
rc = sqlite3_prepare_v3(pConfig->db, zSql, -1,
|
||||
SQLITE_PREPARE_PERSISTENT, &pRet, 0);
|
||||
if( rc!=SQLITE_OK ){
|
||||
*pConfig->pzErrmsg = sqlite3_mprintf("%s", sqlite3_errmsg(pConfig->db));
|
||||
}
|
||||
@@ -1019,7 +1020,8 @@ static int fts5FindRankFunction(Fts5Cursor *pCsr){
|
||||
char *zSql = sqlite3Fts5Mprintf(&rc, "SELECT %s", zRankArgs);
|
||||
if( zSql ){
|
||||
sqlite3_stmt *pStmt = 0;
|
||||
rc = sqlite3_prepare_v2(pConfig->db, zSql, -1, &pStmt, 0);
|
||||
rc = sqlite3_prepare_v3(pConfig->db, zSql, -1,
|
||||
SQLITE_PREPARE_PERSISTENT, &pStmt, 0);
|
||||
sqlite3_free(zSql);
|
||||
assert( rc==SQLITE_OK || pCsr->pRankArgStmt==0 );
|
||||
if( rc==SQLITE_OK ){
|
||||
@@ -2607,15 +2609,14 @@ static void fts5ModuleDestroy(void *pCtx){
|
||||
static void fts5Fts5Func(
|
||||
sqlite3_context *pCtx, /* Function call context */
|
||||
int nArg, /* Number of args */
|
||||
sqlite3_value **apUnused /* Function arguments */
|
||||
sqlite3_value **apArg /* Function arguments */
|
||||
){
|
||||
Fts5Global *pGlobal = (Fts5Global*)sqlite3_user_data(pCtx);
|
||||
char buf[8];
|
||||
UNUSED_PARAM2(nArg, apUnused);
|
||||
assert( nArg==0 );
|
||||
assert( sizeof(buf)>=sizeof(pGlobal) );
|
||||
memcpy(buf, (void*)&pGlobal, sizeof(pGlobal));
|
||||
sqlite3_result_blob(pCtx, buf, sizeof(pGlobal), SQLITE_TRANSIENT);
|
||||
fts5_api **ppApi;
|
||||
UNUSED_PARAM(nArg);
|
||||
assert( nArg==1 );
|
||||
ppApi = (fts5_api**)sqlite3_value_pointer(apArg[0], "fts5_api_ptr");
|
||||
if( ppApi ) *ppApi = &pGlobal->api;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2680,7 +2681,7 @@ static int fts5Init(sqlite3 *db){
|
||||
if( rc==SQLITE_OK ) rc = sqlite3Fts5VocabInit(pGlobal, db);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3_create_function(
|
||||
db, "fts5", 0, SQLITE_UTF8, p, fts5Fts5Func, 0, 0
|
||||
db, "fts5", 1, SQLITE_UTF8, p, fts5Fts5Func, 0, 0
|
||||
);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
|
||||
@@ -136,7 +136,8 @@ static int fts5StorageGetStmt(
|
||||
if( zSql==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
rc = sqlite3_prepare_v2(pC->db, zSql, -1, &p->aStmt[eStmt], 0);
|
||||
rc = sqlite3_prepare_v3(pC->db, zSql, -1,
|
||||
SQLITE_PREPARE_PERSISTENT, &p->aStmt[eStmt], 0);
|
||||
sqlite3_free(zSql);
|
||||
if( rc!=SQLITE_OK && pzErrMsg ){
|
||||
*pzErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(pC->db));
|
||||
|
||||
+3
-6
@@ -99,16 +99,13 @@ static int SQLITE_TCLAPI f5tDbAndApi(
|
||||
sqlite3_stmt *pStmt = 0;
|
||||
fts5_api *pApi = 0;
|
||||
|
||||
rc = sqlite3_prepare_v2(db, "SELECT fts5()", -1, &pStmt, 0);
|
||||
rc = sqlite3_prepare_v2(db, "SELECT fts5(?1)", -1, &pStmt, 0);
|
||||
if( rc!=SQLITE_OK ){
|
||||
Tcl_AppendResult(interp, "error: ", sqlite3_errmsg(db), 0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
if( SQLITE_ROW==sqlite3_step(pStmt) ){
|
||||
const void *pPtr = sqlite3_column_blob(pStmt, 0);
|
||||
memcpy((void*)&pApi, pPtr, sizeof(pApi));
|
||||
}
|
||||
sqlite3_bind_pointer(pStmt, 1, (void*)&pApi, "fts5_api_ptr", 0);
|
||||
sqlite3_step(pStmt);
|
||||
|
||||
if( sqlite3_finalize(pStmt)!=SQLITE_OK ){
|
||||
Tcl_AppendResult(interp, "error: ", sqlite3_errmsg(db), 0);
|
||||
|
||||
@@ -73,13 +73,10 @@ static int fts5_api_from_db(sqlite3 *db, fts5_api **ppApi){
|
||||
int rc;
|
||||
|
||||
*ppApi = 0;
|
||||
rc = sqlite3_prepare(db, "SELECT fts5()", -1, &pStmt, 0);
|
||||
rc = sqlite3_prepare(db, "SELECT fts5(?1)", -1, &pStmt, 0);
|
||||
if( rc==SQLITE_OK ){
|
||||
if( SQLITE_ROW==sqlite3_step(pStmt)
|
||||
&& sizeof(fts5_api*)==sqlite3_column_bytes(pStmt, 0)
|
||||
){
|
||||
memcpy(ppApi, sqlite3_column_blob(pStmt, 0), sizeof(fts5_api*));
|
||||
}
|
||||
sqlite3_bind_pointer(pStmt, 1, (void*)ppApi, "fts5_api_ptr", 0);
|
||||
(void)sqlite3_step(pStmt);
|
||||
rc = sqlite3_finalize(pStmt);
|
||||
}
|
||||
|
||||
@@ -422,4 +419,3 @@ int sqlite3Fts5TestRegisterMatchinfo(sqlite3 *db){
|
||||
}
|
||||
|
||||
#endif /* SQLITE_ENABLE_FTS5 */
|
||||
|
||||
|
||||
@@ -182,7 +182,7 @@ static int fts5tokConnectMethod(
|
||||
Fts5tokTable *pTab = 0;
|
||||
int rc;
|
||||
char **azDequote = 0;
|
||||
int nDequote;
|
||||
int nDequote = 0;
|
||||
|
||||
rc = sqlite3_declare_vtab(db,
|
||||
"CREATE TABLE x(input HIDDEN, token, start, end, position)"
|
||||
|
||||
+139
-26
@@ -29,6 +29,11 @@
|
||||
** the number of fts5 rows that contain at least one instance of term
|
||||
** $term. Field $cnt is set to the total number of instances of term
|
||||
** $term in the database.
|
||||
**
|
||||
** instance:
|
||||
** CREATE TABLE vocab(term, doc, col, offset, PRIMARY KEY(<all-fields>));
|
||||
**
|
||||
** One row for each term instance in the database.
|
||||
*/
|
||||
|
||||
|
||||
@@ -44,7 +49,7 @@ struct Fts5VocabTable {
|
||||
char *zFts5Db; /* Db containing fts5 table */
|
||||
sqlite3 *db; /* Database handle */
|
||||
Fts5Global *pGlobal; /* FTS5 global object for this database */
|
||||
int eType; /* FTS5_VOCAB_COL or ROW */
|
||||
int eType; /* FTS5_VOCAB_COL, ROW or INSTANCE */
|
||||
};
|
||||
|
||||
struct Fts5VocabCursor {
|
||||
@@ -64,16 +69,22 @@ struct Fts5VocabCursor {
|
||||
i64 *aCnt;
|
||||
i64 *aDoc;
|
||||
|
||||
/* Output values used by 'row' and 'col' tables */
|
||||
/* Output values used by all tables. */
|
||||
i64 rowid; /* This table's current rowid value */
|
||||
Fts5Buffer term; /* Current value of 'term' column */
|
||||
|
||||
/* Output values Used by 'instance' tables only */
|
||||
i64 iInstPos;
|
||||
int iInstOff;
|
||||
};
|
||||
|
||||
#define FTS5_VOCAB_COL 0
|
||||
#define FTS5_VOCAB_ROW 1
|
||||
#define FTS5_VOCAB_COL 0
|
||||
#define FTS5_VOCAB_ROW 1
|
||||
#define FTS5_VOCAB_INSTANCE 2
|
||||
|
||||
#define FTS5_VOCAB_COL_SCHEMA "term, col, doc, cnt"
|
||||
#define FTS5_VOCAB_ROW_SCHEMA "term, doc, cnt"
|
||||
#define FTS5_VOCAB_INST_SCHEMA "term, doc, col, offset"
|
||||
|
||||
/*
|
||||
** Bits for the mask used as the idxNum value by xBestIndex/xFilter.
|
||||
@@ -101,6 +112,9 @@ static int fts5VocabTableType(const char *zType, char **pzErr, int *peType){
|
||||
if( sqlite3_stricmp(zCopy, "row")==0 ){
|
||||
*peType = FTS5_VOCAB_ROW;
|
||||
}else
|
||||
if( sqlite3_stricmp(zCopy, "instance")==0 ){
|
||||
*peType = FTS5_VOCAB_INSTANCE;
|
||||
}else
|
||||
{
|
||||
*pzErr = sqlite3_mprintf("fts5vocab: unknown table type: %Q", zCopy);
|
||||
rc = SQLITE_ERROR;
|
||||
@@ -161,7 +175,8 @@ static int fts5VocabInitVtab(
|
||||
){
|
||||
const char *azSchema[] = {
|
||||
"CREATE TABlE vocab(" FTS5_VOCAB_COL_SCHEMA ")",
|
||||
"CREATE TABlE vocab(" FTS5_VOCAB_ROW_SCHEMA ")"
|
||||
"CREATE TABlE vocab(" FTS5_VOCAB_ROW_SCHEMA ")",
|
||||
"CREATE TABlE vocab(" FTS5_VOCAB_INST_SCHEMA ")"
|
||||
};
|
||||
|
||||
Fts5VocabTable *pRet = 0;
|
||||
@@ -235,6 +250,15 @@ static int fts5VocabCreateMethod(
|
||||
|
||||
/*
|
||||
** Implementation of the xBestIndex method.
|
||||
**
|
||||
** Only constraints of the form:
|
||||
**
|
||||
** term <= ?
|
||||
** term == ?
|
||||
** term >= ?
|
||||
**
|
||||
** are interpreted. Less-than and less-than-or-equal are treated
|
||||
** identically, as are greater-than and greater-than-or-equal.
|
||||
*/
|
||||
static int fts5VocabBestIndexMethod(
|
||||
sqlite3_vtab *pUnused,
|
||||
@@ -378,6 +402,54 @@ static int fts5VocabCloseMethod(sqlite3_vtab_cursor *pCursor){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
static int fts5VocabInstanceNewTerm(Fts5VocabCursor *pCsr){
|
||||
int rc = SQLITE_OK;
|
||||
|
||||
if( sqlite3Fts5IterEof(pCsr->pIter) ){
|
||||
pCsr->bEof = 1;
|
||||
}else{
|
||||
const char *zTerm;
|
||||
int nTerm;
|
||||
zTerm = sqlite3Fts5IterTerm(pCsr->pIter, &nTerm);
|
||||
if( pCsr->nLeTerm>=0 ){
|
||||
int nCmp = MIN(nTerm, pCsr->nLeTerm);
|
||||
int bCmp = memcmp(pCsr->zLeTerm, zTerm, nCmp);
|
||||
if( bCmp<0 || (bCmp==0 && pCsr->nLeTerm<nTerm) ){
|
||||
pCsr->bEof = 1;
|
||||
}
|
||||
}
|
||||
|
||||
sqlite3Fts5BufferSet(&rc, &pCsr->term, nTerm, (const u8*)zTerm);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int fts5VocabInstanceNext(Fts5VocabCursor *pCsr){
|
||||
int eDetail = pCsr->pConfig->eDetail;
|
||||
int rc = SQLITE_OK;
|
||||
Fts5IndexIter *pIter = pCsr->pIter;
|
||||
i64 *pp = &pCsr->iInstPos;
|
||||
int *po = &pCsr->iInstOff;
|
||||
|
||||
while( eDetail==FTS5_DETAIL_NONE
|
||||
|| sqlite3Fts5PoslistNext64(pIter->pData, pIter->nData, po, pp)
|
||||
){
|
||||
pCsr->iInstPos = 0;
|
||||
pCsr->iInstOff = 0;
|
||||
|
||||
rc = sqlite3Fts5IterNextScan(pCsr->pIter);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = fts5VocabInstanceNewTerm(pCsr);
|
||||
if( eDetail==FTS5_DETAIL_NONE ) break;
|
||||
}
|
||||
if( rc ){
|
||||
pCsr->bEof = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Advance the cursor to the next row in the table.
|
||||
@@ -390,13 +462,17 @@ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){
|
||||
|
||||
pCsr->rowid++;
|
||||
|
||||
if( pTab->eType==FTS5_VOCAB_INSTANCE ){
|
||||
return fts5VocabInstanceNext(pCsr);
|
||||
}
|
||||
|
||||
if( pTab->eType==FTS5_VOCAB_COL ){
|
||||
for(pCsr->iCol++; pCsr->iCol<nCol; pCsr->iCol++){
|
||||
if( pCsr->aDoc[pCsr->iCol] ) break;
|
||||
}
|
||||
}
|
||||
|
||||
if( pTab->eType==FTS5_VOCAB_ROW || pCsr->iCol>=nCol ){
|
||||
if( pTab->eType!=FTS5_VOCAB_COL || pCsr->iCol>=nCol ){
|
||||
if( sqlite3Fts5IterEof(pCsr->pIter) ){
|
||||
pCsr->bEof = 1;
|
||||
}else{
|
||||
@@ -420,22 +496,26 @@ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){
|
||||
|
||||
assert( pTab->eType==FTS5_VOCAB_COL || pTab->eType==FTS5_VOCAB_ROW );
|
||||
while( rc==SQLITE_OK ){
|
||||
int eDetail = pCsr->pConfig->eDetail;
|
||||
const u8 *pPos; int nPos; /* Position list */
|
||||
i64 iPos = 0; /* 64-bit position read from poslist */
|
||||
int iOff = 0; /* Current offset within position list */
|
||||
|
||||
pPos = pCsr->pIter->pData;
|
||||
nPos = pCsr->pIter->nData;
|
||||
switch( pCsr->pConfig->eDetail ){
|
||||
case FTS5_DETAIL_FULL:
|
||||
pPos = pCsr->pIter->pData;
|
||||
nPos = pCsr->pIter->nData;
|
||||
if( pTab->eType==FTS5_VOCAB_ROW ){
|
||||
|
||||
switch( pTab->eType ){
|
||||
case FTS5_VOCAB_ROW:
|
||||
if( eDetail==FTS5_DETAIL_FULL ){
|
||||
while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff, &iPos) ){
|
||||
pCsr->aCnt[0]++;
|
||||
}
|
||||
pCsr->aDoc[0]++;
|
||||
}else{
|
||||
}
|
||||
pCsr->aDoc[0]++;
|
||||
break;
|
||||
|
||||
case FTS5_VOCAB_COL:
|
||||
if( eDetail==FTS5_DETAIL_FULL ){
|
||||
int iCol = -1;
|
||||
while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff, &iPos) ){
|
||||
int ii = FTS5_POS2COLUMN(iPos);
|
||||
@@ -449,13 +529,7 @@ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){
|
||||
iCol = ii;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case FTS5_DETAIL_COLUMNS:
|
||||
if( pTab->eType==FTS5_VOCAB_ROW ){
|
||||
pCsr->aDoc[0]++;
|
||||
}else{
|
||||
}else if( eDetail==FTS5_DETAIL_COLUMNS ){
|
||||
while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff,&iPos) ){
|
||||
assert_nc( iPos>=0 && iPos<nCol );
|
||||
if( iPos>=nCol ){
|
||||
@@ -464,18 +538,21 @@ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){
|
||||
}
|
||||
pCsr->aDoc[iPos]++;
|
||||
}
|
||||
}else{
|
||||
assert( eDetail==FTS5_DETAIL_NONE );
|
||||
pCsr->aDoc[0]++;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
assert( pCsr->pConfig->eDetail==FTS5_DETAIL_NONE );
|
||||
pCsr->aDoc[0]++;
|
||||
default:
|
||||
assert( pTab->eType==FTS5_VOCAB_INSTANCE );
|
||||
break;
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3Fts5IterNextScan(pCsr->pIter);
|
||||
}
|
||||
if( pTab->eType==FTS5_VOCAB_INSTANCE ) break;
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
zTerm = sqlite3Fts5IterTerm(pCsr->pIter, &nTerm);
|
||||
@@ -505,7 +582,9 @@ static int fts5VocabFilterMethod(
|
||||
int nUnused, /* Number of elements in apVal */
|
||||
sqlite3_value **apVal /* Arguments for the indexing scheme */
|
||||
){
|
||||
Fts5VocabTable *pTab = (Fts5VocabTable*)pCursor->pVtab;
|
||||
Fts5VocabCursor *pCsr = (Fts5VocabCursor*)pCursor;
|
||||
int eType = pTab->eType;
|
||||
int rc = SQLITE_OK;
|
||||
|
||||
int iVal = 0;
|
||||
@@ -545,11 +624,16 @@ static int fts5VocabFilterMethod(
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3Fts5IndexQuery(pCsr->pIndex, zTerm, nTerm, f, 0, &pCsr->pIter);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
if( rc==SQLITE_OK && eType==FTS5_VOCAB_INSTANCE ){
|
||||
rc = fts5VocabInstanceNewTerm(pCsr);
|
||||
}
|
||||
if( rc==SQLITE_OK
|
||||
&& !pCsr->bEof
|
||||
&& (eType!=FTS5_VOCAB_INSTANCE || pCsr->pConfig->eDetail!=FTS5_DETAIL_NONE)
|
||||
){
|
||||
rc = fts5VocabNextMethod(pCursor);
|
||||
}
|
||||
|
||||
@@ -591,13 +675,42 @@ static int fts5VocabColumnMethod(
|
||||
}else{
|
||||
iVal = pCsr->aCnt[pCsr->iCol];
|
||||
}
|
||||
}else{
|
||||
}else if( eType==FTS5_VOCAB_ROW ){
|
||||
assert( iCol==1 || iCol==2 );
|
||||
if( iCol==1 ){
|
||||
iVal = pCsr->aDoc[0];
|
||||
}else{
|
||||
iVal = pCsr->aCnt[0];
|
||||
}
|
||||
}else{
|
||||
int eDetail = pCsr->pConfig->eDetail;
|
||||
assert( eType==FTS5_VOCAB_INSTANCE );
|
||||
switch( iCol ){
|
||||
case 1:
|
||||
sqlite3_result_int64(pCtx, pCsr->pIter->iRowid);
|
||||
break;
|
||||
case 2: {
|
||||
int ii = -1;
|
||||
if( eDetail==FTS5_DETAIL_FULL ){
|
||||
ii = FTS5_POS2COLUMN(pCsr->iInstPos);
|
||||
}else if( eDetail==FTS5_DETAIL_COLUMNS ){
|
||||
ii = pCsr->iInstPos;
|
||||
}
|
||||
if( ii>=0 && ii<pCsr->pConfig->nCol ){
|
||||
const char *z = pCsr->pConfig->azCol[ii];
|
||||
sqlite3_result_text(pCtx, z, -1, SQLITE_STATIC);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
assert( iCol==3 );
|
||||
if( eDetail==FTS5_DETAIL_FULL ){
|
||||
int ii = FTS5_POS2OFFSET(pCsr->iInstPos);
|
||||
sqlite3_result_int(pCtx, ii);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( iVal>0 ) sqlite3_result_int64(pCtx, iVal);
|
||||
|
||||
@@ -441,7 +441,7 @@ db func funk funk
|
||||
do_catchsql_test 16.2 {
|
||||
SELECT funk(), bm25(n1), funk() FROM n1 WHERE n1 MATCH 'a+b+c+d'
|
||||
} {0 {{} -1e-06 {}}}
|
||||
# {1 {SQL logic error or missing database}}
|
||||
# {1 {SQL logic error}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
@@ -595,5 +595,3 @@ do_execsql_test 22.1 {
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
|
||||
@@ -294,4 +294,3 @@ do_execsql_test 7.0 {
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -276,4 +276,3 @@ foreach {tn expr tclexpr} {
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -231,7 +231,6 @@ foreach {T create} {
|
||||
set res [lsort -integer -increasing $res]
|
||||
}
|
||||
set n [llength $res]
|
||||
if {$T==5} breakpoint
|
||||
do_execsql_test $T.$bAsc.$tn.$n $sql $res
|
||||
}
|
||||
}
|
||||
@@ -242,4 +241,3 @@ foreach {T create} {
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -309,4 +309,3 @@ foreach {tn q cnt} {
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -178,4 +178,3 @@ do_execsql_test 5.1 {
|
||||
} ;# foreach_detail_mode
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -142,4 +142,3 @@ if {[detail_is_full]} {
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -167,4 +167,3 @@ do_execsql_test 1.8.2 {
|
||||
#db eval {SELECT rowid, fts5_decode(rowid, block) aS r FROM t1_data} {puts $r}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -55,4 +55,3 @@ do_execsql_test 1.2 {
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -66,4 +66,3 @@ do_execsql_test 2.0 { INSERT INTO t1(t1) VALUES('integrity-check') }
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -147,4 +147,3 @@ do_execsql_test 3.1 {
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ foreach {tn defn} {
|
||||
} {
|
||||
do_test 2.2.$tn {
|
||||
catchsql { INSERT INTO ft1(ft1, rank) VALUES('rank', $defn) }
|
||||
} {1 {SQL logic error or missing database}}
|
||||
} {1 {SQL logic error}}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
@@ -297,4 +297,3 @@ do_catchsql_test 4.4.4 {
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -89,7 +89,6 @@ do_execsql_test 3.1 {
|
||||
BEGIN;
|
||||
INSERT INTO abc(rowid, a) VALUES(2, 'a');
|
||||
}
|
||||
breakpoint
|
||||
do_execsql_test 3.2 {
|
||||
SELECT rowid FROM abc WHERE abc MATCH 'a';
|
||||
} {1 2}
|
||||
@@ -100,4 +99,3 @@ do_execsql_test 3.3 {
|
||||
} {1 2}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -342,4 +342,3 @@ foreach {tn expr} {
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -240,7 +240,6 @@ foreach {tn lRow res} {
|
||||
} {
|
||||
execsql { DELETE FROM x1 }
|
||||
foreach row $lRow { execsql { INSERT INTO x1 VALUES($row) } }
|
||||
breakpoint
|
||||
do_execsql_test 8.$tn {
|
||||
SELECT highlight(x1, 0, '[', ']') FROM x1 WHERE x1 MATCH 'a OR (b AND d)';
|
||||
} $res
|
||||
@@ -279,4 +278,3 @@ do_execsql_test 9.3 {
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -112,4 +112,3 @@ db eval {
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -61,4 +61,3 @@ do_test 2.1...slow {
|
||||
} {}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -64,5 +64,3 @@ foreach_detail_mode $::testprefix {
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
|
||||
@@ -84,5 +84,3 @@ foreach_detail_mode $::testprefix {
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
|
||||
@@ -143,7 +143,6 @@ do_execsql_test 4.1.1 {
|
||||
INSERT INTO t5 VALUES('2 4 6 8');
|
||||
}
|
||||
|
||||
breakpoint
|
||||
do_execsql_test 4.1.2 {
|
||||
INSERT INTO t5(t5) VALUES('integrity-check');
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ foreach {tn val} {
|
||||
} {
|
||||
do_catchsql_test 3.$tn {
|
||||
INSERT INTO t1(t1, rank) VALUES('rank', $val);
|
||||
} {1 {SQL logic error or missing database}}
|
||||
} {1 {SQL logic error}}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
@@ -110,7 +110,6 @@ do_catchsql_test 5.1 {
|
||||
CREATE VIRTUAL TABLE xx USING fts5(x, tokenize="porter 'ascii");
|
||||
} {1 {parse error in tokenize directive}}
|
||||
|
||||
breakpoint
|
||||
do_catchsql_test 5.2 {
|
||||
CREATE VIRTUAL TABLE xx USING fts5(x, [y[]);
|
||||
} {0 {}}
|
||||
@@ -169,33 +168,33 @@ do_execsql_test 9.0 {
|
||||
} {}
|
||||
do_catchsql_test 9.1.1 {
|
||||
INSERT INTO abc(abc, rank) VALUES('pgsz', -5);
|
||||
} {1 {SQL logic error or missing database}}
|
||||
} {1 {SQL logic error}}
|
||||
do_catchsql_test 9.1.2 {
|
||||
INSERT INTO abc(abc, rank) VALUES('pgsz', 50000000);
|
||||
} {1 {SQL logic error or missing database}}
|
||||
} {1 {SQL logic error}}
|
||||
do_catchsql_test 9.1.3 {
|
||||
INSERT INTO abc(abc, rank) VALUES('pgsz', 66.67);
|
||||
} {1 {SQL logic error or missing database}}
|
||||
} {1 {SQL logic error}}
|
||||
|
||||
do_catchsql_test 9.2.1 {
|
||||
INSERT INTO abc(abc, rank) VALUES('automerge', -5);
|
||||
} {1 {SQL logic error or missing database}}
|
||||
} {1 {SQL logic error}}
|
||||
do_catchsql_test 9.2.2 {
|
||||
INSERT INTO abc(abc, rank) VALUES('automerge', 50000000);
|
||||
} {1 {SQL logic error or missing database}}
|
||||
} {1 {SQL logic error}}
|
||||
do_catchsql_test 9.2.3 {
|
||||
INSERT INTO abc(abc, rank) VALUES('automerge', 66.67);
|
||||
} {1 {SQL logic error or missing database}}
|
||||
} {1 {SQL logic error}}
|
||||
do_execsql_test 9.2.4 {
|
||||
INSERT INTO abc(abc, rank) VALUES('automerge', 1);
|
||||
} {}
|
||||
|
||||
do_catchsql_test 9.3.1 {
|
||||
INSERT INTO abc(abc, rank) VALUES('crisismerge', -5);
|
||||
} {1 {SQL logic error or missing database}}
|
||||
} {1 {SQL logic error}}
|
||||
do_catchsql_test 9.3.2 {
|
||||
INSERT INTO abc(abc, rank) VALUES('crisismerge', 66.67);
|
||||
} {1 {SQL logic error or missing database}}
|
||||
} {1 {SQL logic error}}
|
||||
do_execsql_test 9.3.3 {
|
||||
INSERT INTO abc(abc, rank) VALUES('crisismerge', 1);
|
||||
} {}
|
||||
@@ -205,14 +204,14 @@ do_execsql_test 9.3.4 {
|
||||
|
||||
do_catchsql_test 9.4.1 {
|
||||
INSERT INTO abc(abc, rank) VALUES('nosuchoption', 1);
|
||||
} {1 {SQL logic error or missing database}}
|
||||
} {1 {SQL logic error}}
|
||||
|
||||
do_catchsql_test 9.5.1 {
|
||||
INSERT INTO abc(abc, rank) VALUES('hashsize', 'not an integer');
|
||||
} {1 {SQL logic error or missing database}}
|
||||
} {1 {SQL logic error}}
|
||||
do_catchsql_test 9.5.2 {
|
||||
INSERT INTO abc(abc, rank) VALUES('hashsize', -500000);
|
||||
} {1 {SQL logic error or missing database}}
|
||||
} {1 {SQL logic error}}
|
||||
do_catchsql_test 9.5.3 {
|
||||
INSERT INTO abc(abc, rank) VALUES('hashsize', 500000);
|
||||
} {0 {}}
|
||||
@@ -245,7 +244,7 @@ foreach {tn opt} {
|
||||
|
||||
do_catchsql_test 12.1 {
|
||||
INSERT INTO t1(t1, rank) VALUES('rank', NULL);;
|
||||
} {1 {SQL logic error or missing database}}
|
||||
} {1 {SQL logic error}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# errors in the 'usermerge' option
|
||||
@@ -260,8 +259,7 @@ foreach {tn val} {
|
||||
4 1
|
||||
} {
|
||||
set sql "INSERT INTO tt(tt, rank) VALUES('usermerge', $val)"
|
||||
do_catchsql_test 13.$tn $sql {1 {SQL logic error or missing database}}
|
||||
do_catchsql_test 13.$tn $sql {1 {SQL logic error}}
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -66,5 +66,3 @@ do_execsql_test 2.1 {
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,247 @@
|
||||
# 2017 August 17
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
#*************************************************************************
|
||||
#
|
||||
|
||||
|
||||
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5connect
|
||||
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# The tests in this file test the outcome of a schema-reset happening
|
||||
# within the xConnect() method of an FTS5 table. At one point this
|
||||
# was causing a problem in SQLite. Each test proceeds as follows:
|
||||
#
|
||||
# 1. Connection [db] opens the db and reads from some unrelated, non-FTS5
|
||||
# table causing SQLite to load the db schema into memory.
|
||||
#
|
||||
# 2. Connection [db2] opens the db and modifies the db schema.
|
||||
#
|
||||
# 3. Connection [db] reads or writes an existing fts5 table. That the
|
||||
# schema has been modified is detected inside the fts5 xConnect()
|
||||
# callback that is invoked by sqlite3_prepare().
|
||||
#
|
||||
# 4. Verify that the statement in 3 has worked. SQLite should detect
|
||||
# that the schema has changed and successfully prepare the
|
||||
# statement against the new schema.
|
||||
#
|
||||
# Test plan:
|
||||
#
|
||||
# 1.*: Trigger the xConnect()/schema-reset using statements executed
|
||||
# directly against an FTS5 table.
|
||||
#
|
||||
# 2.*: Using various statements executed by various BEFORE triggers.
|
||||
#
|
||||
# 3.*: Using various statements executed by various AFTER triggers.
|
||||
#
|
||||
# 4.*: Using various statements executed by various INSTEAD OF triggers.
|
||||
#
|
||||
|
||||
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE VIRTUAL TABLE ft1 USING fts5(a, b);
|
||||
CREATE TABLE abc(x INTEGER PRIMARY KEY);
|
||||
CREATE TABLE t1(i INTEGER PRIMARY KEY, a, b);
|
||||
|
||||
INSERT INTO ft1 VALUES('one', 'two');
|
||||
INSERT INTO ft1 VALUES('three', 'four');
|
||||
}
|
||||
|
||||
foreach {tn sql res} {
|
||||
1 "SELECT * FROM ft1" {one two three four}
|
||||
2 "REPLACE INTO ft1(rowid, a, b) VALUES(1, 'five', 'six')" {}
|
||||
3 "SELECT * FROM ft1" {five six three four}
|
||||
4 "INSERT INTO ft1 VALUES('seven', 'eight')" {}
|
||||
5 "SELECT * FROM ft1" {five six three four seven eight}
|
||||
6 "DELETE FROM ft1 WHERE rowid=2" {}
|
||||
7 "UPDATE ft1 SET b='nine' WHERE rowid=1" {}
|
||||
8 "SELECT * FROM ft1" {five nine seven eight}
|
||||
} {
|
||||
|
||||
catch { db close }
|
||||
catch { db2 close }
|
||||
sqlite3 db test.db
|
||||
sqlite3 db2 test.db
|
||||
|
||||
do_test 1.$tn.1 {
|
||||
db eval { INSERT INTO abc DEFAULT VALUES }
|
||||
db2 eval { CREATE TABLE newtable(x,y); DROP TABLE newtable }
|
||||
} {}
|
||||
|
||||
do_execsql_test 1.$tn.2 $sql $res
|
||||
|
||||
do_execsql_test 1.$tn.3 {
|
||||
INSERT INTO ft1(ft1) VALUES('integrity-check');
|
||||
}
|
||||
}
|
||||
|
||||
do_execsql_test 2.0 {
|
||||
CREATE VIRTUAL TABLE ft2 USING fts5(a, b);
|
||||
CREATE TABLE t2(a, b);
|
||||
CREATE TABLE log(txt);
|
||||
|
||||
CREATE TRIGGER t2_ai AFTER INSERT ON t2 BEGIN
|
||||
INSERT INTO ft2(rowid, a, b) VALUES(new.rowid, new.a, new.b);
|
||||
INSERT INTO log VALUES('insert');
|
||||
END;
|
||||
|
||||
CREATE TRIGGER t2_ad AFTER DELETE ON t2 BEGIN
|
||||
DELETE FROM ft2 WHERE rowid = old.rowid;
|
||||
INSERT INTO log VALUES('delete');
|
||||
END;
|
||||
|
||||
CREATE TRIGGER t2_au AFTER UPDATE ON t2 BEGIN
|
||||
UPDATE ft2 SET a=new.a, b=new.b WHERE rowid=new.rowid;
|
||||
INSERT INTO log VALUES('update');
|
||||
END;
|
||||
|
||||
INSERT INTO t2 VALUES('one', 'two');
|
||||
INSERT INTO t2 VALUES('three', 'four');
|
||||
}
|
||||
|
||||
foreach {tn sql res} {
|
||||
1 "SELECT * FROM t2" {one two three four}
|
||||
2 "REPLACE INTO t2(rowid, a, b) VALUES(1, 'five', 'six')" {}
|
||||
3 "SELECT * FROM ft2" {five six three four}
|
||||
4 "INSERT INTO t2 VALUES('seven', 'eight')" {}
|
||||
5 "SELECT * FROM ft2" {five six three four seven eight}
|
||||
6 "DELETE FROM t2 WHERE rowid=2" {}
|
||||
7 "UPDATE t2 SET b='nine' WHERE rowid=1" {}
|
||||
8 "SELECT * FROM ft2" {five nine seven eight}
|
||||
} {
|
||||
|
||||
catch { db close }
|
||||
catch { db2 close }
|
||||
sqlite3 db test.db
|
||||
sqlite3 db2 test.db
|
||||
|
||||
do_test 2.$tn.1 {
|
||||
db eval { INSERT INTO abc DEFAULT VALUES }
|
||||
db2 eval { CREATE TABLE newtable(x,y); DROP TABLE newtable }
|
||||
} {}
|
||||
|
||||
do_execsql_test 2.$tn.2 $sql $res
|
||||
|
||||
do_execsql_test 2.$tn.3 {
|
||||
INSERT INTO ft2(ft2) VALUES('integrity-check');
|
||||
}
|
||||
}
|
||||
|
||||
do_execsql_test 3.0 {
|
||||
CREATE VIRTUAL TABLE ft3 USING fts5(a, b);
|
||||
CREATE TABLE t3(a, b);
|
||||
|
||||
CREATE TRIGGER t3_ai BEFORE INSERT ON t3 BEGIN
|
||||
INSERT INTO ft3(rowid, a, b) VALUES(new.rowid, new.a, new.b);
|
||||
INSERT INTO log VALUES('insert');
|
||||
END;
|
||||
|
||||
CREATE TRIGGER t3_ad BEFORE DELETE ON t3 BEGIN
|
||||
DELETE FROM ft3 WHERE rowid = old.rowid;
|
||||
INSERT INTO log VALUES('delete');
|
||||
END;
|
||||
|
||||
CREATE TRIGGER t3_au BEFORE UPDATE ON t3 BEGIN
|
||||
UPDATE ft3 SET a=new.a, b=new.b WHERE rowid=new.rowid;
|
||||
INSERT INTO log VALUES('update');
|
||||
END;
|
||||
|
||||
INSERT INTO t3(rowid, a, b) VALUES(1, 'one', 'two');
|
||||
INSERT INTO t3(rowid, a, b) VALUES(2, 'three', 'four');
|
||||
}
|
||||
|
||||
foreach {tn sql res} {
|
||||
1 "SELECT * FROM t3" {one two three four}
|
||||
2 "REPLACE INTO t3(rowid, a, b) VALUES(1, 'five', 'six')" {}
|
||||
3 "SELECT * FROM ft3" {five six three four}
|
||||
4 "INSERT INTO t3(rowid, a, b) VALUES(3, 'seven', 'eight')" {}
|
||||
5 "SELECT * FROM ft3" {five six three four seven eight}
|
||||
6 "DELETE FROM t3 WHERE rowid=2" {}
|
||||
7 "UPDATE t3 SET b='nine' WHERE rowid=1" {}
|
||||
8 "SELECT * FROM ft3" {five nine seven eight}
|
||||
} {
|
||||
|
||||
catch { db close }
|
||||
catch { db2 close }
|
||||
sqlite3 db test.db
|
||||
sqlite3 db2 test.db
|
||||
|
||||
do_test 3.$tn.1 {
|
||||
db eval { INSERT INTO abc DEFAULT VALUES }
|
||||
db2 eval { CREATE TABLE newtable(x,y); DROP TABLE newtable }
|
||||
} {}
|
||||
|
||||
do_execsql_test 3.$tn.2 $sql $res
|
||||
|
||||
do_execsql_test 3.$tn.3 {
|
||||
INSERT INTO ft3(ft3) VALUES('integrity-check');
|
||||
}
|
||||
}
|
||||
|
||||
do_execsql_test 4.0 {
|
||||
CREATE VIRTUAL TABLE ft4 USING fts5(a, b);
|
||||
CREATE VIEW v4 AS SELECT rowid, * FROM ft4;
|
||||
|
||||
CREATE TRIGGER t4_ai INSTEAD OF INSERT ON v4 BEGIN
|
||||
INSERT INTO ft4(rowid, a, b) VALUES(new.rowid, new.a, new.b);
|
||||
INSERT INTO log VALUES('insert');
|
||||
END;
|
||||
|
||||
CREATE TRIGGER t4_ad INSTEAD OF DELETE ON v4 BEGIN
|
||||
DELETE FROM ft4 WHERE rowid = old.rowid;
|
||||
INSERT INTO log VALUES('delete');
|
||||
END;
|
||||
|
||||
CREATE TRIGGER t4_au INSTEAD OF UPDATE ON v4 BEGIN
|
||||
UPDATE ft4 SET a=new.a, b=new.b WHERE rowid=new.rowid;
|
||||
INSERT INTO log VALUES('update');
|
||||
END;
|
||||
|
||||
INSERT INTO ft4(rowid, a, b) VALUES(1, 'one', 'two');
|
||||
INSERT INTO ft4(rowid, a, b) VALUES(2, 'three', 'four');
|
||||
}
|
||||
|
||||
foreach {tn sql res} {
|
||||
1 "SELECT * FROM ft4" {one two three four}
|
||||
2 "REPLACE INTO v4(rowid, a, b) VALUES(1, 'five', 'six')" {}
|
||||
3 "SELECT * FROM ft4" {five six three four}
|
||||
4 "INSERT INTO v4(rowid, a, b) VALUES(3, 'seven', 'eight')" {}
|
||||
5 "SELECT * FROM ft4" {five six three four seven eight}
|
||||
6 "DELETE FROM v4 WHERE rowid=2" {}
|
||||
7 "UPDATE v4 SET b='nine' WHERE rowid=1" {}
|
||||
8 "SELECT * FROM ft4" {five nine seven eight}
|
||||
} {
|
||||
|
||||
catch { db close }
|
||||
catch { db2 close }
|
||||
sqlite3 db test.db
|
||||
sqlite3 db2 test.db
|
||||
|
||||
do_test 4.$tn.1 {
|
||||
db eval { INSERT INTO abc DEFAULT VALUES }
|
||||
db2 eval { CREATE TABLE newtable(x,y); DROP TABLE newtable }
|
||||
} {}
|
||||
|
||||
do_execsql_test 4.$tn.2 $sql $res
|
||||
|
||||
do_execsql_test 4.$tn.3 {
|
||||
INSERT INTO ft3(ft3) VALUES('integrity-check');
|
||||
}
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -255,4 +255,3 @@ do_execsql_test 6.2 {
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -96,4 +96,3 @@ do_catchsql_test 3.1 {
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -269,4 +269,3 @@ do_catchsql_test 6.2 {
|
||||
|
||||
sqlite3_fts5_may_be_corrupt 0
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -409,4 +409,3 @@ do_catchsql_test 9.2.2 {
|
||||
|
||||
sqlite3_fts5_may_be_corrupt 0
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -51,4 +51,3 @@ do_test 1.2 {
|
||||
} {}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -241,4 +241,3 @@ do_execsql_test 5.3 {
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -63,5 +63,3 @@ foreach_detail_mode $::testprefix {
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
|
||||
@@ -66,7 +66,6 @@ proc do_dlidx_test1 {tn spc1 spc2 nEntry iFirst nStep} {
|
||||
}
|
||||
execsql COMMIT
|
||||
|
||||
breakpoint
|
||||
do_test $tn.1 {
|
||||
execsql { INSERT INTO t1(t1) VALUES('integrity-check') }
|
||||
} {}
|
||||
@@ -124,7 +123,6 @@ proc do_dlidx_test2 {tn nEntry iFirst nStep} {
|
||||
do_execsql_test $tn.1 {
|
||||
SELECT rowid FROM t1 WHERE t1 MATCH 'b AND a'
|
||||
} {1}
|
||||
breakpoint
|
||||
do_execsql_test $tn.2 {
|
||||
SELECT rowid FROM t1 WHERE t1 MATCH 'b AND a' ORDER BY rowid DESC
|
||||
} {1}
|
||||
@@ -197,4 +195,3 @@ foreach v $vocab {
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -44,4 +44,3 @@ do_execsql_test 1.2 {
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -81,6 +81,3 @@ do_execsql_test 3.3 {
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -351,4 +351,3 @@ do_faultsim_test 9.1 -faults oom-* -prep {
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -137,4 +137,3 @@ do_faultsim_test 5.0 -faults oom-* -prep {
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -110,4 +110,3 @@ do_faultsim_test 3.2 -faults oom-* -prep {
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -395,4 +395,3 @@ do_faultsim_test 14.1 -faults oom-t* -prep {
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -105,7 +105,6 @@ do_faultsim_test 3.2 -faults oom-t* -body {
|
||||
faultsim_test_result {0 {1 10 11 12 13 14 15 16 17 18 19 2}}
|
||||
}
|
||||
|
||||
breakpoint
|
||||
do_execsql_test 3.3.0 {
|
||||
SELECT * FROM tv2;
|
||||
} {
|
||||
@@ -130,4 +129,3 @@ do_faultsim_test 3.3 -faults oom-t* -body {
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -280,7 +280,6 @@ do_faultsim_test 5.4 -faults oom* -prep {
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
catch { db close }
|
||||
breakpoint
|
||||
do_faultsim_test 6 -faults oom* -prep {
|
||||
sqlite_orig db test.db
|
||||
sqlite3_db_config_lookaside db 0 0 0
|
||||
@@ -292,4 +291,3 @@ do_faultsim_test 6 -faults oom* -prep {
|
||||
db close
|
||||
}
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -116,4 +116,3 @@ do_faultsim_test 2.2 -faults oom-* -body {
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -82,4 +82,3 @@ do_faultsim_test 4 -faults oom-* -prep {
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -153,4 +153,3 @@ do_faultsim_test 6 -faults oom-* -body {
|
||||
} ;# foreach_detail_mode...
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -61,4 +61,3 @@ do_faultsim_test 2 -faults oom* -prep {
|
||||
faultsim_test_result {0 {1 2}}
|
||||
}
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -132,4 +132,3 @@ do_faultsim_test 4.2 -faults oom* -body {
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -40,4 +40,3 @@ do_test 1.1 {
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -90,4 +90,3 @@ do_catchsql_test 4.1 {
|
||||
} {1 {fts5: syntax error near "`"}}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -121,7 +121,6 @@ foreach_detail_mode $testprefix {
|
||||
}
|
||||
|
||||
execsql { CREATE VIRTUAL TABLE t2 USING fts5(x, detail=%DETAIL%) }
|
||||
breakpoint
|
||||
execsql {
|
||||
INSERT INTO t2 VALUES($small || ' ' || $big);
|
||||
}
|
||||
@@ -130,4 +129,3 @@ breakpoint
|
||||
} ;# foreach_detail_mode
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -210,4 +210,3 @@ foreach {tn pgsz} {
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -70,4 +70,3 @@ do_execsql_test 1.6 {
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
# 2014 June 17
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#*************************************************************************
|
||||
# This file implements regression tests for SQLite library. The
|
||||
# focus of this script is testing the FTS5 module.
|
||||
#
|
||||
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5leftjoin
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE VIRTUAL TABLE vt USING fts5(x);
|
||||
INSERT INTO vt VALUES('abc');
|
||||
INSERT INTO vt VALUES('xyz');
|
||||
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY);
|
||||
INSERT INTO t1 VALUES(1), (2);
|
||||
}
|
||||
|
||||
do_execsql_test 1.1 {
|
||||
SELECT * FROM t1 LEFT JOIN (
|
||||
SELECT rowid AS rrr, * FROM vt WHERE vt MATCH 'abc'
|
||||
) ON t1.a = rrr
|
||||
} {1 1 abc 2 {} {}}
|
||||
|
||||
do_execsql_test 1.2 {
|
||||
SELECT * FROM t1 LEFT JOIN vt ON (vt MATCH 'abc')
|
||||
} {1 abc 2 abc}
|
||||
|
||||
finish_test
|
||||
@@ -472,7 +472,7 @@ do_execsql_test 12.1 {
|
||||
#
|
||||
reset_db
|
||||
proc xyz {} {}
|
||||
db func fts5 -argcount 0 xyz
|
||||
db func fts5 -argcount 1 xyz
|
||||
do_test 13.1 {
|
||||
list [catch { sqlite3_fts5_register_matchinfo db } msg] $msg
|
||||
} {1 SQLITE_ERROR}
|
||||
@@ -492,4 +492,3 @@ do_catchsql_test 14.2 {
|
||||
} {1 {unrecognized matchinfo flag: d}}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -241,4 +241,3 @@ do_execsql_test 6.3 {
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -55,4 +55,3 @@ do_execsql_test 1.2 {
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -45,4 +45,3 @@ do_multiclient_test tn {
|
||||
};# do_multiclient_test
|
||||
};# foreach_detail_mode
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -68,4 +68,3 @@ do_near_test 1.25 "a b c d e f g h i" { NEAR(i a+b+c+d b+c, 4) } 0
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -178,4 +178,3 @@ do_execsql_test 4.3.1 {
|
||||
do_test 4.2.2 { fts5_level_segs ttt } {3}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -106,4 +106,3 @@ foreach {tn nStep} {
|
||||
do_test 2.$tn.6 { fts5_segcount t1 } 1
|
||||
}
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -116,4 +116,3 @@ do_execsql_test 2.0 {
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -64,4 +64,3 @@ do_eqp_test 1.5 {
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -11803,4 +11803,3 @@ foreach {in out} $test_vocab {
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -67,4 +67,3 @@ foreach {in out} $test_vocab {
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -341,5 +341,3 @@ foreach {tn create} {
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
|
||||
@@ -79,5 +79,3 @@ for {set tn 1 ; set pgsz 64} {$tn<32} {incr tn; incr pgsz 16} {
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
|
||||
@@ -90,6 +90,7 @@ do_test 2.7 {
|
||||
execsql { SELECT rowid FROM tt('a') ORDER BY rank; } db
|
||||
} {1 3 2}
|
||||
|
||||
db2 close
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
# At one point there was a problem with queries such as:
|
||||
@@ -151,4 +152,3 @@ do_execsql_test 4.1 {
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -64,4 +64,3 @@ do_catchsql_test 2.2 {
|
||||
INSERT INTO nc(nc) VALUES('rebuild');
|
||||
} {1 {'rebuild' may not be used with a contentless fts5 table}}
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -149,4 +149,3 @@ do_test 4.3 {
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -216,4 +216,3 @@ do_execsql_test 6.2 {
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -411,7 +411,6 @@ do_catchsql_test 19.2 {
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
breakpoint
|
||||
do_execsql_test 20.0 {
|
||||
CREATE VIRTUAL TABLE x1 USING fts5(x);
|
||||
INSERT INTO x1(x1, rank) VALUES('pgsz', 32);
|
||||
|
||||
@@ -370,4 +370,3 @@ do_execsql_test 17.6 {
|
||||
#db eval {SELECT rowid, fts5_decode_none(rowid, block) aS r FROM t2_data} {puts $r}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -116,4 +116,3 @@ do_execsql_test 4.6 {
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -421,4 +421,3 @@ do_execsql_test 7.1.2 {
|
||||
} ;# foreach_detail_mode
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -161,4 +161,3 @@ foreach {tn expr} {
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -109,7 +109,7 @@ do_catchsql_test 2.0 {
|
||||
do_catchsql_test 2.1 {
|
||||
CREATE VIRTUAL TABLE t4 USING fts5tokenize;
|
||||
SELECT * FROM t4;
|
||||
} {1 {SQL logic error or missing database}}
|
||||
} {1 {SQL logic error}}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -302,4 +302,3 @@ do_test 9.5.2 { set ::flags } {query}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -50,7 +50,6 @@ do_execsql_test 2.0 "
|
||||
INSERT INTO t2 VALUES('\xC0\xC8\xCC');
|
||||
INSERT INTO t3 VALUES('\xC0\xC8\xCC');
|
||||
"
|
||||
breakpoint
|
||||
do_execsql_test 2.1 "
|
||||
SELECT 't1' FROM t1 WHERE t1 MATCH '\xE0\xE8\xEC';
|
||||
SELECT 't2' FROM t2 WHERE t2 MATCH '\xE0\xE8\xEC';
|
||||
@@ -59,4 +58,3 @@ do_execsql_test 2.1 "
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -281,7 +281,6 @@ do_test 4.4 {
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
breakpoint
|
||||
do_unicode_token_test3 5.1 {tokenchars {}} {
|
||||
sqlite3_reset sqlite3_column_int
|
||||
} {
|
||||
|
||||
@@ -126,4 +126,3 @@ do_test 1.5 {
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -76,4 +76,3 @@ do_execsql_test 3.2 {
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -117,5 +117,3 @@ do_execsql_test 2.2.integrity {
|
||||
|
||||
}
|
||||
finish_test
|
||||
|
||||
|
||||
|
||||
@@ -61,4 +61,3 @@ do_test 1.7 {
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -210,7 +210,6 @@ do_execsql_test 5.0 {
|
||||
INSERT INTO aux.t1 VALUES('x n z');
|
||||
}
|
||||
|
||||
breakpoint
|
||||
do_execsql_test 5.1 {
|
||||
CREATE VIRTUAL TABLE temp.vm USING fts5vocab(main, t1, row);
|
||||
CREATE VIRTUAL TABLE temp.vt1 USING fts5vocab(t1, row);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user