Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 2a3489ae82 |
+12
-50
@@ -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 stmt.lo \
|
||||
sqlite3session.lo select.lo sqlite3rbu.lo status.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,8 +350,7 @@ SRC += \
|
||||
$(TOP)/ext/rbu/sqlite3rbu.h \
|
||||
$(TOP)/ext/rbu/sqlite3rbu.c
|
||||
SRC += \
|
||||
$(TOP)/ext/misc/json1.c \
|
||||
$(TOP)/ext/misc/stmt.c
|
||||
$(TOP)/ext/misc/json1.c
|
||||
|
||||
# Generated source code files
|
||||
#
|
||||
@@ -431,11 +430,9 @@ TESTSRC += \
|
||||
$(TOP)/ext/misc/nextchar.c \
|
||||
$(TOP)/ext/misc/percentile.c \
|
||||
$(TOP)/ext/misc/regexp.c \
|
||||
$(TOP)/ext/misc/remember.c \
|
||||
$(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
|
||||
@@ -485,8 +482,7 @@ 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/misc/stmt.c
|
||||
$(TOP)/ext/session/sqlite3session.c
|
||||
|
||||
# Header files used by all library source files.
|
||||
#
|
||||
@@ -554,8 +550,7 @@ FUZZDATA = \
|
||||
$(TOP)/test/fuzzdata1.db \
|
||||
$(TOP)/test/fuzzdata2.db \
|
||||
$(TOP)/test/fuzzdata3.db \
|
||||
$(TOP)/test/fuzzdata4.db \
|
||||
$(TOP)/test/fuzzdata5.db
|
||||
$(TOP)/test/fuzzdata4.db
|
||||
|
||||
# Standard options to testfixture
|
||||
#
|
||||
@@ -567,12 +562,8 @@ 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
|
||||
FUZZCHECK_SRC = $(TOP)/test/fuzzcheck.c $(TOP)/test/ossfuzz.c
|
||||
DBFUZZ_OPT =
|
||||
FUZZCHECK_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5
|
||||
|
||||
# This is the default Makefile target. The objects listed here
|
||||
# are what get build when you type just "make" with no arguments.
|
||||
@@ -621,15 +612,8 @@ fuzzershell$(TEXE): $(TOP)/tool/fuzzershell.c sqlite3.c sqlite3.h
|
||||
$(LTLINK) -o $@ $(FUZZERSHELL_OPT) \
|
||||
$(TOP)/tool/fuzzershell.c sqlite3.c $(TLIBS)
|
||||
|
||||
fuzzcheck$(TEXE): $(FUZZCHECK_SRC) sqlite3.c sqlite3.h
|
||||
$(LTLINK) -o $@ $(FUZZCHECK_OPT) $(FUZZCHECK_SRC) sqlite3.c $(TLIBS)
|
||||
|
||||
ossshell$(TEXE): $(TOP)/test/ossfuzz.c $(TOP)/test/ossshell.c sqlite3.c sqlite3.h
|
||||
$(LTLINK) -o $@ $(FUZZCHECK_OPT) $(TOP)/test/ossshell.c \
|
||||
$(TOP)/test/ossfuzz.c sqlite3.c $(TLIBS)
|
||||
|
||||
dbfuzz$(TEXE): $(TOP)/test/dbfuzz.c sqlite3.c sqlite3.h
|
||||
$(LTLINK) -o $@ $(DBFUZZ_OPT) $(TOP)/test/dbfuzz.c sqlite3.c $(TLIBS)
|
||||
fuzzcheck$(TEXE): $(TOP)/test/fuzzcheck.c sqlite3.c sqlite3.h
|
||||
$(LTLINK) -o $@ $(FUZZCHECK_OPT) $(TOP)/test/fuzzcheck.c sqlite3.c $(TLIBS)
|
||||
|
||||
mptester$(TEXE): sqlite3.lo $(TOP)/mptest/mptest.c
|
||||
$(LTLINK) -o $@ -I. $(TOP)/mptest/mptest.c sqlite3.lo \
|
||||
@@ -693,11 +677,6 @@ 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:
|
||||
#
|
||||
@@ -963,7 +942,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 mksourceid$(BEXE) $(TOP)/VERSION
|
||||
sqlite3.h: $(TOP)/src/sqlite.h.in $(TOP)/manifest.uuid $(TOP)/VERSION
|
||||
$(TCLSH_CMD) $(TOP)/tool/mksqlite3h.tcl $(TOP) >sqlite3.h
|
||||
|
||||
keywordhash.h: $(TOP)/tool/mkkeywordhash.c
|
||||
@@ -1043,9 +1022,6 @@ 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 = \
|
||||
@@ -1095,7 +1071,6 @@ 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
|
||||
@@ -1128,11 +1103,6 @@ fastfuzztest: fuzzcheck$(TEXE) $(FUZZDATA)
|
||||
valgrindfuzz: fuzzcheck$(TEXT) $(FUZZDATA)
|
||||
valgrind ./fuzzcheck$(TEXE) --cell-size-check --limit-mem 10M --timeout 600 $(FUZZDATA)
|
||||
|
||||
# The veryquick.test TCL tests.
|
||||
#
|
||||
tcltest: ./testfixture$(TEXE)
|
||||
./testfixture$(TEXE) $(TOP)/test/veryquick.test $(TESTOPTS)
|
||||
|
||||
# Minimal testing that runs in less than 3 minutes
|
||||
#
|
||||
quicktest: ./testfixture$(TEXE)
|
||||
@@ -1141,7 +1111,8 @@ quicktest: ./testfixture$(TEXE)
|
||||
# This is the common case. Run many tests that do not take too long,
|
||||
# including fuzzcheck, sqlite3_analyzer, and sqldiff tests.
|
||||
#
|
||||
test: fastfuzztest sourcetest $(TESTPROGS) tcltest
|
||||
test: $(TESTPROGS) sourcetest fastfuzztest
|
||||
./testfixture$(TEXE) $(TOP)/test/veryquick.test $(TESTOPTS)
|
||||
|
||||
# Run a test using valgrind. This can take a really long time
|
||||
# because valgrind is so much slower than a native machine.
|
||||
@@ -1168,10 +1139,6 @@ sqlite3_analyzer.c: sqlite3.c $(TOP)/src/tclsqlite.c $(TOP)/tool/spaceanal.tcl
|
||||
sqlite3_analyzer$(TEXE): sqlite3_analyzer.c
|
||||
$(LTLINK) sqlite3_analyzer.c -o $@ $(LIBTCL) $(TLIBS)
|
||||
|
||||
dbdump$(TEXE): $(TOP)/ext/misc/dbdump.c sqlite3.lo
|
||||
$(LTLINK) -DDBDUMP_STANDALONE -o $@ \
|
||||
$(TOP)/ext/misc/dbdump.c sqlite3.lo $(TLIBS)
|
||||
|
||||
showdb$(TEXE): $(TOP)/tool/showdb.c sqlite3.lo
|
||||
$(LTLINK) -o $@ $(TOP)/tool/showdb.c sqlite3.lo $(TLIBS)
|
||||
|
||||
@@ -1196,13 +1163,8 @@ LogEst$(TEXE): $(TOP)/tool/logest.c sqlite3.h
|
||||
wordcount$(TEXE): $(TOP)/test/wordcount.c sqlite3.lo
|
||||
$(LTLINK) -o $@ $(TOP)/test/wordcount.c sqlite3.lo $(TLIBS)
|
||||
|
||||
speedtest1$(TEXE): $(TOP)/test/speedtest1.c sqlite3.c
|
||||
$(LTLINK) $(ST_OPT) -o $@ $(TOP)/test/speedtest1.c sqlite3.c $(TLIBS)
|
||||
|
||||
KV_OPT += -DSQLITE_DIRECT_OVERFLOW_READ
|
||||
|
||||
kvtest$(TEXE): $(TOP)/test/kvtest.c sqlite3.c
|
||||
$(LTLINK) $(KV_OPT) -o $@ $(TOP)/test/kvtest.c sqlite3.c $(TLIBS)
|
||||
speedtest1$(TEXE): $(TOP)/test/speedtest1.c sqlite3.lo
|
||||
$(LTLINK) -o $@ $(TOP)/test/speedtest1.c sqlite3.lo $(TLIBS)
|
||||
|
||||
rbu$(EXE): $(TOP)/ext/rbu/rbu.c $(TOP)/ext/rbu/sqlite3rbu.c sqlite3.lo
|
||||
$(LTLINK) -I. -o $@ $(TOP)/ext/rbu/rbu.c sqlite3.lo $(TLIBS)
|
||||
|
||||
+25
-81
@@ -21,14 +21,7 @@ USE_AMALGAMATION = 1
|
||||
# Set this non-0 to enable full warnings (-W4, etc) when compiling.
|
||||
#
|
||||
!IFNDEF USE_FULLWARN
|
||||
USE_FULLWARN = 1
|
||||
!ENDIF
|
||||
|
||||
# Set this non-0 to enable treating warnings as errors (-WX, etc) when
|
||||
# compiling.
|
||||
#
|
||||
!IFNDEF USE_FATAL_WARN
|
||||
USE_FATAL_WARN = 0
|
||||
USE_FULLWARN = 0
|
||||
!ENDIF
|
||||
|
||||
# Set this non-0 to enable full runtime error checks (-RTC1, etc). This
|
||||
@@ -500,12 +493,6 @@ TCC = $(CC) -nologo -W4 -DINCLUDE_MSVC_H=1 $(CCOPTS) $(TCCOPTS)
|
||||
TCC = $(CC) -nologo -W3 $(CCOPTS) $(TCCOPTS)
|
||||
!ENDIF
|
||||
|
||||
# Check if warnings should be treated as errors when compiling.
|
||||
#
|
||||
!IF $(USE_FATAL_WARN)!=0
|
||||
TCC = $(TCC) -WX
|
||||
!ENDIF
|
||||
|
||||
TCC = $(TCC) -DSQLITE_OS_WIN=1 -I. -I$(TOP) -I$(TOP)\src -fp:precise
|
||||
RCC = $(RC) -DSQLITE_OS_WIN=1 -I. -I$(TOP) -I$(TOP)\src $(RCOPTS) $(RCCOPTS)
|
||||
|
||||
@@ -746,10 +733,6 @@ RCC = $(RCC) -DSQLITE_ENABLE_API_ARMOR=1
|
||||
!IF $(DEBUG)>2
|
||||
TCC = $(TCC) -DSQLITE_DEBUG=1
|
||||
RCC = $(RCC) -DSQLITE_DEBUG=1
|
||||
!IF $(DYNAMIC_SHELL)==0
|
||||
TCC = $(TCC) -DSQLITE_ENABLE_WHERETRACE -DSQLITE_ENABLE_SELECTTRACE
|
||||
RCC = $(RCC) -DSQLITE_ENABLE_WHERETRACE -DSQLITE_ENABLE_SELECTTRACE
|
||||
!ENDIF
|
||||
!ENDIF
|
||||
|
||||
!IF $(DEBUG)>4 || $(OSTRACE)!=0
|
||||
@@ -811,11 +794,11 @@ TCLLIBDIR = c:\tcl\lib
|
||||
!ENDIF
|
||||
|
||||
!IFNDEF LIBTCL
|
||||
LIBTCL = tcl86.lib
|
||||
LIBTCL = tcl85.lib
|
||||
!ENDIF
|
||||
|
||||
!IFNDEF LIBTCLSTUB
|
||||
LIBTCLSTUB = tclstub86.lib
|
||||
LIBTCLSTUB = tclstub85.lib
|
||||
!ENDIF
|
||||
|
||||
!IFNDEF LIBTCLPATH
|
||||
@@ -845,7 +828,7 @@ LIBICU = icuuc.lib icuin.lib
|
||||
# specific Tcl shell to use.
|
||||
#
|
||||
!IFNDEF TCLSH_CMD
|
||||
TCLSH_CMD = tclsh
|
||||
TCLSH_CMD = tclsh85
|
||||
!ENDIF
|
||||
# <</mark>>
|
||||
|
||||
@@ -1294,8 +1277,7 @@ SRC07 = \
|
||||
$(TOP)\ext\rtree\rtree.c \
|
||||
$(TOP)\ext\session\sqlite3session.c \
|
||||
$(TOP)\ext\rbu\sqlite3rbu.c \
|
||||
$(TOP)\ext\misc\json1.c \
|
||||
$(TOP)\ext\misc\stmt.c
|
||||
$(TOP)\ext\misc\json1.c
|
||||
|
||||
# Extension header files, part 1.
|
||||
#
|
||||
@@ -1414,11 +1396,9 @@ TESTEXT = \
|
||||
$(TOP)\ext\misc\nextchar.c \
|
||||
$(TOP)\ext\misc\percentile.c \
|
||||
$(TOP)\ext\misc\regexp.c \
|
||||
$(TOP)\ext\misc\remember.c \
|
||||
$(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
|
||||
@@ -1499,15 +1479,14 @@ FUZZDATA = \
|
||||
$(TOP)\test\fuzzdata1.db \
|
||||
$(TOP)\test\fuzzdata2.db \
|
||||
$(TOP)\test\fuzzdata3.db \
|
||||
$(TOP)\test\fuzzdata4.db \
|
||||
$(TOP)\test\fuzzdata5.db
|
||||
$(TOP)\test\fuzzdata4.db
|
||||
# <</mark>>
|
||||
|
||||
# Additional compiler options for the shell. These are only effective
|
||||
# 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 -DSQLITE_ENABLE_STMTVTAB
|
||||
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_SHELL_JSON1 -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS
|
||||
!ENDIF
|
||||
|
||||
# <<mark>>
|
||||
@@ -1515,13 +1494,7 @@ SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_SHELL_JSON1 -DSQLITE_ENABLE_
|
||||
#
|
||||
MPTESTER_COMPILE_OPTS = -DSQLITE_SHELL_JSON1 -DSQLITE_ENABLE_FTS5
|
||||
FUZZERSHELL_COMPILE_OPTS = -DSQLITE_ENABLE_JSON1
|
||||
FUZZCHECK_COMPILE_OPTS = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5 -DSQLITE_OSS_FUZZ -DSQLITE_MAX_MEMORY=50000000
|
||||
FUZZCHECK_SRC = $(TOP)\test\fuzzcheck.c $(TOP)\test\ossfuzz.c
|
||||
OSSSHELL_SRC = $(TOP)\test\ossshell.c $(TOP)\test\ossfuzz.c
|
||||
DBFUZZ_COMPILE_OPTS = -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION
|
||||
KV_COMPILE_OPTS = -DSQLITE_THREADSAFE=0 -DSQLITE_DIRECT_OVERFLOW_READ
|
||||
DBSELFTEST_COMPILE_OPTS = -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_ENABLE_RTREE -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_FTS5
|
||||
ST_COMPILE_OPTS = -DSQLITE_THREADSAFE=0
|
||||
FUZZCHECK_COMPILE_OPTS = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5
|
||||
|
||||
# Standard options to testfixture.
|
||||
#
|
||||
@@ -1564,7 +1537,7 @@ $(SQLITE3DLL): $(LIBOBJ) $(LIBRESOBJS) $(CORE_LINK_DEP)
|
||||
sqlite3.def: libsqlite3.lib
|
||||
echo EXPORTS > sqlite3.def
|
||||
dumpbin /all libsqlite3.lib \
|
||||
| $(TCLSH_CMD) $(TOP)\tool\replace.tcl include "^\s+1 _?(sqlite3(?:session|changeset|changegroup)?_[^@]*)(?:@\d+)?$$" \1 \
|
||||
| $(TCLSH_CMD) $(TOP)\tool\replace.tcl include "^\s+1 _?(sqlite3_[^@]*)(?:@\d+)?$$" \1 \
|
||||
| sort >> sqlite3.def
|
||||
# <</block2>>
|
||||
|
||||
@@ -1591,14 +1564,8 @@ sourcetest: srcck1.exe sqlite3.c
|
||||
fuzzershell.exe: $(TOP)\tool\fuzzershell.c $(SQLITE3C) $(SQLITE3H)
|
||||
$(LTLINK) $(NO_WARN) $(FUZZERSHELL_COMPILE_OPTS) $(TOP)\tool\fuzzershell.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
||||
|
||||
dbfuzz.exe: $(TOP)\test\dbfuzz.c $(SQLITE3C) $(SQLITE3H)
|
||||
$(LTLINK) $(NO_WARN) $(DBFUZZ_COMPILE_OPTS) $(TOP)\test\dbfuzz.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
||||
|
||||
fuzzcheck.exe: $(FUZZCHECK_SRC) $(SQLITE3C) $(SQLITE3H)
|
||||
$(LTLINK) $(NO_WARN) $(FUZZCHECK_COMPILE_OPTS) $(FUZZCHECK_SRC) $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
||||
|
||||
ossshell.exe: $(OSSSHELL_SRC) $(SQLITE3C) $(SQLITE3H)
|
||||
$(LTLINK) $(NO_WARN) $(FUZZCHECK_COMPILE_OPTS) $(OSSSHELL_SRC) $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
||||
fuzzcheck.exe: $(TOP)\test\fuzzcheck.c $(SQLITE3C) $(SQLITE3H)
|
||||
$(LTLINK) $(NO_WARN) $(FUZZCHECK_COMPILE_OPTS) $(TOP)\test\fuzzcheck.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
||||
|
||||
mptester.exe: $(TOP)\mptest\mptest.c $(SQLITE3C) $(SQLITE3H)
|
||||
$(LTLINK) $(NO_WARN) $(MPTESTER_COMPILE_OPTS) $(TOP)\mptest\mptest.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
||||
@@ -1670,12 +1637,6 @@ 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:
|
||||
#
|
||||
@@ -1954,7 +1915,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 mksourceid.exe $(TOP)\VERSION
|
||||
$(SQLITE3H): $(TOP)\src\sqlite.h.in $(TOP)\manifest.uuid $(TOP)\VERSION
|
||||
$(TCLSH_CMD) $(TOP)\tool\mksqlite3h.tcl $(TOP:\=/) > $(SQLITE3H) $(MKSQLITE3H_ARGS)
|
||||
|
||||
sqlite3ext.h: .target_source
|
||||
@@ -2097,7 +2058,6 @@ 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)
|
||||
@@ -2190,10 +2150,6 @@ sqlite3_analyzer.exe: sqlite3_analyzer.c $(LIBRESOBJS)
|
||||
$(LTLINK) $(NO_WARN) -DBUILD_sqlite -I$(TCLINCDIR) sqlite3_analyzer.c \
|
||||
/link $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LTLIBS) $(TLIBS)
|
||||
|
||||
dbdump.exe: $(TOP)\ext\misc\dbdump.c $(SQLITE3C) $(SQLITE3H)
|
||||
$(LTLINK) $(NO_WARN) -DDBDUMP_STANDALONE $(TOP)\ext\misc\dbdump.c $(SQLITE3C) \
|
||||
/link $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LTLIBS)
|
||||
|
||||
testloadext.lo: $(TOP)\src\test_loadext.c
|
||||
$(LTCOMPILE) $(NO_WARN) -c $(TOP)\src\test_loadext.c
|
||||
|
||||
@@ -2201,59 +2157,48 @@ testloadext.dll: testloadext.lo
|
||||
$(LD) $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) /DLL /OUT:$@ testloadext.lo
|
||||
|
||||
showdb.exe: $(TOP)\tool\showdb.c $(SQLITE3C) $(SQLITE3H)
|
||||
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
|
||||
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \
|
||||
$(TOP)\tool\showdb.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
||||
|
||||
showstat4.exe: $(TOP)\tool\showstat4.c $(SQLITE3C) $(SQLITE3H)
|
||||
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
|
||||
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \
|
||||
$(TOP)\tool\showstat4.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
||||
|
||||
showjournal.exe: $(TOP)\tool\showjournal.c $(SQLITE3C) $(SQLITE3H)
|
||||
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
|
||||
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \
|
||||
$(TOP)\tool\showjournal.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
||||
|
||||
showwal.exe: $(TOP)\tool\showwal.c $(SQLITE3C) $(SQLITE3H)
|
||||
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
|
||||
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \
|
||||
$(TOP)\tool\showwal.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
||||
|
||||
changeset.exe: $(TOP)\ext\session\changeset.c $(SQLITE3C) $(SQLITE3H)
|
||||
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
|
||||
-DSQLITE_ENABLE_SESSION=1 -DSQLITE_ENABLE_PREUPDATE_HOOK=1 \
|
||||
changeset.exe: $(TOP)\ext\session\changeset.c $(SQLITE3C)
|
||||
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \
|
||||
$(TOP)\ext\session\changeset.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
||||
|
||||
fts3view.exe: $(TOP)\ext\fts3\tool\fts3view.c $(SQLITE3C) $(SQLITE3H)
|
||||
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
|
||||
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \
|
||||
$(TOP)\ext\fts3\tool\fts3view.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
||||
|
||||
rollback-test.exe: $(TOP)\tool\rollback-test.c $(SQLITE3C) $(SQLITE3H)
|
||||
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
|
||||
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \
|
||||
$(TOP)\tool\rollback-test.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
||||
|
||||
LogEst.exe: $(TOP)\tool\logest.c $(SQLITE3H)
|
||||
$(LTLINK) $(NO_WARN) $(TOP)\tool\LogEst.c /link $(LDFLAGS) $(LTLINKOPTS)
|
||||
$(LTLINK) $(NO_WARN) -Fe$@ $(TOP)\tool\LogEst.c /link $(LDFLAGS) $(LTLINKOPTS)
|
||||
|
||||
wordcount.exe: $(TOP)\test\wordcount.c $(SQLITE3C) $(SQLITE3H)
|
||||
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
|
||||
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \
|
||||
$(TOP)\test\wordcount.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
||||
|
||||
speedtest1.exe: $(TOP)\test\speedtest1.c $(SQLITE3C) $(SQLITE3H)
|
||||
$(LTLINK) $(NO_WARN) $(ST_COMPILE_OPTS) -DSQLITE_OMIT_LOAD_EXTENSION \
|
||||
$(LTLINK) $(NO_WARN) -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \
|
||||
$(TOP)\test\speedtest1.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
||||
|
||||
kvtest.exe: $(TOP)\test\kvtest.c $(SQLITE3C) $(SQLITE3H)
|
||||
$(LTLINK) $(NO_WARN) $(KV_COMPILE_OPTS) \
|
||||
$(TOP)\test\kvtest.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
||||
|
||||
dbselftest.exe: $(TOP)\test\dbselftest.c $(SQLITE3C) $(SQLITE3H)
|
||||
$(LTLINK) $(NO_WARN) $(DBSELFTEST_COMPILE_OPTS) $(TOP)\test\dbselftest.c $(SQLITE3C)
|
||||
|
||||
rbu.exe: $(TOP)\ext\rbu\rbu.c $(TOP)\ext\rbu\sqlite3rbu.c $(SQLITE3C) $(SQLITE3H)
|
||||
$(LTLINK) $(NO_WARN) -DSQLITE_ENABLE_RBU \
|
||||
$(LTLINK) $(NO_WARN) -DSQLITE_ENABLE_RBU -Fe$@ \
|
||||
$(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>>
|
||||
@@ -2273,10 +2218,9 @@ clean:
|
||||
-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
|
||||
del /Q LogEst.exe fts3view.exe rollback-test.exe showdb.exe 2>NUL
|
||||
del /Q changeset.exe 2>NUL
|
||||
del /Q showjournal.exe showstat4.exe showwal.exe speedtest1.exe 2>NUL
|
||||
del /Q mptester.exe wordcount.exe rbu.exe srcck1.exe 2>NUL
|
||||
|
||||
@@ -8,50 +8,6 @@ If you are reading this on a Git mirror someplace, you are doing it wrong.
|
||||
The [official repository](https://www.sqlite.org/src/) is better. Go there
|
||||
now.
|
||||
|
||||
## Obtaining The Code
|
||||
|
||||
SQLite sources are managed using the
|
||||
[Fossil](https://www.fossil-scm.org/), a distributed version control system
|
||||
that was specifically designed to support SQLite development.
|
||||
If you do not want to use Fossil, you can download tarballs or ZIP
|
||||
archives as follows:
|
||||
|
||||
* Lastest trunk check-in:
|
||||
<https://www.sqlite.org/src/tarball/sqlite.tar.gz> or
|
||||
<https://www.sqlite.org/src/zip/sqlite.zip>.
|
||||
|
||||
* Latest release:
|
||||
<https://www.sqlite.org/src/tarball/sqlite.tar.gz?r=release> or
|
||||
<https://www.sqlite.org/src/zip/sqlite.zip?r=release>.
|
||||
|
||||
* For other check-ins, substitute an appropriate branch name or
|
||||
tag or hash prefix for "release" in the URLs of the previous
|
||||
bullet. Or browse the [timeline](https://www.sqlite.org/src/timeline)
|
||||
to locate the check-in desired, click on its information page link,
|
||||
then click on the "Tarball" or "ZIP Archive" links on the information
|
||||
page.
|
||||
|
||||
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). 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
|
||||
cd ~/sqlite
|
||||
fossil clone https://www.sqlite.org/src sqlite.fossil
|
||||
fossil open sqlite.fossil
|
||||
|
||||
After setting up a repository using the steps above, you can always
|
||||
update to the lastest version using:
|
||||
|
||||
fossil update trunk ;# latest trunk check-in
|
||||
fossil update release ;# latest official release
|
||||
|
||||
Or type "fossil ui" to get a web-based user interface.
|
||||
|
||||
## Compiling
|
||||
|
||||
First create a directory in which to place
|
||||
@@ -62,13 +18,13 @@ script found at the root of the source tree. Then run "make".
|
||||
|
||||
For example:
|
||||
|
||||
tar xzf sqlite.tar.gz ;# Unpack the source tree into "sqlite"
|
||||
mkdir bld ;# Build will occur in a sibling directory
|
||||
cd bld ;# Change to the build directory
|
||||
../sqlite/configure ;# Run the configure script
|
||||
make ;# Run the makefile.
|
||||
make sqlite3.c ;# Build the "amalgamation" source file
|
||||
make test ;# Run some tests (requires Tcl)
|
||||
tar xzf sqlite.tar.gz ;# Unpack the source tree into "sqlite"
|
||||
mkdir bld ;# Build will occur in a sibling directory
|
||||
cd bld ;# Change to the build directory
|
||||
../sqlite/configure ;# Run the configure script
|
||||
make ;# Run the makefile.
|
||||
make sqlite3.c ;# Build the "amalgamation" source file
|
||||
make test ;# Run some tests (requires Tcl)
|
||||
|
||||
See the makefile for additional targets.
|
||||
|
||||
@@ -87,13 +43,13 @@ with the provided "Makefile.msc" to build one of the supported targets.
|
||||
|
||||
For example:
|
||||
|
||||
mkdir bld
|
||||
cd bld
|
||||
nmake /f Makefile.msc TOP=..\sqlite
|
||||
nmake /f Makefile.msc sqlite3.c TOP=..\sqlite
|
||||
nmake /f Makefile.msc sqlite3.dll TOP=..\sqlite
|
||||
nmake /f Makefile.msc sqlite3.exe TOP=..\sqlite
|
||||
nmake /f Makefile.msc test TOP=..\sqlite
|
||||
mkdir bld
|
||||
cd bld
|
||||
nmake /f Makefile.msc TOP=..\sqlite
|
||||
nmake /f Makefile.msc sqlite3.c TOP=..\sqlite
|
||||
nmake /f Makefile.msc sqlite3.dll TOP=..\sqlite
|
||||
nmake /f Makefile.msc sqlite3.exe TOP=..\sqlite
|
||||
nmake /f Makefile.msc test TOP=..\sqlite
|
||||
|
||||
There are several build options that can be set via the NMAKE command
|
||||
line. For example, to build for WinRT, simply add "FOR_WINRT=1" argument
|
||||
@@ -108,22 +64,19 @@ The makefiles also require AWK.
|
||||
|
||||
## Source Code Tour
|
||||
|
||||
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
|
||||
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
|
||||
extension and only later escaped to the wild as an independent library.)
|
||||
|
||||
Test scripts and programs are found in the **test/** subdirectory.
|
||||
Addtional test code is found in other source repositories.
|
||||
See [How SQLite Is Tested](http://www.sqlite.org/testing.html) for
|
||||
additional information.
|
||||
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.
|
||||
|
||||
The **ext/** subdirectory contains code for extensions. The
|
||||
Full-text search engine is in **ext/fts3**. The R-Tree engine is in
|
||||
@@ -147,7 +100,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 SHA3 hash of the particular check-in
|
||||
The manifest.uuid file contains the SHA1 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
|
||||
@@ -158,8 +111,9 @@ 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 the tool/lempar.c file as a
|
||||
template for generating its parser.
|
||||
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.
|
||||
|
||||
Lemon also generates the **parse.h** header file, at the same time it
|
||||
generates parse.c. But the parse.h header file is
|
||||
@@ -179,13 +133,6 @@ 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
|
||||
@@ -203,7 +150,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 200K lines long. Some symbolic
|
||||
The amalgamation source file is more than 100K 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
|
||||
@@ -220,15 +167,14 @@ 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/opcode.html) that runs
|
||||
the [virtual machine](http://www.sqlite.org/vdbe.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).
|
||||
|
||||
Years of effort have gone into optimizating SQLite, both
|
||||
Unfortunately, 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 current SQLite
|
||||
implementation. It will not be the easiest library in the world to hack.
|
||||
complex code. So there is a lot of complexity in the SQLite implementation.
|
||||
|
||||
Key files:
|
||||
|
||||
@@ -239,7 +185,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) grammar that SQLite uses
|
||||
* **parse.y** - This file describes the LALR(1) grammer that SQLite uses
|
||||
to parse SQL statements, and the actions that are taken at each step
|
||||
in the parsing process.
|
||||
|
||||
@@ -272,13 +218,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 succinct header comment that
|
||||
There are many other source files. Each has a suscinct 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 backups at
|
||||
with geographically distributed backup servers at
|
||||
[http://www2.sqlite.org/](http://www2.sqlite.org) and
|
||||
[http://www3.sqlite.org/](http://www3.sqlite.org).
|
||||
|
||||
+3
-20
@@ -21,14 +21,7 @@ TOP = .
|
||||
# Set this non-0 to enable full warnings (-W4, etc) when compiling.
|
||||
#
|
||||
!IFNDEF USE_FULLWARN
|
||||
USE_FULLWARN = 1
|
||||
!ENDIF
|
||||
|
||||
# Set this non-0 to enable treating warnings as errors (-WX, etc) when
|
||||
# compiling.
|
||||
#
|
||||
!IFNDEF USE_FATAL_WARN
|
||||
USE_FATAL_WARN = 0
|
||||
USE_FULLWARN = 0
|
||||
!ENDIF
|
||||
|
||||
# Set this non-0 to enable full runtime error checks (-RTC1, etc). This
|
||||
@@ -461,12 +454,6 @@ TCC = $(CC) -nologo -W4 -DINCLUDE_MSVC_H=1 $(CCOPTS) $(TCCOPTS)
|
||||
TCC = $(CC) -nologo -W3 $(CCOPTS) $(TCCOPTS)
|
||||
!ENDIF
|
||||
|
||||
# Check if warnings should be treated as errors when compiling.
|
||||
#
|
||||
!IF $(USE_FATAL_WARN)!=0
|
||||
TCC = $(TCC) -WX
|
||||
!ENDIF
|
||||
|
||||
TCC = $(TCC) -DSQLITE_OS_WIN=1 -I. -I$(TOP) -fp:precise
|
||||
RCC = $(RC) -DSQLITE_OS_WIN=1 -I. -I$(TOP) $(RCOPTS) $(RCCOPTS)
|
||||
|
||||
@@ -645,10 +632,6 @@ RCC = $(RCC) -DSQLITE_ENABLE_API_ARMOR=1
|
||||
!IF $(DEBUG)>2
|
||||
TCC = $(TCC) -DSQLITE_DEBUG=1
|
||||
RCC = $(RCC) -DSQLITE_DEBUG=1
|
||||
!IF $(DYNAMIC_SHELL)==0
|
||||
TCC = $(TCC) -DSQLITE_ENABLE_WHERETRACE -DSQLITE_ENABLE_SELECTTRACE
|
||||
RCC = $(RCC) -DSQLITE_ENABLE_WHERETRACE -DSQLITE_ENABLE_SELECTTRACE
|
||||
!ENDIF
|
||||
!ENDIF
|
||||
|
||||
!IF $(DEBUG)>4 || $(OSTRACE)!=0
|
||||
@@ -927,7 +910,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 -DSQLITE_ENABLE_STMTVTAB
|
||||
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_SHELL_JSON1 -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS
|
||||
!ENDIF
|
||||
|
||||
|
||||
@@ -954,7 +937,7 @@ Replace.exe:
|
||||
sqlite3.def: Replace.exe $(LIBOBJ)
|
||||
echo EXPORTS > sqlite3.def
|
||||
dumpbin /all $(LIBOBJ) \
|
||||
| .\Replace.exe "^\s+/EXPORT:_?(sqlite3(?:session|changeset|changegroup)?_[^@,]*)(?:@\d+|,DATA)?$$" $$1 true \
|
||||
| .\Replace.exe "^\s+/EXPORT:_?(sqlite3_[^@,]*)(?:@\d+|,DATA)?$$" $$1 true \
|
||||
| sort >> sqlite3.def
|
||||
|
||||
$(SQLITE3EXE): $(TOP)\shell.c $(SHELL_CORE_DEP) $(LIBRESOBJS) $(SHELL_CORE_SRC) $(SQLITE3H)
|
||||
|
||||
@@ -55,9 +55,9 @@ AS_IF([ test x"$enable_editline" != xno ],[
|
||||
LIBS=""
|
||||
AC_SEARCH_LIBS([readline],[edit],[
|
||||
AC_DEFINE([HAVE_EDITLINE],1,Define to use BSD editline)
|
||||
READLINE_LIBS="$LIBS -ltinfo"
|
||||
READLINE_LIBS=$LIBS
|
||||
enable_readline=no
|
||||
],[],[-ltinfo])
|
||||
])
|
||||
AS_UNSET(ac_cv_search_readline)
|
||||
LIBS=$sLIBS
|
||||
])
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#! /bin/sh
|
||||
# Guess values for system-dependent variables and create Makefiles.
|
||||
# Generated by GNU Autoconf 2.69 for sqlite 3.21.0.
|
||||
# Generated by GNU Autoconf 2.69 for sqlite 3.16.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.21.0'
|
||||
PACKAGE_STRING='sqlite 3.21.0'
|
||||
PACKAGE_VERSION='3.16.0'
|
||||
PACKAGE_STRING='sqlite 3.16.0'
|
||||
PACKAGE_BUGREPORT=''
|
||||
PACKAGE_URL=''
|
||||
|
||||
@@ -1463,7 +1463,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.21.0 to adapt to many kinds of systems.
|
||||
\`configure' configures sqlite 3.16.0 to adapt to many kinds of systems.
|
||||
|
||||
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||
|
||||
@@ -1528,7 +1528,7 @@ fi
|
||||
|
||||
if test -n "$ac_init_help"; then
|
||||
case $ac_init_help in
|
||||
short | recursive ) echo "Configuration of sqlite 3.21.0:";;
|
||||
short | recursive ) echo "Configuration of sqlite 3.16.0:";;
|
||||
esac
|
||||
cat <<\_ACEOF
|
||||
|
||||
@@ -1652,7 +1652,7 @@ fi
|
||||
test -n "$ac_init_help" && exit $ac_status
|
||||
if $ac_init_version; then
|
||||
cat <<\_ACEOF
|
||||
sqlite configure 3.21.0
|
||||
sqlite configure 3.16.0
|
||||
generated by GNU Autoconf 2.69
|
||||
|
||||
Copyright (C) 2012 Free Software Foundation, Inc.
|
||||
@@ -2071,7 +2071,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.21.0, which was
|
||||
It was created by sqlite $as_me 3.16.0, which was
|
||||
generated by GNU Autoconf 2.69. Invocation command line was
|
||||
|
||||
$ $0 $@
|
||||
@@ -11252,7 +11252,7 @@ else
|
||||
fi
|
||||
|
||||
if test "${use_debug}" = "yes" ; then
|
||||
TARGET_DEBUG="-DSQLITE_DEBUG=1 -DSQLITE_ENABLE_SELECTTRACE -DSQLITE_ENABLE_WHERETRACE -O0"
|
||||
TARGET_DEBUG="-DSQLITE_DEBUG=1"
|
||||
else
|
||||
TARGET_DEBUG="-DNDEBUG"
|
||||
fi
|
||||
@@ -11356,7 +11356,7 @@ fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to support MEMSYS5" >&5
|
||||
$as_echo_n "checking whether to support MEMSYS5... " >&6; }
|
||||
if test "${enable_memsys5}" = "yes"; then
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_MEMSYS5"
|
||||
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_MEMSYS5"
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
$as_echo "yes" >&6; }
|
||||
else
|
||||
@@ -11373,7 +11373,7 @@ fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to support MEMSYS3" >&5
|
||||
$as_echo_n "checking whether to support MEMSYS3... " >&6; }
|
||||
if test "${enable_memsys3}" = "yes" -a "${enable_memsys5}" = "no"; then
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_MEMSYS3"
|
||||
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_MEMSYS3"
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
$as_echo "yes" >&6; }
|
||||
else
|
||||
@@ -11391,7 +11391,7 @@ else
|
||||
fi
|
||||
|
||||
if test "${enable_fts3}" = "yes" ; then
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_FTS3"
|
||||
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_FTS3"
|
||||
fi
|
||||
# Check whether --enable-fts4 was given.
|
||||
if test "${enable_fts4+set}" = set; then :
|
||||
@@ -11401,7 +11401,7 @@ else
|
||||
fi
|
||||
|
||||
if test "${enable_fts4}" = "yes" ; then
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_FTS4"
|
||||
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_FTS4"
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing log" >&5
|
||||
$as_echo_n "checking for library containing log... " >&6; }
|
||||
if ${ac_cv_search_log+:} false; then :
|
||||
@@ -11467,7 +11467,7 @@ else
|
||||
fi
|
||||
|
||||
if test "${enable_fts5}" = "yes" ; then
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_FTS5"
|
||||
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_FTS5"
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing log" >&5
|
||||
$as_echo_n "checking for library containing log... " >&6; }
|
||||
if ${ac_cv_search_log+:} false; then :
|
||||
@@ -11536,7 +11536,7 @@ else
|
||||
fi
|
||||
|
||||
if test "${enable_json1}" = "yes" ; then
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_JSON1"
|
||||
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_JSON1"
|
||||
fi
|
||||
|
||||
#########
|
||||
@@ -11549,7 +11549,7 @@ else
|
||||
fi
|
||||
|
||||
if test "${enable_rtree}" = "yes" ; then
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_RTREE"
|
||||
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_RTREE"
|
||||
fi
|
||||
|
||||
#########
|
||||
@@ -11562,12 +11562,12 @@ else
|
||||
fi
|
||||
|
||||
if test "${enable_session}" = "yes" ; then
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_SESSION"
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_PREUPDATE_HOOK"
|
||||
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_SESSION"
|
||||
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_PREUPDATE_HOOK"
|
||||
fi
|
||||
|
||||
#########
|
||||
# attempt to duplicate any OMITS and ENABLES into the ${OPT_FEATURE_FLAGS} parameter
|
||||
# attempt to duplicate any OMITS and ENABLES into the $(OPT_FEATURE_FLAGS) parameter
|
||||
for option in $CFLAGS $CPPFLAGS
|
||||
do
|
||||
case $option in
|
||||
@@ -12151,7 +12151,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.21.0, which was
|
||||
This file was extended by sqlite $as_me 3.16.0, which was
|
||||
generated by GNU Autoconf 2.69. Invocation command line was
|
||||
|
||||
CONFIG_FILES = $CONFIG_FILES
|
||||
@@ -12217,7 +12217,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.21.0
|
||||
sqlite config.status 3.16.0
|
||||
configured by $0, generated by GNU Autoconf 2.69,
|
||||
with options \\"\$ac_cs_config\\"
|
||||
|
||||
|
||||
+11
-11
@@ -560,7 +560,7 @@ AC_SEARCH_LIBS(fdatasync, [rt])
|
||||
AC_ARG_ENABLE(debug, AC_HELP_STRING([--enable-debug],[enable debugging & verbose explain]),
|
||||
[use_debug=$enableval],[use_debug=no])
|
||||
if test "${use_debug}" = "yes" ; then
|
||||
TARGET_DEBUG="-DSQLITE_DEBUG=1 -DSQLITE_ENABLE_SELECTTRACE -DSQLITE_ENABLE_WHERETRACE -O0"
|
||||
TARGET_DEBUG="-DSQLITE_DEBUG=1"
|
||||
else
|
||||
TARGET_DEBUG="-DNDEBUG"
|
||||
fi
|
||||
@@ -596,7 +596,7 @@ AC_ARG_ENABLE(memsys5,
|
||||
[enable_memsys5=yes],[enable_memsys5=no])
|
||||
AC_MSG_CHECKING([whether to support MEMSYS5])
|
||||
if test "${enable_memsys5}" = "yes"; then
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_MEMSYS5"
|
||||
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_MEMSYS5"
|
||||
AC_MSG_RESULT([yes])
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
@@ -606,7 +606,7 @@ AC_ARG_ENABLE(memsys3,
|
||||
[enable_memsys3=yes],[enable_memsys3=no])
|
||||
AC_MSG_CHECKING([whether to support MEMSYS3])
|
||||
if test "${enable_memsys3}" = "yes" -a "${enable_memsys5}" = "no"; then
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_MEMSYS3"
|
||||
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_MEMSYS3"
|
||||
AC_MSG_RESULT([yes])
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
@@ -618,20 +618,20 @@ AC_ARG_ENABLE(fts3, AC_HELP_STRING([--enable-fts3],
|
||||
[Enable the FTS3 extension]),
|
||||
[enable_fts3=yes],[enable_fts3=no])
|
||||
if test "${enable_fts3}" = "yes" ; then
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_FTS3"
|
||||
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_FTS3"
|
||||
fi
|
||||
AC_ARG_ENABLE(fts4, AC_HELP_STRING([--enable-fts4],
|
||||
[Enable the FTS4 extension]),
|
||||
[enable_fts4=yes],[enable_fts4=no])
|
||||
if test "${enable_fts4}" = "yes" ; then
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_FTS4"
|
||||
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_FTS4"
|
||||
AC_SEARCH_LIBS([log],[m])
|
||||
fi
|
||||
AC_ARG_ENABLE(fts5, AC_HELP_STRING([--enable-fts5],
|
||||
[Enable the FTS5 extension]),
|
||||
[enable_fts5=yes],[enable_fts5=no])
|
||||
if test "${enable_fts5}" = "yes" ; then
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_FTS5"
|
||||
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_FTS5"
|
||||
AC_SEARCH_LIBS([log],[m])
|
||||
fi
|
||||
|
||||
@@ -641,7 +641,7 @@ AC_ARG_ENABLE(json1, AC_HELP_STRING([--enable-json1],
|
||||
[Enable the JSON1 extension]),
|
||||
[enable_json1=yes],[enable_json1=no])
|
||||
if test "${enable_json1}" = "yes" ; then
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_JSON1"
|
||||
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_JSON1"
|
||||
fi
|
||||
|
||||
#########
|
||||
@@ -650,7 +650,7 @@ AC_ARG_ENABLE(rtree, AC_HELP_STRING([--enable-rtree],
|
||||
[Enable the RTREE extension]),
|
||||
[enable_rtree=yes],[enable_rtree=no])
|
||||
if test "${enable_rtree}" = "yes" ; then
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_RTREE"
|
||||
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_RTREE"
|
||||
fi
|
||||
|
||||
#########
|
||||
@@ -659,12 +659,12 @@ AC_ARG_ENABLE(session, AC_HELP_STRING([--enable-session],
|
||||
[Enable the SESSION extension]),
|
||||
[enable_session=yes],[enable_session=no])
|
||||
if test "${enable_session}" = "yes" ; then
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_SESSION"
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_PREUPDATE_HOOK"
|
||||
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_SESSION"
|
||||
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_PREUPDATE_HOOK"
|
||||
fi
|
||||
|
||||
#########
|
||||
# attempt to duplicate any OMITS and ENABLES into the ${OPT_FEATURE_FLAGS} parameter
|
||||
# attempt to duplicate any OMITS and ENABLES into the $(OPT_FEATURE_FLAGS) parameter
|
||||
for option in $CFLAGS $CPPFLAGS
|
||||
do
|
||||
case $option in
|
||||
|
||||
@@ -23,26 +23,6 @@ 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)
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
## Loadable Extensions
|
||||
|
||||
Various [loadable extensions](https://www.sqlite.org/loadext.html) for
|
||||
SQLite are found in subfolders.
|
||||
|
||||
Most subfolders are dedicated to a single loadable extension (for
|
||||
example FTS5, or RTREE). But the misc/ subfolder contains a collection
|
||||
of smaller single-file extensions.
|
||||
@@ -0,0 +1,2 @@
|
||||
Version loadable extensions to SQLite are found in subfolders
|
||||
of this folder.
|
||||
+166
-201
@@ -349,9 +349,8 @@ int sqlite3Fts3PutVarint(char *p, sqlite_int64 v){
|
||||
** Return the number of bytes read, or 0 on error.
|
||||
** The value is stored in *v.
|
||||
*/
|
||||
int sqlite3Fts3GetVarint(const char *pBuf, sqlite_int64 *v){
|
||||
const unsigned char *p = (const unsigned char*)pBuf;
|
||||
const unsigned char *pStart = p;
|
||||
int sqlite3Fts3GetVarint(const char *p, sqlite_int64 *v){
|
||||
const char *pStart = p;
|
||||
u32 a;
|
||||
u64 b;
|
||||
int shift;
|
||||
@@ -372,8 +371,8 @@ int sqlite3Fts3GetVarint(const char *pBuf, sqlite_int64 *v){
|
||||
}
|
||||
|
||||
/*
|
||||
** Similar to sqlite3Fts3GetVarint(), except that the output is truncated to
|
||||
** a non-negative 32-bit integer before it is returned.
|
||||
** Similar to sqlite3Fts3GetVarint(), except that the output is truncated to a
|
||||
** 32-bit integer before it is returned.
|
||||
*/
|
||||
int sqlite3Fts3GetVarint32(const char *p, int *pi){
|
||||
u32 a;
|
||||
@@ -389,9 +388,7 @@ int sqlite3Fts3GetVarint32(const char *p, int *pi){
|
||||
GETVARINT_STEP(a, p, 14, 0x3FFF, 0x200000, *pi, 3);
|
||||
GETVARINT_STEP(a, p, 21, 0x1FFFFF, 0x10000000, *pi, 4);
|
||||
a = (a & 0x0FFFFFFF );
|
||||
*pi = (int)(a | ((u32)(*p & 0x07) << 28));
|
||||
assert( 0==(a & 0x80000000) );
|
||||
assert( *pi>=0 );
|
||||
*pi = (int)(a | ((u32)(*p & 0x0F) << 28));
|
||||
return 5;
|
||||
}
|
||||
|
||||
@@ -495,7 +492,6 @@ static int fts3DisconnectMethod(sqlite3_vtab *pVtab){
|
||||
assert( p->pSegments==0 );
|
||||
|
||||
/* Free any prepared statements held */
|
||||
sqlite3_finalize(p->pSeekStmt);
|
||||
for(i=0; i<SizeofArray(p->aStmt); i++){
|
||||
sqlite3_finalize(p->aStmt[i]);
|
||||
}
|
||||
@@ -1221,66 +1217,65 @@ static int fts3InitVtab(
|
||||
break;
|
||||
}
|
||||
}
|
||||
switch( iOpt ){
|
||||
case 0: /* MATCHINFO */
|
||||
if( strlen(zVal)!=4 || sqlite3_strnicmp(zVal, "fts3", 4) ){
|
||||
sqlite3Fts3ErrMsg(pzErr, "unrecognized matchinfo: %s", zVal);
|
||||
rc = SQLITE_ERROR;
|
||||
}
|
||||
bNoDocsize = 1;
|
||||
break;
|
||||
if( iOpt==SizeofArray(aFts4Opt) ){
|
||||
sqlite3Fts3ErrMsg(pzErr, "unrecognized parameter: %s", z);
|
||||
rc = SQLITE_ERROR;
|
||||
}else{
|
||||
switch( iOpt ){
|
||||
case 0: /* MATCHINFO */
|
||||
if( strlen(zVal)!=4 || sqlite3_strnicmp(zVal, "fts3", 4) ){
|
||||
sqlite3Fts3ErrMsg(pzErr, "unrecognized matchinfo: %s", zVal);
|
||||
rc = SQLITE_ERROR;
|
||||
}
|
||||
bNoDocsize = 1;
|
||||
break;
|
||||
|
||||
case 1: /* PREFIX */
|
||||
sqlite3_free(zPrefix);
|
||||
zPrefix = zVal;
|
||||
zVal = 0;
|
||||
break;
|
||||
case 1: /* PREFIX */
|
||||
sqlite3_free(zPrefix);
|
||||
zPrefix = zVal;
|
||||
zVal = 0;
|
||||
break;
|
||||
|
||||
case 2: /* COMPRESS */
|
||||
sqlite3_free(zCompress);
|
||||
zCompress = zVal;
|
||||
zVal = 0;
|
||||
break;
|
||||
case 2: /* COMPRESS */
|
||||
sqlite3_free(zCompress);
|
||||
zCompress = zVal;
|
||||
zVal = 0;
|
||||
break;
|
||||
|
||||
case 3: /* UNCOMPRESS */
|
||||
sqlite3_free(zUncompress);
|
||||
zUncompress = zVal;
|
||||
zVal = 0;
|
||||
break;
|
||||
case 3: /* UNCOMPRESS */
|
||||
sqlite3_free(zUncompress);
|
||||
zUncompress = zVal;
|
||||
zVal = 0;
|
||||
break;
|
||||
|
||||
case 4: /* ORDER */
|
||||
if( (strlen(zVal)!=3 || sqlite3_strnicmp(zVal, "asc", 3))
|
||||
&& (strlen(zVal)!=4 || sqlite3_strnicmp(zVal, "desc", 4))
|
||||
){
|
||||
sqlite3Fts3ErrMsg(pzErr, "unrecognized order: %s", zVal);
|
||||
rc = SQLITE_ERROR;
|
||||
}
|
||||
bDescIdx = (zVal[0]=='d' || zVal[0]=='D');
|
||||
break;
|
||||
case 4: /* ORDER */
|
||||
if( (strlen(zVal)!=3 || sqlite3_strnicmp(zVal, "asc", 3))
|
||||
&& (strlen(zVal)!=4 || sqlite3_strnicmp(zVal, "desc", 4))
|
||||
){
|
||||
sqlite3Fts3ErrMsg(pzErr, "unrecognized order: %s", zVal);
|
||||
rc = SQLITE_ERROR;
|
||||
}
|
||||
bDescIdx = (zVal[0]=='d' || zVal[0]=='D');
|
||||
break;
|
||||
|
||||
case 5: /* CONTENT */
|
||||
sqlite3_free(zContent);
|
||||
zContent = zVal;
|
||||
zVal = 0;
|
||||
break;
|
||||
case 5: /* CONTENT */
|
||||
sqlite3_free(zContent);
|
||||
zContent = zVal;
|
||||
zVal = 0;
|
||||
break;
|
||||
|
||||
case 6: /* LANGUAGEID */
|
||||
assert( iOpt==6 );
|
||||
sqlite3_free(zLanguageid);
|
||||
zLanguageid = zVal;
|
||||
zVal = 0;
|
||||
break;
|
||||
case 6: /* LANGUAGEID */
|
||||
assert( iOpt==6 );
|
||||
sqlite3_free(zLanguageid);
|
||||
zLanguageid = zVal;
|
||||
zVal = 0;
|
||||
break;
|
||||
|
||||
case 7: /* NOTINDEXED */
|
||||
azNotindexed[nNotindexed++] = zVal;
|
||||
zVal = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
assert( iOpt==SizeofArray(aFts4Opt) );
|
||||
sqlite3Fts3ErrMsg(pzErr, "unrecognized parameter: %s", z);
|
||||
rc = SQLITE_ERROR;
|
||||
break;
|
||||
case 7: /* NOTINDEXED */
|
||||
azNotindexed[nNotindexed++] = zVal;
|
||||
zVal = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
sqlite3_free(zVal);
|
||||
}
|
||||
@@ -1368,9 +1363,9 @@ static int fts3InitVtab(
|
||||
p->pTokenizer = pTokenizer;
|
||||
p->nMaxPendingData = FTS3_MAX_PENDING_DATA;
|
||||
p->bHasDocsize = (isFts4 && bNoDocsize==0);
|
||||
p->bHasStat = (u8)isFts4;
|
||||
p->bFts4 = (u8)isFts4;
|
||||
p->bDescIdx = (u8)bDescIdx;
|
||||
p->bHasStat = isFts4;
|
||||
p->bFts4 = isFts4;
|
||||
p->bDescIdx = bDescIdx;
|
||||
p->nAutoincrmerge = 0xff; /* 0xff means setting unknown */
|
||||
p->zContentTbl = zContent;
|
||||
p->zLanguageid = zLanguageid;
|
||||
@@ -1401,9 +1396,7 @@ static int fts3InitVtab(
|
||||
char *z;
|
||||
int n = 0;
|
||||
z = (char *)sqlite3Fts3NextToken(aCol[iCol], &n);
|
||||
if( n>0 ){
|
||||
memcpy(zCsr, z, n);
|
||||
}
|
||||
memcpy(zCsr, z, n);
|
||||
zCsr[n] = '\0';
|
||||
sqlite3Fts3Dequote(zCsr);
|
||||
p->azColumn[iCol] = zCsr;
|
||||
@@ -1687,39 +1680,6 @@ static int fts3OpenMethod(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCsr){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Finalize the statement handle at pCsr->pStmt.
|
||||
**
|
||||
** Or, if that statement handle is one created by fts3CursorSeekStmt(),
|
||||
** and the Fts3Table.pSeekStmt slot is currently NULL, save the statement
|
||||
** pointer there instead of finalizing it.
|
||||
*/
|
||||
static void fts3CursorFinalizeStmt(Fts3Cursor *pCsr){
|
||||
if( pCsr->bSeekStmt ){
|
||||
Fts3Table *p = (Fts3Table *)pCsr->base.pVtab;
|
||||
if( p->pSeekStmt==0 ){
|
||||
p->pSeekStmt = pCsr->pStmt;
|
||||
sqlite3_reset(pCsr->pStmt);
|
||||
pCsr->pStmt = 0;
|
||||
}
|
||||
pCsr->bSeekStmt = 0;
|
||||
}
|
||||
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.
|
||||
@@ -1727,7 +1687,11 @@ static void fts3ClearCursor(Fts3Cursor *pCsr){
|
||||
static int fts3CloseMethod(sqlite3_vtab_cursor *pCursor){
|
||||
Fts3Cursor *pCsr = (Fts3Cursor *)pCursor;
|
||||
assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 );
|
||||
fts3ClearCursor(pCsr);
|
||||
sqlite3_finalize(pCsr->pStmt);
|
||||
sqlite3Fts3ExprFree(pCsr->pExpr);
|
||||
sqlite3Fts3FreeDeferredTokens(pCsr);
|
||||
sqlite3_free(pCsr->aDoclist);
|
||||
sqlite3Fts3MIBufferFree(pCsr->pMIBuffer);
|
||||
assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 );
|
||||
sqlite3_free(pCsr);
|
||||
return SQLITE_OK;
|
||||
@@ -1741,23 +1705,20 @@ static int fts3CloseMethod(sqlite3_vtab_cursor *pCursor){
|
||||
**
|
||||
** (or the equivalent for a content=xxx table) and set pCsr->pStmt to
|
||||
** it. If an error occurs, return an SQLite error code.
|
||||
**
|
||||
** Otherwise, set *ppStmt to point to pCsr->pStmt and return SQLITE_OK.
|
||||
*/
|
||||
static int fts3CursorSeekStmt(Fts3Cursor *pCsr){
|
||||
static int fts3CursorSeekStmt(Fts3Cursor *pCsr, sqlite3_stmt **ppStmt){
|
||||
int rc = SQLITE_OK;
|
||||
if( pCsr->pStmt==0 ){
|
||||
Fts3Table *p = (Fts3Table *)pCsr->base.pVtab;
|
||||
char *zSql;
|
||||
if( p->pSeekStmt ){
|
||||
pCsr->pStmt = p->pSeekStmt;
|
||||
p->pSeekStmt = 0;
|
||||
}else{
|
||||
zSql = sqlite3_mprintf("SELECT %s WHERE rowid = ?", p->zReadExprlist);
|
||||
if( !zSql ) return SQLITE_NOMEM;
|
||||
rc = sqlite3_prepare_v3(p->db, zSql,-1,SQLITE_PREPARE_PERSISTENT,&pCsr->pStmt,0);
|
||||
sqlite3_free(zSql);
|
||||
}
|
||||
if( rc==SQLITE_OK ) pCsr->bSeekStmt = 1;
|
||||
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);
|
||||
sqlite3_free(zSql);
|
||||
}
|
||||
*ppStmt = pCsr->pStmt;
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -1769,7 +1730,9 @@ static int fts3CursorSeekStmt(Fts3Cursor *pCsr){
|
||||
static int fts3CursorSeek(sqlite3_context *pContext, Fts3Cursor *pCsr){
|
||||
int rc = SQLITE_OK;
|
||||
if( pCsr->isRequireSeek ){
|
||||
rc = fts3CursorSeekStmt(pCsr);
|
||||
sqlite3_stmt *pStmt = 0;
|
||||
|
||||
rc = fts3CursorSeekStmt(pCsr, &pStmt);
|
||||
if( rc==SQLITE_OK ){
|
||||
sqlite3_bind_int64(pCsr->pStmt, 1, pCsr->iPrevId);
|
||||
pCsr->isRequireSeek = 0;
|
||||
@@ -1858,8 +1821,7 @@ static int fts3ScanInteriorNode(
|
||||
isFirstTerm = 0;
|
||||
zCsr += fts3GetVarint32(zCsr, &nSuffix);
|
||||
|
||||
assert( nPrefix>=0 && nSuffix>=0 );
|
||||
if( &zCsr[nSuffix]>zEnd ){
|
||||
if( nPrefix<0 || nSuffix<0 || &zCsr[nSuffix]>zEnd ){
|
||||
rc = FTS_CORRUPT_VTAB;
|
||||
goto finish_scan;
|
||||
}
|
||||
@@ -2669,7 +2631,7 @@ int sqlite3Fts3FirstFilter(
|
||||
fts3ColumnlistCopy(0, &p);
|
||||
}
|
||||
|
||||
while( p<pEnd ){
|
||||
while( p<pEnd && *p==0x01 ){
|
||||
sqlite3_int64 iCol;
|
||||
p++;
|
||||
p += sqlite3Fts3GetVarint(p, &iCol);
|
||||
@@ -3228,7 +3190,11 @@ static int fts3FilterMethod(
|
||||
assert( iIdx==nVal );
|
||||
|
||||
/* In case the cursor has been used before, clear it now. */
|
||||
fts3ClearCursor(pCsr);
|
||||
sqlite3_finalize(pCsr->pStmt);
|
||||
sqlite3_free(pCsr->aDoclist);
|
||||
sqlite3Fts3MIBufferFree(pCsr->pMIBuffer);
|
||||
sqlite3Fts3ExprFree(pCsr->pExpr);
|
||||
memset(&pCursor[1], 0, sizeof(Fts3Cursor)-sizeof(sqlite3_vtab_cursor));
|
||||
|
||||
/* Set the lower and upper bounds on docids to return */
|
||||
pCsr->iMinDocid = fts3DocidRange(pDocidGe, SMALLEST_INT64);
|
||||
@@ -3286,13 +3252,13 @@ static int fts3FilterMethod(
|
||||
);
|
||||
}
|
||||
if( zSql ){
|
||||
rc = sqlite3_prepare_v3(p->db,zSql,-1,SQLITE_PREPARE_PERSISTENT,&pCsr->pStmt,0);
|
||||
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pCsr->pStmt, 0);
|
||||
sqlite3_free(zSql);
|
||||
}else{
|
||||
rc = SQLITE_NOMEM;
|
||||
}
|
||||
}else if( eSearch==FTS3_DOCID_SEARCH ){
|
||||
rc = fts3CursorSeekStmt(pCsr);
|
||||
rc = fts3CursorSeekStmt(pCsr, &pCsr->pStmt);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3_bind_value(pCsr->pStmt, 1, pCons);
|
||||
}
|
||||
@@ -3307,12 +3273,7 @@ static int fts3FilterMethod(
|
||||
** routine to find out if it has reached the end of a result set.
|
||||
*/
|
||||
static int fts3EofMethod(sqlite3_vtab_cursor *pCursor){
|
||||
Fts3Cursor *pCsr = (Fts3Cursor*)pCursor;
|
||||
if( pCsr->isEof ){
|
||||
fts3ClearCursor(pCsr);
|
||||
pCsr->isEof = 1;
|
||||
}
|
||||
return pCsr->isEof;
|
||||
return ((Fts3Cursor *)pCursor)->isEof;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3350,37 +3311,33 @@ static int fts3ColumnMethod(
|
||||
/* The column value supplied by SQLite must be in range. */
|
||||
assert( iCol>=0 && iCol<=p->nColumn+2 );
|
||||
|
||||
switch( iCol-p->nColumn ){
|
||||
case 0:
|
||||
/* The special 'table-name' column */
|
||||
sqlite3_result_pointer(pCtx, pCsr, "fts3cursor", 0);
|
||||
break;
|
||||
if( iCol==p->nColumn+1 ){
|
||||
/* This call is a request for the "docid" column. Since "docid" is an
|
||||
** alias for "rowid", use the xRowid() method to obtain the value.
|
||||
*/
|
||||
sqlite3_result_int64(pCtx, pCsr->iPrevId);
|
||||
}else if( iCol==p->nColumn ){
|
||||
/* The extra column whose name is the same as the table.
|
||||
** Return a blob which is a pointer to the cursor. */
|
||||
sqlite3_result_blob(pCtx, &pCsr, sizeof(pCsr), SQLITE_TRANSIENT);
|
||||
}else if( iCol==p->nColumn+2 && pCsr->pExpr ){
|
||||
sqlite3_result_int64(pCtx, pCsr->iLangid);
|
||||
}else{
|
||||
/* The requested column is either a user column (one that contains
|
||||
** indexed data), or the language-id column. */
|
||||
rc = fts3CursorSeek(0, pCsr);
|
||||
|
||||
case 1:
|
||||
/* The docid column */
|
||||
sqlite3_result_int64(pCtx, pCsr->iPrevId);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
if( pCsr->pExpr ){
|
||||
sqlite3_result_int64(pCtx, pCsr->iLangid);
|
||||
break;
|
||||
}else if( p->zLanguageid==0 ){
|
||||
sqlite3_result_int(pCtx, 0);
|
||||
break;
|
||||
}else{
|
||||
iCol = p->nColumn;
|
||||
/* fall-through */
|
||||
}
|
||||
|
||||
default:
|
||||
/* A user column. Or, if this is a full-table scan, possibly the
|
||||
** language-id column. Seek the cursor. */
|
||||
rc = fts3CursorSeek(0, pCsr);
|
||||
if( rc==SQLITE_OK && sqlite3_data_count(pCsr->pStmt)-1>iCol ){
|
||||
if( rc==SQLITE_OK ){
|
||||
if( iCol==p->nColumn+2 ){
|
||||
int iLangid = 0;
|
||||
if( p->zLanguageid ){
|
||||
iLangid = sqlite3_column_int(pCsr->pStmt, p->nColumn+1);
|
||||
}
|
||||
sqlite3_result_int(pCtx, iLangid);
|
||||
}else if( sqlite3_data_count(pCsr->pStmt)>(iCol+1) ){
|
||||
sqlite3_result_value(pCtx, sqlite3_column_value(pCsr->pStmt, iCol+1));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 );
|
||||
@@ -3429,10 +3386,8 @@ static int fts3SyncMethod(sqlite3_vtab *pVtab){
|
||||
const u32 nMinMerge = 64; /* Minimum amount of incr-merge work to do */
|
||||
|
||||
Fts3Table *p = (Fts3Table*)pVtab;
|
||||
int rc;
|
||||
i64 iLastRowid = sqlite3_last_insert_rowid(p->db);
|
||||
int rc = sqlite3Fts3PendingTermsFlush(p);
|
||||
|
||||
rc = sqlite3Fts3PendingTermsFlush(p);
|
||||
if( rc==SQLITE_OK
|
||||
&& p->nLeafAdd>(nMinMerge/16)
|
||||
&& p->nAutoincrmerge && p->nAutoincrmerge!=0xff
|
||||
@@ -3447,7 +3402,6 @@ static int fts3SyncMethod(sqlite3_vtab *pVtab){
|
||||
if( A>(int)nMinMerge ) rc = sqlite3Fts3Incrmerge(p, A, p->nAutoincrmerge);
|
||||
}
|
||||
sqlite3Fts3SegmentsClose(p);
|
||||
sqlite3_set_last_insert_rowid(p->db, iLastRowid);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -3460,11 +3414,17 @@ static int fts3SyncMethod(sqlite3_vtab *pVtab){
|
||||
static int fts3SetHasStat(Fts3Table *p){
|
||||
int rc = SQLITE_OK;
|
||||
if( p->bHasStat==2 ){
|
||||
char *zTbl = sqlite3_mprintf("%s_stat", p->zName);
|
||||
if( zTbl ){
|
||||
int res = sqlite3_table_column_metadata(p->db, p->zDb, zTbl, 0,0,0,0,0,0);
|
||||
sqlite3_free(zTbl);
|
||||
p->bHasStat = (res==SQLITE_OK);
|
||||
const char *zFmt ="SELECT 1 FROM %Q.sqlite_master WHERE tbl_name='%q_stat'";
|
||||
char *zSql = sqlite3_mprintf(zFmt, p->zDb, p->zName);
|
||||
if( zSql ){
|
||||
sqlite3_stmt *pStmt = 0;
|
||||
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
|
||||
if( rc==SQLITE_OK ){
|
||||
int bHasStat = (sqlite3_step(pStmt)==SQLITE_ROW);
|
||||
rc = sqlite3_finalize(pStmt);
|
||||
if( rc==SQLITE_OK ) p->bHasStat = bHasStat;
|
||||
}
|
||||
sqlite3_free(zSql);
|
||||
}else{
|
||||
rc = SQLITE_NOMEM;
|
||||
}
|
||||
@@ -3571,17 +3531,18 @@ static int fts3FunctionArg(
|
||||
sqlite3_value *pVal, /* argv[0] passed to function */
|
||||
Fts3Cursor **ppCsr /* OUT: Store cursor handle here */
|
||||
){
|
||||
int rc;
|
||||
*ppCsr = (Fts3Cursor*)sqlite3_value_pointer(pVal, "fts3cursor");
|
||||
if( (*ppCsr)!=0 ){
|
||||
rc = SQLITE_OK;
|
||||
}else{
|
||||
Fts3Cursor *pRet;
|
||||
if( sqlite3_value_type(pVal)!=SQLITE_BLOB
|
||||
|| sqlite3_value_bytes(pVal)!=sizeof(Fts3Cursor *)
|
||||
){
|
||||
char *zErr = sqlite3_mprintf("illegal first argument to %s", zFunc);
|
||||
sqlite3_result_error(pContext, zErr, -1);
|
||||
sqlite3_free(zErr);
|
||||
rc = SQLITE_ERROR;
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
return rc;
|
||||
memcpy(&pRet, sqlite3_value_blob(pVal), sizeof(Fts3Cursor *));
|
||||
*ppCsr = pRet;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3968,7 +3929,7 @@ int sqlite3Fts3Init(sqlite3 *db){
|
||||
#endif
|
||||
|
||||
/* Create the virtual table wrapper around the hash-table and overload
|
||||
** the four scalar functions. If this is successful, register the
|
||||
** the two scalar functions. If this is successful, register the
|
||||
** module with sqlite.
|
||||
*/
|
||||
if( SQLITE_OK==rc
|
||||
@@ -4551,7 +4512,7 @@ static int fts3EvalIncrPhraseNext(
|
||||
** one incremental token. In which case the bIncr flag is set. */
|
||||
assert( p->bIncr==1 );
|
||||
|
||||
if( p->nToken==1 ){
|
||||
if( p->nToken==1 && p->bIncr ){
|
||||
rc = sqlite3Fts3MsrIncrNext(pTab, p->aToken[0].pSegcsr,
|
||||
&pDL->iDocid, &pDL->pList, &pDL->nList
|
||||
);
|
||||
@@ -4784,7 +4745,6 @@ static void fts3EvalTokenCosts(
|
||||
** the number of overflow pages consumed by a record B bytes in size.
|
||||
*/
|
||||
static int fts3EvalAverageDocsize(Fts3Cursor *pCsr, int *pnPage){
|
||||
int rc = SQLITE_OK;
|
||||
if( pCsr->nRowAvg==0 ){
|
||||
/* The average document size, which is required to calculate the cost
|
||||
** of each doclist, has not yet been determined. Read the required
|
||||
@@ -4797,6 +4757,7 @@ static int fts3EvalAverageDocsize(Fts3Cursor *pCsr, int *pnPage){
|
||||
** data stored in all rows of each column of the table, from left
|
||||
** to right.
|
||||
*/
|
||||
int rc;
|
||||
Fts3Table *p = (Fts3Table*)pCsr->base.pVtab;
|
||||
sqlite3_stmt *pStmt;
|
||||
sqlite3_int64 nDoc = 0;
|
||||
@@ -4823,10 +4784,11 @@ static int fts3EvalAverageDocsize(Fts3Cursor *pCsr, int *pnPage){
|
||||
pCsr->nRowAvg = (int)(((nByte / nDoc) + p->nPgsz) / p->nPgsz);
|
||||
assert( pCsr->nRowAvg>0 );
|
||||
rc = sqlite3_reset(pStmt);
|
||||
if( rc!=SQLITE_OK ) return rc;
|
||||
}
|
||||
|
||||
*pnPage = pCsr->nRowAvg;
|
||||
return rc;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -5176,8 +5138,7 @@ static void fts3EvalNextRow(
|
||||
pExpr->iDocid = pLeft->iDocid;
|
||||
pExpr->bEof = (pLeft->bEof || pRight->bEof);
|
||||
if( pExpr->eType==FTSQUERY_NEAR && pExpr->bEof ){
|
||||
assert( pRight->eType==FTSQUERY_PHRASE );
|
||||
if( pRight->pPhrase->doclist.aAll ){
|
||||
if( pRight->pPhrase && pRight->pPhrase->doclist.aAll ){
|
||||
Fts3Doclist *pDl = &pRight->pPhrase->doclist;
|
||||
while( *pRc==SQLITE_OK && pRight->bEof==0 ){
|
||||
memset(pDl->pList, 0, pDl->nList);
|
||||
@@ -5206,7 +5167,7 @@ static void fts3EvalNextRow(
|
||||
|
||||
if( pRight->bEof || (pLeft->bEof==0 && iCmp<0) ){
|
||||
fts3EvalNextRow(pCsr, pLeft, pRc);
|
||||
}else if( pLeft->bEof || iCmp>0 ){
|
||||
}else if( pLeft->bEof || (pRight->bEof==0 && iCmp>0) ){
|
||||
fts3EvalNextRow(pCsr, pRight, pRc);
|
||||
}else{
|
||||
fts3EvalNextRow(pCsr, pLeft, pRc);
|
||||
@@ -5298,6 +5259,7 @@ static int fts3EvalNearTest(Fts3Expr *pExpr, int *pRc){
|
||||
*/
|
||||
if( *pRc==SQLITE_OK
|
||||
&& pExpr->eType==FTSQUERY_NEAR
|
||||
&& pExpr->bEof==0
|
||||
&& (pExpr->pParent==0 || pExpr->pParent->eType!=FTSQUERY_NEAR)
|
||||
){
|
||||
Fts3Expr *p;
|
||||
@@ -5306,39 +5268,42 @@ static int fts3EvalNearTest(Fts3Expr *pExpr, int *pRc){
|
||||
|
||||
/* Allocate temporary working space. */
|
||||
for(p=pExpr; p->pLeft; p=p->pLeft){
|
||||
assert( p->pRight->pPhrase->doclist.nList>0 );
|
||||
nTmp += p->pRight->pPhrase->doclist.nList;
|
||||
}
|
||||
nTmp += p->pPhrase->doclist.nList;
|
||||
aTmp = sqlite3_malloc(nTmp*2);
|
||||
if( !aTmp ){
|
||||
*pRc = SQLITE_NOMEM;
|
||||
if( nTmp==0 ){
|
||||
res = 0;
|
||||
}else{
|
||||
char *aPoslist = p->pPhrase->doclist.pList;
|
||||
int nToken = p->pPhrase->nToken;
|
||||
aTmp = sqlite3_malloc(nTmp*2);
|
||||
if( !aTmp ){
|
||||
*pRc = SQLITE_NOMEM;
|
||||
res = 0;
|
||||
}else{
|
||||
char *aPoslist = p->pPhrase->doclist.pList;
|
||||
int nToken = p->pPhrase->nToken;
|
||||
|
||||
for(p=p->pParent;res && p && p->eType==FTSQUERY_NEAR; p=p->pParent){
|
||||
Fts3Phrase *pPhrase = p->pRight->pPhrase;
|
||||
int nNear = p->nNear;
|
||||
res = fts3EvalNearTrim(nNear, aTmp, &aPoslist, &nToken, pPhrase);
|
||||
for(p=p->pParent;res && p && p->eType==FTSQUERY_NEAR; p=p->pParent){
|
||||
Fts3Phrase *pPhrase = p->pRight->pPhrase;
|
||||
int nNear = p->nNear;
|
||||
res = fts3EvalNearTrim(nNear, aTmp, &aPoslist, &nToken, pPhrase);
|
||||
}
|
||||
|
||||
aPoslist = pExpr->pRight->pPhrase->doclist.pList;
|
||||
nToken = pExpr->pRight->pPhrase->nToken;
|
||||
for(p=pExpr->pLeft; p && res; p=p->pLeft){
|
||||
int nNear;
|
||||
Fts3Phrase *pPhrase;
|
||||
assert( p->pParent && p->pParent->pLeft==p );
|
||||
nNear = p->pParent->nNear;
|
||||
pPhrase = (
|
||||
p->eType==FTSQUERY_NEAR ? p->pRight->pPhrase : p->pPhrase
|
||||
);
|
||||
res = fts3EvalNearTrim(nNear, aTmp, &aPoslist, &nToken, pPhrase);
|
||||
}
|
||||
}
|
||||
|
||||
aPoslist = pExpr->pRight->pPhrase->doclist.pList;
|
||||
nToken = pExpr->pRight->pPhrase->nToken;
|
||||
for(p=pExpr->pLeft; p && res; p=p->pLeft){
|
||||
int nNear;
|
||||
Fts3Phrase *pPhrase;
|
||||
assert( p->pParent && p->pParent->pLeft==p );
|
||||
nNear = p->pParent->nNear;
|
||||
pPhrase = (
|
||||
p->eType==FTSQUERY_NEAR ? p->pRight->pPhrase : p->pPhrase
|
||||
);
|
||||
res = fts3EvalNearTrim(nNear, aTmp, &aPoslist, &nToken, pPhrase);
|
||||
}
|
||||
sqlite3_free(aTmp);
|
||||
}
|
||||
|
||||
sqlite3_free(aTmp);
|
||||
}
|
||||
|
||||
return res;
|
||||
|
||||
@@ -230,7 +230,6 @@ struct Fts3Table {
|
||||
** statements is run and reset within a single virtual table API call.
|
||||
*/
|
||||
sqlite3_stmt *aStmt[40];
|
||||
sqlite3_stmt *pSeekStmt; /* Cache for fts3CursorSeekStmt() */
|
||||
|
||||
char *zReadExprlist;
|
||||
char *zWriteExprlist;
|
||||
@@ -300,7 +299,6 @@ struct Fts3Cursor {
|
||||
i16 eSearch; /* Search strategy (see below) */
|
||||
u8 isEof; /* True if at End Of Results */
|
||||
u8 isRequireSeek; /* True if must seek pStmt to %_content row */
|
||||
u8 bSeekStmt; /* True if pStmt is a seek */
|
||||
sqlite3_stmt *pStmt; /* Prepared statement in use by the cursor */
|
||||
Fts3Expr *pExpr; /* Parsed MATCH query string */
|
||||
int iLangid; /* Language being queried for */
|
||||
|
||||
+13
-13
@@ -136,16 +136,16 @@ static int unicodeAddExceptions(
|
||||
){
|
||||
const unsigned char *z = (const unsigned char *)zIn;
|
||||
const unsigned char *zTerm = &z[nIn];
|
||||
unsigned int iCode;
|
||||
int iCode;
|
||||
int nEntry = 0;
|
||||
|
||||
assert( bAlnum==0 || bAlnum==1 );
|
||||
|
||||
while( z<zTerm ){
|
||||
READ_UTF8(z, zTerm, iCode);
|
||||
assert( (sqlite3FtsUnicodeIsalnum((int)iCode) & 0xFFFFFFFE)==0 );
|
||||
if( sqlite3FtsUnicodeIsalnum((int)iCode)!=bAlnum
|
||||
&& sqlite3FtsUnicodeIsdiacritic((int)iCode)==0
|
||||
assert( (sqlite3FtsUnicodeIsalnum(iCode) & 0xFFFFFFFE)==0 );
|
||||
if( sqlite3FtsUnicodeIsalnum(iCode)!=bAlnum
|
||||
&& sqlite3FtsUnicodeIsdiacritic(iCode)==0
|
||||
){
|
||||
nEntry++;
|
||||
}
|
||||
@@ -162,13 +162,13 @@ static int unicodeAddExceptions(
|
||||
z = (const unsigned char *)zIn;
|
||||
while( z<zTerm ){
|
||||
READ_UTF8(z, zTerm, iCode);
|
||||
if( sqlite3FtsUnicodeIsalnum((int)iCode)!=bAlnum
|
||||
&& sqlite3FtsUnicodeIsdiacritic((int)iCode)==0
|
||||
if( sqlite3FtsUnicodeIsalnum(iCode)!=bAlnum
|
||||
&& sqlite3FtsUnicodeIsdiacritic(iCode)==0
|
||||
){
|
||||
int i, j;
|
||||
for(i=0; i<nNew && aNew[i]<(int)iCode; i++);
|
||||
for(i=0; i<nNew && aNew[i]<iCode; i++);
|
||||
for(j=nNew; j>i; j--) aNew[j] = aNew[j-1];
|
||||
aNew[i] = (int)iCode;
|
||||
aNew[i] = iCode;
|
||||
nNew++;
|
||||
}
|
||||
}
|
||||
@@ -318,7 +318,7 @@ static int unicodeNext(
|
||||
){
|
||||
unicode_cursor *pCsr = (unicode_cursor *)pC;
|
||||
unicode_tokenizer *p = ((unicode_tokenizer *)pCsr->base.pTokenizer);
|
||||
unsigned int iCode = 0;
|
||||
int iCode = 0;
|
||||
char *zOut;
|
||||
const unsigned char *z = &pCsr->aInput[pCsr->iOff];
|
||||
const unsigned char *zStart = z;
|
||||
@@ -330,7 +330,7 @@ static int unicodeNext(
|
||||
** the input. */
|
||||
while( z<zTerm ){
|
||||
READ_UTF8(z, zTerm, iCode);
|
||||
if( unicodeIsAlnum(p, (int)iCode) ) break;
|
||||
if( unicodeIsAlnum(p, iCode) ) break;
|
||||
zStart = z;
|
||||
}
|
||||
if( zStart>=zTerm ) return SQLITE_DONE;
|
||||
@@ -350,7 +350,7 @@ static int unicodeNext(
|
||||
|
||||
/* Write the folded case of the last character read to the output */
|
||||
zEnd = z;
|
||||
iOut = sqlite3FtsUnicodeFold((int)iCode, p->bRemoveDiacritic);
|
||||
iOut = sqlite3FtsUnicodeFold(iCode, p->bRemoveDiacritic);
|
||||
if( iOut ){
|
||||
WRITE_UTF8(zOut, iOut);
|
||||
}
|
||||
@@ -358,8 +358,8 @@ static int unicodeNext(
|
||||
/* If the cursor is not at EOF, read the next character */
|
||||
if( z>=zTerm ) break;
|
||||
READ_UTF8(z, zTerm, iCode);
|
||||
}while( unicodeIsAlnum(p, (int)iCode)
|
||||
|| sqlite3FtsUnicodeIsdiacritic((int)iCode)
|
||||
}while( unicodeIsAlnum(p, iCode)
|
||||
|| sqlite3FtsUnicodeIsdiacritic(iCode)
|
||||
);
|
||||
|
||||
/* Set the output variables and return. */
|
||||
|
||||
+11
-10
@@ -127,9 +127,9 @@ int sqlite3FtsUnicodeIsalnum(int c){
|
||||
0xFFFFFFFF, 0xFC00FFFF, 0xF8000001, 0xF8000001,
|
||||
};
|
||||
|
||||
if( (unsigned int)c<128 ){
|
||||
return ( (aAscii[c >> 5] & ((unsigned int)1 << (c & 0x001F)))==0 );
|
||||
}else if( (unsigned int)c<(1<<22) ){
|
||||
if( c<128 ){
|
||||
return ( (aAscii[c >> 5] & (1 << (c & 0x001F)))==0 );
|
||||
}else if( c<(1<<22) ){
|
||||
unsigned int key = (((unsigned int)c)<<10) | 0x000003FF;
|
||||
int iRes = 0;
|
||||
int iHi = sizeof(aEntry)/sizeof(aEntry[0]) - 1;
|
||||
@@ -322,17 +322,16 @@ int sqlite3FtsUnicodeFold(int c, int bRemoveDiacritic){
|
||||
|
||||
int ret = c;
|
||||
|
||||
assert( c>=0 );
|
||||
assert( sizeof(unsigned short)==2 && sizeof(unsigned char)==1 );
|
||||
|
||||
if( c<128 ){
|
||||
if( c>='A' && c<='Z' ) ret = c + ('a' - 'A');
|
||||
}else if( c<65536 ){
|
||||
const struct TableEntry *p;
|
||||
int iHi = sizeof(aEntry)/sizeof(aEntry[0]) - 1;
|
||||
int iLo = 0;
|
||||
int iRes = -1;
|
||||
|
||||
assert( c>aEntry[0].iCode );
|
||||
while( iHi>=iLo ){
|
||||
int iTest = (iHi + iLo) / 2;
|
||||
int cmp = (c - aEntry[iTest].iCode);
|
||||
@@ -343,12 +342,14 @@ int sqlite3FtsUnicodeFold(int c, int bRemoveDiacritic){
|
||||
iHi = iTest-1;
|
||||
}
|
||||
}
|
||||
assert( iRes<0 || c>=aEntry[iRes].iCode );
|
||||
|
||||
assert( iRes>=0 && c>=aEntry[iRes].iCode );
|
||||
p = &aEntry[iRes];
|
||||
if( c<(p->iCode + p->nRange) && 0==(0x01 & p->flags & (p->iCode ^ c)) ){
|
||||
ret = (c + (aiOff[p->flags>>1])) & 0x0000FFFF;
|
||||
assert( ret>0 );
|
||||
if( iRes>=0 ){
|
||||
const struct TableEntry *p = &aEntry[iRes];
|
||||
if( c<(p->iCode + p->nRange) && 0==(0x01 & p->flags & (p->iCode ^ c)) ){
|
||||
ret = (c + (aiOff[p->flags>>1])) & 0x0000FFFF;
|
||||
assert( ret>0 );
|
||||
}
|
||||
}
|
||||
|
||||
if( bRemoveDiacritic ) ret = remove_diacritic(ret);
|
||||
|
||||
@@ -407,8 +407,7 @@ static int fts3SqlStmt(
|
||||
if( !zSql ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
rc = sqlite3_prepare_v3(p->db, zSql, -1, SQLITE_PREPARE_PERSISTENT,
|
||||
&pStmt, NULL);
|
||||
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, NULL);
|
||||
sqlite3_free(zSql);
|
||||
assert( rc==SQLITE_OK || pStmt==0 );
|
||||
p->aStmt[eStmt] = pStmt;
|
||||
@@ -4957,14 +4956,11 @@ int sqlite3Fts3Incrmerge(Fts3Table *p, int nMerge, int nMin){
|
||||
** Convert the text beginning at *pz into an integer and return
|
||||
** its value. Advance *pz to point to the first character past
|
||||
** the integer.
|
||||
**
|
||||
** This function used for parameters to merge= and incrmerge=
|
||||
** commands.
|
||||
*/
|
||||
static int fts3Getint(const char **pz){
|
||||
const char *z = *pz;
|
||||
int i = 0;
|
||||
while( (*z)>='0' && (*z)<='9' && i<214748363 ) i = 10*i + *(z++) - '0';
|
||||
while( (*z)>='0' && (*z)<='9' ) i = 10*i + *(z++) - '0';
|
||||
*pz = z;
|
||||
return i;
|
||||
}
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
srcdir=`dirname $(dirname $(dirname $(dirname $0)))`
|
||||
./testfixture $srcdir/test/fts3.test --output=fts3cov-out.txt
|
||||
|
||||
echo ""
|
||||
|
||||
for f in `ls $srcdir/ext/fts3/*.c`
|
||||
do
|
||||
f=`basename $f`
|
||||
echo -ne "$f: "
|
||||
gcov -b $f | grep Taken | sed 's/Taken at least once://'
|
||||
done
|
||||
|
||||
@@ -227,7 +227,7 @@ proc print_isalnum {zFunc lRange} {
|
||||
an_print_ascii_bitmap $lRange
|
||||
puts {
|
||||
if( (unsigned int)c<128 ){
|
||||
return ( (aAscii[c >> 5] & ((unsigned int)1 << (c & 0x001F)))==0 );
|
||||
return ( (aAscii[c >> 5] & (1 << (c & 0x001F)))==0 );
|
||||
}else if( (unsigned int)c<(1<<22) ){
|
||||
unsigned int key = (((unsigned int)c)<<10) | 0x000003FF;
|
||||
int iRes = 0;
|
||||
|
||||
+5
-8
@@ -30,9 +30,7 @@ typedef short i16;
|
||||
typedef sqlite3_int64 i64;
|
||||
typedef sqlite3_uint64 u64;
|
||||
|
||||
#ifndef ArraySize
|
||||
# define ArraySize(x) ((int)(sizeof(x) / sizeof(x[0])))
|
||||
#endif
|
||||
#define ArraySize(x) ((int)(sizeof(x) / sizeof(x[0])))
|
||||
|
||||
#define testcase(x)
|
||||
#define ALWAYS(x) 1
|
||||
@@ -446,9 +444,9 @@ int sqlite3Fts5IndexBeginWrite(
|
||||
|
||||
/*
|
||||
** Flush any data stored in the in-memory hash tables to the database.
|
||||
** Also close any open blob handles.
|
||||
** If the bCommit flag is true, also close any open blob handles.
|
||||
*/
|
||||
int sqlite3Fts5IndexSync(Fts5Index *p);
|
||||
int sqlite3Fts5IndexSync(Fts5Index *p, int bCommit);
|
||||
|
||||
/*
|
||||
** Discard any data stored in the in-memory hash tables. Do not write it
|
||||
@@ -618,7 +616,7 @@ int sqlite3Fts5StorageDocsize(Fts5Storage *p, i64 iRowid, int *aCol);
|
||||
int sqlite3Fts5StorageSize(Fts5Storage *p, int iCol, i64 *pnAvg);
|
||||
int sqlite3Fts5StorageRowCount(Fts5Storage *p, i64 *pnRow);
|
||||
|
||||
int sqlite3Fts5StorageSync(Fts5Storage *p);
|
||||
int sqlite3Fts5StorageSync(Fts5Storage *p, int bCommit);
|
||||
int sqlite3Fts5StorageRollback(Fts5Storage *p);
|
||||
|
||||
int sqlite3Fts5StorageConfigValue(
|
||||
@@ -654,7 +652,6 @@ struct Fts5Token {
|
||||
/* Parse a MATCH expression. */
|
||||
int sqlite3Fts5ExprNew(
|
||||
Fts5Config *pConfig,
|
||||
int iCol, /* Column on LHS of MATCH operator */
|
||||
const char *zExpr,
|
||||
Fts5Expr **ppNew,
|
||||
char **pzErr
|
||||
@@ -739,7 +736,7 @@ void sqlite3Fts5ParseNearsetFree(Fts5ExprNearset*);
|
||||
void sqlite3Fts5ParseNodeFree(Fts5ExprNode*);
|
||||
|
||||
void sqlite3Fts5ParseSetDistance(Fts5Parse*, Fts5ExprNearset*, Fts5Token*);
|
||||
void sqlite3Fts5ParseSetColset(Fts5Parse*, Fts5ExprNode*, Fts5Colset*);
|
||||
void sqlite3Fts5ParseSetColset(Fts5Parse*, Fts5ExprNearset*, Fts5Colset*);
|
||||
Fts5Colset *sqlite3Fts5ParseColsetInvert(Fts5Parse*, Fts5Colset*);
|
||||
void sqlite3Fts5ParseFinished(Fts5Parse *pParse, Fts5ExprNode *p);
|
||||
void sqlite3Fts5ParseNear(Fts5Parse *pParse, Fts5Token*);
|
||||
|
||||
@@ -67,11 +67,9 @@ void sqlite3Fts5BufferAppendBlob(
|
||||
const u8 *pData
|
||||
){
|
||||
assert_nc( *pRc || nData>=0 );
|
||||
if( nData ){
|
||||
if( fts5BufferGrow(pRc, pBuf, nData) ) return;
|
||||
memcpy(&pBuf->p[pBuf->n], pData, nData);
|
||||
pBuf->n += nData;
|
||||
}
|
||||
if( fts5BufferGrow(pRc, pBuf, nData) ) return;
|
||||
memcpy(&pBuf->p[pBuf->n], pData, nData);
|
||||
pBuf->n += nData;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -248,8 +246,8 @@ void *sqlite3Fts5MallocZero(int *pRc, int nByte){
|
||||
void *pRet = 0;
|
||||
if( *pRc==SQLITE_OK ){
|
||||
pRet = sqlite3_malloc(nByte);
|
||||
if( pRet==0 ){
|
||||
if( nByte>0 ) *pRc = SQLITE_NOMEM;
|
||||
if( pRet==0 && nByte>0 ){
|
||||
*pRc = SQLITE_NOMEM;
|
||||
}else{
|
||||
memset(pRet, 0, nByte);
|
||||
}
|
||||
|
||||
+41
-166
@@ -213,7 +213,6 @@ static void fts5ParseFree(void *p){ sqlite3_free(p); }
|
||||
|
||||
int sqlite3Fts5ExprNew(
|
||||
Fts5Config *pConfig, /* FTS5 Configuration */
|
||||
int iCol,
|
||||
const char *zExpr, /* Expression text */
|
||||
Fts5Expr **ppNew,
|
||||
char **pzErr
|
||||
@@ -238,18 +237,6 @@ int sqlite3Fts5ExprNew(
|
||||
}while( sParse.rc==SQLITE_OK && t!=FTS5_EOF );
|
||||
sqlite3Fts5ParserFree(pEngine, fts5ParseFree);
|
||||
|
||||
/* If the LHS of the MATCH expression was a user column, apply the
|
||||
** implicit column-filter. */
|
||||
if( iCol<pConfig->nCol && sParse.pExpr && sParse.rc==SQLITE_OK ){
|
||||
int n = sizeof(Fts5Colset);
|
||||
Fts5Colset *pColset = (Fts5Colset*)sqlite3Fts5MallocZero(&sParse.rc, n);
|
||||
if( pColset ){
|
||||
pColset->nCol = 1;
|
||||
pColset->aiCol[0] = iCol;
|
||||
sqlite3Fts5ParseSetColset(&sParse, sParse.pExpr, pColset);
|
||||
}
|
||||
}
|
||||
|
||||
assert( sParse.rc!=SQLITE_OK || sParse.zErr==0 );
|
||||
if( sParse.rc==SQLITE_OK ){
|
||||
*ppNew = pNew = sqlite3_malloc(sizeof(Fts5Expr));
|
||||
@@ -759,61 +746,48 @@ static int fts5ExprNearTest(
|
||||
** Initialize all term iterators in the pNear object. If any term is found
|
||||
** to match no documents at all, return immediately without initializing any
|
||||
** further iterators.
|
||||
**
|
||||
** If an error occurs, return an SQLite error code. Otherwise, return
|
||||
** SQLITE_OK. It is not considered an error if some term matches zero
|
||||
** documents.
|
||||
*/
|
||||
static int fts5ExprNearInitAll(
|
||||
Fts5Expr *pExpr,
|
||||
Fts5ExprNode *pNode
|
||||
){
|
||||
Fts5ExprNearset *pNear = pNode->pNear;
|
||||
int i;
|
||||
int i, j;
|
||||
int rc = SQLITE_OK;
|
||||
int bEof = 1;
|
||||
|
||||
assert( pNode->bNomatch==0 );
|
||||
for(i=0; i<pNear->nPhrase; i++){
|
||||
for(i=0; rc==SQLITE_OK && i<pNear->nPhrase; i++){
|
||||
Fts5ExprPhrase *pPhrase = pNear->apPhrase[i];
|
||||
if( pPhrase->nTerm==0 ){
|
||||
pNode->bEof = 1;
|
||||
return SQLITE_OK;
|
||||
}else{
|
||||
int j;
|
||||
for(j=0; j<pPhrase->nTerm; j++){
|
||||
Fts5ExprTerm *pTerm = &pPhrase->aTerm[j];
|
||||
Fts5ExprTerm *p;
|
||||
int bHit = 0;
|
||||
for(j=0; j<pPhrase->nTerm; j++){
|
||||
Fts5ExprTerm *pTerm = &pPhrase->aTerm[j];
|
||||
Fts5ExprTerm *p;
|
||||
|
||||
for(p=pTerm; p; p=p->pSynonym){
|
||||
int rc;
|
||||
if( p->pIter ){
|
||||
sqlite3Fts5IterClose(p->pIter);
|
||||
p->pIter = 0;
|
||||
}
|
||||
rc = sqlite3Fts5IndexQuery(
|
||||
pExpr->pIndex, p->zTerm, (int)strlen(p->zTerm),
|
||||
(pTerm->bPrefix ? FTS5INDEX_QUERY_PREFIX : 0) |
|
||||
(pExpr->bDesc ? FTS5INDEX_QUERY_DESC : 0),
|
||||
pNear->pColset,
|
||||
&p->pIter
|
||||
);
|
||||
assert( (rc==SQLITE_OK)==(p->pIter!=0) );
|
||||
if( rc!=SQLITE_OK ) return rc;
|
||||
if( 0==sqlite3Fts5IterEof(p->pIter) ){
|
||||
bHit = 1;
|
||||
}
|
||||
for(p=pTerm; p && rc==SQLITE_OK; p=p->pSynonym){
|
||||
if( p->pIter ){
|
||||
sqlite3Fts5IterClose(p->pIter);
|
||||
p->pIter = 0;
|
||||
}
|
||||
|
||||
if( bHit==0 ){
|
||||
pNode->bEof = 1;
|
||||
return SQLITE_OK;
|
||||
rc = sqlite3Fts5IndexQuery(
|
||||
pExpr->pIndex, p->zTerm, (int)strlen(p->zTerm),
|
||||
(pTerm->bPrefix ? FTS5INDEX_QUERY_PREFIX : 0) |
|
||||
(pExpr->bDesc ? FTS5INDEX_QUERY_DESC : 0),
|
||||
pNear->pColset,
|
||||
&p->pIter
|
||||
);
|
||||
assert( rc==SQLITE_OK || p->pIter==0 );
|
||||
if( p->pIter && 0==sqlite3Fts5IterEof(p->pIter) ){
|
||||
bEof = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if( bEof ) break;
|
||||
}
|
||||
if( bEof ) break;
|
||||
}
|
||||
|
||||
pNode->bEof = 0;
|
||||
return SQLITE_OK;
|
||||
pNode->bEof = bEof;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -946,7 +920,7 @@ static int fts5ExprNodeTest_STRING(
|
||||
}
|
||||
}else{
|
||||
Fts5IndexIter *pIter = pPhrase->aTerm[j].pIter;
|
||||
if( pIter->iRowid==iLast || pIter->bEof ) continue;
|
||||
if( pIter->iRowid==iLast ) continue;
|
||||
bMatch = 0;
|
||||
if( fts5ExprAdvanceto(pIter, bDesc, &iLast, &rc, &pNode->bEof) ){
|
||||
return rc;
|
||||
@@ -1123,10 +1097,7 @@ static int fts5ExprNodeNext_OR(
|
||||
|| (bFromValid && fts5RowidCmp(pExpr, p1->iRowid, iFrom)<0)
|
||||
){
|
||||
int rc = fts5ExprNodeNext(pExpr, p1, bFromValid, iFrom);
|
||||
if( rc!=SQLITE_OK ){
|
||||
pNode->bNomatch = 0;
|
||||
return rc;
|
||||
}
|
||||
if( rc!=SQLITE_OK ) return rc;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1157,10 +1128,7 @@ static int fts5ExprNodeTest_AND(
|
||||
if( cmp>0 ){
|
||||
/* Advance pChild until it points to iLast or laster */
|
||||
rc = fts5ExprNodeNext(pExpr, pChild, 1, iLast);
|
||||
if( rc!=SQLITE_OK ){
|
||||
pAnd->bNomatch = 0;
|
||||
return rc;
|
||||
}
|
||||
if( rc!=SQLITE_OK ) return rc;
|
||||
}
|
||||
|
||||
/* If the child node is now at EOF, so is the parent AND node. Otherwise,
|
||||
@@ -1199,8 +1167,6 @@ static int fts5ExprNodeNext_AND(
|
||||
int rc = fts5ExprNodeNext(pExpr, pNode->apChild[0], bFromValid, iFrom);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = fts5ExprNodeTest_AND(pExpr, pNode);
|
||||
}else{
|
||||
pNode->bNomatch = 0;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
@@ -1243,9 +1209,6 @@ static int fts5ExprNodeNext_NOT(
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = fts5ExprNodeTest_NOT(pExpr, pNode);
|
||||
}
|
||||
if( rc!=SQLITE_OK ){
|
||||
pNode->bNomatch = 0;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -1368,10 +1331,7 @@ int sqlite3Fts5ExprFirst(Fts5Expr *p, Fts5Index *pIdx, i64 iFirst, int bDesc){
|
||||
|
||||
/* If not at EOF but the current rowid occurs earlier than iFirst in
|
||||
** the iteration order, move to document iFirst or later. */
|
||||
if( rc==SQLITE_OK
|
||||
&& 0==pRoot->bEof
|
||||
&& fts5RowidCmp(p, pRoot->iRowid, iFirst)<0
|
||||
){
|
||||
if( pRoot->bEof==0 && fts5RowidCmp(p, pRoot->iRowid, iFirst)<0 ){
|
||||
rc = fts5ExprNodeNext(p, pRoot, 1, iFirst);
|
||||
}
|
||||
|
||||
@@ -1625,7 +1585,7 @@ Fts5ExprPhrase *sqlite3Fts5ParseTerm(
|
||||
|
||||
rc = fts5ParseStringFromToken(pToken, &z);
|
||||
if( rc==SQLITE_OK ){
|
||||
int flags = FTS5_TOKENIZE_QUERY | (bPrefix ? FTS5_TOKENIZE_PREFIX : 0);
|
||||
int flags = FTS5_TOKENIZE_QUERY | (bPrefix ? FTS5_TOKENIZE_QUERY : 0);
|
||||
int n;
|
||||
sqlite3Fts5Dequote(z);
|
||||
n = (int)strlen(z);
|
||||
@@ -1899,110 +1859,25 @@ Fts5Colset *sqlite3Fts5ParseColset(
|
||||
return pRet;
|
||||
}
|
||||
|
||||
/*
|
||||
** If argument pOrig is NULL, or if (*pRc) is set to anything other than
|
||||
** SQLITE_OK when this function is called, NULL is returned.
|
||||
**
|
||||
** Otherwise, a copy of (*pOrig) is made into memory obtained from
|
||||
** sqlite3Fts5MallocZero() and a pointer to it returned. If the allocation
|
||||
** fails, (*pRc) is set to SQLITE_NOMEM and NULL is returned.
|
||||
*/
|
||||
static Fts5Colset *fts5CloneColset(int *pRc, Fts5Colset *pOrig){
|
||||
Fts5Colset *pRet;
|
||||
if( pOrig ){
|
||||
int nByte = sizeof(Fts5Colset) + (pOrig->nCol-1) * sizeof(int);
|
||||
pRet = (Fts5Colset*)sqlite3Fts5MallocZero(pRc, nByte);
|
||||
if( pRet ){
|
||||
memcpy(pRet, pOrig, nByte);
|
||||
}
|
||||
}else{
|
||||
pRet = 0;
|
||||
}
|
||||
return pRet;
|
||||
}
|
||||
|
||||
/*
|
||||
** Remove from colset pColset any columns that are not also in colset pMerge.
|
||||
*/
|
||||
static void fts5MergeColset(Fts5Colset *pColset, Fts5Colset *pMerge){
|
||||
int iIn = 0; /* Next input in pColset */
|
||||
int iMerge = 0; /* Next input in pMerge */
|
||||
int iOut = 0; /* Next output slot in pColset */
|
||||
|
||||
while( iIn<pColset->nCol && iMerge<pMerge->nCol ){
|
||||
int iDiff = pColset->aiCol[iIn] - pMerge->aiCol[iMerge];
|
||||
if( iDiff==0 ){
|
||||
pColset->aiCol[iOut++] = pMerge->aiCol[iMerge];
|
||||
iMerge++;
|
||||
iIn++;
|
||||
}else if( iDiff>0 ){
|
||||
iMerge++;
|
||||
}else{
|
||||
iIn++;
|
||||
}
|
||||
}
|
||||
pColset->nCol = iOut;
|
||||
}
|
||||
|
||||
/*
|
||||
** Recursively apply colset pColset to expression node pNode and all of
|
||||
** its decendents. If (*ppFree) is not NULL, it contains a spare copy
|
||||
** of pColset. This function may use the spare copy and set (*ppFree) to
|
||||
** zero, or it may create copies of pColset using fts5CloneColset().
|
||||
*/
|
||||
static void fts5ParseSetColset(
|
||||
Fts5Parse *pParse,
|
||||
Fts5ExprNode *pNode,
|
||||
Fts5Colset *pColset,
|
||||
Fts5Colset **ppFree
|
||||
){
|
||||
if( pParse->rc==SQLITE_OK ){
|
||||
assert( pNode->eType==FTS5_TERM || pNode->eType==FTS5_STRING
|
||||
|| pNode->eType==FTS5_AND || pNode->eType==FTS5_OR
|
||||
|| pNode->eType==FTS5_NOT || pNode->eType==FTS5_EOF
|
||||
);
|
||||
if( pNode->eType==FTS5_STRING || pNode->eType==FTS5_TERM ){
|
||||
Fts5ExprNearset *pNear = pNode->pNear;
|
||||
if( pNear->pColset ){
|
||||
fts5MergeColset(pNear->pColset, pColset);
|
||||
if( pNear->pColset->nCol==0 ){
|
||||
pNode->eType = FTS5_EOF;
|
||||
pNode->xNext = 0;
|
||||
}
|
||||
}else if( *ppFree ){
|
||||
pNear->pColset = pColset;
|
||||
*ppFree = 0;
|
||||
}else{
|
||||
pNear->pColset = fts5CloneColset(&pParse->rc, pColset);
|
||||
}
|
||||
}else{
|
||||
int i;
|
||||
assert( pNode->eType!=FTS5_EOF || pNode->nChild==0 );
|
||||
for(i=0; i<pNode->nChild; i++){
|
||||
fts5ParseSetColset(pParse, pNode->apChild[i], pColset, ppFree);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Apply colset pColset to expression node pExpr and all of its descendents.
|
||||
*/
|
||||
void sqlite3Fts5ParseSetColset(
|
||||
Fts5Parse *pParse,
|
||||
Fts5ExprNode *pExpr,
|
||||
Fts5ExprNearset *pNear,
|
||||
Fts5Colset *pColset
|
||||
){
|
||||
Fts5Colset *pFree = pColset;
|
||||
if( pParse->pConfig->eDetail==FTS5_DETAIL_NONE ){
|
||||
pParse->rc = SQLITE_ERROR;
|
||||
pParse->zErr = sqlite3_mprintf(
|
||||
"fts5: column queries are not supported (detail=none)"
|
||||
);
|
||||
}else{
|
||||
fts5ParseSetColset(pParse, pExpr, pColset, &pFree);
|
||||
sqlite3_free(pColset);
|
||||
return;
|
||||
}
|
||||
|
||||
if( pNear ){
|
||||
pNear->pColset = pColset;
|
||||
}else{
|
||||
sqlite3_free(pColset);
|
||||
}
|
||||
sqlite3_free(pFree);
|
||||
}
|
||||
|
||||
static void fts5ExprAssignXNext(Fts5ExprNode *pNode){
|
||||
@@ -2456,7 +2331,7 @@ static void fts5ExprFunction(
|
||||
|
||||
rc = sqlite3Fts5ConfigParse(pGlobal, db, nConfig, azConfig, &pConfig, &zErr);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3Fts5ExprNew(pConfig, pConfig->nCol, zExpr, &pExpr, &zErr);
|
||||
rc = sqlite3Fts5ExprNew(pConfig, zExpr, &pExpr, &zErr);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
char *zText;
|
||||
|
||||
+29
-39
@@ -36,10 +36,9 @@ struct Fts5Hash {
|
||||
|
||||
/*
|
||||
** Each entry in the hash table is represented by an object of the
|
||||
** following type. Each object, its key (a nul-terminated string) and
|
||||
** its current data are stored in a single memory allocation. The
|
||||
** key immediately follows the object in memory. The position list
|
||||
** data immediately follows the key data in memory.
|
||||
** following type. Each object, its key (zKey[]) and its current data
|
||||
** are stored in a single memory allocation. The position list data
|
||||
** immediately follows the key data in memory.
|
||||
**
|
||||
** The data that follows the key is in a similar, but not identical format
|
||||
** to the doclist data stored in the database. It is:
|
||||
@@ -63,20 +62,20 @@ struct Fts5HashEntry {
|
||||
int nAlloc; /* Total size of allocation */
|
||||
int iSzPoslist; /* Offset of space for 4-byte poslist size */
|
||||
int nData; /* Total bytes of data (incl. structure) */
|
||||
int nKey; /* Length of key in bytes */
|
||||
int nKey; /* Length of zKey[] in bytes */
|
||||
u8 bDel; /* Set delete-flag @ iSzPoslist */
|
||||
u8 bContent; /* Set content-flag (detail=none mode) */
|
||||
i16 iCol; /* Column of last value written */
|
||||
int iPos; /* Position of last value written */
|
||||
i64 iRowid; /* Rowid of last value written */
|
||||
char zKey[8]; /* Nul-terminated entry key */
|
||||
};
|
||||
|
||||
/*
|
||||
** Eqivalent to:
|
||||
**
|
||||
** char *fts5EntryKey(Fts5HashEntry *pEntry){ return zKey; }
|
||||
** Size of Fts5HashEntry without the zKey[] array.
|
||||
*/
|
||||
#define fts5EntryKey(p) ( ((char *)(&(p)[1])) )
|
||||
#define FTS5_HASHENTRYSIZE (sizeof(Fts5HashEntry)-8)
|
||||
|
||||
|
||||
|
||||
/*
|
||||
@@ -171,11 +170,10 @@ static int fts5HashResize(Fts5Hash *pHash){
|
||||
|
||||
for(i=0; i<pHash->nSlot; i++){
|
||||
while( apOld[i] ){
|
||||
unsigned int iHash;
|
||||
int iHash;
|
||||
Fts5HashEntry *p = apOld[i];
|
||||
apOld[i] = p->pHashNext;
|
||||
iHash = fts5HashKey(nNew, (u8*)fts5EntryKey(p),
|
||||
(int)strlen(fts5EntryKey(p)));
|
||||
iHash = fts5HashKey(nNew, (u8*)p->zKey, (int)strlen(p->zKey));
|
||||
p->pHashNext = apNew[iHash];
|
||||
apNew[iHash] = p;
|
||||
}
|
||||
@@ -246,10 +244,9 @@ int sqlite3Fts5HashWrite(
|
||||
/* Attempt to locate an existing hash entry */
|
||||
iHash = fts5HashKey2(pHash->nSlot, (u8)bByte, (const u8*)pToken, nToken);
|
||||
for(p=pHash->aSlot[iHash]; p; p=p->pHashNext){
|
||||
char *zKey = fts5EntryKey(p);
|
||||
if( zKey[0]==bByte
|
||||
if( p->zKey[0]==bByte
|
||||
&& p->nKey==nToken
|
||||
&& memcmp(&zKey[1], pToken, nToken)==0
|
||||
&& memcmp(&p->zKey[1], pToken, nToken)==0
|
||||
){
|
||||
break;
|
||||
}
|
||||
@@ -258,8 +255,7 @@ int sqlite3Fts5HashWrite(
|
||||
/* If an existing hash entry cannot be found, create a new one. */
|
||||
if( p==0 ){
|
||||
/* Figure out how much space to allocate */
|
||||
char *zKey;
|
||||
int nByte = sizeof(Fts5HashEntry) + (nToken+1) + 1 + 64;
|
||||
int nByte = FTS5_HASHENTRYSIZE + (nToken+1) + 1 + 64;
|
||||
if( nByte<128 ) nByte = 128;
|
||||
|
||||
/* Grow the Fts5Hash.aSlot[] array if necessary. */
|
||||
@@ -272,15 +268,14 @@ int sqlite3Fts5HashWrite(
|
||||
/* Allocate new Fts5HashEntry and add it to the hash table. */
|
||||
p = (Fts5HashEntry*)sqlite3_malloc(nByte);
|
||||
if( !p ) return SQLITE_NOMEM;
|
||||
memset(p, 0, sizeof(Fts5HashEntry));
|
||||
memset(p, 0, FTS5_HASHENTRYSIZE);
|
||||
p->nAlloc = nByte;
|
||||
zKey = fts5EntryKey(p);
|
||||
zKey[0] = bByte;
|
||||
memcpy(&zKey[1], pToken, nToken);
|
||||
assert( iHash==fts5HashKey(pHash->nSlot, (u8*)zKey, nToken+1) );
|
||||
p->zKey[0] = bByte;
|
||||
memcpy(&p->zKey[1], pToken, nToken);
|
||||
assert( iHash==fts5HashKey(pHash->nSlot, (u8*)p->zKey, nToken+1) );
|
||||
p->nKey = nToken;
|
||||
zKey[nToken+1] = '\0';
|
||||
p->nData = nToken+1 + 1 + sizeof(Fts5HashEntry);
|
||||
p->zKey[nToken+1] = '\0';
|
||||
p->nData = nToken+1 + 1 + FTS5_HASHENTRYSIZE;
|
||||
p->pHashNext = pHash->aSlot[iHash];
|
||||
pHash->aSlot[iHash] = p;
|
||||
pHash->nEntry++;
|
||||
@@ -398,11 +393,9 @@ static Fts5HashEntry *fts5HashEntryMerge(
|
||||
p1 = 0;
|
||||
}else{
|
||||
int i = 0;
|
||||
char *zKey1 = fts5EntryKey(p1);
|
||||
char *zKey2 = fts5EntryKey(p2);
|
||||
while( zKey1[i]==zKey2[i] ) i++;
|
||||
while( p1->zKey[i]==p2->zKey[i] ) i++;
|
||||
|
||||
if( ((u8)zKey1[i])>((u8)zKey2[i]) ){
|
||||
if( ((u8)p1->zKey[i])>((u8)p2->zKey[i]) ){
|
||||
/* p2 is smaller */
|
||||
*ppOut = p2;
|
||||
ppOut = &p2->pScanNext;
|
||||
@@ -445,7 +438,7 @@ static int fts5HashEntrySort(
|
||||
for(iSlot=0; iSlot<pHash->nSlot; iSlot++){
|
||||
Fts5HashEntry *pIter;
|
||||
for(pIter=pHash->aSlot[iSlot]; pIter; pIter=pIter->pHashNext){
|
||||
if( pTerm==0 || 0==memcmp(fts5EntryKey(pIter), pTerm, nTerm) ){
|
||||
if( pTerm==0 || 0==memcmp(pIter->zKey, pTerm, nTerm) ){
|
||||
Fts5HashEntry *pEntry = pIter;
|
||||
pEntry->pScanNext = 0;
|
||||
for(i=0; ap[i]; i++){
|
||||
@@ -478,18 +471,16 @@ int sqlite3Fts5HashQuery(
|
||||
int *pnDoclist /* OUT: Size of doclist in bytes */
|
||||
){
|
||||
unsigned int iHash = fts5HashKey(pHash->nSlot, (const u8*)pTerm, nTerm);
|
||||
char *zKey = 0;
|
||||
Fts5HashEntry *p;
|
||||
|
||||
for(p=pHash->aSlot[iHash]; p; p=p->pHashNext){
|
||||
zKey = fts5EntryKey(p);
|
||||
if( memcmp(zKey, pTerm, nTerm)==0 && zKey[nTerm]==0 ) break;
|
||||
if( memcmp(p->zKey, pTerm, nTerm)==0 && p->zKey[nTerm]==0 ) break;
|
||||
}
|
||||
|
||||
if( p ){
|
||||
fts5HashAddPoslistSize(pHash, p);
|
||||
*ppDoclist = (const u8*)&zKey[nTerm+1];
|
||||
*pnDoclist = p->nData - (sizeof(Fts5HashEntry) + nTerm + 1);
|
||||
*ppDoclist = (const u8*)&p->zKey[nTerm+1];
|
||||
*pnDoclist = p->nData - (FTS5_HASHENTRYSIZE + nTerm + 1);
|
||||
}else{
|
||||
*ppDoclist = 0;
|
||||
*pnDoclist = 0;
|
||||
@@ -522,12 +513,11 @@ void sqlite3Fts5HashScanEntry(
|
||||
){
|
||||
Fts5HashEntry *p;
|
||||
if( (p = pHash->pScan) ){
|
||||
char *zKey = fts5EntryKey(p);
|
||||
int nTerm = (int)strlen(zKey);
|
||||
int nTerm = (int)strlen(p->zKey);
|
||||
fts5HashAddPoslistSize(pHash, p);
|
||||
*pzTerm = zKey;
|
||||
*ppDoclist = (const u8*)&zKey[nTerm+1];
|
||||
*pnDoclist = p->nData - (sizeof(Fts5HashEntry) + nTerm + 1);
|
||||
*pzTerm = p->zKey;
|
||||
*ppDoclist = (const u8*)&p->zKey[nTerm+1];
|
||||
*pnDoclist = p->nData - (FTS5_HASHENTRYSIZE + nTerm + 1);
|
||||
}else{
|
||||
*pzTerm = 0;
|
||||
*ppDoclist = 0;
|
||||
|
||||
+33
-38
@@ -628,6 +628,7 @@ static void fts5CloseReader(Fts5Index *p){
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Retrieve a record from the %_data table.
|
||||
**
|
||||
@@ -728,8 +729,7 @@ static int fts5IndexPrepareStmt(
|
||||
){
|
||||
if( p->rc==SQLITE_OK ){
|
||||
if( zSql ){
|
||||
p->rc = sqlite3_prepare_v3(p->pConfig->db, zSql, -1,
|
||||
SQLITE_PREPARE_PERSISTENT, ppStmt, 0);
|
||||
p->rc = sqlite3_prepare_v2(p->pConfig->db, zSql, -1, ppStmt, 0);
|
||||
}else{
|
||||
p->rc = SQLITE_NOMEM;
|
||||
}
|
||||
@@ -778,8 +778,7 @@ static void fts5DataDelete(Fts5Index *p, i64 iFirst, i64 iLast){
|
||||
if( zSql==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
rc = sqlite3_prepare_v3(pConfig->db, zSql, -1,
|
||||
SQLITE_PREPARE_PERSISTENT, &p->pDeleter, 0);
|
||||
rc = sqlite3_prepare_v2(pConfig->db, zSql, -1, &p->pDeleter, 0);
|
||||
sqlite3_free(zSql);
|
||||
}
|
||||
if( rc!=SQLITE_OK ){
|
||||
@@ -2040,7 +2039,7 @@ static void fts5SegIterNext(
|
||||
else if( pLeaf->nn>pLeaf->szLeaf ){
|
||||
pIter->iPgidxOff = pLeaf->szLeaf + fts5GetVarint32(
|
||||
&pLeaf->p[pLeaf->szLeaf], iOff
|
||||
);
|
||||
);
|
||||
pIter->iLeafOffset = iOff;
|
||||
pIter->iEndofDoclist = iOff;
|
||||
bNewTerm = 1;
|
||||
@@ -2074,7 +2073,6 @@ static void fts5SegIterNext(
|
||||
*/
|
||||
int nSz;
|
||||
assert( p->rc==SQLITE_OK );
|
||||
assert( pIter->iLeafOffset<=pIter->pLeaf->nn );
|
||||
fts5FastGetVarint32(pIter->pLeaf->p, pIter->iLeafOffset, nSz);
|
||||
pIter->bDel = (nSz & 0x0001);
|
||||
pIter->nPos = nSz>>1;
|
||||
@@ -2842,7 +2840,6 @@ static void fts5MultiIterNext(
|
||||
i64 iFrom /* Advance at least as far as this */
|
||||
){
|
||||
int bUseFrom = bFrom;
|
||||
assert( pIter->base.bEof==0 );
|
||||
while( p->rc==SQLITE_OK ){
|
||||
int iFirst = pIter->aFirst[1].iFirst;
|
||||
int bNewTerm = 0;
|
||||
@@ -2880,8 +2877,7 @@ static void fts5MultiIterNext2(
|
||||
){
|
||||
assert( pIter->bSkipEmpty );
|
||||
if( p->rc==SQLITE_OK ){
|
||||
*pbNewTerm = 0;
|
||||
do{
|
||||
do {
|
||||
int iFirst = pIter->aFirst[1].iFirst;
|
||||
Fts5SegIter *pSeg = &pIter->aSeg[iFirst];
|
||||
int bNewTerm = 0;
|
||||
@@ -2894,6 +2890,8 @@ static void fts5MultiIterNext2(
|
||||
fts5MultiIterAdvanced(p, pIter, iFirst, 1);
|
||||
fts5MultiIterSetEof(pIter);
|
||||
*pbNewTerm = 1;
|
||||
}else{
|
||||
*pbNewTerm = 0;
|
||||
}
|
||||
fts5AssertMultiIterSetup(p, pIter);
|
||||
|
||||
@@ -3068,7 +3066,7 @@ static void fts5ChunkIterate(
|
||||
break;
|
||||
}else{
|
||||
pgno++;
|
||||
pData = fts5LeafRead(p, FTS5_SEGMENT_ROWID(pSeg->pSeg->iSegid, pgno));
|
||||
pData = fts5DataRead(p, FTS5_SEGMENT_ROWID(pSeg->pSeg->iSegid, pgno));
|
||||
if( pData==0 ) break;
|
||||
pChunk = &pData->p[4];
|
||||
nChunk = MIN(nRem, pData->szLeaf - 4);
|
||||
@@ -3159,23 +3157,23 @@ static int fts5IndexExtractCol(
|
||||
return p - (*pa);
|
||||
}
|
||||
|
||||
static void fts5IndexExtractColset(
|
||||
int *pRc,
|
||||
static int fts5IndexExtractColset (
|
||||
Fts5Colset *pColset, /* Colset to filter on */
|
||||
const u8 *pPos, int nPos, /* Position list */
|
||||
Fts5Buffer *pBuf /* Output buffer */
|
||||
){
|
||||
if( *pRc==SQLITE_OK ){
|
||||
int i;
|
||||
fts5BufferZero(pBuf);
|
||||
for(i=0; i<pColset->nCol; i++){
|
||||
const u8 *pSub = pPos;
|
||||
int nSub = fts5IndexExtractCol(&pSub, nPos, pColset->aiCol[i]);
|
||||
if( nSub ){
|
||||
fts5BufferAppendBlob(pRc, pBuf, nSub, pSub);
|
||||
}
|
||||
int rc = SQLITE_OK;
|
||||
int i;
|
||||
|
||||
fts5BufferZero(pBuf);
|
||||
for(i=0; i<pColset->nCol; i++){
|
||||
const u8 *pSub = pPos;
|
||||
int nSub = fts5IndexExtractCol(&pSub, nPos, pColset->aiCol[i]);
|
||||
if( nSub ){
|
||||
fts5BufferAppendBlob(&rc, pBuf, nSub, pSub);
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3299,9 +3297,8 @@ static void fts5IterSetOutputs_Full(Fts5Iter *pIter, Fts5SegIter *pSeg){
|
||||
pIter->base.nData = fts5IndexExtractCol(&a, pSeg->nPos,pColset->aiCol[0]);
|
||||
pIter->base.pData = a;
|
||||
}else{
|
||||
int *pRc = &pIter->pIndex->rc;
|
||||
fts5BufferZero(&pIter->poslist);
|
||||
fts5IndexExtractColset(pRc, pColset, a, pSeg->nPos, &pIter->poslist);
|
||||
fts5IndexExtractColset(pColset, a, pSeg->nPos, &pIter->poslist);
|
||||
pIter->base.pData = pIter->poslist.p;
|
||||
pIter->base.nData = pIter->poslist.n;
|
||||
}
|
||||
@@ -3846,6 +3843,9 @@ static void fts5WriteFlushLeaf(Fts5Index *p, Fts5SegWriter *pWriter){
|
||||
Fts5PageWriter *pPage = &pWriter->writer;
|
||||
i64 iRowid;
|
||||
|
||||
static int nCall = 0;
|
||||
nCall++;
|
||||
|
||||
assert( (pPage->pgidx.n==0)==(pWriter->bFirstTermInPage) );
|
||||
|
||||
/* Set the szLeaf header field. */
|
||||
@@ -4194,7 +4194,6 @@ static void fts5IndexMergeLevel(
|
||||
int bOldest; /* True if the output segment is the oldest */
|
||||
int eDetail = p->pConfig->eDetail;
|
||||
const int flags = FTS5INDEX_QUERY_NOOUTPUT;
|
||||
int bTermWritten = 0; /* True if current term already output */
|
||||
|
||||
assert( iLvl<pStruct->nLevel );
|
||||
assert( pLvl->nMerge<=pLvl->nSeg );
|
||||
@@ -4248,22 +4247,18 @@ static void fts5IndexMergeLevel(
|
||||
int nTerm;
|
||||
const u8 *pTerm;
|
||||
|
||||
/* Check for key annihilation. */
|
||||
if( pSegIter->nPos==0 && (bOldest || pSegIter->bDel==0) ) continue;
|
||||
|
||||
pTerm = fts5MultiIterTerm(pIter, &nTerm);
|
||||
if( nTerm!=term.n || memcmp(pTerm, term.p, nTerm) ){
|
||||
if( pnRem && writer.nLeafWritten>nRem ){
|
||||
break;
|
||||
}
|
||||
fts5BufferSet(&p->rc, &term, nTerm, pTerm);
|
||||
bTermWritten =0;
|
||||
}
|
||||
|
||||
/* Check for key annihilation. */
|
||||
if( pSegIter->nPos==0 && (bOldest || pSegIter->bDel==0) ) continue;
|
||||
|
||||
if( p->rc==SQLITE_OK && bTermWritten==0 ){
|
||||
/* This is a new term. Append a term to the output segment. */
|
||||
fts5WriteAppendTerm(p, &writer, nTerm, pTerm);
|
||||
bTermWritten = 1;
|
||||
fts5BufferSet(&p->rc, &term, nTerm, pTerm);
|
||||
}
|
||||
|
||||
/* Append the rowid to the output */
|
||||
@@ -5095,7 +5090,7 @@ static void fts5SetupPrefixIter(
|
||||
if( pData ){
|
||||
pData->p = (u8*)&pData[1];
|
||||
pData->nn = pData->szLeaf = doclist.n;
|
||||
if( doclist.n ) memcpy(pData->p, doclist.p, doclist.n);
|
||||
memcpy(pData->p, doclist.p, doclist.n);
|
||||
fts5MultiIterNew2(p, pData, bDesc, ppIter);
|
||||
}
|
||||
fts5BufferFree(&doclist);
|
||||
@@ -5134,10 +5129,10 @@ int sqlite3Fts5IndexBeginWrite(Fts5Index *p, int bDelete, i64 iRowid){
|
||||
/*
|
||||
** Commit data to disk.
|
||||
*/
|
||||
int sqlite3Fts5IndexSync(Fts5Index *p){
|
||||
int sqlite3Fts5IndexSync(Fts5Index *p, int bCommit){
|
||||
assert( p->rc==SQLITE_OK );
|
||||
fts5IndexFlush(p);
|
||||
fts5CloseReader(p);
|
||||
if( bCommit ) fts5CloseReader(p);
|
||||
return fts5IndexReturn(p);
|
||||
}
|
||||
|
||||
@@ -5334,7 +5329,7 @@ int sqlite3Fts5IndexQuery(
|
||||
|
||||
if( sqlite3Fts5BufferSize(&p->rc, &buf, nToken+1)==0 ){
|
||||
int iIdx = 0; /* Index to search */
|
||||
if( nToken ) memcpy(&buf.p[1], pToken, nToken);
|
||||
memcpy(&buf.p[1], pToken, nToken);
|
||||
|
||||
/* Figure out which index to search and set iIdx accordingly. If this
|
||||
** is a prefix query for which there is no prefix index, set iIdx to
|
||||
@@ -5383,7 +5378,7 @@ int sqlite3Fts5IndexQuery(
|
||||
}
|
||||
|
||||
if( p->rc ){
|
||||
sqlite3Fts5IterClose((Fts5IndexIter*)pRet);
|
||||
sqlite3Fts5IterClose(&pRet->base);
|
||||
pRet = 0;
|
||||
fts5CloseReader(p);
|
||||
}
|
||||
@@ -5833,7 +5828,7 @@ static void fts5IndexIntegrityCheckSegment(
|
||||
** ignore this b-tree entry. Otherwise, load it into memory. */
|
||||
if( iIdxLeaf<pSeg->pgnoFirst ) continue;
|
||||
iRow = FTS5_SEGMENT_ROWID(pSeg->iSegid, iIdxLeaf);
|
||||
pLeaf = fts5LeafRead(p, iRow);
|
||||
pLeaf = fts5DataRead(p, iRow);
|
||||
if( pLeaf==0 ) break;
|
||||
|
||||
/* Check that the leaf contains at least one term, and that it is equal
|
||||
|
||||
+26
-41
@@ -506,7 +506,6 @@ static void fts5SetUniqueFlag(sqlite3_index_info *pIdxInfo){
|
||||
static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
|
||||
Fts5Table *pTab = (Fts5Table*)pVTab;
|
||||
Fts5Config *pConfig = pTab->pConfig;
|
||||
const int nCol = pConfig->nCol;
|
||||
int idxFlags = 0; /* Parameter passed through to xFilter() */
|
||||
int bHasMatch;
|
||||
int iNext;
|
||||
@@ -532,34 +531,24 @@ static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
|
||||
|
||||
int aColMap[3];
|
||||
aColMap[0] = -1;
|
||||
aColMap[1] = nCol;
|
||||
aColMap[2] = nCol+1;
|
||||
aColMap[1] = pConfig->nCol;
|
||||
aColMap[2] = pConfig->nCol+1;
|
||||
|
||||
/* Set idxFlags flags for all WHERE clause terms that will be used. */
|
||||
for(i=0; i<pInfo->nConstraint; i++){
|
||||
struct sqlite3_index_constraint *p = &pInfo->aConstraint[i];
|
||||
int iCol = p->iColumn;
|
||||
|
||||
if( (p->op==SQLITE_INDEX_CONSTRAINT_MATCH && iCol>=0 && iCol<=nCol)
|
||||
|| (p->op==SQLITE_INDEX_CONSTRAINT_EQ && iCol==nCol)
|
||||
){
|
||||
/* A MATCH operator or equivalent */
|
||||
if( p->usable ){
|
||||
idxFlags = (idxFlags & 0xFFFF) | FTS5_BI_MATCH | (iCol << 16);
|
||||
aConstraint[0].iConsIndex = i;
|
||||
}else{
|
||||
/* As there exists an unusable MATCH constraint this is an
|
||||
** unusable plan. Set a prohibitively high cost. */
|
||||
pInfo->estimatedCost = 1e50;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
}else{
|
||||
int j;
|
||||
for(j=1; j<ArraySize(aConstraint); j++){
|
||||
struct Constraint *pC = &aConstraint[j];
|
||||
if( iCol==aColMap[pC->iCol] && p->op & pC->op && p->usable ){
|
||||
int j;
|
||||
for(j=0; j<ArraySize(aConstraint); j++){
|
||||
struct Constraint *pC = &aConstraint[j];
|
||||
if( p->iColumn==aColMap[pC->iCol] && p->op & pC->op ){
|
||||
if( p->usable ){
|
||||
pC->iConsIndex = i;
|
||||
idxFlags |= pC->fts5op;
|
||||
}else if( j==0 ){
|
||||
/* As there exists an unusable MATCH constraint this is an
|
||||
** unusable plan. Set a prohibitively high cost. */
|
||||
pInfo->estimatedCost = 1e50;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -883,8 +872,7 @@ static int fts5PrepareStatement(
|
||||
if( zSql==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
rc = sqlite3_prepare_v3(pConfig->db, zSql, -1,
|
||||
SQLITE_PREPARE_PERSISTENT, &pRet, 0);
|
||||
rc = sqlite3_prepare_v2(pConfig->db, zSql, -1, &pRet, 0);
|
||||
if( rc!=SQLITE_OK ){
|
||||
*pConfig->pzErrmsg = sqlite3_mprintf("%s", sqlite3_errmsg(pConfig->db));
|
||||
}
|
||||
@@ -1020,8 +1008,7 @@ static int fts5FindRankFunction(Fts5Cursor *pCsr){
|
||||
char *zSql = sqlite3Fts5Mprintf(&rc, "SELECT %s", zRankArgs);
|
||||
if( zSql ){
|
||||
sqlite3_stmt *pStmt = 0;
|
||||
rc = sqlite3_prepare_v3(pConfig->db, zSql, -1,
|
||||
SQLITE_PREPARE_PERSISTENT, &pStmt, 0);
|
||||
rc = sqlite3_prepare_v2(pConfig->db, zSql, -1, &pStmt, 0);
|
||||
sqlite3_free(zSql);
|
||||
assert( rc==SQLITE_OK || pCsr->pRankArgStmt==0 );
|
||||
if( rc==SQLITE_OK ){
|
||||
@@ -1136,7 +1123,6 @@ static int fts5FilterMethod(
|
||||
sqlite3_value *pRowidEq = 0; /* rowid = ? expression (or NULL) */
|
||||
sqlite3_value *pRowidLe = 0; /* rowid <= ? expression (or NULL) */
|
||||
sqlite3_value *pRowidGe = 0; /* rowid >= ? expression (or NULL) */
|
||||
int iCol; /* Column on LHS of MATCH operator */
|
||||
char **pzErrmsg = pConfig->pzErrmsg;
|
||||
|
||||
UNUSED_PARAM(zUnused);
|
||||
@@ -1167,8 +1153,6 @@ static int fts5FilterMethod(
|
||||
if( BitFlagTest(idxNum, FTS5_BI_ROWID_EQ) ) pRowidEq = apVal[iVal++];
|
||||
if( BitFlagTest(idxNum, FTS5_BI_ROWID_LE) ) pRowidLe = apVal[iVal++];
|
||||
if( BitFlagTest(idxNum, FTS5_BI_ROWID_GE) ) pRowidGe = apVal[iVal++];
|
||||
iCol = (idxNum>>16);
|
||||
assert( iCol>=0 && iCol<=pConfig->nCol );
|
||||
assert( iVal==nVal );
|
||||
bOrderByRank = ((idxNum & FTS5_BI_ORDER_RANK) ? 1 : 0);
|
||||
pCsr->bDesc = bDesc = ((idxNum & FTS5_BI_ORDER_DESC) ? 1 : 0);
|
||||
@@ -1215,7 +1199,7 @@ static int fts5FilterMethod(
|
||||
rc = fts5SpecialMatch(pTab, pCsr, &zExpr[1]);
|
||||
}else{
|
||||
char **pzErr = &pTab->base.zErrMsg;
|
||||
rc = sqlite3Fts5ExprNew(pConfig, iCol, zExpr, &pCsr->pExpr, pzErr);
|
||||
rc = sqlite3Fts5ExprNew(pConfig, zExpr, &pCsr->pExpr, pzErr);
|
||||
if( rc==SQLITE_OK ){
|
||||
if( bOrderByRank ){
|
||||
pCsr->ePlan = FTS5_PLAN_SORTED_MATCH;
|
||||
@@ -1595,7 +1579,7 @@ static int fts5SyncMethod(sqlite3_vtab *pVtab){
|
||||
fts5CheckTransactionState(pTab, FTS5_SYNC, 0);
|
||||
pTab->pConfig->pzErrmsg = &pTab->base.zErrMsg;
|
||||
fts5TripCursors(pTab);
|
||||
rc = sqlite3Fts5StorageSync(pTab->pStorage);
|
||||
rc = sqlite3Fts5StorageSync(pTab->pStorage, 1);
|
||||
pTab->pConfig->pzErrmsg = 0;
|
||||
return rc;
|
||||
}
|
||||
@@ -2406,7 +2390,7 @@ static int fts5SavepointMethod(sqlite3_vtab *pVtab, int iSavepoint){
|
||||
UNUSED_PARAM(iSavepoint); /* Call below is a no-op for NDEBUG builds */
|
||||
fts5CheckTransactionState(pTab, FTS5_SAVEPOINT, iSavepoint);
|
||||
fts5TripCursors(pTab);
|
||||
return sqlite3Fts5StorageSync(pTab->pStorage);
|
||||
return sqlite3Fts5StorageSync(pTab->pStorage, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2419,7 +2403,7 @@ static int fts5ReleaseMethod(sqlite3_vtab *pVtab, int iSavepoint){
|
||||
UNUSED_PARAM(iSavepoint); /* Call below is a no-op for NDEBUG builds */
|
||||
fts5CheckTransactionState(pTab, FTS5_RELEASE, iSavepoint);
|
||||
fts5TripCursors(pTab);
|
||||
return sqlite3Fts5StorageSync(pTab->pStorage);
|
||||
return sqlite3Fts5StorageSync(pTab->pStorage, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2609,14 +2593,15 @@ static void fts5ModuleDestroy(void *pCtx){
|
||||
static void fts5Fts5Func(
|
||||
sqlite3_context *pCtx, /* Function call context */
|
||||
int nArg, /* Number of args */
|
||||
sqlite3_value **apArg /* Function arguments */
|
||||
sqlite3_value **apUnused /* Function arguments */
|
||||
){
|
||||
Fts5Global *pGlobal = (Fts5Global*)sqlite3_user_data(pCtx);
|
||||
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;
|
||||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2681,7 +2666,7 @@ static int fts5Init(sqlite3 *db){
|
||||
if( rc==SQLITE_OK ) rc = sqlite3Fts5VocabInit(pGlobal, db);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3_create_function(
|
||||
db, "fts5", 1, SQLITE_UTF8, p, fts5Fts5Func, 0, 0
|
||||
db, "fts5", 0, SQLITE_UTF8, p, fts5Fts5Func, 0, 0
|
||||
);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
|
||||
+17
-13
@@ -136,8 +136,7 @@ static int fts5StorageGetStmt(
|
||||
if( zSql==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
rc = sqlite3_prepare_v3(pC->db, zSql, -1,
|
||||
SQLITE_PREPARE_PERSISTENT, &p->aStmt[eStmt], 0);
|
||||
rc = sqlite3_prepare_v2(pC->db, zSql, -1, &p->aStmt[eStmt], 0);
|
||||
sqlite3_free(zSql);
|
||||
if( rc!=SQLITE_OK && pzErrMsg ){
|
||||
*pzErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(pC->db));
|
||||
@@ -219,7 +218,7 @@ static void fts5StorageRenameOne(
|
||||
|
||||
int sqlite3Fts5StorageRename(Fts5Storage *pStorage, const char *zName){
|
||||
Fts5Config *pConfig = pStorage->pConfig;
|
||||
int rc = sqlite3Fts5StorageSync(pStorage);
|
||||
int rc = sqlite3Fts5StorageSync(pStorage, 1);
|
||||
|
||||
fts5StorageRenameOne(pConfig, &rc, "data", zName);
|
||||
fts5StorageRenameOne(pConfig, &rc, "idx", zName);
|
||||
@@ -546,6 +545,11 @@ int sqlite3Fts5StorageDelete(Fts5Storage *p, i64 iDel, sqlite3_value **apVal){
|
||||
}
|
||||
}
|
||||
|
||||
/* Write the averages record */
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = fts5StorageSaveTotals(p);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -749,6 +753,11 @@ int sqlite3Fts5StorageIndexInsert(
|
||||
}
|
||||
sqlite3_free(buf.p);
|
||||
|
||||
/* Write the averages record */
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = fts5StorageSaveTotals(p);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -1082,18 +1091,13 @@ int sqlite3Fts5StorageRowCount(Fts5Storage *p, i64 *pnRow){
|
||||
/*
|
||||
** Flush any data currently held in-memory to disk.
|
||||
*/
|
||||
int sqlite3Fts5StorageSync(Fts5Storage *p){
|
||||
int rc = SQLITE_OK;
|
||||
i64 iLastRowid = sqlite3_last_insert_rowid(p->pConfig->db);
|
||||
if( p->bTotalsValid ){
|
||||
rc = fts5StorageSaveTotals(p);
|
||||
int sqlite3Fts5StorageSync(Fts5Storage *p, int bCommit){
|
||||
if( bCommit && p->bTotalsValid ){
|
||||
int rc = fts5StorageSaveTotals(p);
|
||||
p->bTotalsValid = 0;
|
||||
if( rc!=SQLITE_OK ) return rc;
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3Fts5IndexSync(p->pIndex);
|
||||
}
|
||||
sqlite3_set_last_insert_rowid(p->pConfig->db, iLastRowid);
|
||||
return rc;
|
||||
return sqlite3Fts5IndexSync(p->pIndex, bCommit);
|
||||
}
|
||||
|
||||
int sqlite3Fts5StorageRollback(Fts5Storage *p){
|
||||
|
||||
+6
-3
@@ -99,13 +99,16 @@ static int SQLITE_TCLAPI f5tDbAndApi(
|
||||
sqlite3_stmt *pStmt = 0;
|
||||
fts5_api *pApi = 0;
|
||||
|
||||
rc = sqlite3_prepare_v2(db, "SELECT fts5(?1)", -1, &pStmt, 0);
|
||||
rc = sqlite3_prepare_v2(db, "SELECT fts5()", -1, &pStmt, 0);
|
||||
if( rc!=SQLITE_OK ){
|
||||
Tcl_AppendResult(interp, "error: ", sqlite3_errmsg(db), 0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
sqlite3_bind_pointer(pStmt, 1, (void*)&pApi, "fts5_api_ptr", 0);
|
||||
sqlite3_step(pStmt);
|
||||
|
||||
if( SQLITE_ROW==sqlite3_step(pStmt) ){
|
||||
const void *pPtr = sqlite3_column_blob(pStmt, 0);
|
||||
memcpy((void*)&pApi, pPtr, sizeof(pApi));
|
||||
}
|
||||
|
||||
if( sqlite3_finalize(pStmt)!=SQLITE_OK ){
|
||||
Tcl_AppendResult(interp, "error: ", sqlite3_errmsg(db), 0);
|
||||
|
||||
@@ -73,10 +73,13 @@ static int fts5_api_from_db(sqlite3 *db, fts5_api **ppApi){
|
||||
int rc;
|
||||
|
||||
*ppApi = 0;
|
||||
rc = sqlite3_prepare(db, "SELECT fts5(?1)", -1, &pStmt, 0);
|
||||
rc = sqlite3_prepare(db, "SELECT fts5()", -1, &pStmt, 0);
|
||||
if( rc==SQLITE_OK ){
|
||||
sqlite3_bind_pointer(pStmt, 1, (void*)ppApi, "fts5_api_ptr", 0);
|
||||
(void)sqlite3_step(pStmt);
|
||||
if( SQLITE_ROW==sqlite3_step(pStmt)
|
||||
&& sizeof(fts5_api*)==sqlite3_column_bytes(pStmt, 0)
|
||||
){
|
||||
memcpy(ppApi, sqlite3_column_blob(pStmt, 0), sizeof(fts5_api*));
|
||||
}
|
||||
rc = sqlite3_finalize(pStmt);
|
||||
}
|
||||
|
||||
@@ -419,3 +422,4 @@ int sqlite3Fts5TestRegisterMatchinfo(sqlite3 *db){
|
||||
}
|
||||
|
||||
#endif /* SQLITE_ENABLE_FTS5 */
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
*/
|
||||
#if defined(SQLITE_TEST) && defined(SQLITE_ENABLE_FTS5)
|
||||
|
||||
#include "fts5.h"
|
||||
#include <fts5.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
@@ -182,7 +182,7 @@ static int fts5tokConnectMethod(
|
||||
Fts5tokTable *pTab = 0;
|
||||
int rc;
|
||||
char **azDequote = 0;
|
||||
int nDequote = 0;
|
||||
int nDequote;
|
||||
|
||||
rc = sqlite3_declare_vtab(db,
|
||||
"CREATE TABLE x(input HIDDEN, token, start, end, position)"
|
||||
|
||||
+26
-139
@@ -29,11 +29,6 @@
|
||||
** 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.
|
||||
*/
|
||||
|
||||
|
||||
@@ -49,7 +44,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, ROW or INSTANCE */
|
||||
int eType; /* FTS5_VOCAB_COL or ROW */
|
||||
};
|
||||
|
||||
struct Fts5VocabCursor {
|
||||
@@ -69,22 +64,16 @@ struct Fts5VocabCursor {
|
||||
i64 *aCnt;
|
||||
i64 *aDoc;
|
||||
|
||||
/* Output values used by all tables. */
|
||||
/* Output values used by 'row' and 'col' 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_INSTANCE 2
|
||||
#define FTS5_VOCAB_COL 0
|
||||
#define FTS5_VOCAB_ROW 1
|
||||
|
||||
#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.
|
||||
@@ -112,9 +101,6 @@ 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;
|
||||
@@ -175,8 +161,7 @@ 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_INST_SCHEMA ")"
|
||||
"CREATE TABlE vocab(" FTS5_VOCAB_ROW_SCHEMA ")"
|
||||
};
|
||||
|
||||
Fts5VocabTable *pRet = 0;
|
||||
@@ -250,15 +235,6 @@ 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,
|
||||
@@ -402,54 +378,6 @@ 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.
|
||||
@@ -462,17 +390,13 @@ 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_COL || pCsr->iCol>=nCol ){
|
||||
if( pTab->eType==FTS5_VOCAB_ROW || pCsr->iCol>=nCol ){
|
||||
if( sqlite3Fts5IterEof(pCsr->pIter) ){
|
||||
pCsr->bEof = 1;
|
||||
}else{
|
||||
@@ -496,26 +420,22 @@ 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( pTab->eType ){
|
||||
case FTS5_VOCAB_ROW:
|
||||
if( eDetail==FTS5_DETAIL_FULL ){
|
||||
switch( pCsr->pConfig->eDetail ){
|
||||
case FTS5_DETAIL_FULL:
|
||||
pPos = pCsr->pIter->pData;
|
||||
nPos = pCsr->pIter->nData;
|
||||
if( pTab->eType==FTS5_VOCAB_ROW ){
|
||||
while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff, &iPos) ){
|
||||
pCsr->aCnt[0]++;
|
||||
}
|
||||
}
|
||||
pCsr->aDoc[0]++;
|
||||
break;
|
||||
|
||||
case FTS5_VOCAB_COL:
|
||||
if( eDetail==FTS5_DETAIL_FULL ){
|
||||
pCsr->aDoc[0]++;
|
||||
}else{
|
||||
int iCol = -1;
|
||||
while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff, &iPos) ){
|
||||
int ii = FTS5_POS2COLUMN(iPos);
|
||||
@@ -529,7 +449,13 @@ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){
|
||||
iCol = ii;
|
||||
}
|
||||
}
|
||||
}else if( eDetail==FTS5_DETAIL_COLUMNS ){
|
||||
}
|
||||
break;
|
||||
|
||||
case FTS5_DETAIL_COLUMNS:
|
||||
if( pTab->eType==FTS5_VOCAB_ROW ){
|
||||
pCsr->aDoc[0]++;
|
||||
}else{
|
||||
while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff,&iPos) ){
|
||||
assert_nc( iPos>=0 && iPos<nCol );
|
||||
if( iPos>=nCol ){
|
||||
@@ -538,21 +464,18 @@ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){
|
||||
}
|
||||
pCsr->aDoc[iPos]++;
|
||||
}
|
||||
}else{
|
||||
assert( eDetail==FTS5_DETAIL_NONE );
|
||||
pCsr->aDoc[0]++;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
assert( pTab->eType==FTS5_VOCAB_INSTANCE );
|
||||
default:
|
||||
assert( pCsr->pConfig->eDetail==FTS5_DETAIL_NONE );
|
||||
pCsr->aDoc[0]++;
|
||||
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);
|
||||
@@ -582,9 +505,7 @@ 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;
|
||||
@@ -624,16 +545,11 @@ static int fts5VocabFilterMethod(
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3Fts5IndexQuery(pCsr->pIndex, zTerm, nTerm, f, 0, &pCsr->pIter);
|
||||
}
|
||||
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)
|
||||
){
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = fts5VocabNextMethod(pCursor);
|
||||
}
|
||||
|
||||
@@ -675,42 +591,13 @@ static int fts5VocabColumnMethod(
|
||||
}else{
|
||||
iVal = pCsr->aCnt[pCsr->iCol];
|
||||
}
|
||||
}else if( eType==FTS5_VOCAB_ROW ){
|
||||
}else{
|
||||
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);
|
||||
|
||||
+26
-31
@@ -89,6 +89,32 @@ input ::= expr(X). { sqlite3Fts5ParseFinished(pParse, X); }
|
||||
%destructor expr { sqlite3Fts5ParseNodeFree($$); }
|
||||
%destructor exprlist { sqlite3Fts5ParseNodeFree($$); }
|
||||
|
||||
expr(A) ::= expr(X) AND expr(Y). {
|
||||
A = sqlite3Fts5ParseNode(pParse, FTS5_AND, X, Y, 0);
|
||||
}
|
||||
expr(A) ::= expr(X) OR expr(Y). {
|
||||
A = sqlite3Fts5ParseNode(pParse, FTS5_OR, X, Y, 0);
|
||||
}
|
||||
expr(A) ::= expr(X) NOT expr(Y). {
|
||||
A = sqlite3Fts5ParseNode(pParse, FTS5_NOT, X, Y, 0);
|
||||
}
|
||||
|
||||
expr(A) ::= LP expr(X) RP. {A = X;}
|
||||
expr(A) ::= exprlist(X). {A = X;}
|
||||
|
||||
exprlist(A) ::= cnearset(X). {A = X;}
|
||||
exprlist(A) ::= exprlist(X) cnearset(Y). {
|
||||
A = sqlite3Fts5ParseImplicitAnd(pParse, X, Y);
|
||||
}
|
||||
|
||||
cnearset(A) ::= nearset(X). {
|
||||
A = sqlite3Fts5ParseNode(pParse, FTS5_STRING, 0, 0, X);
|
||||
}
|
||||
cnearset(A) ::= colset(X) COLON nearset(Y). {
|
||||
sqlite3Fts5ParseSetColset(pParse, Y, X);
|
||||
A = sqlite3Fts5ParseNode(pParse, FTS5_STRING, 0, 0, Y);
|
||||
}
|
||||
|
||||
%type colset {Fts5Colset*}
|
||||
%destructor colset { sqlite3_free($$); }
|
||||
%type colsetlist {Fts5Colset*}
|
||||
@@ -112,37 +138,6 @@ colsetlist(A) ::= STRING(X). {
|
||||
A = sqlite3Fts5ParseColset(pParse, 0, &X);
|
||||
}
|
||||
|
||||
expr(A) ::= expr(X) AND expr(Y). {
|
||||
A = sqlite3Fts5ParseNode(pParse, FTS5_AND, X, Y, 0);
|
||||
}
|
||||
expr(A) ::= expr(X) OR expr(Y). {
|
||||
A = sqlite3Fts5ParseNode(pParse, FTS5_OR, X, Y, 0);
|
||||
}
|
||||
expr(A) ::= expr(X) NOT expr(Y). {
|
||||
A = sqlite3Fts5ParseNode(pParse, FTS5_NOT, X, Y, 0);
|
||||
}
|
||||
|
||||
expr(A) ::= colset(X) COLON LP expr(Y) RP. {
|
||||
sqlite3Fts5ParseSetColset(pParse, Y, X);
|
||||
A = Y;
|
||||
}
|
||||
expr(A) ::= LP expr(X) RP. {A = X;}
|
||||
expr(A) ::= exprlist(X). {A = X;}
|
||||
|
||||
exprlist(A) ::= cnearset(X). {A = X;}
|
||||
exprlist(A) ::= exprlist(X) cnearset(Y). {
|
||||
A = sqlite3Fts5ParseImplicitAnd(pParse, X, Y);
|
||||
}
|
||||
|
||||
cnearset(A) ::= nearset(X). {
|
||||
A = sqlite3Fts5ParseNode(pParse, FTS5_STRING, 0, 0, X);
|
||||
}
|
||||
cnearset(A) ::= colset(X) COLON nearset(Y). {
|
||||
A = sqlite3Fts5ParseNode(pParse, FTS5_STRING, 0, 0, Y);
|
||||
sqlite3Fts5ParseSetColset(pParse, A, X);
|
||||
}
|
||||
|
||||
|
||||
%type nearset {Fts5ExprNearset*}
|
||||
%type nearphrases {Fts5ExprNearset*}
|
||||
%destructor nearset { sqlite3Fts5ParseNearsetFree($$); }
|
||||
|
||||
@@ -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}}
|
||||
# {1 {SQL logic error or missing database}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
@@ -561,37 +561,9 @@ do_test 20.1 {
|
||||
execsql { SELECT rowid FROM tmp WHERE tmp MATCH 'y' }
|
||||
} $::ids
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# Test that a DROP TABLE may be executed within a transaction that
|
||||
# writes to an FTS5 table.
|
||||
#
|
||||
do_execsql_test 21.0 {
|
||||
CREATE TEMP TABLE t8(a, b);
|
||||
CREATE VIRTUAL TABLE ft USING fts5(x, detail=%DETAIL%);
|
||||
}
|
||||
|
||||
do_execsql_test 21.1 {
|
||||
BEGIN;
|
||||
INSERT INTO ft VALUES('a b c');
|
||||
DROP TABLE t8;
|
||||
COMMIT;
|
||||
}
|
||||
|
||||
do_execsql_test 22.0 {
|
||||
CREATE VIRTUAL TABLE t9 USING fts5(x, detail=%DETAIL%);
|
||||
INSERT INTO t9(rowid, x) VALUES(2, 'bbb');
|
||||
BEGIN;
|
||||
INSERT INTO t9(rowid, x) VALUES(1, 'aaa');
|
||||
DELETE FROM t9 WHERE rowid = 2;
|
||||
INSERT INTO t9(rowid, x) VALUES(3, 'bbb');
|
||||
COMMIT;
|
||||
}
|
||||
|
||||
do_execsql_test 22.1 {
|
||||
SELECT rowid FROM t9('a*')
|
||||
} {1}
|
||||
|
||||
}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
|
||||
@@ -294,3 +294,4 @@ do_execsql_test 7.0 {
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -276,3 +276,4 @@ foreach {tn expr tclexpr} {
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -231,6 +231,7 @@ 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
|
||||
}
|
||||
}
|
||||
@@ -241,3 +242,4 @@ foreach {T create} {
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -309,3 +309,4 @@ foreach {tn q cnt} {
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -178,3 +178,4 @@ do_execsql_test 5.1 {
|
||||
} ;# foreach_detail_mode
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -142,3 +142,4 @@ if {[detail_is_full]} {
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -167,3 +167,4 @@ do_execsql_test 1.8.2 {
|
||||
#db eval {SELECT rowid, fts5_decode(rowid, block) aS r FROM t1_data} {puts $r}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -55,3 +55,4 @@ do_execsql_test 1.2 {
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -66,3 +66,4 @@ do_execsql_test 2.0 { INSERT INTO t1(t1) VALUES('integrity-check') }
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -147,3 +147,4 @@ 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}}
|
||||
} {1 {SQL logic error or missing database}}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
@@ -297,3 +297,4 @@ do_catchsql_test 4.4.4 {
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -89,6 +89,7 @@ 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}
|
||||
@@ -99,3 +100,4 @@ do_execsql_test 3.3 {
|
||||
} {1 2}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -342,3 +342,4 @@ foreach {tn expr} {
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -240,6 +240,7 @@ 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
|
||||
@@ -278,3 +279,4 @@ do_execsql_test 9.3 {
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -112,3 +112,4 @@ db eval {
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -61,3 +61,4 @@ do_test 2.1...slow {
|
||||
} {}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -64,3 +64,5 @@ foreach_detail_mode $::testprefix {
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
|
||||
@@ -44,43 +44,16 @@ foreach_detail_mode $::testprefix {
|
||||
9 "-c : a" {1 2 4}
|
||||
10 "-\"c\" : a" {1 2 4}
|
||||
} {
|
||||
breakpoint
|
||||
do_execsql_test 1.$tn {
|
||||
SELECT rowid FROM t1($q)
|
||||
} $res
|
||||
}
|
||||
|
||||
foreach {tn q res} {
|
||||
0 {{a} : (a AND ":")} {}
|
||||
1 "{a b c} : (a AND d)" {2 3}
|
||||
2 "{a b c} : (a AND b:d)" {3}
|
||||
3 "{a b c} : (a AND d:d)" {}
|
||||
4 "{b} : ( {b a} : ( {c b a} : ( {d b c a} : ( d OR c ) ) ) )" {3 4}
|
||||
5 "{a} : ( {b a} : ( {c b a} : ( {d b c a} : ( d OR c ) ) ) )" {2 3}
|
||||
6 "{a} : ( {b a} : ( {c b} : ( {d b c a} : ( d OR c ) ) ) )" {}
|
||||
7 "{a b c} : (b:a AND c:b)" {2}
|
||||
} {
|
||||
do_execsql_test 2.$tn {
|
||||
SELECT rowid FROM t1($q)
|
||||
} $res
|
||||
}
|
||||
|
||||
foreach {tn w res} {
|
||||
0 "a MATCH 'a'" {1}
|
||||
1 "b MATCH 'a'" {2}
|
||||
2 "b MATCH '{a b c} : a'" {2}
|
||||
3 "b MATCH 'a OR b'" {1 2}
|
||||
4 "b MATCH 'a OR a:b'" {2}
|
||||
5 "b MATCH 'a OR b:b'" {1 2}
|
||||
} {
|
||||
do_execsql_test 3.$tn "
|
||||
SELECT rowid FROM t1 WHERE $w
|
||||
" $res
|
||||
}
|
||||
|
||||
do_catchsql_test 4.1 {
|
||||
SELECT * FROM t1 WHERE rowid MATCH 'a'
|
||||
} {1 {unable to use function MATCH in the requested context}}
|
||||
}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
|
||||
@@ -143,6 +143,7 @@ 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}}
|
||||
} {1 {SQL logic error or missing database}}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
@@ -110,6 +110,7 @@ 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 {}}
|
||||
@@ -168,33 +169,33 @@ do_execsql_test 9.0 {
|
||||
} {}
|
||||
do_catchsql_test 9.1.1 {
|
||||
INSERT INTO abc(abc, rank) VALUES('pgsz', -5);
|
||||
} {1 {SQL logic error}}
|
||||
} {1 {SQL logic error or missing database}}
|
||||
do_catchsql_test 9.1.2 {
|
||||
INSERT INTO abc(abc, rank) VALUES('pgsz', 50000000);
|
||||
} {1 {SQL logic error}}
|
||||
} {1 {SQL logic error or missing database}}
|
||||
do_catchsql_test 9.1.3 {
|
||||
INSERT INTO abc(abc, rank) VALUES('pgsz', 66.67);
|
||||
} {1 {SQL logic error}}
|
||||
} {1 {SQL logic error or missing database}}
|
||||
|
||||
do_catchsql_test 9.2.1 {
|
||||
INSERT INTO abc(abc, rank) VALUES('automerge', -5);
|
||||
} {1 {SQL logic error}}
|
||||
} {1 {SQL logic error or missing database}}
|
||||
do_catchsql_test 9.2.2 {
|
||||
INSERT INTO abc(abc, rank) VALUES('automerge', 50000000);
|
||||
} {1 {SQL logic error}}
|
||||
} {1 {SQL logic error or missing database}}
|
||||
do_catchsql_test 9.2.3 {
|
||||
INSERT INTO abc(abc, rank) VALUES('automerge', 66.67);
|
||||
} {1 {SQL logic error}}
|
||||
} {1 {SQL logic error or missing database}}
|
||||
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}}
|
||||
} {1 {SQL logic error or missing database}}
|
||||
do_catchsql_test 9.3.2 {
|
||||
INSERT INTO abc(abc, rank) VALUES('crisismerge', 66.67);
|
||||
} {1 {SQL logic error}}
|
||||
} {1 {SQL logic error or missing database}}
|
||||
do_execsql_test 9.3.3 {
|
||||
INSERT INTO abc(abc, rank) VALUES('crisismerge', 1);
|
||||
} {}
|
||||
@@ -204,14 +205,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}}
|
||||
} {1 {SQL logic error or missing database}}
|
||||
|
||||
do_catchsql_test 9.5.1 {
|
||||
INSERT INTO abc(abc, rank) VALUES('hashsize', 'not an integer');
|
||||
} {1 {SQL logic error}}
|
||||
} {1 {SQL logic error or missing database}}
|
||||
do_catchsql_test 9.5.2 {
|
||||
INSERT INTO abc(abc, rank) VALUES('hashsize', -500000);
|
||||
} {1 {SQL logic error}}
|
||||
} {1 {SQL logic error or missing database}}
|
||||
do_catchsql_test 9.5.3 {
|
||||
INSERT INTO abc(abc, rank) VALUES('hashsize', 500000);
|
||||
} {0 {}}
|
||||
@@ -244,7 +245,7 @@ foreach {tn opt} {
|
||||
|
||||
do_catchsql_test 12.1 {
|
||||
INSERT INTO t1(t1, rank) VALUES('rank', NULL);;
|
||||
} {1 {SQL logic error}}
|
||||
} {1 {SQL logic error or missing database}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# errors in the 'usermerge' option
|
||||
@@ -259,7 +260,8 @@ 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}}
|
||||
do_catchsql_test 13.$tn $sql {1 {SQL logic error or missing database}}
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -66,3 +66,5 @@ do_execsql_test 2.1 {
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
|
||||
@@ -1,247 +0,0 @@
|
||||
# 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,3 +255,4 @@ do_execsql_test 6.2 {
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -96,3 +96,4 @@ do_catchsql_test 3.1 {
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -269,3 +269,4 @@ do_catchsql_test 6.2 {
|
||||
|
||||
sqlite3_fts5_may_be_corrupt 0
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -409,3 +409,4 @@ do_catchsql_test 9.2.2 {
|
||||
|
||||
sqlite3_fts5_may_be_corrupt 0
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
# 2017 May 12
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#*************************************************************************
|
||||
# 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 fts5delete
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
fts5_aux_test_functions db
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE VIRTUAL TABLE t1 USING fts5(x);
|
||||
WITH s(i) AS (
|
||||
SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<5000
|
||||
)
|
||||
INSERT INTO t1(rowid, x) SELECT i, (i/2)*2 FROM s;
|
||||
}
|
||||
|
||||
do_test 1.1 {
|
||||
execsql BEGIN
|
||||
for {set i 1} {$i<=5000} {incr i} {
|
||||
if {$i % 2} {
|
||||
execsql { INSERT INTO t1 VALUES($i) }
|
||||
} else {
|
||||
execsql { DELETE FROM t1 WHERE rowid = $i }
|
||||
}
|
||||
}
|
||||
execsql COMMIT
|
||||
} {}
|
||||
|
||||
do_test 1.2 {
|
||||
execsql { INSERT INTO t1(t1, rank) VALUES('usermerge', 2); }
|
||||
for {set i 0} {$i < 5} {incr i} {
|
||||
execsql { INSERT INTO t1(t1, rank) VALUES('merge', 1) }
|
||||
execsql { INSERT INTO t1(t1) VALUES('integrity-check') }
|
||||
}
|
||||
} {}
|
||||
|
||||
finish_test
|
||||
@@ -241,3 +241,4 @@ do_execsql_test 5.3 {
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -63,3 +63,5 @@ foreach_detail_mode $::testprefix {
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
|
||||
@@ -66,6 +66,7 @@ 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') }
|
||||
} {}
|
||||
@@ -123,6 +124,7 @@ 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}
|
||||
@@ -195,3 +197,4 @@ foreach v $vocab {
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -44,3 +44,4 @@ do_execsql_test 1.2 {
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -81,3 +81,6 @@ do_execsql_test 3.3 {
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -351,3 +351,4 @@ do_faultsim_test 9.1 -faults oom-* -prep {
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -137,3 +137,4 @@ do_faultsim_test 5.0 -faults oom-* -prep {
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -110,3 +110,4 @@ do_faultsim_test 3.2 -faults oom-* -prep {
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -395,3 +395,4 @@ do_faultsim_test 14.1 -faults oom-t* -prep {
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -105,6 +105,7 @@ 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;
|
||||
} {
|
||||
@@ -129,3 +130,4 @@ do_faultsim_test 3.3 -faults oom-t* -body {
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -280,6 +280,7 @@ 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
|
||||
@@ -291,3 +292,4 @@ do_faultsim_test 6 -faults oom* -prep {
|
||||
db close
|
||||
}
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -116,3 +116,4 @@ do_faultsim_test 2.2 -faults oom-* -body {
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -82,3 +82,4 @@ do_faultsim_test 4 -faults oom-* -prep {
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -153,3 +153,4 @@ do_faultsim_test 6 -faults oom-* -body {
|
||||
} ;# foreach_detail_mode...
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -61,3 +61,4 @@ do_faultsim_test 2 -faults oom* -prep {
|
||||
faultsim_test_result {0 {1 2}}
|
||||
}
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -78,57 +78,6 @@ do_faultsim_test 2.4 -faults oom* -body {
|
||||
faultsim_test_result {0 {{3 2} {2 3}}}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 3.0 {
|
||||
CREATE VIRTUAL TABLE x1 USING fts5(z);
|
||||
}
|
||||
|
||||
do_faultsim_test 3.1 -faults oom* -body {
|
||||
execsql {
|
||||
SELECT rowid FROM x1('c') WHERE rowid>1;
|
||||
}
|
||||
} -test {
|
||||
faultsim_test_result {0 {}}
|
||||
}
|
||||
|
||||
do_execsql_test 3.2 {
|
||||
INSERT INTO x1 VALUES('a b c');
|
||||
INSERT INTO x1 VALUES('b c d');
|
||||
INSERT INTO x1 VALUES('c d e');
|
||||
INSERT INTO x1 VALUES('d e f');
|
||||
}
|
||||
do_faultsim_test 3.3 -faults oom* -body {
|
||||
execsql {
|
||||
SELECT rowid FROM x1('c') WHERE rowid>1;
|
||||
}
|
||||
} -test {
|
||||
faultsim_test_result {0 {2 3}}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test OOM injection with nested colsets.
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 4.0 {
|
||||
CREATE VIRTUAL TABLE t1 USING fts5(a, b, c, d);
|
||||
INSERT INTO t1 VALUES('a', 'b', 'c', 'd'); -- 1
|
||||
INSERT INTO t1 VALUES('d', 'a', 'b', 'c'); -- 2
|
||||
INSERT INTO t1 VALUES('c', 'd', 'a', 'b'); -- 3
|
||||
INSERT INTO t1 VALUES('b', 'c', 'd', 'a'); -- 4
|
||||
}
|
||||
do_faultsim_test 4.1 -faults oom* -body {
|
||||
execsql { SELECT rowid FROM t1('{a b c} : (b:a AND c:b)'); }
|
||||
} -test {
|
||||
faultsim_test_result {0 2}
|
||||
}
|
||||
|
||||
do_faultsim_test 4.2 -faults oom* -body {
|
||||
execsql { SELECT rowid FROM t1('{a b c} : (a AND d)') }
|
||||
} -test {
|
||||
faultsim_test_result {0 {2 3}}
|
||||
}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -1,87 +0,0 @@
|
||||
# 2016 February 2
|
||||
#
|
||||
# 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 is focused on OOM errors.
|
||||
#
|
||||
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
source $testdir/malloc_common.tcl
|
||||
set testprefix fts5faultA
|
||||
|
||||
# If SQLITE_ENABLE_FTS3 is defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
foreach_detail_mode $testprefix {
|
||||
if {"%DETAIL%"=="none"} continue
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE VIRTUAL TABLE o1 USING fts5(a, b, c, detail=%DETAIL%);
|
||||
INSERT INTO o1(o1, rank) VALUES('pgsz', 32);
|
||||
|
||||
WITH s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<60 )
|
||||
INSERT INTO o1 SELECT 'A', 'B', 'C' FROM s;
|
||||
|
||||
WITH s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<60 )
|
||||
INSERT INTO o1 SELECT 'C', 'A', 'B' FROM s;
|
||||
|
||||
WITH s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<60 )
|
||||
INSERT INTO o1 SELECT 'B', 'C', 'A' FROM s;
|
||||
}
|
||||
|
||||
do_faultsim_test 1 -faults int* -prep {
|
||||
sqlite3 db test.db
|
||||
} -body {
|
||||
execsql { SELECT count(*) FROM o1('a') }
|
||||
} -test {
|
||||
faultsim_test_result {0 180} {1 {vtable constructor failed: o1}}
|
||||
}
|
||||
|
||||
do_faultsim_test 2 -faults int* -prep {
|
||||
sqlite3 db test.db
|
||||
} -body {
|
||||
execsql { SELECT * FROM o1('a:a AND {b c}:b') ORDER BY rank }
|
||||
expr 1
|
||||
} -test {
|
||||
faultsim_test_result {0 1} {1 {vtable constructor failed: o1}}
|
||||
}
|
||||
|
||||
do_faultsim_test 3 -faults int* -prep {
|
||||
sqlite3 db test.db
|
||||
} -body {
|
||||
execsql { SELECT * FROM o1('{b c}:b NOT a:a') ORDER BY rank }
|
||||
expr 1
|
||||
} -test {
|
||||
faultsim_test_result {0 1} {1 {vtable constructor failed: o1}}
|
||||
}
|
||||
|
||||
do_faultsim_test 4 -faults int* -prep {
|
||||
sqlite3 db test.db
|
||||
} -body {
|
||||
execsql { SELECT * FROM o1('b:b OR a:a') }
|
||||
expr 1
|
||||
} -test {
|
||||
faultsim_test_result {0 1} {1 {vtable constructor failed: o1}}
|
||||
}
|
||||
|
||||
do_faultsim_test 5 -faults int* -prep {
|
||||
sqlite3 db test.db
|
||||
} -body {
|
||||
execsql { SELECT count(*) FROM o1('c:b') }
|
||||
expr 1
|
||||
} -test {
|
||||
faultsim_test_result {0 1} {1 {vtable constructor failed: o1}}
|
||||
}
|
||||
}
|
||||
|
||||
finish_test
|
||||
@@ -40,3 +40,4 @@ do_test 1.1 {
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -90,3 +90,4 @@ do_catchsql_test 4.1 {
|
||||
} {1 {fts5: syntax error near "`"}}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -121,6 +121,7 @@ foreach_detail_mode $testprefix {
|
||||
}
|
||||
|
||||
execsql { CREATE VIRTUAL TABLE t2 USING fts5(x, detail=%DETAIL%) }
|
||||
breakpoint
|
||||
execsql {
|
||||
INSERT INTO t2 VALUES($small || ' ' || $big);
|
||||
}
|
||||
@@ -129,3 +130,4 @@ foreach_detail_mode $testprefix {
|
||||
} ;# foreach_detail_mode
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -210,3 +210,4 @@ foreach {tn pgsz} {
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -1,72 +0,0 @@
|
||||
# 2017 Feb 27
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
# Tests of the last_insert_rowid functionality with fts5.
|
||||
#
|
||||
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5lastrowid
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE VIRTUAL TABLE t1 USING fts5(str);
|
||||
}
|
||||
|
||||
do_execsql_test 1.1 {
|
||||
INSERT INTO t1 VALUES('one string');
|
||||
INSERT INTO t1 VALUES('two string');
|
||||
INSERT INTO t1 VALUES('three string');
|
||||
SELECT last_insert_rowid();
|
||||
} {3}
|
||||
|
||||
do_execsql_test 1.2 {
|
||||
BEGIN;
|
||||
INSERT INTO t1 VALUES('one string');
|
||||
INSERT INTO t1 VALUES('two string');
|
||||
INSERT INTO t1 VALUES('three string');
|
||||
COMMIT;
|
||||
SELECT last_insert_rowid();
|
||||
} {6}
|
||||
|
||||
do_execsql_test 1.3 {
|
||||
INSERT INTO t1(rowid, str) VALUES(-22, 'some more text');
|
||||
SELECT last_insert_rowid();
|
||||
} {-22}
|
||||
|
||||
do_execsql_test 1.4 {
|
||||
BEGIN;
|
||||
INSERT INTO t1(rowid, str) VALUES(45, 'some more text');
|
||||
INSERT INTO t1(rowid, str) VALUES(46, 'some more text');
|
||||
INSERT INTO t1(rowid, str) VALUES(222, 'some more text');
|
||||
SELECT last_insert_rowid();
|
||||
COMMIT;
|
||||
SELECT last_insert_rowid();
|
||||
} {222 222}
|
||||
|
||||
do_execsql_test 1.5 {
|
||||
CREATE TABLE x1(x);
|
||||
INSERT INTO x1 VALUES('john'), ('paul'), ('george'), ('ringo');
|
||||
INSERT INTO t1 SELECT x FROM x1;
|
||||
SELECT last_insert_rowid();
|
||||
} {226}
|
||||
|
||||
do_execsql_test 1.6 {
|
||||
INSERT INTO t1(rowid, str) SELECT rowid+10, x FROM x1;
|
||||
SELECT last_insert_rowid();
|
||||
} {14}
|
||||
|
||||
|
||||
finish_test
|
||||
@@ -1,43 +0,0 @@
|
||||
# 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 1 xyz
|
||||
db func fts5 -argcount 0 xyz
|
||||
do_test 13.1 {
|
||||
list [catch { sqlite3_fts5_register_matchinfo db } msg] $msg
|
||||
} {1 SQLITE_ERROR}
|
||||
@@ -492,3 +492,4 @@ do_catchsql_test 14.2 {
|
||||
} {1 {unrecognized matchinfo flag: d}}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -241,3 +241,4 @@ do_execsql_test 6.3 {
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -55,3 +55,4 @@ do_execsql_test 1.2 {
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -45,3 +45,4 @@ do_multiclient_test tn {
|
||||
};# do_multiclient_test
|
||||
};# foreach_detail_mode
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -68,3 +68,4 @@ 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,3 +178,4 @@ do_execsql_test 4.3.1 {
|
||||
do_test 4.2.2 { fts5_level_segs ttt } {3}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -106,3 +106,4 @@ foreach {tn nStep} {
|
||||
do_test 2.$tn.6 { fts5_segcount t1 } 1
|
||||
}
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -116,3 +116,4 @@ do_execsql_test 2.0 {
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ do_eqp_test 1.1 {
|
||||
SELECT * FROM t1, f1 WHERE f1 MATCH t1.x
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t1}
|
||||
0 1 1 {SCAN TABLE f1 VIRTUAL TABLE INDEX 65537:}
|
||||
0 1 1 {SCAN TABLE f1 VIRTUAL TABLE INDEX 1:}
|
||||
}
|
||||
|
||||
do_eqp_test 1.2 {
|
||||
@@ -43,7 +43,7 @@ do_eqp_test 1.2 {
|
||||
do_eqp_test 1.3 {
|
||||
SELECT * FROM f1 WHERE f1 MATCH ? ORDER BY ff
|
||||
} {
|
||||
0 0 0 {SCAN TABLE f1 VIRTUAL TABLE INDEX 65537:}
|
||||
0 0 0 {SCAN TABLE f1 VIRTUAL TABLE INDEX 1:}
|
||||
0 0 0 {USE TEMP B-TREE FOR ORDER BY}
|
||||
}
|
||||
|
||||
@@ -64,3 +64,4 @@ do_eqp_test 1.5 {
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -11803,3 +11803,4 @@ foreach {in out} $test_vocab {
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -67,3 +67,4 @@ foreach {in out} $test_vocab {
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
# This file contains tests focused on prefix indexes.
|
||||
# This file containst tests focused on prefix indexes.
|
||||
#
|
||||
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
@@ -341,3 +341,5 @@ foreach {tn create} {
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
|
||||
@@ -79,3 +79,5 @@ for {set tn 1 ; set pgsz 64} {$tn<32} {incr tn; incr pgsz 16} {
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
|
||||
@@ -90,7 +90,6 @@ 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:
|
||||
@@ -152,3 +151,4 @@ do_execsql_test 4.1 {
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -64,3 +64,4 @@ 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,3 +149,4 @@ do_test 4.3 {
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -216,3 +216,4 @@ do_execsql_test 6.2 {
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -411,6 +411,7 @@ 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);
|
||||
|
||||
@@ -332,41 +332,7 @@ do_execsql_test 16.0 {
|
||||
DELETE FROM t2;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 17.0 {
|
||||
CREATE VIRTUAL TABLE t2 USING fts5(x, y);
|
||||
BEGIN;
|
||||
INSERT INTO t2 VALUES('a aa aaa', 'b bb bbb');
|
||||
INSERT INTO t2 VALUES('a aa aaa', 'b bb bbb');
|
||||
INSERT INTO t2 VALUES('a aa aaa', 'b bb bbb');
|
||||
COMMIT;
|
||||
}
|
||||
do_execsql_test 17.1 { SELECT * FROM t2('y:a*') WHERE rowid BETWEEN 10 AND 20 }
|
||||
do_execsql_test 17.2 {
|
||||
BEGIN;
|
||||
INSERT INTO t2 VALUES('a aa aaa', 'b bb bbb');
|
||||
SELECT * FROM t2('y:a*') WHERE rowid BETWEEN 10 AND 20 ;
|
||||
}
|
||||
do_execsql_test 17.3 {
|
||||
COMMIT
|
||||
}
|
||||
|
||||
reset_db
|
||||
do_execsql_test 17.4 {
|
||||
CREATE VIRTUAL TABLE t2 USING fts5(x, y);
|
||||
BEGIN;
|
||||
INSERT INTO t2 VALUES('a aa aaa', 'b bb bbb');
|
||||
INSERT INTO t2 VALUES('a aa aaa', 'b bb bbb');
|
||||
SELECT * FROM t2('y:a*') WHERE rowid>66;
|
||||
}
|
||||
do_execsql_test 17.5 { SELECT * FROM t2('x:b* OR y:a*') }
|
||||
do_execsql_test 17.5 { COMMIT ; SELECT * FROM t2('x:b* OR y:a*') }
|
||||
do_execsql_test 17.6 {
|
||||
SELECT * FROM t2('x:b* OR y:a*') WHERE rowid>55
|
||||
}
|
||||
|
||||
#db eval {SELECT rowid, fts5_decode_none(rowid, block) aS r FROM t2_data} {puts $r}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user