mirror of
https://github.com/status-im/sqlcipher.git
synced 2025-02-23 09:18:11 +00:00
Snapshot of upstream SQLite 3.20.1
This commit is contained in:
parent
51ec837e61
commit
1f3bc22483
55
Makefile.in
55
Makefile.in
@ -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 \
|
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 \
|
pager.lo parse.lo pcache.lo pcache1.lo pragma.lo prepare.lo printf.lo \
|
||||||
random.lo resolve.lo rowset.lo rtree.lo \
|
random.lo resolve.lo rowset.lo rtree.lo \
|
||||||
sqlite3session.lo select.lo sqlite3rbu.lo status.lo \
|
sqlite3session.lo select.lo sqlite3rbu.lo status.lo stmt.lo \
|
||||||
table.lo threads.lo tokenize.lo treeview.lo trigger.lo \
|
table.lo threads.lo tokenize.lo treeview.lo trigger.lo \
|
||||||
update.lo util.lo vacuum.lo \
|
update.lo util.lo vacuum.lo \
|
||||||
vdbe.lo vdbeapi.lo vdbeaux.lo vdbeblob.lo vdbemem.lo vdbesort.lo \
|
vdbe.lo vdbeapi.lo vdbeaux.lo vdbeblob.lo vdbemem.lo vdbesort.lo \
|
||||||
@ -350,7 +350,8 @@ SRC += \
|
|||||||
$(TOP)/ext/rbu/sqlite3rbu.h \
|
$(TOP)/ext/rbu/sqlite3rbu.h \
|
||||||
$(TOP)/ext/rbu/sqlite3rbu.c
|
$(TOP)/ext/rbu/sqlite3rbu.c
|
||||||
SRC += \
|
SRC += \
|
||||||
$(TOP)/ext/misc/json1.c
|
$(TOP)/ext/misc/json1.c \
|
||||||
|
$(TOP)/ext/misc/stmt.c
|
||||||
|
|
||||||
# Generated source code files
|
# Generated source code files
|
||||||
#
|
#
|
||||||
@ -430,9 +431,11 @@ TESTSRC += \
|
|||||||
$(TOP)/ext/misc/nextchar.c \
|
$(TOP)/ext/misc/nextchar.c \
|
||||||
$(TOP)/ext/misc/percentile.c \
|
$(TOP)/ext/misc/percentile.c \
|
||||||
$(TOP)/ext/misc/regexp.c \
|
$(TOP)/ext/misc/regexp.c \
|
||||||
|
$(TOP)/ext/misc/remember.c \
|
||||||
$(TOP)/ext/misc/series.c \
|
$(TOP)/ext/misc/series.c \
|
||||||
$(TOP)/ext/misc/spellfix.c \
|
$(TOP)/ext/misc/spellfix.c \
|
||||||
$(TOP)/ext/misc/totype.c \
|
$(TOP)/ext/misc/totype.c \
|
||||||
|
$(TOP)/ext/misc/unionvtab.c \
|
||||||
$(TOP)/ext/misc/wholenumber.c
|
$(TOP)/ext/misc/wholenumber.c
|
||||||
|
|
||||||
# Source code to the library files needed by the test fixture
|
# Source code to the library files needed by the test fixture
|
||||||
@ -482,7 +485,8 @@ TESTSRC2 = \
|
|||||||
$(TOP)/ext/fts3/fts3_tokenizer.c \
|
$(TOP)/ext/fts3/fts3_tokenizer.c \
|
||||||
$(TOP)/ext/fts3/fts3_write.c \
|
$(TOP)/ext/fts3/fts3_write.c \
|
||||||
$(TOP)/ext/async/sqlite3async.c \
|
$(TOP)/ext/async/sqlite3async.c \
|
||||||
$(TOP)/ext/session/sqlite3session.c
|
$(TOP)/ext/session/sqlite3session.c \
|
||||||
|
$(TOP)/ext/misc/stmt.c
|
||||||
|
|
||||||
# Header files used by all library source files.
|
# Header files used by all library source files.
|
||||||
#
|
#
|
||||||
@ -550,7 +554,8 @@ FUZZDATA = \
|
|||||||
$(TOP)/test/fuzzdata1.db \
|
$(TOP)/test/fuzzdata1.db \
|
||||||
$(TOP)/test/fuzzdata2.db \
|
$(TOP)/test/fuzzdata2.db \
|
||||||
$(TOP)/test/fuzzdata3.db \
|
$(TOP)/test/fuzzdata3.db \
|
||||||
$(TOP)/test/fuzzdata4.db
|
$(TOP)/test/fuzzdata4.db \
|
||||||
|
$(TOP)/test/fuzzdata5.db
|
||||||
|
|
||||||
# Standard options to testfixture
|
# Standard options to testfixture
|
||||||
#
|
#
|
||||||
@ -562,8 +567,12 @@ SHELL_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS4
|
|||||||
# SHELL_OPT += -DSQLITE_ENABLE_FTS5
|
# SHELL_OPT += -DSQLITE_ENABLE_FTS5
|
||||||
SHELL_OPT += -DSQLITE_ENABLE_EXPLAIN_COMMENTS
|
SHELL_OPT += -DSQLITE_ENABLE_EXPLAIN_COMMENTS
|
||||||
SHELL_OPT += -DSQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
|
SHELL_OPT += -DSQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
|
||||||
|
SHELL_OPT += -DSQLITE_ENABLE_STMTVTAB
|
||||||
FUZZERSHELL_OPT = -DSQLITE_ENABLE_JSON1
|
FUZZERSHELL_OPT = -DSQLITE_ENABLE_JSON1
|
||||||
FUZZCHECK_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5
|
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 =
|
||||||
|
|
||||||
# This is the default Makefile target. The objects listed here
|
# This is the default Makefile target. The objects listed here
|
||||||
# are what get build when you type just "make" with no arguments.
|
# are what get build when you type just "make" with no arguments.
|
||||||
@ -612,8 +621,15 @@ fuzzershell$(TEXE): $(TOP)/tool/fuzzershell.c sqlite3.c sqlite3.h
|
|||||||
$(LTLINK) -o $@ $(FUZZERSHELL_OPT) \
|
$(LTLINK) -o $@ $(FUZZERSHELL_OPT) \
|
||||||
$(TOP)/tool/fuzzershell.c sqlite3.c $(TLIBS)
|
$(TOP)/tool/fuzzershell.c sqlite3.c $(TLIBS)
|
||||||
|
|
||||||
fuzzcheck$(TEXE): $(TOP)/test/fuzzcheck.c sqlite3.c sqlite3.h
|
fuzzcheck$(TEXE): $(FUZZCHECK_SRC) sqlite3.c sqlite3.h
|
||||||
$(LTLINK) -o $@ $(FUZZCHECK_OPT) $(TOP)/test/fuzzcheck.c sqlite3.c $(TLIBS)
|
$(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)
|
||||||
|
|
||||||
mptester$(TEXE): sqlite3.lo $(TOP)/mptest/mptest.c
|
mptester$(TEXE): sqlite3.lo $(TOP)/mptest/mptest.c
|
||||||
$(LTLINK) -o $@ -I. $(TOP)/mptest/mptest.c sqlite3.lo \
|
$(LTLINK) -o $@ -I. $(TOP)/mptest/mptest.c sqlite3.lo \
|
||||||
@ -1022,6 +1038,9 @@ sqlite3session.lo: $(TOP)/ext/session/sqlite3session.c $(HDR) $(EXTHDR)
|
|||||||
json1.lo: $(TOP)/ext/misc/json1.c
|
json1.lo: $(TOP)/ext/misc/json1.c
|
||||||
$(LTCOMPILE) -DSQLITE_CORE -c $(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 things
|
||||||
#
|
#
|
||||||
FTS5_SRC = \
|
FTS5_SRC = \
|
||||||
@ -1071,6 +1090,7 @@ TESTFIXTURE_FLAGS += -DSQLITE_SERVER=1 -DSQLITE_PRIVATE="" -DSQLITE_CORE
|
|||||||
TESTFIXTURE_FLAGS += -DBUILD_sqlite
|
TESTFIXTURE_FLAGS += -DBUILD_sqlite
|
||||||
TESTFIXTURE_FLAGS += -DSQLITE_SERIES_CONSTRAINT_VERIFY=1
|
TESTFIXTURE_FLAGS += -DSQLITE_SERIES_CONSTRAINT_VERIFY=1
|
||||||
TESTFIXTURE_FLAGS += -DSQLITE_DEFAULT_PAGE_SIZE=1024
|
TESTFIXTURE_FLAGS += -DSQLITE_DEFAULT_PAGE_SIZE=1024
|
||||||
|
TESTFIXTURE_FLAGS += -DSQLITE_ENABLE_STMTVTAB
|
||||||
|
|
||||||
TESTFIXTURE_SRC0 = $(TESTSRC2) libsqlite3.la
|
TESTFIXTURE_SRC0 = $(TESTSRC2) libsqlite3.la
|
||||||
TESTFIXTURE_SRC1 = sqlite3.c
|
TESTFIXTURE_SRC1 = sqlite3.c
|
||||||
@ -1103,6 +1123,11 @@ fastfuzztest: fuzzcheck$(TEXE) $(FUZZDATA)
|
|||||||
valgrindfuzz: fuzzcheck$(TEXT) $(FUZZDATA)
|
valgrindfuzz: fuzzcheck$(TEXT) $(FUZZDATA)
|
||||||
valgrind ./fuzzcheck$(TEXE) --cell-size-check --limit-mem 10M --timeout 600 $(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
|
# Minimal testing that runs in less than 3 minutes
|
||||||
#
|
#
|
||||||
quicktest: ./testfixture$(TEXE)
|
quicktest: ./testfixture$(TEXE)
|
||||||
@ -1111,8 +1136,7 @@ quicktest: ./testfixture$(TEXE)
|
|||||||
# This is the common case. Run many tests that do not take too long,
|
# This is the common case. Run many tests that do not take too long,
|
||||||
# including fuzzcheck, sqlite3_analyzer, and sqldiff tests.
|
# including fuzzcheck, sqlite3_analyzer, and sqldiff tests.
|
||||||
#
|
#
|
||||||
test: $(TESTPROGS) sourcetest fastfuzztest
|
test: fastfuzztest sourcetest $(TESTPROGS) tcltest
|
||||||
./testfixture$(TEXE) $(TOP)/test/veryquick.test $(TESTOPTS)
|
|
||||||
|
|
||||||
# Run a test using valgrind. This can take a really long time
|
# Run a test using valgrind. This can take a really long time
|
||||||
# because valgrind is so much slower than a native machine.
|
# because valgrind is so much slower than a native machine.
|
||||||
@ -1139,6 +1163,10 @@ sqlite3_analyzer.c: sqlite3.c $(TOP)/src/tclsqlite.c $(TOP)/tool/spaceanal.tcl
|
|||||||
sqlite3_analyzer$(TEXE): sqlite3_analyzer.c
|
sqlite3_analyzer$(TEXE): sqlite3_analyzer.c
|
||||||
$(LTLINK) sqlite3_analyzer.c -o $@ $(LIBTCL) $(TLIBS)
|
$(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
|
showdb$(TEXE): $(TOP)/tool/showdb.c sqlite3.lo
|
||||||
$(LTLINK) -o $@ $(TOP)/tool/showdb.c sqlite3.lo $(TLIBS)
|
$(LTLINK) -o $@ $(TOP)/tool/showdb.c sqlite3.lo $(TLIBS)
|
||||||
|
|
||||||
@ -1163,8 +1191,13 @@ LogEst$(TEXE): $(TOP)/tool/logest.c sqlite3.h
|
|||||||
wordcount$(TEXE): $(TOP)/test/wordcount.c sqlite3.lo
|
wordcount$(TEXE): $(TOP)/test/wordcount.c sqlite3.lo
|
||||||
$(LTLINK) -o $@ $(TOP)/test/wordcount.c sqlite3.lo $(TLIBS)
|
$(LTLINK) -o $@ $(TOP)/test/wordcount.c sqlite3.lo $(TLIBS)
|
||||||
|
|
||||||
speedtest1$(TEXE): $(TOP)/test/speedtest1.c sqlite3.lo
|
speedtest1$(TEXE): $(TOP)/test/speedtest1.c sqlite3.c
|
||||||
$(LTLINK) -o $@ $(TOP)/test/speedtest1.c sqlite3.lo $(TLIBS)
|
$(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)
|
||||||
|
|
||||||
rbu$(EXE): $(TOP)/ext/rbu/rbu.c $(TOP)/ext/rbu/sqlite3rbu.c sqlite3.lo
|
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)
|
$(LTLINK) -I. -o $@ $(TOP)/ext/rbu/rbu.c sqlite3.lo $(TLIBS)
|
||||||
|
92
Makefile.msc
92
Makefile.msc
@ -21,7 +21,14 @@ USE_AMALGAMATION = 1
|
|||||||
# Set this non-0 to enable full warnings (-W4, etc) when compiling.
|
# Set this non-0 to enable full warnings (-W4, etc) when compiling.
|
||||||
#
|
#
|
||||||
!IFNDEF USE_FULLWARN
|
!IFNDEF USE_FULLWARN
|
||||||
USE_FULLWARN = 0
|
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
|
||||||
!ENDIF
|
!ENDIF
|
||||||
|
|
||||||
# Set this non-0 to enable full runtime error checks (-RTC1, etc). This
|
# Set this non-0 to enable full runtime error checks (-RTC1, etc). This
|
||||||
@ -493,6 +500,12 @@ TCC = $(CC) -nologo -W4 -DINCLUDE_MSVC_H=1 $(CCOPTS) $(TCCOPTS)
|
|||||||
TCC = $(CC) -nologo -W3 $(CCOPTS) $(TCCOPTS)
|
TCC = $(CC) -nologo -W3 $(CCOPTS) $(TCCOPTS)
|
||||||
!ENDIF
|
!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
|
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)
|
RCC = $(RC) -DSQLITE_OS_WIN=1 -I. -I$(TOP) -I$(TOP)\src $(RCOPTS) $(RCCOPTS)
|
||||||
|
|
||||||
@ -733,6 +746,10 @@ RCC = $(RCC) -DSQLITE_ENABLE_API_ARMOR=1
|
|||||||
!IF $(DEBUG)>2
|
!IF $(DEBUG)>2
|
||||||
TCC = $(TCC) -DSQLITE_DEBUG=1
|
TCC = $(TCC) -DSQLITE_DEBUG=1
|
||||||
RCC = $(RCC) -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
|
!ENDIF
|
||||||
|
|
||||||
!IF $(DEBUG)>4 || $(OSTRACE)!=0
|
!IF $(DEBUG)>4 || $(OSTRACE)!=0
|
||||||
@ -1277,7 +1294,8 @@ SRC07 = \
|
|||||||
$(TOP)\ext\rtree\rtree.c \
|
$(TOP)\ext\rtree\rtree.c \
|
||||||
$(TOP)\ext\session\sqlite3session.c \
|
$(TOP)\ext\session\sqlite3session.c \
|
||||||
$(TOP)\ext\rbu\sqlite3rbu.c \
|
$(TOP)\ext\rbu\sqlite3rbu.c \
|
||||||
$(TOP)\ext\misc\json1.c
|
$(TOP)\ext\misc\json1.c \
|
||||||
|
$(TOP)\ext\misc\stmt.c
|
||||||
|
|
||||||
# Extension header files, part 1.
|
# Extension header files, part 1.
|
||||||
#
|
#
|
||||||
@ -1396,9 +1414,11 @@ TESTEXT = \
|
|||||||
$(TOP)\ext\misc\nextchar.c \
|
$(TOP)\ext\misc\nextchar.c \
|
||||||
$(TOP)\ext\misc\percentile.c \
|
$(TOP)\ext\misc\percentile.c \
|
||||||
$(TOP)\ext\misc\regexp.c \
|
$(TOP)\ext\misc\regexp.c \
|
||||||
|
$(TOP)\ext\misc\remember.c \
|
||||||
$(TOP)\ext\misc\series.c \
|
$(TOP)\ext\misc\series.c \
|
||||||
$(TOP)\ext\misc\spellfix.c \
|
$(TOP)\ext\misc\spellfix.c \
|
||||||
$(TOP)\ext\misc\totype.c \
|
$(TOP)\ext\misc\totype.c \
|
||||||
|
$(TOP)\ext\misc\unionvtab.c \
|
||||||
$(TOP)\ext\misc\wholenumber.c
|
$(TOP)\ext\misc\wholenumber.c
|
||||||
|
|
||||||
# Source code to the library files needed by the test fixture
|
# Source code to the library files needed by the test fixture
|
||||||
@ -1479,14 +1499,15 @@ FUZZDATA = \
|
|||||||
$(TOP)\test\fuzzdata1.db \
|
$(TOP)\test\fuzzdata1.db \
|
||||||
$(TOP)\test\fuzzdata2.db \
|
$(TOP)\test\fuzzdata2.db \
|
||||||
$(TOP)\test\fuzzdata3.db \
|
$(TOP)\test\fuzzdata3.db \
|
||||||
$(TOP)\test\fuzzdata4.db
|
$(TOP)\test\fuzzdata4.db \
|
||||||
|
$(TOP)\test\fuzzdata5.db
|
||||||
# <</mark>>
|
# <</mark>>
|
||||||
|
|
||||||
# Additional compiler options for the shell. These are only effective
|
# Additional compiler options for the shell. These are only effective
|
||||||
# when the shell is not being dynamically linked.
|
# when the shell is not being dynamically linked.
|
||||||
#
|
#
|
||||||
!IF $(DYNAMIC_SHELL)==0 && $(FOR_WIN10)==0
|
!IF $(DYNAMIC_SHELL)==0 && $(FOR_WIN10)==0
|
||||||
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_SHELL_JSON1 -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS
|
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_SHELL_JSON1 -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_STMTVTAB
|
||||||
!ENDIF
|
!ENDIF
|
||||||
|
|
||||||
# <<mark>>
|
# <<mark>>
|
||||||
@ -1494,7 +1515,13 @@ SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_SHELL_JSON1 -DSQLITE_ENABLE_
|
|||||||
#
|
#
|
||||||
MPTESTER_COMPILE_OPTS = -DSQLITE_SHELL_JSON1 -DSQLITE_ENABLE_FTS5
|
MPTESTER_COMPILE_OPTS = -DSQLITE_SHELL_JSON1 -DSQLITE_ENABLE_FTS5
|
||||||
FUZZERSHELL_COMPILE_OPTS = -DSQLITE_ENABLE_JSON1
|
FUZZERSHELL_COMPILE_OPTS = -DSQLITE_ENABLE_JSON1
|
||||||
FUZZCHECK_COMPILE_OPTS = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5
|
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
|
||||||
|
|
||||||
# Standard options to testfixture.
|
# Standard options to testfixture.
|
||||||
#
|
#
|
||||||
@ -1537,7 +1564,7 @@ $(SQLITE3DLL): $(LIBOBJ) $(LIBRESOBJS) $(CORE_LINK_DEP)
|
|||||||
sqlite3.def: libsqlite3.lib
|
sqlite3.def: libsqlite3.lib
|
||||||
echo EXPORTS > sqlite3.def
|
echo EXPORTS > sqlite3.def
|
||||||
dumpbin /all libsqlite3.lib \
|
dumpbin /all libsqlite3.lib \
|
||||||
| $(TCLSH_CMD) $(TOP)\tool\replace.tcl include "^\s+1 _?(sqlite3_[^@]*)(?:@\d+)?$$" \1 \
|
| $(TCLSH_CMD) $(TOP)\tool\replace.tcl include "^\s+1 _?(sqlite3(?:session|changeset|changegroup)?_[^@]*)(?:@\d+)?$$" \1 \
|
||||||
| sort >> sqlite3.def
|
| sort >> sqlite3.def
|
||||||
# <</block2>>
|
# <</block2>>
|
||||||
|
|
||||||
@ -1564,8 +1591,14 @@ sourcetest: srcck1.exe sqlite3.c
|
|||||||
fuzzershell.exe: $(TOP)\tool\fuzzershell.c $(SQLITE3C) $(SQLITE3H)
|
fuzzershell.exe: $(TOP)\tool\fuzzershell.c $(SQLITE3C) $(SQLITE3H)
|
||||||
$(LTLINK) $(NO_WARN) $(FUZZERSHELL_COMPILE_OPTS) $(TOP)\tool\fuzzershell.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
$(LTLINK) $(NO_WARN) $(FUZZERSHELL_COMPILE_OPTS) $(TOP)\tool\fuzzershell.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
||||||
|
|
||||||
fuzzcheck.exe: $(TOP)\test\fuzzcheck.c $(SQLITE3C) $(SQLITE3H)
|
dbfuzz.exe: $(TOP)\test\dbfuzz.c $(SQLITE3C) $(SQLITE3H)
|
||||||
$(LTLINK) $(NO_WARN) $(FUZZCHECK_COMPILE_OPTS) $(TOP)\test\fuzzcheck.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
$(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)
|
||||||
|
|
||||||
mptester.exe: $(TOP)\mptest\mptest.c $(SQLITE3C) $(SQLITE3H)
|
mptester.exe: $(TOP)\mptest\mptest.c $(SQLITE3C) $(SQLITE3H)
|
||||||
$(LTLINK) $(NO_WARN) $(MPTESTER_COMPILE_OPTS) $(TOP)\mptest\mptest.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
$(LTLINK) $(NO_WARN) $(MPTESTER_COMPILE_OPTS) $(TOP)\mptest\mptest.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
||||||
@ -2058,6 +2091,7 @@ TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_SERVER=1 -DSQLITE_PRIVATE=""
|
|||||||
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_CORE $(NO_WARN)
|
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_CORE $(NO_WARN)
|
||||||
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_SERIES_CONSTRAINT_VERIFY=1
|
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_SERIES_CONSTRAINT_VERIFY=1
|
||||||
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_DEFAULT_PAGE_SIZE=1024
|
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_DEFAULT_PAGE_SIZE=1024
|
||||||
|
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_ENABLE_STMTVTAB
|
||||||
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) $(TEST_CCONV_OPTS)
|
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) $(TEST_CCONV_OPTS)
|
||||||
|
|
||||||
TESTFIXTURE_SRC0 = $(TESTEXT) $(TESTSRC2)
|
TESTFIXTURE_SRC0 = $(TESTEXT) $(TESTSRC2)
|
||||||
@ -2150,6 +2184,10 @@ sqlite3_analyzer.exe: sqlite3_analyzer.c $(LIBRESOBJS)
|
|||||||
$(LTLINK) $(NO_WARN) -DBUILD_sqlite -I$(TCLINCDIR) sqlite3_analyzer.c \
|
$(LTLINK) $(NO_WARN) -DBUILD_sqlite -I$(TCLINCDIR) sqlite3_analyzer.c \
|
||||||
/link $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LTLIBS) $(TLIBS)
|
/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
|
testloadext.lo: $(TOP)\src\test_loadext.c
|
||||||
$(LTCOMPILE) $(NO_WARN) -c $(TOP)\src\test_loadext.c
|
$(LTCOMPILE) $(NO_WARN) -c $(TOP)\src\test_loadext.c
|
||||||
|
|
||||||
@ -2157,48 +2195,59 @@ testloadext.dll: testloadext.lo
|
|||||||
$(LD) $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) /DLL /OUT:$@ testloadext.lo
|
$(LD) $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) /DLL /OUT:$@ testloadext.lo
|
||||||
|
|
||||||
showdb.exe: $(TOP)\tool\showdb.c $(SQLITE3C) $(SQLITE3H)
|
showdb.exe: $(TOP)\tool\showdb.c $(SQLITE3C) $(SQLITE3H)
|
||||||
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \
|
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
|
||||||
$(TOP)\tool\showdb.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
$(TOP)\tool\showdb.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
||||||
|
|
||||||
showstat4.exe: $(TOP)\tool\showstat4.c $(SQLITE3C) $(SQLITE3H)
|
showstat4.exe: $(TOP)\tool\showstat4.c $(SQLITE3C) $(SQLITE3H)
|
||||||
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \
|
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
|
||||||
$(TOP)\tool\showstat4.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
$(TOP)\tool\showstat4.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
||||||
|
|
||||||
showjournal.exe: $(TOP)\tool\showjournal.c $(SQLITE3C) $(SQLITE3H)
|
showjournal.exe: $(TOP)\tool\showjournal.c $(SQLITE3C) $(SQLITE3H)
|
||||||
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \
|
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
|
||||||
$(TOP)\tool\showjournal.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
$(TOP)\tool\showjournal.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
||||||
|
|
||||||
showwal.exe: $(TOP)\tool\showwal.c $(SQLITE3C) $(SQLITE3H)
|
showwal.exe: $(TOP)\tool\showwal.c $(SQLITE3C) $(SQLITE3H)
|
||||||
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \
|
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
|
||||||
$(TOP)\tool\showwal.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
$(TOP)\tool\showwal.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
||||||
|
|
||||||
changeset.exe: $(TOP)\ext\session\changeset.c $(SQLITE3C)
|
changeset.exe: $(TOP)\ext\session\changeset.c $(SQLITE3C) $(SQLITE3H)
|
||||||
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \
|
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
|
||||||
|
-DSQLITE_ENABLE_SESSION=1 -DSQLITE_ENABLE_PREUPDATE_HOOK=1 \
|
||||||
$(TOP)\ext\session\changeset.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
$(TOP)\ext\session\changeset.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
||||||
|
|
||||||
fts3view.exe: $(TOP)\ext\fts3\tool\fts3view.c $(SQLITE3C) $(SQLITE3H)
|
fts3view.exe: $(TOP)\ext\fts3\tool\fts3view.c $(SQLITE3C) $(SQLITE3H)
|
||||||
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \
|
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
|
||||||
$(TOP)\ext\fts3\tool\fts3view.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
$(TOP)\ext\fts3\tool\fts3view.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
||||||
|
|
||||||
rollback-test.exe: $(TOP)\tool\rollback-test.c $(SQLITE3C) $(SQLITE3H)
|
rollback-test.exe: $(TOP)\tool\rollback-test.c $(SQLITE3C) $(SQLITE3H)
|
||||||
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \
|
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
|
||||||
$(TOP)\tool\rollback-test.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
$(TOP)\tool\rollback-test.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
||||||
|
|
||||||
LogEst.exe: $(TOP)\tool\logest.c $(SQLITE3H)
|
LogEst.exe: $(TOP)\tool\logest.c $(SQLITE3H)
|
||||||
$(LTLINK) $(NO_WARN) -Fe$@ $(TOP)\tool\LogEst.c /link $(LDFLAGS) $(LTLINKOPTS)
|
$(LTLINK) $(NO_WARN) $(TOP)\tool\LogEst.c /link $(LDFLAGS) $(LTLINKOPTS)
|
||||||
|
|
||||||
wordcount.exe: $(TOP)\test\wordcount.c $(SQLITE3C) $(SQLITE3H)
|
wordcount.exe: $(TOP)\test\wordcount.c $(SQLITE3C) $(SQLITE3H)
|
||||||
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \
|
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
|
||||||
$(TOP)\test\wordcount.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
$(TOP)\test\wordcount.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
||||||
|
|
||||||
speedtest1.exe: $(TOP)\test\speedtest1.c $(SQLITE3C) $(SQLITE3H)
|
speedtest1.exe: $(TOP)\test\speedtest1.c $(SQLITE3C) $(SQLITE3H)
|
||||||
$(LTLINK) $(NO_WARN) -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \
|
$(LTLINK) $(NO_WARN) $(ST_COMPILE_OPTS) -DSQLITE_OMIT_LOAD_EXTENSION \
|
||||||
$(TOP)\test\speedtest1.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
$(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)
|
rbu.exe: $(TOP)\ext\rbu\rbu.c $(TOP)\ext\rbu\sqlite3rbu.c $(SQLITE3C) $(SQLITE3H)
|
||||||
$(LTLINK) $(NO_WARN) -DSQLITE_ENABLE_RBU -Fe$@ \
|
$(LTLINK) $(NO_WARN) -DSQLITE_ENABLE_RBU \
|
||||||
$(TOP)\ext\rbu\rbu.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
$(TOP)\ext\rbu\rbu.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
||||||
|
|
||||||
|
LSMDIR=$(TOP)\ext\lsm1
|
||||||
|
!INCLUDE $(LSMDIR)\Makefile.msc
|
||||||
|
|
||||||
moreclean: clean
|
moreclean: clean
|
||||||
del /Q $(SQLITE3C) $(SQLITE3H) 2>NUL
|
del /Q $(SQLITE3C) $(SQLITE3H) 2>NUL
|
||||||
# <</mark>>
|
# <</mark>>
|
||||||
@ -2218,9 +2267,10 @@ clean:
|
|||||||
-rmdir /Q/S tsrc 2>NUL
|
-rmdir /Q/S tsrc 2>NUL
|
||||||
del /Q .target_source 2>NUL
|
del /Q .target_source 2>NUL
|
||||||
del /Q tclsqlite3.exe $(SQLITETCLH) $(SQLITETCLDECLSH) 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 testloadext.dll 2>NUL
|
||||||
del /Q testfixture.exe test.db 2>NUL
|
del /Q testfixture.exe test.db 2>NUL
|
||||||
del /Q LogEst.exe fts3view.exe rollback-test.exe showdb.exe 2>NUL
|
del /Q LogEst.exe fts3view.exe rollback-test.exe showdb.exe dbdump.exe 2>NUL
|
||||||
del /Q changeset.exe 2>NUL
|
del /Q changeset.exe 2>NUL
|
||||||
del /Q showjournal.exe showstat4.exe showwal.exe speedtest1.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
|
del /Q mptester.exe wordcount.exe rbu.exe srcck1.exe 2>NUL
|
||||||
|
124
README.md
124
README.md
@ -8,6 +8,50 @@ 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
|
The [official repository](https://www.sqlite.org/src/) is better. Go there
|
||||||
now.
|
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
|
## Compiling
|
||||||
|
|
||||||
First create a directory in which to place
|
First create a directory in which to place
|
||||||
@ -18,13 +62,13 @@ script found at the root of the source tree. Then run "make".
|
|||||||
|
|
||||||
For example:
|
For example:
|
||||||
|
|
||||||
tar xzf sqlite.tar.gz ;# Unpack the source tree into "sqlite"
|
tar xzf sqlite.tar.gz ;# Unpack the source tree into "sqlite"
|
||||||
mkdir bld ;# Build will occur in a sibling directory
|
mkdir bld ;# Build will occur in a sibling directory
|
||||||
cd bld ;# Change to the build directory
|
cd bld ;# Change to the build directory
|
||||||
../sqlite/configure ;# Run the configure script
|
../sqlite/configure ;# Run the configure script
|
||||||
make ;# Run the makefile.
|
make ;# Run the makefile.
|
||||||
make sqlite3.c ;# Build the "amalgamation" source file
|
make sqlite3.c ;# Build the "amalgamation" source file
|
||||||
make test ;# Run some tests (requires Tcl)
|
make test ;# Run some tests (requires Tcl)
|
||||||
|
|
||||||
See the makefile for additional targets.
|
See the makefile for additional targets.
|
||||||
|
|
||||||
@ -43,13 +87,13 @@ with the provided "Makefile.msc" to build one of the supported targets.
|
|||||||
|
|
||||||
For example:
|
For example:
|
||||||
|
|
||||||
mkdir bld
|
mkdir bld
|
||||||
cd bld
|
cd bld
|
||||||
nmake /f Makefile.msc TOP=..\sqlite
|
nmake /f Makefile.msc TOP=..\sqlite
|
||||||
nmake /f Makefile.msc sqlite3.c TOP=..\sqlite
|
nmake /f Makefile.msc sqlite3.c TOP=..\sqlite
|
||||||
nmake /f Makefile.msc sqlite3.dll TOP=..\sqlite
|
nmake /f Makefile.msc sqlite3.dll TOP=..\sqlite
|
||||||
nmake /f Makefile.msc sqlite3.exe TOP=..\sqlite
|
nmake /f Makefile.msc sqlite3.exe TOP=..\sqlite
|
||||||
nmake /f Makefile.msc test TOP=..\sqlite
|
nmake /f Makefile.msc test TOP=..\sqlite
|
||||||
|
|
||||||
There are several build options that can be set via the NMAKE command
|
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
|
line. For example, to build for WinRT, simply add "FOR_WINRT=1" argument
|
||||||
@ -64,19 +108,22 @@ The makefiles also require AWK.
|
|||||||
|
|
||||||
## Source Code Tour
|
## Source Code Tour
|
||||||
|
|
||||||
Most of the core source files are in the **src/** subdirectory. But
|
Most of the core source files are in the **src/** subdirectory. The
|
||||||
src/ also contains files used to build the "testfixture" test harness;
|
**src/** folder also contains files used to build the "testfixture" test
|
||||||
those file all begin with "test". And src/ contains the "shell.c" file
|
harness. The names of the source files used by "testfixture" all begin
|
||||||
which is the main program for the "sqlite3.exe" command-line shell and
|
with "test".
|
||||||
the "tclsqlite.c" file which implements the bindings to SQLite from the
|
The **src/** also contains the "shell.c" file
|
||||||
Tcl programming language. (Historical note: SQLite began as a Tcl
|
which is the main program for the "sqlite3.exe"
|
||||||
|
[command-line shell](https://sqlite.org/cli.html) and
|
||||||
|
the "tclsqlite.c" file which implements the
|
||||||
|
[TCL bindings](https://sqlite.org/tclsqlite.html) for SQLite.
|
||||||
|
(Historical note: SQLite began as a Tcl
|
||||||
extension and only later escaped to the wild as an independent library.)
|
extension and only later escaped to the wild as an independent library.)
|
||||||
|
|
||||||
Test scripts and programs are found in the **test/** subdirectory.
|
Test scripts and programs are found in the **test/** subdirectory.
|
||||||
There are other test suites for SQLite (see
|
Addtional test code is found in other source repositories.
|
||||||
[How SQLite Is Tested](http://www.sqlite.org/testing.html))
|
See [How SQLite Is Tested](http://www.sqlite.org/testing.html) for
|
||||||
but those other test suites are
|
additional information.
|
||||||
in separate source repositories.
|
|
||||||
|
|
||||||
The **ext/** subdirectory contains code for extensions. The
|
The **ext/** subdirectory contains code for extensions. The
|
||||||
Full-text search engine is in **ext/fts3**. The R-Tree engine is in
|
Full-text search engine is in **ext/fts3**. The R-Tree engine is in
|
||||||
@ -100,7 +147,7 @@ manually-edited files and automatically-generated files.
|
|||||||
The SQLite interface is defined by the **sqlite3.h** header file, which is
|
The SQLite interface is defined by the **sqlite3.h** header file, which is
|
||||||
generated from src/sqlite.h.in, ./manifest.uuid, and ./VERSION. The
|
generated from src/sqlite.h.in, ./manifest.uuid, and ./VERSION. The
|
||||||
[Tcl script](http://www.tcl.tk) at tool/mksqlite3h.tcl does the conversion.
|
[Tcl script](http://www.tcl.tk) at tool/mksqlite3h.tcl does the conversion.
|
||||||
The manifest.uuid file contains the SHA1 hash of the particular check-in
|
The manifest.uuid file contains the SHA3 hash of the particular check-in
|
||||||
and is used to generate the SQLITE\_SOURCE\_ID macro. The VERSION file
|
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
|
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
|
just a copy of src/sqlite.h.in with the source-id and version number inserted
|
||||||
@ -111,9 +158,8 @@ used to generate that documentation are in a separate source repository.
|
|||||||
The SQL language parser is **parse.c** which is generate from a grammar in
|
The 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
|
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
|
by the [lemon](./doc/lemon.html) LALR(1) parser generator. The source code
|
||||||
for lemon is at tool/lemon.c. Lemon uses a
|
for lemon is at tool/lemon.c. Lemon uses the tool/lempar.c file as a
|
||||||
template for generating its parser. A generic template is in tool/lempar.c,
|
template for generating its parser.
|
||||||
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
|
Lemon also generates the **parse.h** header file, at the same time it
|
||||||
generates parse.c. But the parse.h header file is
|
generates parse.c. But the parse.h header file is
|
||||||
@ -133,6 +179,13 @@ that maps SQL language keywords (ex: "CREATE", "SELECT", "INDEX", etc.) into
|
|||||||
the numeric codes used by the parse.c parser. The keywordhash.h file is
|
the numeric codes used by the parse.c parser. The keywordhash.h file is
|
||||||
generated by a C-language program at tool mkkeywordhash.c.
|
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
|
### The Amalgamation
|
||||||
|
|
||||||
All of the individual C source code and header files (both manually-edited
|
All of the individual C source code and header files (both manually-edited
|
||||||
@ -150,7 +203,7 @@ subdirectory (using the equivalent of "make target_source") then the
|
|||||||
tool/mksqlite3c.tcl script is run to copy them all together in just the
|
tool/mksqlite3c.tcl script is run to copy them all together in just the
|
||||||
right order while resolving internal "#include" references.
|
right order while resolving internal "#include" references.
|
||||||
|
|
||||||
The amalgamation source file is more than 100K lines long. Some symbolic
|
The amalgamation source file is more than 200K lines long. Some symbolic
|
||||||
debuggers (most notably MSVC) are unable to deal with files longer than 64K
|
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,
|
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
|
can be run on the amalgamation to break it up into a single small C file
|
||||||
@ -167,14 +220,15 @@ See the [architectural description](http://www.sqlite.org/arch.html)
|
|||||||
for details. Other documents that are useful in
|
for details. Other documents that are useful in
|
||||||
(helping to understand how SQLite works include the
|
(helping to understand how SQLite works include the
|
||||||
[file format](http://www.sqlite.org/fileformat2.html) description,
|
[file format](http://www.sqlite.org/fileformat2.html) description,
|
||||||
the [virtual machine](http://www.sqlite.org/vdbe.html) that runs
|
the [virtual machine](http://www.sqlite.org/opcode.html) that runs
|
||||||
prepared statements, the description of
|
prepared statements, the description of
|
||||||
[how transactions work](http://www.sqlite.org/atomiccommit.html), and
|
[how transactions work](http://www.sqlite.org/atomiccommit.html), and
|
||||||
the [overview of the query planner](http://www.sqlite.org/optoverview.html).
|
the [overview of the query planner](http://www.sqlite.org/optoverview.html).
|
||||||
|
|
||||||
Unfortunately, years of effort have gone into optimizating SQLite, both
|
Years of effort have gone into optimizating SQLite, both
|
||||||
for small size and high performance. And optimizations tend to result in
|
for small size and high performance. And optimizations tend to result in
|
||||||
complex code. So there is a lot of complexity in the SQLite implementation.
|
complex code. So there is a lot of complexity in the current SQLite
|
||||||
|
implementation. It will not be the easiest library in the world to hack.
|
||||||
|
|
||||||
Key files:
|
Key files:
|
||||||
|
|
||||||
@ -185,7 +239,7 @@ Key files:
|
|||||||
* **sqliteInt.h** - this header file defines many of the data objects
|
* **sqliteInt.h** - this header file defines many of the data objects
|
||||||
used internally by SQLite.
|
used internally by SQLite.
|
||||||
|
|
||||||
* **parse.y** - This file describes the LALR(1) grammer that SQLite uses
|
* **parse.y** - This file describes the LALR(1) grammar that SQLite uses
|
||||||
to parse SQL statements, and the actions that are taken at each step
|
to parse SQL statements, and the actions that are taken at each step
|
||||||
in the parsing process.
|
in the parsing process.
|
||||||
|
|
||||||
@ -218,13 +272,13 @@ Key files:
|
|||||||
is not part of the core SQLite library. But as most of the tests in this
|
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.
|
repository are written in Tcl, the Tcl language bindings are important.
|
||||||
|
|
||||||
There are many other source files. Each has a suscinct header comment that
|
There are many other source files. Each has a succinct header comment that
|
||||||
describes its purpose and role within the larger system.
|
describes its purpose and role within the larger system.
|
||||||
|
|
||||||
|
|
||||||
## Contacts
|
## Contacts
|
||||||
|
|
||||||
The main SQLite webpage is [http://www.sqlite.org/](http://www.sqlite.org/)
|
The main SQLite webpage is [http://www.sqlite.org/](http://www.sqlite.org/)
|
||||||
with geographically distributed backup servers at
|
with geographically distributed backups at
|
||||||
[http://www2.sqlite.org/](http://www2.sqlite.org) and
|
[http://www2.sqlite.org/](http://www2.sqlite.org) and
|
||||||
[http://www3.sqlite.org/](http://www3.sqlite.org).
|
[http://www3.sqlite.org/](http://www3.sqlite.org).
|
||||||
|
@ -21,7 +21,14 @@ TOP = .
|
|||||||
# Set this non-0 to enable full warnings (-W4, etc) when compiling.
|
# Set this non-0 to enable full warnings (-W4, etc) when compiling.
|
||||||
#
|
#
|
||||||
!IFNDEF USE_FULLWARN
|
!IFNDEF USE_FULLWARN
|
||||||
USE_FULLWARN = 0
|
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
|
||||||
!ENDIF
|
!ENDIF
|
||||||
|
|
||||||
# Set this non-0 to enable full runtime error checks (-RTC1, etc). This
|
# Set this non-0 to enable full runtime error checks (-RTC1, etc). This
|
||||||
@ -454,6 +461,12 @@ TCC = $(CC) -nologo -W4 -DINCLUDE_MSVC_H=1 $(CCOPTS) $(TCCOPTS)
|
|||||||
TCC = $(CC) -nologo -W3 $(CCOPTS) $(TCCOPTS)
|
TCC = $(CC) -nologo -W3 $(CCOPTS) $(TCCOPTS)
|
||||||
!ENDIF
|
!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
|
TCC = $(TCC) -DSQLITE_OS_WIN=1 -I. -I$(TOP) -fp:precise
|
||||||
RCC = $(RC) -DSQLITE_OS_WIN=1 -I. -I$(TOP) $(RCOPTS) $(RCCOPTS)
|
RCC = $(RC) -DSQLITE_OS_WIN=1 -I. -I$(TOP) $(RCOPTS) $(RCCOPTS)
|
||||||
|
|
||||||
@ -632,6 +645,10 @@ RCC = $(RCC) -DSQLITE_ENABLE_API_ARMOR=1
|
|||||||
!IF $(DEBUG)>2
|
!IF $(DEBUG)>2
|
||||||
TCC = $(TCC) -DSQLITE_DEBUG=1
|
TCC = $(TCC) -DSQLITE_DEBUG=1
|
||||||
RCC = $(RCC) -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
|
!ENDIF
|
||||||
|
|
||||||
!IF $(DEBUG)>4 || $(OSTRACE)!=0
|
!IF $(DEBUG)>4 || $(OSTRACE)!=0
|
||||||
@ -910,7 +927,7 @@ LIBRESOBJS =
|
|||||||
# when the shell is not being dynamically linked.
|
# when the shell is not being dynamically linked.
|
||||||
#
|
#
|
||||||
!IF $(DYNAMIC_SHELL)==0 && $(FOR_WIN10)==0
|
!IF $(DYNAMIC_SHELL)==0 && $(FOR_WIN10)==0
|
||||||
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_SHELL_JSON1 -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS
|
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_SHELL_JSON1 -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_STMTVTAB
|
||||||
!ENDIF
|
!ENDIF
|
||||||
|
|
||||||
|
|
||||||
@ -937,7 +954,7 @@ Replace.exe:
|
|||||||
sqlite3.def: Replace.exe $(LIBOBJ)
|
sqlite3.def: Replace.exe $(LIBOBJ)
|
||||||
echo EXPORTS > sqlite3.def
|
echo EXPORTS > sqlite3.def
|
||||||
dumpbin /all $(LIBOBJ) \
|
dumpbin /all $(LIBOBJ) \
|
||||||
| .\Replace.exe "^\s+/EXPORT:_?(sqlite3_[^@,]*)(?:@\d+|,DATA)?$$" $$1 true \
|
| .\Replace.exe "^\s+/EXPORT:_?(sqlite3(?:session|changeset|changegroup)?_[^@,]*)(?:@\d+|,DATA)?$$" $$1 true \
|
||||||
| sort >> sqlite3.def
|
| sort >> sqlite3.def
|
||||||
|
|
||||||
$(SQLITE3EXE): $(TOP)\shell.c $(SHELL_CORE_DEP) $(LIBRESOBJS) $(SHELL_CORE_SRC) $(SQLITE3H)
|
$(SQLITE3EXE): $(TOP)\shell.c $(SHELL_CORE_DEP) $(LIBRESOBJS) $(SHELL_CORE_SRC) $(SQLITE3H)
|
||||||
|
@ -55,9 +55,9 @@ AS_IF([ test x"$enable_editline" != xno ],[
|
|||||||
LIBS=""
|
LIBS=""
|
||||||
AC_SEARCH_LIBS([readline],[edit],[
|
AC_SEARCH_LIBS([readline],[edit],[
|
||||||
AC_DEFINE([HAVE_EDITLINE],1,Define to use BSD editline)
|
AC_DEFINE([HAVE_EDITLINE],1,Define to use BSD editline)
|
||||||
READLINE_LIBS=$LIBS
|
READLINE_LIBS="$LIBS -ltinfo"
|
||||||
enable_readline=no
|
enable_readline=no
|
||||||
])
|
],[],[-ltinfo])
|
||||||
AS_UNSET(ac_cv_search_readline)
|
AS_UNSET(ac_cv_search_readline)
|
||||||
LIBS=$sLIBS
|
LIBS=$sLIBS
|
||||||
])
|
])
|
||||||
|
40
configure
vendored
40
configure
vendored
@ -1,6 +1,6 @@
|
|||||||
#! /bin/sh
|
#! /bin/sh
|
||||||
# Guess values for system-dependent variables and create Makefiles.
|
# Guess values for system-dependent variables and create Makefiles.
|
||||||
# Generated by GNU Autoconf 2.69 for sqlite 3.15.2.
|
# Generated by GNU Autoconf 2.69 for sqlite 3.20.1.
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
|
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
|
||||||
@ -726,8 +726,8 @@ MAKEFLAGS=
|
|||||||
# Identity of this package.
|
# Identity of this package.
|
||||||
PACKAGE_NAME='sqlite'
|
PACKAGE_NAME='sqlite'
|
||||||
PACKAGE_TARNAME='sqlite'
|
PACKAGE_TARNAME='sqlite'
|
||||||
PACKAGE_VERSION='3.15.2'
|
PACKAGE_VERSION='3.20.1'
|
||||||
PACKAGE_STRING='sqlite 3.15.2'
|
PACKAGE_STRING='sqlite 3.20.1'
|
||||||
PACKAGE_BUGREPORT=''
|
PACKAGE_BUGREPORT=''
|
||||||
PACKAGE_URL=''
|
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.
|
# 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.
|
# This message is too long to be a string in the A/UX 3.1 sh.
|
||||||
cat <<_ACEOF
|
cat <<_ACEOF
|
||||||
\`configure' configures sqlite 3.15.2 to adapt to many kinds of systems.
|
\`configure' configures sqlite 3.20.1 to adapt to many kinds of systems.
|
||||||
|
|
||||||
Usage: $0 [OPTION]... [VAR=VALUE]...
|
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||||
|
|
||||||
@ -1528,7 +1528,7 @@ fi
|
|||||||
|
|
||||||
if test -n "$ac_init_help"; then
|
if test -n "$ac_init_help"; then
|
||||||
case $ac_init_help in
|
case $ac_init_help in
|
||||||
short | recursive ) echo "Configuration of sqlite 3.15.2:";;
|
short | recursive ) echo "Configuration of sqlite 3.20.1:";;
|
||||||
esac
|
esac
|
||||||
cat <<\_ACEOF
|
cat <<\_ACEOF
|
||||||
|
|
||||||
@ -1652,7 +1652,7 @@ fi
|
|||||||
test -n "$ac_init_help" && exit $ac_status
|
test -n "$ac_init_help" && exit $ac_status
|
||||||
if $ac_init_version; then
|
if $ac_init_version; then
|
||||||
cat <<\_ACEOF
|
cat <<\_ACEOF
|
||||||
sqlite configure 3.15.2
|
sqlite configure 3.20.1
|
||||||
generated by GNU Autoconf 2.69
|
generated by GNU Autoconf 2.69
|
||||||
|
|
||||||
Copyright (C) 2012 Free Software Foundation, Inc.
|
Copyright (C) 2012 Free Software Foundation, Inc.
|
||||||
@ -2071,7 +2071,7 @@ cat >config.log <<_ACEOF
|
|||||||
This file contains any messages produced by compilers while
|
This file contains any messages produced by compilers while
|
||||||
running configure, to aid debugging if configure makes a mistake.
|
running configure, to aid debugging if configure makes a mistake.
|
||||||
|
|
||||||
It was created by sqlite $as_me 3.15.2, which was
|
It was created by sqlite $as_me 3.20.1, which was
|
||||||
generated by GNU Autoconf 2.69. Invocation command line was
|
generated by GNU Autoconf 2.69. Invocation command line was
|
||||||
|
|
||||||
$ $0 $@
|
$ $0 $@
|
||||||
@ -11252,7 +11252,7 @@ else
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
if test "${use_debug}" = "yes" ; then
|
if test "${use_debug}" = "yes" ; then
|
||||||
TARGET_DEBUG="-DSQLITE_DEBUG=1"
|
TARGET_DEBUG="-DSQLITE_DEBUG=1 -DSQLITE_ENABLE_SELECTTRACE -DSQLITE_ENABLE_WHERETRACE -O0"
|
||||||
else
|
else
|
||||||
TARGET_DEBUG="-DNDEBUG"
|
TARGET_DEBUG="-DNDEBUG"
|
||||||
fi
|
fi
|
||||||
@ -11356,7 +11356,7 @@ fi
|
|||||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to support MEMSYS5" >&5
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to support MEMSYS5" >&5
|
||||||
$as_echo_n "checking whether to support MEMSYS5... " >&6; }
|
$as_echo_n "checking whether to support MEMSYS5... " >&6; }
|
||||||
if test "${enable_memsys5}" = "yes"; then
|
if test "${enable_memsys5}" = "yes"; then
|
||||||
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_MEMSYS5"
|
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_MEMSYS5"
|
||||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||||
$as_echo "yes" >&6; }
|
$as_echo "yes" >&6; }
|
||||||
else
|
else
|
||||||
@ -11373,7 +11373,7 @@ fi
|
|||||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to support MEMSYS3" >&5
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to support MEMSYS3" >&5
|
||||||
$as_echo_n "checking whether to support MEMSYS3... " >&6; }
|
$as_echo_n "checking whether to support MEMSYS3... " >&6; }
|
||||||
if test "${enable_memsys3}" = "yes" -a "${enable_memsys5}" = "no"; then
|
if test "${enable_memsys3}" = "yes" -a "${enable_memsys5}" = "no"; then
|
||||||
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_MEMSYS3"
|
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_MEMSYS3"
|
||||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||||
$as_echo "yes" >&6; }
|
$as_echo "yes" >&6; }
|
||||||
else
|
else
|
||||||
@ -11391,7 +11391,7 @@ else
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
if test "${enable_fts3}" = "yes" ; then
|
if test "${enable_fts3}" = "yes" ; then
|
||||||
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_FTS3"
|
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_FTS3"
|
||||||
fi
|
fi
|
||||||
# Check whether --enable-fts4 was given.
|
# Check whether --enable-fts4 was given.
|
||||||
if test "${enable_fts4+set}" = set; then :
|
if test "${enable_fts4+set}" = set; then :
|
||||||
@ -11401,7 +11401,7 @@ else
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
if test "${enable_fts4}" = "yes" ; then
|
if test "${enable_fts4}" = "yes" ; then
|
||||||
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_FTS4"
|
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_FTS4"
|
||||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing log" >&5
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing log" >&5
|
||||||
$as_echo_n "checking for library containing log... " >&6; }
|
$as_echo_n "checking for library containing log... " >&6; }
|
||||||
if ${ac_cv_search_log+:} false; then :
|
if ${ac_cv_search_log+:} false; then :
|
||||||
@ -11467,7 +11467,7 @@ else
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
if test "${enable_fts5}" = "yes" ; then
|
if test "${enable_fts5}" = "yes" ; then
|
||||||
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_FTS5"
|
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_FTS5"
|
||||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing log" >&5
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing log" >&5
|
||||||
$as_echo_n "checking for library containing log... " >&6; }
|
$as_echo_n "checking for library containing log... " >&6; }
|
||||||
if ${ac_cv_search_log+:} false; then :
|
if ${ac_cv_search_log+:} false; then :
|
||||||
@ -11536,7 +11536,7 @@ else
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
if test "${enable_json1}" = "yes" ; then
|
if test "${enable_json1}" = "yes" ; then
|
||||||
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_JSON1"
|
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_JSON1"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
#########
|
#########
|
||||||
@ -11549,7 +11549,7 @@ else
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
if test "${enable_rtree}" = "yes" ; then
|
if test "${enable_rtree}" = "yes" ; then
|
||||||
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_RTREE"
|
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_RTREE"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
#########
|
#########
|
||||||
@ -11562,12 +11562,12 @@ else
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
if test "${enable_session}" = "yes" ; then
|
if test "${enable_session}" = "yes" ; then
|
||||||
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_SESSION"
|
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_SESSION"
|
||||||
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_PREUPDATE_HOOK"
|
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_PREUPDATE_HOOK"
|
||||||
fi
|
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
|
for option in $CFLAGS $CPPFLAGS
|
||||||
do
|
do
|
||||||
case $option in
|
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
|
# report actual input values of CONFIG_FILES etc. instead of their
|
||||||
# values after options handling.
|
# values after options handling.
|
||||||
ac_log="
|
ac_log="
|
||||||
This file was extended by sqlite $as_me 3.15.2, which was
|
This file was extended by sqlite $as_me 3.20.1, which was
|
||||||
generated by GNU Autoconf 2.69. Invocation command line was
|
generated by GNU Autoconf 2.69. Invocation command line was
|
||||||
|
|
||||||
CONFIG_FILES = $CONFIG_FILES
|
CONFIG_FILES = $CONFIG_FILES
|
||||||
@ -12217,7 +12217,7 @@ _ACEOF
|
|||||||
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
||||||
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
|
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
|
||||||
ac_cs_version="\\
|
ac_cs_version="\\
|
||||||
sqlite config.status 3.15.2
|
sqlite config.status 3.20.1
|
||||||
configured by $0, generated by GNU Autoconf 2.69,
|
configured by $0, generated by GNU Autoconf 2.69,
|
||||||
with options \\"\$ac_cs_config\\"
|
with options \\"\$ac_cs_config\\"
|
||||||
|
|
||||||
|
22
configure.ac
22
configure.ac
@ -560,7 +560,7 @@ AC_SEARCH_LIBS(fdatasync, [rt])
|
|||||||
AC_ARG_ENABLE(debug, AC_HELP_STRING([--enable-debug],[enable debugging & verbose explain]),
|
AC_ARG_ENABLE(debug, AC_HELP_STRING([--enable-debug],[enable debugging & verbose explain]),
|
||||||
[use_debug=$enableval],[use_debug=no])
|
[use_debug=$enableval],[use_debug=no])
|
||||||
if test "${use_debug}" = "yes" ; then
|
if test "${use_debug}" = "yes" ; then
|
||||||
TARGET_DEBUG="-DSQLITE_DEBUG=1"
|
TARGET_DEBUG="-DSQLITE_DEBUG=1 -DSQLITE_ENABLE_SELECTTRACE -DSQLITE_ENABLE_WHERETRACE -O0"
|
||||||
else
|
else
|
||||||
TARGET_DEBUG="-DNDEBUG"
|
TARGET_DEBUG="-DNDEBUG"
|
||||||
fi
|
fi
|
||||||
@ -596,7 +596,7 @@ AC_ARG_ENABLE(memsys5,
|
|||||||
[enable_memsys5=yes],[enable_memsys5=no])
|
[enable_memsys5=yes],[enable_memsys5=no])
|
||||||
AC_MSG_CHECKING([whether to support MEMSYS5])
|
AC_MSG_CHECKING([whether to support MEMSYS5])
|
||||||
if test "${enable_memsys5}" = "yes"; then
|
if test "${enable_memsys5}" = "yes"; then
|
||||||
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_MEMSYS5"
|
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_MEMSYS5"
|
||||||
AC_MSG_RESULT([yes])
|
AC_MSG_RESULT([yes])
|
||||||
else
|
else
|
||||||
AC_MSG_RESULT([no])
|
AC_MSG_RESULT([no])
|
||||||
@ -606,7 +606,7 @@ AC_ARG_ENABLE(memsys3,
|
|||||||
[enable_memsys3=yes],[enable_memsys3=no])
|
[enable_memsys3=yes],[enable_memsys3=no])
|
||||||
AC_MSG_CHECKING([whether to support MEMSYS3])
|
AC_MSG_CHECKING([whether to support MEMSYS3])
|
||||||
if test "${enable_memsys3}" = "yes" -a "${enable_memsys5}" = "no"; then
|
if test "${enable_memsys3}" = "yes" -a "${enable_memsys5}" = "no"; then
|
||||||
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_MEMSYS3"
|
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_MEMSYS3"
|
||||||
AC_MSG_RESULT([yes])
|
AC_MSG_RESULT([yes])
|
||||||
else
|
else
|
||||||
AC_MSG_RESULT([no])
|
AC_MSG_RESULT([no])
|
||||||
@ -618,20 +618,20 @@ AC_ARG_ENABLE(fts3, AC_HELP_STRING([--enable-fts3],
|
|||||||
[Enable the FTS3 extension]),
|
[Enable the FTS3 extension]),
|
||||||
[enable_fts3=yes],[enable_fts3=no])
|
[enable_fts3=yes],[enable_fts3=no])
|
||||||
if test "${enable_fts3}" = "yes" ; then
|
if test "${enable_fts3}" = "yes" ; then
|
||||||
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_FTS3"
|
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_FTS3"
|
||||||
fi
|
fi
|
||||||
AC_ARG_ENABLE(fts4, AC_HELP_STRING([--enable-fts4],
|
AC_ARG_ENABLE(fts4, AC_HELP_STRING([--enable-fts4],
|
||||||
[Enable the FTS4 extension]),
|
[Enable the FTS4 extension]),
|
||||||
[enable_fts4=yes],[enable_fts4=no])
|
[enable_fts4=yes],[enable_fts4=no])
|
||||||
if test "${enable_fts4}" = "yes" ; then
|
if test "${enable_fts4}" = "yes" ; then
|
||||||
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_FTS4"
|
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_FTS4"
|
||||||
AC_SEARCH_LIBS([log],[m])
|
AC_SEARCH_LIBS([log],[m])
|
||||||
fi
|
fi
|
||||||
AC_ARG_ENABLE(fts5, AC_HELP_STRING([--enable-fts5],
|
AC_ARG_ENABLE(fts5, AC_HELP_STRING([--enable-fts5],
|
||||||
[Enable the FTS5 extension]),
|
[Enable the FTS5 extension]),
|
||||||
[enable_fts5=yes],[enable_fts5=no])
|
[enable_fts5=yes],[enable_fts5=no])
|
||||||
if test "${enable_fts5}" = "yes" ; then
|
if test "${enable_fts5}" = "yes" ; then
|
||||||
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_FTS5"
|
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_FTS5"
|
||||||
AC_SEARCH_LIBS([log],[m])
|
AC_SEARCH_LIBS([log],[m])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@ -641,7 +641,7 @@ AC_ARG_ENABLE(json1, AC_HELP_STRING([--enable-json1],
|
|||||||
[Enable the JSON1 extension]),
|
[Enable the JSON1 extension]),
|
||||||
[enable_json1=yes],[enable_json1=no])
|
[enable_json1=yes],[enable_json1=no])
|
||||||
if test "${enable_json1}" = "yes" ; then
|
if test "${enable_json1}" = "yes" ; then
|
||||||
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_JSON1"
|
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_JSON1"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
#########
|
#########
|
||||||
@ -650,7 +650,7 @@ AC_ARG_ENABLE(rtree, AC_HELP_STRING([--enable-rtree],
|
|||||||
[Enable the RTREE extension]),
|
[Enable the RTREE extension]),
|
||||||
[enable_rtree=yes],[enable_rtree=no])
|
[enable_rtree=yes],[enable_rtree=no])
|
||||||
if test "${enable_rtree}" = "yes" ; then
|
if test "${enable_rtree}" = "yes" ; then
|
||||||
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_RTREE"
|
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_RTREE"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
#########
|
#########
|
||||||
@ -659,12 +659,12 @@ AC_ARG_ENABLE(session, AC_HELP_STRING([--enable-session],
|
|||||||
[Enable the SESSION extension]),
|
[Enable the SESSION extension]),
|
||||||
[enable_session=yes],[enable_session=no])
|
[enable_session=yes],[enable_session=no])
|
||||||
if test "${enable_session}" = "yes" ; then
|
if test "${enable_session}" = "yes" ; then
|
||||||
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_SESSION"
|
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_SESSION"
|
||||||
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_PREUPDATE_HOOK"
|
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_PREUPDATE_HOOK"
|
||||||
fi
|
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
|
for option in $CFLAGS $CPPFLAGS
|
||||||
do
|
do
|
||||||
case $option in
|
case $option in
|
||||||
|
@ -23,6 +23,26 @@ or embedded controllers.</p>
|
|||||||
<p>This document is an introduction to the Lemon
|
<p>This document is an introduction to the Lemon
|
||||||
parser generator.</p>
|
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>
|
<h2>Theory of Operation</h2>
|
||||||
|
|
||||||
<p>The main goal of Lemon is to translate a context free grammar (CFG)
|
<p>The main goal of Lemon is to translate a context free grammar (CFG)
|
||||||
|
8
ext/README.md
Normal file
8
ext/README.md
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
## 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.
|
@ -1,2 +0,0 @@
|
|||||||
Version loadable extensions to SQLite are found in subfolders
|
|
||||||
of this folder.
|
|
367
ext/fts3/fts3.c
367
ext/fts3/fts3.c
@ -349,8 +349,9 @@ int sqlite3Fts3PutVarint(char *p, sqlite_int64 v){
|
|||||||
** Return the number of bytes read, or 0 on error.
|
** Return the number of bytes read, or 0 on error.
|
||||||
** The value is stored in *v.
|
** The value is stored in *v.
|
||||||
*/
|
*/
|
||||||
int sqlite3Fts3GetVarint(const char *p, sqlite_int64 *v){
|
int sqlite3Fts3GetVarint(const char *pBuf, sqlite_int64 *v){
|
||||||
const char *pStart = p;
|
const unsigned char *p = (const unsigned char*)pBuf;
|
||||||
|
const unsigned char *pStart = p;
|
||||||
u32 a;
|
u32 a;
|
||||||
u64 b;
|
u64 b;
|
||||||
int shift;
|
int shift;
|
||||||
@ -371,8 +372,8 @@ int sqlite3Fts3GetVarint(const char *p, sqlite_int64 *v){
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Similar to sqlite3Fts3GetVarint(), except that the output is truncated to a
|
** Similar to sqlite3Fts3GetVarint(), except that the output is truncated to
|
||||||
** 32-bit integer before it is returned.
|
** a non-negative 32-bit integer before it is returned.
|
||||||
*/
|
*/
|
||||||
int sqlite3Fts3GetVarint32(const char *p, int *pi){
|
int sqlite3Fts3GetVarint32(const char *p, int *pi){
|
||||||
u32 a;
|
u32 a;
|
||||||
@ -388,7 +389,9 @@ int sqlite3Fts3GetVarint32(const char *p, int *pi){
|
|||||||
GETVARINT_STEP(a, p, 14, 0x3FFF, 0x200000, *pi, 3);
|
GETVARINT_STEP(a, p, 14, 0x3FFF, 0x200000, *pi, 3);
|
||||||
GETVARINT_STEP(a, p, 21, 0x1FFFFF, 0x10000000, *pi, 4);
|
GETVARINT_STEP(a, p, 21, 0x1FFFFF, 0x10000000, *pi, 4);
|
||||||
a = (a & 0x0FFFFFFF );
|
a = (a & 0x0FFFFFFF );
|
||||||
*pi = (int)(a | ((u32)(*p & 0x0F) << 28));
|
*pi = (int)(a | ((u32)(*p & 0x07) << 28));
|
||||||
|
assert( 0==(a & 0x80000000) );
|
||||||
|
assert( *pi>=0 );
|
||||||
return 5;
|
return 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -492,6 +495,7 @@ static int fts3DisconnectMethod(sqlite3_vtab *pVtab){
|
|||||||
assert( p->pSegments==0 );
|
assert( p->pSegments==0 );
|
||||||
|
|
||||||
/* Free any prepared statements held */
|
/* Free any prepared statements held */
|
||||||
|
sqlite3_finalize(p->pSeekStmt);
|
||||||
for(i=0; i<SizeofArray(p->aStmt); i++){
|
for(i=0; i<SizeofArray(p->aStmt); i++){
|
||||||
sqlite3_finalize(p->aStmt[i]);
|
sqlite3_finalize(p->aStmt[i]);
|
||||||
}
|
}
|
||||||
@ -1217,65 +1221,66 @@ static int fts3InitVtab(
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if( iOpt==SizeofArray(aFts4Opt) ){
|
switch( iOpt ){
|
||||||
sqlite3Fts3ErrMsg(pzErr, "unrecognized parameter: %s", z);
|
case 0: /* MATCHINFO */
|
||||||
rc = SQLITE_ERROR;
|
if( strlen(zVal)!=4 || sqlite3_strnicmp(zVal, "fts3", 4) ){
|
||||||
}else{
|
sqlite3Fts3ErrMsg(pzErr, "unrecognized matchinfo: %s", zVal);
|
||||||
switch( iOpt ){
|
rc = SQLITE_ERROR;
|
||||||
case 0: /* MATCHINFO */
|
}
|
||||||
if( strlen(zVal)!=4 || sqlite3_strnicmp(zVal, "fts3", 4) ){
|
bNoDocsize = 1;
|
||||||
sqlite3Fts3ErrMsg(pzErr, "unrecognized matchinfo: %s", zVal);
|
break;
|
||||||
rc = SQLITE_ERROR;
|
|
||||||
}
|
|
||||||
bNoDocsize = 1;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 1: /* PREFIX */
|
case 1: /* PREFIX */
|
||||||
sqlite3_free(zPrefix);
|
sqlite3_free(zPrefix);
|
||||||
zPrefix = zVal;
|
zPrefix = zVal;
|
||||||
zVal = 0;
|
zVal = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2: /* COMPRESS */
|
case 2: /* COMPRESS */
|
||||||
sqlite3_free(zCompress);
|
sqlite3_free(zCompress);
|
||||||
zCompress = zVal;
|
zCompress = zVal;
|
||||||
zVal = 0;
|
zVal = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3: /* UNCOMPRESS */
|
case 3: /* UNCOMPRESS */
|
||||||
sqlite3_free(zUncompress);
|
sqlite3_free(zUncompress);
|
||||||
zUncompress = zVal;
|
zUncompress = zVal;
|
||||||
zVal = 0;
|
zVal = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 4: /* ORDER */
|
case 4: /* ORDER */
|
||||||
if( (strlen(zVal)!=3 || sqlite3_strnicmp(zVal, "asc", 3))
|
if( (strlen(zVal)!=3 || sqlite3_strnicmp(zVal, "asc", 3))
|
||||||
&& (strlen(zVal)!=4 || sqlite3_strnicmp(zVal, "desc", 4))
|
&& (strlen(zVal)!=4 || sqlite3_strnicmp(zVal, "desc", 4))
|
||||||
){
|
){
|
||||||
sqlite3Fts3ErrMsg(pzErr, "unrecognized order: %s", zVal);
|
sqlite3Fts3ErrMsg(pzErr, "unrecognized order: %s", zVal);
|
||||||
rc = SQLITE_ERROR;
|
rc = SQLITE_ERROR;
|
||||||
}
|
}
|
||||||
bDescIdx = (zVal[0]=='d' || zVal[0]=='D');
|
bDescIdx = (zVal[0]=='d' || zVal[0]=='D');
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 5: /* CONTENT */
|
case 5: /* CONTENT */
|
||||||
sqlite3_free(zContent);
|
sqlite3_free(zContent);
|
||||||
zContent = zVal;
|
zContent = zVal;
|
||||||
zVal = 0;
|
zVal = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 6: /* LANGUAGEID */
|
case 6: /* LANGUAGEID */
|
||||||
assert( iOpt==6 );
|
assert( iOpt==6 );
|
||||||
sqlite3_free(zLanguageid);
|
sqlite3_free(zLanguageid);
|
||||||
zLanguageid = zVal;
|
zLanguageid = zVal;
|
||||||
zVal = 0;
|
zVal = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 7: /* NOTINDEXED */
|
case 7: /* NOTINDEXED */
|
||||||
azNotindexed[nNotindexed++] = zVal;
|
azNotindexed[nNotindexed++] = zVal;
|
||||||
zVal = 0;
|
zVal = 0;
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
default:
|
||||||
|
assert( iOpt==SizeofArray(aFts4Opt) );
|
||||||
|
sqlite3Fts3ErrMsg(pzErr, "unrecognized parameter: %s", z);
|
||||||
|
rc = SQLITE_ERROR;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
sqlite3_free(zVal);
|
sqlite3_free(zVal);
|
||||||
}
|
}
|
||||||
@ -1363,9 +1368,9 @@ static int fts3InitVtab(
|
|||||||
p->pTokenizer = pTokenizer;
|
p->pTokenizer = pTokenizer;
|
||||||
p->nMaxPendingData = FTS3_MAX_PENDING_DATA;
|
p->nMaxPendingData = FTS3_MAX_PENDING_DATA;
|
||||||
p->bHasDocsize = (isFts4 && bNoDocsize==0);
|
p->bHasDocsize = (isFts4 && bNoDocsize==0);
|
||||||
p->bHasStat = isFts4;
|
p->bHasStat = (u8)isFts4;
|
||||||
p->bFts4 = isFts4;
|
p->bFts4 = (u8)isFts4;
|
||||||
p->bDescIdx = bDescIdx;
|
p->bDescIdx = (u8)bDescIdx;
|
||||||
p->nAutoincrmerge = 0xff; /* 0xff means setting unknown */
|
p->nAutoincrmerge = 0xff; /* 0xff means setting unknown */
|
||||||
p->zContentTbl = zContent;
|
p->zContentTbl = zContent;
|
||||||
p->zLanguageid = zLanguageid;
|
p->zLanguageid = zLanguageid;
|
||||||
@ -1396,7 +1401,9 @@ static int fts3InitVtab(
|
|||||||
char *z;
|
char *z;
|
||||||
int n = 0;
|
int n = 0;
|
||||||
z = (char *)sqlite3Fts3NextToken(aCol[iCol], &n);
|
z = (char *)sqlite3Fts3NextToken(aCol[iCol], &n);
|
||||||
memcpy(zCsr, z, n);
|
if( n>0 ){
|
||||||
|
memcpy(zCsr, z, n);
|
||||||
|
}
|
||||||
zCsr[n] = '\0';
|
zCsr[n] = '\0';
|
||||||
sqlite3Fts3Dequote(zCsr);
|
sqlite3Fts3Dequote(zCsr);
|
||||||
p->azColumn[iCol] = zCsr;
|
p->azColumn[iCol] = zCsr;
|
||||||
@ -1680,6 +1687,39 @@ static int fts3OpenMethod(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCsr){
|
|||||||
return SQLITE_OK;
|
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
|
** Close the cursor. For additional information see the documentation
|
||||||
** on the xClose method of the virtual table interface.
|
** on the xClose method of the virtual table interface.
|
||||||
@ -1687,11 +1727,7 @@ static int fts3OpenMethod(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCsr){
|
|||||||
static int fts3CloseMethod(sqlite3_vtab_cursor *pCursor){
|
static int fts3CloseMethod(sqlite3_vtab_cursor *pCursor){
|
||||||
Fts3Cursor *pCsr = (Fts3Cursor *)pCursor;
|
Fts3Cursor *pCsr = (Fts3Cursor *)pCursor;
|
||||||
assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 );
|
assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 );
|
||||||
sqlite3_finalize(pCsr->pStmt);
|
fts3ClearCursor(pCsr);
|
||||||
sqlite3Fts3ExprFree(pCsr->pExpr);
|
|
||||||
sqlite3Fts3FreeDeferredTokens(pCsr);
|
|
||||||
sqlite3_free(pCsr->aDoclist);
|
|
||||||
sqlite3Fts3MIBufferFree(pCsr->pMIBuffer);
|
|
||||||
assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 );
|
assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 );
|
||||||
sqlite3_free(pCsr);
|
sqlite3_free(pCsr);
|
||||||
return SQLITE_OK;
|
return SQLITE_OK;
|
||||||
@ -1705,20 +1741,23 @@ static int fts3CloseMethod(sqlite3_vtab_cursor *pCursor){
|
|||||||
**
|
**
|
||||||
** (or the equivalent for a content=xxx table) and set pCsr->pStmt to
|
** (or the equivalent for a content=xxx table) and set pCsr->pStmt to
|
||||||
** it. If an error occurs, return an SQLite error code.
|
** 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, sqlite3_stmt **ppStmt){
|
static int fts3CursorSeekStmt(Fts3Cursor *pCsr){
|
||||||
int rc = SQLITE_OK;
|
int rc = SQLITE_OK;
|
||||||
if( pCsr->pStmt==0 ){
|
if( pCsr->pStmt==0 ){
|
||||||
Fts3Table *p = (Fts3Table *)pCsr->base.pVtab;
|
Fts3Table *p = (Fts3Table *)pCsr->base.pVtab;
|
||||||
char *zSql;
|
char *zSql;
|
||||||
zSql = sqlite3_mprintf("SELECT %s WHERE rowid = ?", p->zReadExprlist);
|
if( p->pSeekStmt ){
|
||||||
if( !zSql ) return SQLITE_NOMEM;
|
pCsr->pStmt = p->pSeekStmt;
|
||||||
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pCsr->pStmt, 0);
|
p->pSeekStmt = 0;
|
||||||
sqlite3_free(zSql);
|
}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;
|
||||||
}
|
}
|
||||||
*ppStmt = pCsr->pStmt;
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1730,9 +1769,7 @@ static int fts3CursorSeekStmt(Fts3Cursor *pCsr, sqlite3_stmt **ppStmt){
|
|||||||
static int fts3CursorSeek(sqlite3_context *pContext, Fts3Cursor *pCsr){
|
static int fts3CursorSeek(sqlite3_context *pContext, Fts3Cursor *pCsr){
|
||||||
int rc = SQLITE_OK;
|
int rc = SQLITE_OK;
|
||||||
if( pCsr->isRequireSeek ){
|
if( pCsr->isRequireSeek ){
|
||||||
sqlite3_stmt *pStmt = 0;
|
rc = fts3CursorSeekStmt(pCsr);
|
||||||
|
|
||||||
rc = fts3CursorSeekStmt(pCsr, &pStmt);
|
|
||||||
if( rc==SQLITE_OK ){
|
if( rc==SQLITE_OK ){
|
||||||
sqlite3_bind_int64(pCsr->pStmt, 1, pCsr->iPrevId);
|
sqlite3_bind_int64(pCsr->pStmt, 1, pCsr->iPrevId);
|
||||||
pCsr->isRequireSeek = 0;
|
pCsr->isRequireSeek = 0;
|
||||||
@ -1821,7 +1858,8 @@ static int fts3ScanInteriorNode(
|
|||||||
isFirstTerm = 0;
|
isFirstTerm = 0;
|
||||||
zCsr += fts3GetVarint32(zCsr, &nSuffix);
|
zCsr += fts3GetVarint32(zCsr, &nSuffix);
|
||||||
|
|
||||||
if( nPrefix<0 || nSuffix<0 || &zCsr[nSuffix]>zEnd ){
|
assert( nPrefix>=0 && nSuffix>=0 );
|
||||||
|
if( &zCsr[nSuffix]>zEnd ){
|
||||||
rc = FTS_CORRUPT_VTAB;
|
rc = FTS_CORRUPT_VTAB;
|
||||||
goto finish_scan;
|
goto finish_scan;
|
||||||
}
|
}
|
||||||
@ -2631,7 +2669,7 @@ int sqlite3Fts3FirstFilter(
|
|||||||
fts3ColumnlistCopy(0, &p);
|
fts3ColumnlistCopy(0, &p);
|
||||||
}
|
}
|
||||||
|
|
||||||
while( p<pEnd && *p==0x01 ){
|
while( p<pEnd ){
|
||||||
sqlite3_int64 iCol;
|
sqlite3_int64 iCol;
|
||||||
p++;
|
p++;
|
||||||
p += sqlite3Fts3GetVarint(p, &iCol);
|
p += sqlite3Fts3GetVarint(p, &iCol);
|
||||||
@ -3190,11 +3228,7 @@ static int fts3FilterMethod(
|
|||||||
assert( iIdx==nVal );
|
assert( iIdx==nVal );
|
||||||
|
|
||||||
/* In case the cursor has been used before, clear it now. */
|
/* In case the cursor has been used before, clear it now. */
|
||||||
sqlite3_finalize(pCsr->pStmt);
|
fts3ClearCursor(pCsr);
|
||||||
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 */
|
/* Set the lower and upper bounds on docids to return */
|
||||||
pCsr->iMinDocid = fts3DocidRange(pDocidGe, SMALLEST_INT64);
|
pCsr->iMinDocid = fts3DocidRange(pDocidGe, SMALLEST_INT64);
|
||||||
@ -3252,13 +3286,13 @@ static int fts3FilterMethod(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
if( zSql ){
|
if( zSql ){
|
||||||
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pCsr->pStmt, 0);
|
rc = sqlite3_prepare_v3(p->db,zSql,-1,SQLITE_PREPARE_PERSISTENT,&pCsr->pStmt,0);
|
||||||
sqlite3_free(zSql);
|
sqlite3_free(zSql);
|
||||||
}else{
|
}else{
|
||||||
rc = SQLITE_NOMEM;
|
rc = SQLITE_NOMEM;
|
||||||
}
|
}
|
||||||
}else if( eSearch==FTS3_DOCID_SEARCH ){
|
}else if( eSearch==FTS3_DOCID_SEARCH ){
|
||||||
rc = fts3CursorSeekStmt(pCsr, &pCsr->pStmt);
|
rc = fts3CursorSeekStmt(pCsr);
|
||||||
if( rc==SQLITE_OK ){
|
if( rc==SQLITE_OK ){
|
||||||
rc = sqlite3_bind_value(pCsr->pStmt, 1, pCons);
|
rc = sqlite3_bind_value(pCsr->pStmt, 1, pCons);
|
||||||
}
|
}
|
||||||
@ -3273,7 +3307,12 @@ static int fts3FilterMethod(
|
|||||||
** routine to find out if it has reached the end of a result set.
|
** routine to find out if it has reached the end of a result set.
|
||||||
*/
|
*/
|
||||||
static int fts3EofMethod(sqlite3_vtab_cursor *pCursor){
|
static int fts3EofMethod(sqlite3_vtab_cursor *pCursor){
|
||||||
return ((Fts3Cursor *)pCursor)->isEof;
|
Fts3Cursor *pCsr = (Fts3Cursor*)pCursor;
|
||||||
|
if( pCsr->isEof ){
|
||||||
|
fts3ClearCursor(pCsr);
|
||||||
|
pCsr->isEof = 1;
|
||||||
|
}
|
||||||
|
return pCsr->isEof;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -3311,33 +3350,37 @@ static int fts3ColumnMethod(
|
|||||||
/* The column value supplied by SQLite must be in range. */
|
/* The column value supplied by SQLite must be in range. */
|
||||||
assert( iCol>=0 && iCol<=p->nColumn+2 );
|
assert( iCol>=0 && iCol<=p->nColumn+2 );
|
||||||
|
|
||||||
if( iCol==p->nColumn+1 ){
|
switch( iCol-p->nColumn ){
|
||||||
/* This call is a request for the "docid" column. Since "docid" is an
|
case 0:
|
||||||
** alias for "rowid", use the xRowid() method to obtain the value.
|
/* The special 'table-name' column */
|
||||||
*/
|
sqlite3_result_pointer(pCtx, pCsr, "fts3cursor", 0);
|
||||||
sqlite3_result_int64(pCtx, pCsr->iPrevId);
|
break;
|
||||||
}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);
|
|
||||||
|
|
||||||
if( rc==SQLITE_OK ){
|
case 1:
|
||||||
if( iCol==p->nColumn+2 ){
|
/* The docid column */
|
||||||
int iLangid = 0;
|
sqlite3_result_int64(pCtx, pCsr->iPrevId);
|
||||||
if( p->zLanguageid ){
|
break;
|
||||||
iLangid = sqlite3_column_int(pCsr->pStmt, p->nColumn+1);
|
|
||||||
}
|
case 2:
|
||||||
sqlite3_result_int(pCtx, iLangid);
|
if( pCsr->pExpr ){
|
||||||
}else if( sqlite3_data_count(pCsr->pStmt)>(iCol+1) ){
|
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 ){
|
||||||
sqlite3_result_value(pCtx, sqlite3_column_value(pCsr->pStmt, iCol+1));
|
sqlite3_result_value(pCtx, sqlite3_column_value(pCsr->pStmt, iCol+1));
|
||||||
}
|
}
|
||||||
}
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 );
|
assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 );
|
||||||
@ -3386,8 +3429,10 @@ static int fts3SyncMethod(sqlite3_vtab *pVtab){
|
|||||||
const u32 nMinMerge = 64; /* Minimum amount of incr-merge work to do */
|
const u32 nMinMerge = 64; /* Minimum amount of incr-merge work to do */
|
||||||
|
|
||||||
Fts3Table *p = (Fts3Table*)pVtab;
|
Fts3Table *p = (Fts3Table*)pVtab;
|
||||||
int rc = sqlite3Fts3PendingTermsFlush(p);
|
int rc;
|
||||||
|
i64 iLastRowid = sqlite3_last_insert_rowid(p->db);
|
||||||
|
|
||||||
|
rc = sqlite3Fts3PendingTermsFlush(p);
|
||||||
if( rc==SQLITE_OK
|
if( rc==SQLITE_OK
|
||||||
&& p->nLeafAdd>(nMinMerge/16)
|
&& p->nLeafAdd>(nMinMerge/16)
|
||||||
&& p->nAutoincrmerge && p->nAutoincrmerge!=0xff
|
&& p->nAutoincrmerge && p->nAutoincrmerge!=0xff
|
||||||
@ -3402,6 +3447,7 @@ static int fts3SyncMethod(sqlite3_vtab *pVtab){
|
|||||||
if( A>(int)nMinMerge ) rc = sqlite3Fts3Incrmerge(p, A, p->nAutoincrmerge);
|
if( A>(int)nMinMerge ) rc = sqlite3Fts3Incrmerge(p, A, p->nAutoincrmerge);
|
||||||
}
|
}
|
||||||
sqlite3Fts3SegmentsClose(p);
|
sqlite3Fts3SegmentsClose(p);
|
||||||
|
sqlite3_set_last_insert_rowid(p->db, iLastRowid);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3414,17 +3460,11 @@ static int fts3SyncMethod(sqlite3_vtab *pVtab){
|
|||||||
static int fts3SetHasStat(Fts3Table *p){
|
static int fts3SetHasStat(Fts3Table *p){
|
||||||
int rc = SQLITE_OK;
|
int rc = SQLITE_OK;
|
||||||
if( p->bHasStat==2 ){
|
if( p->bHasStat==2 ){
|
||||||
const char *zFmt ="SELECT 1 FROM %Q.sqlite_master WHERE tbl_name='%q_stat'";
|
char *zTbl = sqlite3_mprintf("%s_stat", p->zName);
|
||||||
char *zSql = sqlite3_mprintf(zFmt, p->zDb, p->zName);
|
if( zTbl ){
|
||||||
if( zSql ){
|
int res = sqlite3_table_column_metadata(p->db, p->zDb, zTbl, 0,0,0,0,0,0);
|
||||||
sqlite3_stmt *pStmt = 0;
|
sqlite3_free(zTbl);
|
||||||
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
|
p->bHasStat = (res==SQLITE_OK);
|
||||||
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{
|
}else{
|
||||||
rc = SQLITE_NOMEM;
|
rc = SQLITE_NOMEM;
|
||||||
}
|
}
|
||||||
@ -3531,18 +3571,17 @@ static int fts3FunctionArg(
|
|||||||
sqlite3_value *pVal, /* argv[0] passed to function */
|
sqlite3_value *pVal, /* argv[0] passed to function */
|
||||||
Fts3Cursor **ppCsr /* OUT: Store cursor handle here */
|
Fts3Cursor **ppCsr /* OUT: Store cursor handle here */
|
||||||
){
|
){
|
||||||
Fts3Cursor *pRet;
|
int rc;
|
||||||
if( sqlite3_value_type(pVal)!=SQLITE_BLOB
|
*ppCsr = (Fts3Cursor*)sqlite3_value_pointer(pVal, "fts3cursor");
|
||||||
|| sqlite3_value_bytes(pVal)!=sizeof(Fts3Cursor *)
|
if( (*ppCsr)!=0 ){
|
||||||
){
|
rc = SQLITE_OK;
|
||||||
|
}else{
|
||||||
char *zErr = sqlite3_mprintf("illegal first argument to %s", zFunc);
|
char *zErr = sqlite3_mprintf("illegal first argument to %s", zFunc);
|
||||||
sqlite3_result_error(pContext, zErr, -1);
|
sqlite3_result_error(pContext, zErr, -1);
|
||||||
sqlite3_free(zErr);
|
sqlite3_free(zErr);
|
||||||
return SQLITE_ERROR;
|
rc = SQLITE_ERROR;
|
||||||
}
|
}
|
||||||
memcpy(&pRet, sqlite3_value_blob(pVal), sizeof(Fts3Cursor *));
|
return rc;
|
||||||
*ppCsr = pRet;
|
|
||||||
return SQLITE_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -3929,7 +3968,7 @@ int sqlite3Fts3Init(sqlite3 *db){
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Create the virtual table wrapper around the hash-table and overload
|
/* Create the virtual table wrapper around the hash-table and overload
|
||||||
** the two scalar functions. If this is successful, register the
|
** the four scalar functions. If this is successful, register the
|
||||||
** module with sqlite.
|
** module with sqlite.
|
||||||
*/
|
*/
|
||||||
if( SQLITE_OK==rc
|
if( SQLITE_OK==rc
|
||||||
@ -4512,7 +4551,7 @@ static int fts3EvalIncrPhraseNext(
|
|||||||
** one incremental token. In which case the bIncr flag is set. */
|
** one incremental token. In which case the bIncr flag is set. */
|
||||||
assert( p->bIncr==1 );
|
assert( p->bIncr==1 );
|
||||||
|
|
||||||
if( p->nToken==1 && p->bIncr ){
|
if( p->nToken==1 ){
|
||||||
rc = sqlite3Fts3MsrIncrNext(pTab, p->aToken[0].pSegcsr,
|
rc = sqlite3Fts3MsrIncrNext(pTab, p->aToken[0].pSegcsr,
|
||||||
&pDL->iDocid, &pDL->pList, &pDL->nList
|
&pDL->iDocid, &pDL->pList, &pDL->nList
|
||||||
);
|
);
|
||||||
@ -4745,6 +4784,7 @@ static void fts3EvalTokenCosts(
|
|||||||
** the number of overflow pages consumed by a record B bytes in size.
|
** the number of overflow pages consumed by a record B bytes in size.
|
||||||
*/
|
*/
|
||||||
static int fts3EvalAverageDocsize(Fts3Cursor *pCsr, int *pnPage){
|
static int fts3EvalAverageDocsize(Fts3Cursor *pCsr, int *pnPage){
|
||||||
|
int rc = SQLITE_OK;
|
||||||
if( pCsr->nRowAvg==0 ){
|
if( pCsr->nRowAvg==0 ){
|
||||||
/* The average document size, which is required to calculate the cost
|
/* The average document size, which is required to calculate the cost
|
||||||
** of each doclist, has not yet been determined. Read the required
|
** of each doclist, has not yet been determined. Read the required
|
||||||
@ -4757,7 +4797,6 @@ static int fts3EvalAverageDocsize(Fts3Cursor *pCsr, int *pnPage){
|
|||||||
** data stored in all rows of each column of the table, from left
|
** data stored in all rows of each column of the table, from left
|
||||||
** to right.
|
** to right.
|
||||||
*/
|
*/
|
||||||
int rc;
|
|
||||||
Fts3Table *p = (Fts3Table*)pCsr->base.pVtab;
|
Fts3Table *p = (Fts3Table*)pCsr->base.pVtab;
|
||||||
sqlite3_stmt *pStmt;
|
sqlite3_stmt *pStmt;
|
||||||
sqlite3_int64 nDoc = 0;
|
sqlite3_int64 nDoc = 0;
|
||||||
@ -4784,11 +4823,10 @@ static int fts3EvalAverageDocsize(Fts3Cursor *pCsr, int *pnPage){
|
|||||||
pCsr->nRowAvg = (int)(((nByte / nDoc) + p->nPgsz) / p->nPgsz);
|
pCsr->nRowAvg = (int)(((nByte / nDoc) + p->nPgsz) / p->nPgsz);
|
||||||
assert( pCsr->nRowAvg>0 );
|
assert( pCsr->nRowAvg>0 );
|
||||||
rc = sqlite3_reset(pStmt);
|
rc = sqlite3_reset(pStmt);
|
||||||
if( rc!=SQLITE_OK ) return rc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
*pnPage = pCsr->nRowAvg;
|
*pnPage = pCsr->nRowAvg;
|
||||||
return SQLITE_OK;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -5138,7 +5176,8 @@ static void fts3EvalNextRow(
|
|||||||
pExpr->iDocid = pLeft->iDocid;
|
pExpr->iDocid = pLeft->iDocid;
|
||||||
pExpr->bEof = (pLeft->bEof || pRight->bEof);
|
pExpr->bEof = (pLeft->bEof || pRight->bEof);
|
||||||
if( pExpr->eType==FTSQUERY_NEAR && pExpr->bEof ){
|
if( pExpr->eType==FTSQUERY_NEAR && pExpr->bEof ){
|
||||||
if( pRight->pPhrase && pRight->pPhrase->doclist.aAll ){
|
assert( pRight->eType==FTSQUERY_PHRASE );
|
||||||
|
if( pRight->pPhrase->doclist.aAll ){
|
||||||
Fts3Doclist *pDl = &pRight->pPhrase->doclist;
|
Fts3Doclist *pDl = &pRight->pPhrase->doclist;
|
||||||
while( *pRc==SQLITE_OK && pRight->bEof==0 ){
|
while( *pRc==SQLITE_OK && pRight->bEof==0 ){
|
||||||
memset(pDl->pList, 0, pDl->nList);
|
memset(pDl->pList, 0, pDl->nList);
|
||||||
@ -5167,7 +5206,7 @@ static void fts3EvalNextRow(
|
|||||||
|
|
||||||
if( pRight->bEof || (pLeft->bEof==0 && iCmp<0) ){
|
if( pRight->bEof || (pLeft->bEof==0 && iCmp<0) ){
|
||||||
fts3EvalNextRow(pCsr, pLeft, pRc);
|
fts3EvalNextRow(pCsr, pLeft, pRc);
|
||||||
}else if( pLeft->bEof || (pRight->bEof==0 && iCmp>0) ){
|
}else if( pLeft->bEof || iCmp>0 ){
|
||||||
fts3EvalNextRow(pCsr, pRight, pRc);
|
fts3EvalNextRow(pCsr, pRight, pRc);
|
||||||
}else{
|
}else{
|
||||||
fts3EvalNextRow(pCsr, pLeft, pRc);
|
fts3EvalNextRow(pCsr, pLeft, pRc);
|
||||||
@ -5259,7 +5298,6 @@ static int fts3EvalNearTest(Fts3Expr *pExpr, int *pRc){
|
|||||||
*/
|
*/
|
||||||
if( *pRc==SQLITE_OK
|
if( *pRc==SQLITE_OK
|
||||||
&& pExpr->eType==FTSQUERY_NEAR
|
&& pExpr->eType==FTSQUERY_NEAR
|
||||||
&& pExpr->bEof==0
|
|
||||||
&& (pExpr->pParent==0 || pExpr->pParent->eType!=FTSQUERY_NEAR)
|
&& (pExpr->pParent==0 || pExpr->pParent->eType!=FTSQUERY_NEAR)
|
||||||
){
|
){
|
||||||
Fts3Expr *p;
|
Fts3Expr *p;
|
||||||
@ -5268,42 +5306,39 @@ static int fts3EvalNearTest(Fts3Expr *pExpr, int *pRc){
|
|||||||
|
|
||||||
/* Allocate temporary working space. */
|
/* Allocate temporary working space. */
|
||||||
for(p=pExpr; p->pLeft; p=p->pLeft){
|
for(p=pExpr; p->pLeft; p=p->pLeft){
|
||||||
|
assert( p->pRight->pPhrase->doclist.nList>0 );
|
||||||
nTmp += p->pRight->pPhrase->doclist.nList;
|
nTmp += p->pRight->pPhrase->doclist.nList;
|
||||||
}
|
}
|
||||||
nTmp += p->pPhrase->doclist.nList;
|
nTmp += p->pPhrase->doclist.nList;
|
||||||
if( nTmp==0 ){
|
aTmp = sqlite3_malloc(nTmp*2);
|
||||||
|
if( !aTmp ){
|
||||||
|
*pRc = SQLITE_NOMEM;
|
||||||
res = 0;
|
res = 0;
|
||||||
}else{
|
}else{
|
||||||
aTmp = sqlite3_malloc(nTmp*2);
|
char *aPoslist = p->pPhrase->doclist.pList;
|
||||||
if( !aTmp ){
|
int nToken = p->pPhrase->nToken;
|
||||||
*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){
|
for(p=p->pParent;res && p && p->eType==FTSQUERY_NEAR; p=p->pParent){
|
||||||
Fts3Phrase *pPhrase = p->pRight->pPhrase;
|
Fts3Phrase *pPhrase = p->pRight->pPhrase;
|
||||||
int nNear = p->nNear;
|
int nNear = p->nNear;
|
||||||
res = fts3EvalNearTrim(nNear, aTmp, &aPoslist, &nToken, 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);
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
|
@ -230,6 +230,7 @@ struct Fts3Table {
|
|||||||
** statements is run and reset within a single virtual table API call.
|
** statements is run and reset within a single virtual table API call.
|
||||||
*/
|
*/
|
||||||
sqlite3_stmt *aStmt[40];
|
sqlite3_stmt *aStmt[40];
|
||||||
|
sqlite3_stmt *pSeekStmt; /* Cache for fts3CursorSeekStmt() */
|
||||||
|
|
||||||
char *zReadExprlist;
|
char *zReadExprlist;
|
||||||
char *zWriteExprlist;
|
char *zWriteExprlist;
|
||||||
@ -299,6 +300,7 @@ struct Fts3Cursor {
|
|||||||
i16 eSearch; /* Search strategy (see below) */
|
i16 eSearch; /* Search strategy (see below) */
|
||||||
u8 isEof; /* True if at End Of Results */
|
u8 isEof; /* True if at End Of Results */
|
||||||
u8 isRequireSeek; /* True if must seek pStmt to %_content row */
|
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 */
|
sqlite3_stmt *pStmt; /* Prepared statement in use by the cursor */
|
||||||
Fts3Expr *pExpr; /* Parsed MATCH query string */
|
Fts3Expr *pExpr; /* Parsed MATCH query string */
|
||||||
int iLangid; /* Language being queried for */
|
int iLangid; /* Language being queried for */
|
||||||
|
@ -136,16 +136,16 @@ static int unicodeAddExceptions(
|
|||||||
){
|
){
|
||||||
const unsigned char *z = (const unsigned char *)zIn;
|
const unsigned char *z = (const unsigned char *)zIn;
|
||||||
const unsigned char *zTerm = &z[nIn];
|
const unsigned char *zTerm = &z[nIn];
|
||||||
int iCode;
|
unsigned int iCode;
|
||||||
int nEntry = 0;
|
int nEntry = 0;
|
||||||
|
|
||||||
assert( bAlnum==0 || bAlnum==1 );
|
assert( bAlnum==0 || bAlnum==1 );
|
||||||
|
|
||||||
while( z<zTerm ){
|
while( z<zTerm ){
|
||||||
READ_UTF8(z, zTerm, iCode);
|
READ_UTF8(z, zTerm, iCode);
|
||||||
assert( (sqlite3FtsUnicodeIsalnum(iCode) & 0xFFFFFFFE)==0 );
|
assert( (sqlite3FtsUnicodeIsalnum((int)iCode) & 0xFFFFFFFE)==0 );
|
||||||
if( sqlite3FtsUnicodeIsalnum(iCode)!=bAlnum
|
if( sqlite3FtsUnicodeIsalnum((int)iCode)!=bAlnum
|
||||||
&& sqlite3FtsUnicodeIsdiacritic(iCode)==0
|
&& sqlite3FtsUnicodeIsdiacritic((int)iCode)==0
|
||||||
){
|
){
|
||||||
nEntry++;
|
nEntry++;
|
||||||
}
|
}
|
||||||
@ -162,13 +162,13 @@ static int unicodeAddExceptions(
|
|||||||
z = (const unsigned char *)zIn;
|
z = (const unsigned char *)zIn;
|
||||||
while( z<zTerm ){
|
while( z<zTerm ){
|
||||||
READ_UTF8(z, zTerm, iCode);
|
READ_UTF8(z, zTerm, iCode);
|
||||||
if( sqlite3FtsUnicodeIsalnum(iCode)!=bAlnum
|
if( sqlite3FtsUnicodeIsalnum((int)iCode)!=bAlnum
|
||||||
&& sqlite3FtsUnicodeIsdiacritic(iCode)==0
|
&& sqlite3FtsUnicodeIsdiacritic((int)iCode)==0
|
||||||
){
|
){
|
||||||
int i, j;
|
int i, j;
|
||||||
for(i=0; i<nNew && aNew[i]<iCode; i++);
|
for(i=0; i<nNew && aNew[i]<(int)iCode; i++);
|
||||||
for(j=nNew; j>i; j--) aNew[j] = aNew[j-1];
|
for(j=nNew; j>i; j--) aNew[j] = aNew[j-1];
|
||||||
aNew[i] = iCode;
|
aNew[i] = (int)iCode;
|
||||||
nNew++;
|
nNew++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -318,7 +318,7 @@ static int unicodeNext(
|
|||||||
){
|
){
|
||||||
unicode_cursor *pCsr = (unicode_cursor *)pC;
|
unicode_cursor *pCsr = (unicode_cursor *)pC;
|
||||||
unicode_tokenizer *p = ((unicode_tokenizer *)pCsr->base.pTokenizer);
|
unicode_tokenizer *p = ((unicode_tokenizer *)pCsr->base.pTokenizer);
|
||||||
int iCode = 0;
|
unsigned int iCode = 0;
|
||||||
char *zOut;
|
char *zOut;
|
||||||
const unsigned char *z = &pCsr->aInput[pCsr->iOff];
|
const unsigned char *z = &pCsr->aInput[pCsr->iOff];
|
||||||
const unsigned char *zStart = z;
|
const unsigned char *zStart = z;
|
||||||
@ -330,7 +330,7 @@ static int unicodeNext(
|
|||||||
** the input. */
|
** the input. */
|
||||||
while( z<zTerm ){
|
while( z<zTerm ){
|
||||||
READ_UTF8(z, zTerm, iCode);
|
READ_UTF8(z, zTerm, iCode);
|
||||||
if( unicodeIsAlnum(p, iCode) ) break;
|
if( unicodeIsAlnum(p, (int)iCode) ) break;
|
||||||
zStart = z;
|
zStart = z;
|
||||||
}
|
}
|
||||||
if( zStart>=zTerm ) return SQLITE_DONE;
|
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 */
|
/* Write the folded case of the last character read to the output */
|
||||||
zEnd = z;
|
zEnd = z;
|
||||||
iOut = sqlite3FtsUnicodeFold(iCode, p->bRemoveDiacritic);
|
iOut = sqlite3FtsUnicodeFold((int)iCode, p->bRemoveDiacritic);
|
||||||
if( iOut ){
|
if( iOut ){
|
||||||
WRITE_UTF8(zOut, iOut);
|
WRITE_UTF8(zOut, iOut);
|
||||||
}
|
}
|
||||||
@ -358,8 +358,8 @@ static int unicodeNext(
|
|||||||
/* If the cursor is not at EOF, read the next character */
|
/* If the cursor is not at EOF, read the next character */
|
||||||
if( z>=zTerm ) break;
|
if( z>=zTerm ) break;
|
||||||
READ_UTF8(z, zTerm, iCode);
|
READ_UTF8(z, zTerm, iCode);
|
||||||
}while( unicodeIsAlnum(p, iCode)
|
}while( unicodeIsAlnum(p, (int)iCode)
|
||||||
|| sqlite3FtsUnicodeIsdiacritic(iCode)
|
|| sqlite3FtsUnicodeIsdiacritic((int)iCode)
|
||||||
);
|
);
|
||||||
|
|
||||||
/* Set the output variables and return. */
|
/* Set the output variables and return. */
|
||||||
|
@ -127,9 +127,9 @@ int sqlite3FtsUnicodeIsalnum(int c){
|
|||||||
0xFFFFFFFF, 0xFC00FFFF, 0xF8000001, 0xF8000001,
|
0xFFFFFFFF, 0xFC00FFFF, 0xF8000001, 0xF8000001,
|
||||||
};
|
};
|
||||||
|
|
||||||
if( c<128 ){
|
if( (unsigned int)c<128 ){
|
||||||
return ( (aAscii[c >> 5] & (1 << (c & 0x001F)))==0 );
|
return ( (aAscii[c >> 5] & ((unsigned int)1 << (c & 0x001F)))==0 );
|
||||||
}else if( c<(1<<22) ){
|
}else if( (unsigned int)c<(1<<22) ){
|
||||||
unsigned int key = (((unsigned int)c)<<10) | 0x000003FF;
|
unsigned int key = (((unsigned int)c)<<10) | 0x000003FF;
|
||||||
int iRes = 0;
|
int iRes = 0;
|
||||||
int iHi = sizeof(aEntry)/sizeof(aEntry[0]) - 1;
|
int iHi = sizeof(aEntry)/sizeof(aEntry[0]) - 1;
|
||||||
@ -322,16 +322,17 @@ int sqlite3FtsUnicodeFold(int c, int bRemoveDiacritic){
|
|||||||
|
|
||||||
int ret = c;
|
int ret = c;
|
||||||
|
|
||||||
assert( c>=0 );
|
|
||||||
assert( sizeof(unsigned short)==2 && sizeof(unsigned char)==1 );
|
assert( sizeof(unsigned short)==2 && sizeof(unsigned char)==1 );
|
||||||
|
|
||||||
if( c<128 ){
|
if( c<128 ){
|
||||||
if( c>='A' && c<='Z' ) ret = c + ('a' - 'A');
|
if( c>='A' && c<='Z' ) ret = c + ('a' - 'A');
|
||||||
}else if( c<65536 ){
|
}else if( c<65536 ){
|
||||||
|
const struct TableEntry *p;
|
||||||
int iHi = sizeof(aEntry)/sizeof(aEntry[0]) - 1;
|
int iHi = sizeof(aEntry)/sizeof(aEntry[0]) - 1;
|
||||||
int iLo = 0;
|
int iLo = 0;
|
||||||
int iRes = -1;
|
int iRes = -1;
|
||||||
|
|
||||||
|
assert( c>aEntry[0].iCode );
|
||||||
while( iHi>=iLo ){
|
while( iHi>=iLo ){
|
||||||
int iTest = (iHi + iLo) / 2;
|
int iTest = (iHi + iLo) / 2;
|
||||||
int cmp = (c - aEntry[iTest].iCode);
|
int cmp = (c - aEntry[iTest].iCode);
|
||||||
@ -342,14 +343,12 @@ int sqlite3FtsUnicodeFold(int c, int bRemoveDiacritic){
|
|||||||
iHi = iTest-1;
|
iHi = iTest-1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert( iRes<0 || c>=aEntry[iRes].iCode );
|
|
||||||
|
|
||||||
if( iRes>=0 ){
|
assert( iRes>=0 && c>=aEntry[iRes].iCode );
|
||||||
const struct TableEntry *p = &aEntry[iRes];
|
p = &aEntry[iRes];
|
||||||
if( c<(p->iCode + p->nRange) && 0==(0x01 & p->flags & (p->iCode ^ c)) ){
|
if( c<(p->iCode + p->nRange) && 0==(0x01 & p->flags & (p->iCode ^ c)) ){
|
||||||
ret = (c + (aiOff[p->flags>>1])) & 0x0000FFFF;
|
ret = (c + (aiOff[p->flags>>1])) & 0x0000FFFF;
|
||||||
assert( ret>0 );
|
assert( ret>0 );
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if( bRemoveDiacritic ) ret = remove_diacritic(ret);
|
if( bRemoveDiacritic ) ret = remove_diacritic(ret);
|
||||||
|
@ -407,7 +407,8 @@ static int fts3SqlStmt(
|
|||||||
if( !zSql ){
|
if( !zSql ){
|
||||||
rc = SQLITE_NOMEM;
|
rc = SQLITE_NOMEM;
|
||||||
}else{
|
}else{
|
||||||
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, NULL);
|
rc = sqlite3_prepare_v3(p->db, zSql, -1, SQLITE_PREPARE_PERSISTENT,
|
||||||
|
&pStmt, NULL);
|
||||||
sqlite3_free(zSql);
|
sqlite3_free(zSql);
|
||||||
assert( rc==SQLITE_OK || pStmt==0 );
|
assert( rc==SQLITE_OK || pStmt==0 );
|
||||||
p->aStmt[eStmt] = pStmt;
|
p->aStmt[eStmt] = pStmt;
|
||||||
@ -4956,11 +4957,14 @@ int sqlite3Fts3Incrmerge(Fts3Table *p, int nMerge, int nMin){
|
|||||||
** Convert the text beginning at *pz into an integer and return
|
** Convert the text beginning at *pz into an integer and return
|
||||||
** its value. Advance *pz to point to the first character past
|
** its value. Advance *pz to point to the first character past
|
||||||
** the integer.
|
** the integer.
|
||||||
|
**
|
||||||
|
** This function used for parameters to merge= and incrmerge=
|
||||||
|
** commands.
|
||||||
*/
|
*/
|
||||||
static int fts3Getint(const char **pz){
|
static int fts3Getint(const char **pz){
|
||||||
const char *z = *pz;
|
const char *z = *pz;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while( (*z)>='0' && (*z)<='9' ) i = 10*i + *(z++) - '0';
|
while( (*z)>='0' && (*z)<='9' && i<214748363 ) i = 10*i + *(z++) - '0';
|
||||||
*pz = z;
|
*pz = z;
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
16
ext/fts3/tool/fts3cov.sh
Normal file
16
ext/fts3/tool/fts3cov.sh
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#!/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
|
an_print_ascii_bitmap $lRange
|
||||||
puts {
|
puts {
|
||||||
if( (unsigned int)c<128 ){
|
if( (unsigned int)c<128 ){
|
||||||
return ( (aAscii[c >> 5] & (1 << (c & 0x001F)))==0 );
|
return ( (aAscii[c >> 5] & ((unsigned int)1 << (c & 0x001F)))==0 );
|
||||||
}else if( (unsigned int)c<(1<<22) ){
|
}else if( (unsigned int)c<(1<<22) ){
|
||||||
unsigned int key = (((unsigned int)c)<<10) | 0x000003FF;
|
unsigned int key = (((unsigned int)c)<<10) | 0x000003FF;
|
||||||
int iRes = 0;
|
int iRes = 0;
|
||||||
|
@ -30,7 +30,9 @@ typedef short i16;
|
|||||||
typedef sqlite3_int64 i64;
|
typedef sqlite3_int64 i64;
|
||||||
typedef sqlite3_uint64 u64;
|
typedef sqlite3_uint64 u64;
|
||||||
|
|
||||||
#define ArraySize(x) ((int)(sizeof(x) / sizeof(x[0])))
|
#ifndef ArraySize
|
||||||
|
# define ArraySize(x) ((int)(sizeof(x) / sizeof(x[0])))
|
||||||
|
#endif
|
||||||
|
|
||||||
#define testcase(x)
|
#define testcase(x)
|
||||||
#define ALWAYS(x) 1
|
#define ALWAYS(x) 1
|
||||||
@ -444,9 +446,9 @@ int sqlite3Fts5IndexBeginWrite(
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
** Flush any data stored in the in-memory hash tables to the database.
|
** Flush any data stored in the in-memory hash tables to the database.
|
||||||
** If the bCommit flag is true, also close any open blob handles.
|
** Also close any open blob handles.
|
||||||
*/
|
*/
|
||||||
int sqlite3Fts5IndexSync(Fts5Index *p, int bCommit);
|
int sqlite3Fts5IndexSync(Fts5Index *p);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Discard any data stored in the in-memory hash tables. Do not write it
|
** Discard any data stored in the in-memory hash tables. Do not write it
|
||||||
@ -616,7 +618,7 @@ int sqlite3Fts5StorageDocsize(Fts5Storage *p, i64 iRowid, int *aCol);
|
|||||||
int sqlite3Fts5StorageSize(Fts5Storage *p, int iCol, i64 *pnAvg);
|
int sqlite3Fts5StorageSize(Fts5Storage *p, int iCol, i64 *pnAvg);
|
||||||
int sqlite3Fts5StorageRowCount(Fts5Storage *p, i64 *pnRow);
|
int sqlite3Fts5StorageRowCount(Fts5Storage *p, i64 *pnRow);
|
||||||
|
|
||||||
int sqlite3Fts5StorageSync(Fts5Storage *p, int bCommit);
|
int sqlite3Fts5StorageSync(Fts5Storage *p);
|
||||||
int sqlite3Fts5StorageRollback(Fts5Storage *p);
|
int sqlite3Fts5StorageRollback(Fts5Storage *p);
|
||||||
|
|
||||||
int sqlite3Fts5StorageConfigValue(
|
int sqlite3Fts5StorageConfigValue(
|
||||||
@ -652,6 +654,7 @@ struct Fts5Token {
|
|||||||
/* Parse a MATCH expression. */
|
/* Parse a MATCH expression. */
|
||||||
int sqlite3Fts5ExprNew(
|
int sqlite3Fts5ExprNew(
|
||||||
Fts5Config *pConfig,
|
Fts5Config *pConfig,
|
||||||
|
int iCol, /* Column on LHS of MATCH operator */
|
||||||
const char *zExpr,
|
const char *zExpr,
|
||||||
Fts5Expr **ppNew,
|
Fts5Expr **ppNew,
|
||||||
char **pzErr
|
char **pzErr
|
||||||
@ -736,7 +739,7 @@ void sqlite3Fts5ParseNearsetFree(Fts5ExprNearset*);
|
|||||||
void sqlite3Fts5ParseNodeFree(Fts5ExprNode*);
|
void sqlite3Fts5ParseNodeFree(Fts5ExprNode*);
|
||||||
|
|
||||||
void sqlite3Fts5ParseSetDistance(Fts5Parse*, Fts5ExprNearset*, Fts5Token*);
|
void sqlite3Fts5ParseSetDistance(Fts5Parse*, Fts5ExprNearset*, Fts5Token*);
|
||||||
void sqlite3Fts5ParseSetColset(Fts5Parse*, Fts5ExprNearset*, Fts5Colset*);
|
void sqlite3Fts5ParseSetColset(Fts5Parse*, Fts5ExprNode*, Fts5Colset*);
|
||||||
Fts5Colset *sqlite3Fts5ParseColsetInvert(Fts5Parse*, Fts5Colset*);
|
Fts5Colset *sqlite3Fts5ParseColsetInvert(Fts5Parse*, Fts5Colset*);
|
||||||
void sqlite3Fts5ParseFinished(Fts5Parse *pParse, Fts5ExprNode *p);
|
void sqlite3Fts5ParseFinished(Fts5Parse *pParse, Fts5ExprNode *p);
|
||||||
void sqlite3Fts5ParseNear(Fts5Parse *pParse, Fts5Token*);
|
void sqlite3Fts5ParseNear(Fts5Parse *pParse, Fts5Token*);
|
||||||
|
@ -67,9 +67,11 @@ void sqlite3Fts5BufferAppendBlob(
|
|||||||
const u8 *pData
|
const u8 *pData
|
||||||
){
|
){
|
||||||
assert_nc( *pRc || nData>=0 );
|
assert_nc( *pRc || nData>=0 );
|
||||||
if( fts5BufferGrow(pRc, pBuf, nData) ) return;
|
if( nData ){
|
||||||
memcpy(&pBuf->p[pBuf->n], pData, nData);
|
if( fts5BufferGrow(pRc, pBuf, nData) ) return;
|
||||||
pBuf->n += nData;
|
memcpy(&pBuf->p[pBuf->n], pData, nData);
|
||||||
|
pBuf->n += nData;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -246,8 +248,8 @@ void *sqlite3Fts5MallocZero(int *pRc, int nByte){
|
|||||||
void *pRet = 0;
|
void *pRet = 0;
|
||||||
if( *pRc==SQLITE_OK ){
|
if( *pRc==SQLITE_OK ){
|
||||||
pRet = sqlite3_malloc(nByte);
|
pRet = sqlite3_malloc(nByte);
|
||||||
if( pRet==0 && nByte>0 ){
|
if( pRet==0 ){
|
||||||
*pRc = SQLITE_NOMEM;
|
if( nByte>0 ) *pRc = SQLITE_NOMEM;
|
||||||
}else{
|
}else{
|
||||||
memset(pRet, 0, nByte);
|
memset(pRet, 0, nByte);
|
||||||
}
|
}
|
||||||
|
@ -213,6 +213,7 @@ static void fts5ParseFree(void *p){ sqlite3_free(p); }
|
|||||||
|
|
||||||
int sqlite3Fts5ExprNew(
|
int sqlite3Fts5ExprNew(
|
||||||
Fts5Config *pConfig, /* FTS5 Configuration */
|
Fts5Config *pConfig, /* FTS5 Configuration */
|
||||||
|
int iCol,
|
||||||
const char *zExpr, /* Expression text */
|
const char *zExpr, /* Expression text */
|
||||||
Fts5Expr **ppNew,
|
Fts5Expr **ppNew,
|
||||||
char **pzErr
|
char **pzErr
|
||||||
@ -237,6 +238,18 @@ int sqlite3Fts5ExprNew(
|
|||||||
}while( sParse.rc==SQLITE_OK && t!=FTS5_EOF );
|
}while( sParse.rc==SQLITE_OK && t!=FTS5_EOF );
|
||||||
sqlite3Fts5ParserFree(pEngine, fts5ParseFree);
|
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 );
|
assert( sParse.rc!=SQLITE_OK || sParse.zErr==0 );
|
||||||
if( sParse.rc==SQLITE_OK ){
|
if( sParse.rc==SQLITE_OK ){
|
||||||
*ppNew = pNew = sqlite3_malloc(sizeof(Fts5Expr));
|
*ppNew = pNew = sqlite3_malloc(sizeof(Fts5Expr));
|
||||||
@ -746,48 +759,61 @@ static int fts5ExprNearTest(
|
|||||||
** Initialize all term iterators in the pNear object. If any term is found
|
** Initialize all term iterators in the pNear object. If any term is found
|
||||||
** to match no documents at all, return immediately without initializing any
|
** to match no documents at all, return immediately without initializing any
|
||||||
** further iterators.
|
** 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(
|
static int fts5ExprNearInitAll(
|
||||||
Fts5Expr *pExpr,
|
Fts5Expr *pExpr,
|
||||||
Fts5ExprNode *pNode
|
Fts5ExprNode *pNode
|
||||||
){
|
){
|
||||||
Fts5ExprNearset *pNear = pNode->pNear;
|
Fts5ExprNearset *pNear = pNode->pNear;
|
||||||
int i, j;
|
int i;
|
||||||
int rc = SQLITE_OK;
|
|
||||||
int bEof = 1;
|
|
||||||
|
|
||||||
assert( pNode->bNomatch==0 );
|
assert( pNode->bNomatch==0 );
|
||||||
for(i=0; rc==SQLITE_OK && i<pNear->nPhrase; i++){
|
for(i=0; i<pNear->nPhrase; i++){
|
||||||
Fts5ExprPhrase *pPhrase = pNear->apPhrase[i];
|
Fts5ExprPhrase *pPhrase = pNear->apPhrase[i];
|
||||||
for(j=0; j<pPhrase->nTerm; j++){
|
if( pPhrase->nTerm==0 ){
|
||||||
Fts5ExprTerm *pTerm = &pPhrase->aTerm[j];
|
pNode->bEof = 1;
|
||||||
Fts5ExprTerm *p;
|
return SQLITE_OK;
|
||||||
|
}else{
|
||||||
|
int j;
|
||||||
|
for(j=0; j<pPhrase->nTerm; j++){
|
||||||
|
Fts5ExprTerm *pTerm = &pPhrase->aTerm[j];
|
||||||
|
Fts5ExprTerm *p;
|
||||||
|
int bHit = 0;
|
||||||
|
|
||||||
for(p=pTerm; p && rc==SQLITE_OK; p=p->pSynonym){
|
for(p=pTerm; p; p=p->pSynonym){
|
||||||
if( p->pIter ){
|
int rc;
|
||||||
sqlite3Fts5IterClose(p->pIter);
|
if( p->pIter ){
|
||||||
p->pIter = 0;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
rc = sqlite3Fts5IndexQuery(
|
|
||||||
pExpr->pIndex, p->zTerm, (int)strlen(p->zTerm),
|
if( bHit==0 ){
|
||||||
(pTerm->bPrefix ? FTS5INDEX_QUERY_PREFIX : 0) |
|
pNode->bEof = 1;
|
||||||
(pExpr->bDesc ? FTS5INDEX_QUERY_DESC : 0),
|
return SQLITE_OK;
|
||||||
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 = bEof;
|
pNode->bEof = 0;
|
||||||
return rc;
|
return SQLITE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1097,7 +1123,10 @@ static int fts5ExprNodeNext_OR(
|
|||||||
|| (bFromValid && fts5RowidCmp(pExpr, p1->iRowid, iFrom)<0)
|
|| (bFromValid && fts5RowidCmp(pExpr, p1->iRowid, iFrom)<0)
|
||||||
){
|
){
|
||||||
int rc = fts5ExprNodeNext(pExpr, p1, bFromValid, iFrom);
|
int rc = fts5ExprNodeNext(pExpr, p1, bFromValid, iFrom);
|
||||||
if( rc!=SQLITE_OK ) return rc;
|
if( rc!=SQLITE_OK ){
|
||||||
|
pNode->bNomatch = 0;
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1128,7 +1157,10 @@ static int fts5ExprNodeTest_AND(
|
|||||||
if( cmp>0 ){
|
if( cmp>0 ){
|
||||||
/* Advance pChild until it points to iLast or laster */
|
/* Advance pChild until it points to iLast or laster */
|
||||||
rc = fts5ExprNodeNext(pExpr, pChild, 1, iLast);
|
rc = fts5ExprNodeNext(pExpr, pChild, 1, iLast);
|
||||||
if( rc!=SQLITE_OK ) return rc;
|
if( rc!=SQLITE_OK ){
|
||||||
|
pAnd->bNomatch = 0;
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If the child node is now at EOF, so is the parent AND node. Otherwise,
|
/* If the child node is now at EOF, so is the parent AND node. Otherwise,
|
||||||
@ -1167,6 +1199,8 @@ static int fts5ExprNodeNext_AND(
|
|||||||
int rc = fts5ExprNodeNext(pExpr, pNode->apChild[0], bFromValid, iFrom);
|
int rc = fts5ExprNodeNext(pExpr, pNode->apChild[0], bFromValid, iFrom);
|
||||||
if( rc==SQLITE_OK ){
|
if( rc==SQLITE_OK ){
|
||||||
rc = fts5ExprNodeTest_AND(pExpr, pNode);
|
rc = fts5ExprNodeTest_AND(pExpr, pNode);
|
||||||
|
}else{
|
||||||
|
pNode->bNomatch = 0;
|
||||||
}
|
}
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@ -1209,6 +1243,9 @@ static int fts5ExprNodeNext_NOT(
|
|||||||
if( rc==SQLITE_OK ){
|
if( rc==SQLITE_OK ){
|
||||||
rc = fts5ExprNodeTest_NOT(pExpr, pNode);
|
rc = fts5ExprNodeTest_NOT(pExpr, pNode);
|
||||||
}
|
}
|
||||||
|
if( rc!=SQLITE_OK ){
|
||||||
|
pNode->bNomatch = 0;
|
||||||
|
}
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1331,7 +1368,10 @@ int sqlite3Fts5ExprFirst(Fts5Expr *p, Fts5Index *pIdx, i64 iFirst, int bDesc){
|
|||||||
|
|
||||||
/* If not at EOF but the current rowid occurs earlier than iFirst in
|
/* If not at EOF but the current rowid occurs earlier than iFirst in
|
||||||
** the iteration order, move to document iFirst or later. */
|
** the iteration order, move to document iFirst or later. */
|
||||||
if( pRoot->bEof==0 && fts5RowidCmp(p, pRoot->iRowid, iFirst)<0 ){
|
if( rc==SQLITE_OK
|
||||||
|
&& 0==pRoot->bEof
|
||||||
|
&& fts5RowidCmp(p, pRoot->iRowid, iFirst)<0
|
||||||
|
){
|
||||||
rc = fts5ExprNodeNext(p, pRoot, 1, iFirst);
|
rc = fts5ExprNodeNext(p, pRoot, 1, iFirst);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1585,7 +1625,7 @@ Fts5ExprPhrase *sqlite3Fts5ParseTerm(
|
|||||||
|
|
||||||
rc = fts5ParseStringFromToken(pToken, &z);
|
rc = fts5ParseStringFromToken(pToken, &z);
|
||||||
if( rc==SQLITE_OK ){
|
if( rc==SQLITE_OK ){
|
||||||
int flags = FTS5_TOKENIZE_QUERY | (bPrefix ? FTS5_TOKENIZE_QUERY : 0);
|
int flags = FTS5_TOKENIZE_QUERY | (bPrefix ? FTS5_TOKENIZE_PREFIX : 0);
|
||||||
int n;
|
int n;
|
||||||
sqlite3Fts5Dequote(z);
|
sqlite3Fts5Dequote(z);
|
||||||
n = (int)strlen(z);
|
n = (int)strlen(z);
|
||||||
@ -1859,25 +1899,110 @@ Fts5Colset *sqlite3Fts5ParseColset(
|
|||||||
return pRet;
|
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(
|
void sqlite3Fts5ParseSetColset(
|
||||||
Fts5Parse *pParse,
|
Fts5Parse *pParse,
|
||||||
Fts5ExprNearset *pNear,
|
Fts5ExprNode *pExpr,
|
||||||
Fts5Colset *pColset
|
Fts5Colset *pColset
|
||||||
){
|
){
|
||||||
|
Fts5Colset *pFree = pColset;
|
||||||
if( pParse->pConfig->eDetail==FTS5_DETAIL_NONE ){
|
if( pParse->pConfig->eDetail==FTS5_DETAIL_NONE ){
|
||||||
pParse->rc = SQLITE_ERROR;
|
pParse->rc = SQLITE_ERROR;
|
||||||
pParse->zErr = sqlite3_mprintf(
|
pParse->zErr = sqlite3_mprintf(
|
||||||
"fts5: column queries are not supported (detail=none)"
|
"fts5: column queries are not supported (detail=none)"
|
||||||
);
|
);
|
||||||
sqlite3_free(pColset);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( pNear ){
|
|
||||||
pNear->pColset = pColset;
|
|
||||||
}else{
|
}else{
|
||||||
sqlite3_free(pColset);
|
fts5ParseSetColset(pParse, pExpr, pColset, &pFree);
|
||||||
}
|
}
|
||||||
|
sqlite3_free(pFree);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void fts5ExprAssignXNext(Fts5ExprNode *pNode){
|
static void fts5ExprAssignXNext(Fts5ExprNode *pNode){
|
||||||
@ -2331,7 +2456,7 @@ static void fts5ExprFunction(
|
|||||||
|
|
||||||
rc = sqlite3Fts5ConfigParse(pGlobal, db, nConfig, azConfig, &pConfig, &zErr);
|
rc = sqlite3Fts5ConfigParse(pGlobal, db, nConfig, azConfig, &pConfig, &zErr);
|
||||||
if( rc==SQLITE_OK ){
|
if( rc==SQLITE_OK ){
|
||||||
rc = sqlite3Fts5ExprNew(pConfig, zExpr, &pExpr, &zErr);
|
rc = sqlite3Fts5ExprNew(pConfig, pConfig->nCol, zExpr, &pExpr, &zErr);
|
||||||
}
|
}
|
||||||
if( rc==SQLITE_OK ){
|
if( rc==SQLITE_OK ){
|
||||||
char *zText;
|
char *zText;
|
||||||
|
@ -36,9 +36,10 @@ struct Fts5Hash {
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
** Each entry in the hash table is represented by an object of the
|
** Each entry in the hash table is represented by an object of the
|
||||||
** following type. Each object, its key (zKey[]) and its current data
|
** following type. Each object, its key (a nul-terminated string) and
|
||||||
** are stored in a single memory allocation. The position list data
|
** its current data are stored in a single memory allocation. The
|
||||||
** immediately follows the key data in memory.
|
** key immediately follows the object in memory. 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
|
** The data that follows the key is in a similar, but not identical format
|
||||||
** to the doclist data stored in the database. It is:
|
** to the doclist data stored in the database. It is:
|
||||||
@ -62,20 +63,20 @@ struct Fts5HashEntry {
|
|||||||
int nAlloc; /* Total size of allocation */
|
int nAlloc; /* Total size of allocation */
|
||||||
int iSzPoslist; /* Offset of space for 4-byte poslist size */
|
int iSzPoslist; /* Offset of space for 4-byte poslist size */
|
||||||
int nData; /* Total bytes of data (incl. structure) */
|
int nData; /* Total bytes of data (incl. structure) */
|
||||||
int nKey; /* Length of zKey[] in bytes */
|
int nKey; /* Length of key in bytes */
|
||||||
u8 bDel; /* Set delete-flag @ iSzPoslist */
|
u8 bDel; /* Set delete-flag @ iSzPoslist */
|
||||||
u8 bContent; /* Set content-flag (detail=none mode) */
|
u8 bContent; /* Set content-flag (detail=none mode) */
|
||||||
i16 iCol; /* Column of last value written */
|
i16 iCol; /* Column of last value written */
|
||||||
int iPos; /* Position of last value written */
|
int iPos; /* Position of last value written */
|
||||||
i64 iRowid; /* Rowid of last value written */
|
i64 iRowid; /* Rowid of last value written */
|
||||||
char zKey[8]; /* Nul-terminated entry key */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Size of Fts5HashEntry without the zKey[] array.
|
** Eqivalent to:
|
||||||
|
**
|
||||||
|
** char *fts5EntryKey(Fts5HashEntry *pEntry){ return zKey; }
|
||||||
*/
|
*/
|
||||||
#define FTS5_HASHENTRYSIZE (sizeof(Fts5HashEntry)-8)
|
#define fts5EntryKey(p) ( ((char *)(&(p)[1])) )
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -170,10 +171,11 @@ static int fts5HashResize(Fts5Hash *pHash){
|
|||||||
|
|
||||||
for(i=0; i<pHash->nSlot; i++){
|
for(i=0; i<pHash->nSlot; i++){
|
||||||
while( apOld[i] ){
|
while( apOld[i] ){
|
||||||
int iHash;
|
unsigned int iHash;
|
||||||
Fts5HashEntry *p = apOld[i];
|
Fts5HashEntry *p = apOld[i];
|
||||||
apOld[i] = p->pHashNext;
|
apOld[i] = p->pHashNext;
|
||||||
iHash = fts5HashKey(nNew, (u8*)p->zKey, (int)strlen(p->zKey));
|
iHash = fts5HashKey(nNew, (u8*)fts5EntryKey(p),
|
||||||
|
(int)strlen(fts5EntryKey(p)));
|
||||||
p->pHashNext = apNew[iHash];
|
p->pHashNext = apNew[iHash];
|
||||||
apNew[iHash] = p;
|
apNew[iHash] = p;
|
||||||
}
|
}
|
||||||
@ -244,9 +246,10 @@ int sqlite3Fts5HashWrite(
|
|||||||
/* Attempt to locate an existing hash entry */
|
/* Attempt to locate an existing hash entry */
|
||||||
iHash = fts5HashKey2(pHash->nSlot, (u8)bByte, (const u8*)pToken, nToken);
|
iHash = fts5HashKey2(pHash->nSlot, (u8)bByte, (const u8*)pToken, nToken);
|
||||||
for(p=pHash->aSlot[iHash]; p; p=p->pHashNext){
|
for(p=pHash->aSlot[iHash]; p; p=p->pHashNext){
|
||||||
if( p->zKey[0]==bByte
|
char *zKey = fts5EntryKey(p);
|
||||||
|
if( zKey[0]==bByte
|
||||||
&& p->nKey==nToken
|
&& p->nKey==nToken
|
||||||
&& memcmp(&p->zKey[1], pToken, nToken)==0
|
&& memcmp(&zKey[1], pToken, nToken)==0
|
||||||
){
|
){
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -255,7 +258,8 @@ int sqlite3Fts5HashWrite(
|
|||||||
/* If an existing hash entry cannot be found, create a new one. */
|
/* If an existing hash entry cannot be found, create a new one. */
|
||||||
if( p==0 ){
|
if( p==0 ){
|
||||||
/* Figure out how much space to allocate */
|
/* Figure out how much space to allocate */
|
||||||
int nByte = FTS5_HASHENTRYSIZE + (nToken+1) + 1 + 64;
|
char *zKey;
|
||||||
|
int nByte = sizeof(Fts5HashEntry) + (nToken+1) + 1 + 64;
|
||||||
if( nByte<128 ) nByte = 128;
|
if( nByte<128 ) nByte = 128;
|
||||||
|
|
||||||
/* Grow the Fts5Hash.aSlot[] array if necessary. */
|
/* Grow the Fts5Hash.aSlot[] array if necessary. */
|
||||||
@ -268,14 +272,15 @@ int sqlite3Fts5HashWrite(
|
|||||||
/* Allocate new Fts5HashEntry and add it to the hash table. */
|
/* Allocate new Fts5HashEntry and add it to the hash table. */
|
||||||
p = (Fts5HashEntry*)sqlite3_malloc(nByte);
|
p = (Fts5HashEntry*)sqlite3_malloc(nByte);
|
||||||
if( !p ) return SQLITE_NOMEM;
|
if( !p ) return SQLITE_NOMEM;
|
||||||
memset(p, 0, FTS5_HASHENTRYSIZE);
|
memset(p, 0, sizeof(Fts5HashEntry));
|
||||||
p->nAlloc = nByte;
|
p->nAlloc = nByte;
|
||||||
p->zKey[0] = bByte;
|
zKey = fts5EntryKey(p);
|
||||||
memcpy(&p->zKey[1], pToken, nToken);
|
zKey[0] = bByte;
|
||||||
assert( iHash==fts5HashKey(pHash->nSlot, (u8*)p->zKey, nToken+1) );
|
memcpy(&zKey[1], pToken, nToken);
|
||||||
|
assert( iHash==fts5HashKey(pHash->nSlot, (u8*)zKey, nToken+1) );
|
||||||
p->nKey = nToken;
|
p->nKey = nToken;
|
||||||
p->zKey[nToken+1] = '\0';
|
zKey[nToken+1] = '\0';
|
||||||
p->nData = nToken+1 + 1 + FTS5_HASHENTRYSIZE;
|
p->nData = nToken+1 + 1 + sizeof(Fts5HashEntry);
|
||||||
p->pHashNext = pHash->aSlot[iHash];
|
p->pHashNext = pHash->aSlot[iHash];
|
||||||
pHash->aSlot[iHash] = p;
|
pHash->aSlot[iHash] = p;
|
||||||
pHash->nEntry++;
|
pHash->nEntry++;
|
||||||
@ -393,9 +398,11 @@ static Fts5HashEntry *fts5HashEntryMerge(
|
|||||||
p1 = 0;
|
p1 = 0;
|
||||||
}else{
|
}else{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while( p1->zKey[i]==p2->zKey[i] ) i++;
|
char *zKey1 = fts5EntryKey(p1);
|
||||||
|
char *zKey2 = fts5EntryKey(p2);
|
||||||
|
while( zKey1[i]==zKey2[i] ) i++;
|
||||||
|
|
||||||
if( ((u8)p1->zKey[i])>((u8)p2->zKey[i]) ){
|
if( ((u8)zKey1[i])>((u8)zKey2[i]) ){
|
||||||
/* p2 is smaller */
|
/* p2 is smaller */
|
||||||
*ppOut = p2;
|
*ppOut = p2;
|
||||||
ppOut = &p2->pScanNext;
|
ppOut = &p2->pScanNext;
|
||||||
@ -438,7 +445,7 @@ static int fts5HashEntrySort(
|
|||||||
for(iSlot=0; iSlot<pHash->nSlot; iSlot++){
|
for(iSlot=0; iSlot<pHash->nSlot; iSlot++){
|
||||||
Fts5HashEntry *pIter;
|
Fts5HashEntry *pIter;
|
||||||
for(pIter=pHash->aSlot[iSlot]; pIter; pIter=pIter->pHashNext){
|
for(pIter=pHash->aSlot[iSlot]; pIter; pIter=pIter->pHashNext){
|
||||||
if( pTerm==0 || 0==memcmp(pIter->zKey, pTerm, nTerm) ){
|
if( pTerm==0 || 0==memcmp(fts5EntryKey(pIter), pTerm, nTerm) ){
|
||||||
Fts5HashEntry *pEntry = pIter;
|
Fts5HashEntry *pEntry = pIter;
|
||||||
pEntry->pScanNext = 0;
|
pEntry->pScanNext = 0;
|
||||||
for(i=0; ap[i]; i++){
|
for(i=0; ap[i]; i++){
|
||||||
@ -471,16 +478,18 @@ int sqlite3Fts5HashQuery(
|
|||||||
int *pnDoclist /* OUT: Size of doclist in bytes */
|
int *pnDoclist /* OUT: Size of doclist in bytes */
|
||||||
){
|
){
|
||||||
unsigned int iHash = fts5HashKey(pHash->nSlot, (const u8*)pTerm, nTerm);
|
unsigned int iHash = fts5HashKey(pHash->nSlot, (const u8*)pTerm, nTerm);
|
||||||
|
char *zKey = 0;
|
||||||
Fts5HashEntry *p;
|
Fts5HashEntry *p;
|
||||||
|
|
||||||
for(p=pHash->aSlot[iHash]; p; p=p->pHashNext){
|
for(p=pHash->aSlot[iHash]; p; p=p->pHashNext){
|
||||||
if( memcmp(p->zKey, pTerm, nTerm)==0 && p->zKey[nTerm]==0 ) break;
|
zKey = fts5EntryKey(p);
|
||||||
|
if( memcmp(zKey, pTerm, nTerm)==0 && zKey[nTerm]==0 ) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( p ){
|
if( p ){
|
||||||
fts5HashAddPoslistSize(pHash, p);
|
fts5HashAddPoslistSize(pHash, p);
|
||||||
*ppDoclist = (const u8*)&p->zKey[nTerm+1];
|
*ppDoclist = (const u8*)&zKey[nTerm+1];
|
||||||
*pnDoclist = p->nData - (FTS5_HASHENTRYSIZE + nTerm + 1);
|
*pnDoclist = p->nData - (sizeof(Fts5HashEntry) + nTerm + 1);
|
||||||
}else{
|
}else{
|
||||||
*ppDoclist = 0;
|
*ppDoclist = 0;
|
||||||
*pnDoclist = 0;
|
*pnDoclist = 0;
|
||||||
@ -513,11 +522,12 @@ void sqlite3Fts5HashScanEntry(
|
|||||||
){
|
){
|
||||||
Fts5HashEntry *p;
|
Fts5HashEntry *p;
|
||||||
if( (p = pHash->pScan) ){
|
if( (p = pHash->pScan) ){
|
||||||
int nTerm = (int)strlen(p->zKey);
|
char *zKey = fts5EntryKey(p);
|
||||||
|
int nTerm = (int)strlen(zKey);
|
||||||
fts5HashAddPoslistSize(pHash, p);
|
fts5HashAddPoslistSize(pHash, p);
|
||||||
*pzTerm = p->zKey;
|
*pzTerm = zKey;
|
||||||
*ppDoclist = (const u8*)&p->zKey[nTerm+1];
|
*ppDoclist = (const u8*)&zKey[nTerm+1];
|
||||||
*pnDoclist = p->nData - (FTS5_HASHENTRYSIZE + nTerm + 1);
|
*pnDoclist = p->nData - (sizeof(Fts5HashEntry) + nTerm + 1);
|
||||||
}else{
|
}else{
|
||||||
*pzTerm = 0;
|
*pzTerm = 0;
|
||||||
*ppDoclist = 0;
|
*ppDoclist = 0;
|
||||||
|
@ -628,7 +628,6 @@ static void fts5CloseReader(Fts5Index *p){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Retrieve a record from the %_data table.
|
** Retrieve a record from the %_data table.
|
||||||
**
|
**
|
||||||
@ -729,7 +728,8 @@ static int fts5IndexPrepareStmt(
|
|||||||
){
|
){
|
||||||
if( p->rc==SQLITE_OK ){
|
if( p->rc==SQLITE_OK ){
|
||||||
if( zSql ){
|
if( zSql ){
|
||||||
p->rc = sqlite3_prepare_v2(p->pConfig->db, zSql, -1, ppStmt, 0);
|
p->rc = sqlite3_prepare_v3(p->pConfig->db, zSql, -1,
|
||||||
|
SQLITE_PREPARE_PERSISTENT, ppStmt, 0);
|
||||||
}else{
|
}else{
|
||||||
p->rc = SQLITE_NOMEM;
|
p->rc = SQLITE_NOMEM;
|
||||||
}
|
}
|
||||||
@ -778,7 +778,8 @@ static void fts5DataDelete(Fts5Index *p, i64 iFirst, i64 iLast){
|
|||||||
if( zSql==0 ){
|
if( zSql==0 ){
|
||||||
rc = SQLITE_NOMEM;
|
rc = SQLITE_NOMEM;
|
||||||
}else{
|
}else{
|
||||||
rc = sqlite3_prepare_v2(pConfig->db, zSql, -1, &p->pDeleter, 0);
|
rc = sqlite3_prepare_v3(pConfig->db, zSql, -1,
|
||||||
|
SQLITE_PREPARE_PERSISTENT, &p->pDeleter, 0);
|
||||||
sqlite3_free(zSql);
|
sqlite3_free(zSql);
|
||||||
}
|
}
|
||||||
if( rc!=SQLITE_OK ){
|
if( rc!=SQLITE_OK ){
|
||||||
@ -2039,7 +2040,7 @@ static void fts5SegIterNext(
|
|||||||
else if( pLeaf->nn>pLeaf->szLeaf ){
|
else if( pLeaf->nn>pLeaf->szLeaf ){
|
||||||
pIter->iPgidxOff = pLeaf->szLeaf + fts5GetVarint32(
|
pIter->iPgidxOff = pLeaf->szLeaf + fts5GetVarint32(
|
||||||
&pLeaf->p[pLeaf->szLeaf], iOff
|
&pLeaf->p[pLeaf->szLeaf], iOff
|
||||||
);
|
);
|
||||||
pIter->iLeafOffset = iOff;
|
pIter->iLeafOffset = iOff;
|
||||||
pIter->iEndofDoclist = iOff;
|
pIter->iEndofDoclist = iOff;
|
||||||
bNewTerm = 1;
|
bNewTerm = 1;
|
||||||
@ -2073,6 +2074,7 @@ static void fts5SegIterNext(
|
|||||||
*/
|
*/
|
||||||
int nSz;
|
int nSz;
|
||||||
assert( p->rc==SQLITE_OK );
|
assert( p->rc==SQLITE_OK );
|
||||||
|
assert( pIter->iLeafOffset<=pIter->pLeaf->nn );
|
||||||
fts5FastGetVarint32(pIter->pLeaf->p, pIter->iLeafOffset, nSz);
|
fts5FastGetVarint32(pIter->pLeaf->p, pIter->iLeafOffset, nSz);
|
||||||
pIter->bDel = (nSz & 0x0001);
|
pIter->bDel = (nSz & 0x0001);
|
||||||
pIter->nPos = nSz>>1;
|
pIter->nPos = nSz>>1;
|
||||||
@ -2878,7 +2880,8 @@ static void fts5MultiIterNext2(
|
|||||||
){
|
){
|
||||||
assert( pIter->bSkipEmpty );
|
assert( pIter->bSkipEmpty );
|
||||||
if( p->rc==SQLITE_OK ){
|
if( p->rc==SQLITE_OK ){
|
||||||
do {
|
*pbNewTerm = 0;
|
||||||
|
do{
|
||||||
int iFirst = pIter->aFirst[1].iFirst;
|
int iFirst = pIter->aFirst[1].iFirst;
|
||||||
Fts5SegIter *pSeg = &pIter->aSeg[iFirst];
|
Fts5SegIter *pSeg = &pIter->aSeg[iFirst];
|
||||||
int bNewTerm = 0;
|
int bNewTerm = 0;
|
||||||
@ -2891,8 +2894,6 @@ static void fts5MultiIterNext2(
|
|||||||
fts5MultiIterAdvanced(p, pIter, iFirst, 1);
|
fts5MultiIterAdvanced(p, pIter, iFirst, 1);
|
||||||
fts5MultiIterSetEof(pIter);
|
fts5MultiIterSetEof(pIter);
|
||||||
*pbNewTerm = 1;
|
*pbNewTerm = 1;
|
||||||
}else{
|
|
||||||
*pbNewTerm = 0;
|
|
||||||
}
|
}
|
||||||
fts5AssertMultiIterSetup(p, pIter);
|
fts5AssertMultiIterSetup(p, pIter);
|
||||||
|
|
||||||
@ -3067,7 +3068,7 @@ static void fts5ChunkIterate(
|
|||||||
break;
|
break;
|
||||||
}else{
|
}else{
|
||||||
pgno++;
|
pgno++;
|
||||||
pData = fts5DataRead(p, FTS5_SEGMENT_ROWID(pSeg->pSeg->iSegid, pgno));
|
pData = fts5LeafRead(p, FTS5_SEGMENT_ROWID(pSeg->pSeg->iSegid, pgno));
|
||||||
if( pData==0 ) break;
|
if( pData==0 ) break;
|
||||||
pChunk = &pData->p[4];
|
pChunk = &pData->p[4];
|
||||||
nChunk = MIN(nRem, pData->szLeaf - 4);
|
nChunk = MIN(nRem, pData->szLeaf - 4);
|
||||||
@ -3158,23 +3159,23 @@ static int fts5IndexExtractCol(
|
|||||||
return p - (*pa);
|
return p - (*pa);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int fts5IndexExtractColset (
|
static void fts5IndexExtractColset(
|
||||||
|
int *pRc,
|
||||||
Fts5Colset *pColset, /* Colset to filter on */
|
Fts5Colset *pColset, /* Colset to filter on */
|
||||||
const u8 *pPos, int nPos, /* Position list */
|
const u8 *pPos, int nPos, /* Position list */
|
||||||
Fts5Buffer *pBuf /* Output buffer */
|
Fts5Buffer *pBuf /* Output buffer */
|
||||||
){
|
){
|
||||||
int rc = SQLITE_OK;
|
if( *pRc==SQLITE_OK ){
|
||||||
int i;
|
int i;
|
||||||
|
fts5BufferZero(pBuf);
|
||||||
fts5BufferZero(pBuf);
|
for(i=0; i<pColset->nCol; i++){
|
||||||
for(i=0; i<pColset->nCol; i++){
|
const u8 *pSub = pPos;
|
||||||
const u8 *pSub = pPos;
|
int nSub = fts5IndexExtractCol(&pSub, nPos, pColset->aiCol[i]);
|
||||||
int nSub = fts5IndexExtractCol(&pSub, nPos, pColset->aiCol[i]);
|
if( nSub ){
|
||||||
if( nSub ){
|
fts5BufferAppendBlob(pRc, pBuf, nSub, pSub);
|
||||||
fts5BufferAppendBlob(&rc, pBuf, nSub, pSub);
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return rc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -3298,8 +3299,9 @@ static void fts5IterSetOutputs_Full(Fts5Iter *pIter, Fts5SegIter *pSeg){
|
|||||||
pIter->base.nData = fts5IndexExtractCol(&a, pSeg->nPos,pColset->aiCol[0]);
|
pIter->base.nData = fts5IndexExtractCol(&a, pSeg->nPos,pColset->aiCol[0]);
|
||||||
pIter->base.pData = a;
|
pIter->base.pData = a;
|
||||||
}else{
|
}else{
|
||||||
|
int *pRc = &pIter->pIndex->rc;
|
||||||
fts5BufferZero(&pIter->poslist);
|
fts5BufferZero(&pIter->poslist);
|
||||||
fts5IndexExtractColset(pColset, a, pSeg->nPos, &pIter->poslist);
|
fts5IndexExtractColset(pRc, pColset, a, pSeg->nPos, &pIter->poslist);
|
||||||
pIter->base.pData = pIter->poslist.p;
|
pIter->base.pData = pIter->poslist.p;
|
||||||
pIter->base.nData = pIter->poslist.n;
|
pIter->base.nData = pIter->poslist.n;
|
||||||
}
|
}
|
||||||
@ -3844,9 +3846,6 @@ static void fts5WriteFlushLeaf(Fts5Index *p, Fts5SegWriter *pWriter){
|
|||||||
Fts5PageWriter *pPage = &pWriter->writer;
|
Fts5PageWriter *pPage = &pWriter->writer;
|
||||||
i64 iRowid;
|
i64 iRowid;
|
||||||
|
|
||||||
static int nCall = 0;
|
|
||||||
nCall++;
|
|
||||||
|
|
||||||
assert( (pPage->pgidx.n==0)==(pWriter->bFirstTermInPage) );
|
assert( (pPage->pgidx.n==0)==(pWriter->bFirstTermInPage) );
|
||||||
|
|
||||||
/* Set the szLeaf header field. */
|
/* Set the szLeaf header field. */
|
||||||
@ -4195,6 +4194,7 @@ static void fts5IndexMergeLevel(
|
|||||||
int bOldest; /* True if the output segment is the oldest */
|
int bOldest; /* True if the output segment is the oldest */
|
||||||
int eDetail = p->pConfig->eDetail;
|
int eDetail = p->pConfig->eDetail;
|
||||||
const int flags = FTS5INDEX_QUERY_NOOUTPUT;
|
const int flags = FTS5INDEX_QUERY_NOOUTPUT;
|
||||||
|
int bTermWritten = 0; /* True if current term already output */
|
||||||
|
|
||||||
assert( iLvl<pStruct->nLevel );
|
assert( iLvl<pStruct->nLevel );
|
||||||
assert( pLvl->nMerge<=pLvl->nSeg );
|
assert( pLvl->nMerge<=pLvl->nSeg );
|
||||||
@ -4248,18 +4248,22 @@ static void fts5IndexMergeLevel(
|
|||||||
int nTerm;
|
int nTerm;
|
||||||
const u8 *pTerm;
|
const u8 *pTerm;
|
||||||
|
|
||||||
/* Check for key annihilation. */
|
|
||||||
if( pSegIter->nPos==0 && (bOldest || pSegIter->bDel==0) ) continue;
|
|
||||||
|
|
||||||
pTerm = fts5MultiIterTerm(pIter, &nTerm);
|
pTerm = fts5MultiIterTerm(pIter, &nTerm);
|
||||||
if( nTerm!=term.n || memcmp(pTerm, term.p, nTerm) ){
|
if( nTerm!=term.n || memcmp(pTerm, term.p, nTerm) ){
|
||||||
if( pnRem && writer.nLeafWritten>nRem ){
|
if( pnRem && writer.nLeafWritten>nRem ){
|
||||||
break;
|
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. */
|
/* This is a new term. Append a term to the output segment. */
|
||||||
fts5WriteAppendTerm(p, &writer, nTerm, pTerm);
|
fts5WriteAppendTerm(p, &writer, nTerm, pTerm);
|
||||||
fts5BufferSet(&p->rc, &term, nTerm, pTerm);
|
bTermWritten = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Append the rowid to the output */
|
/* Append the rowid to the output */
|
||||||
@ -5091,7 +5095,7 @@ static void fts5SetupPrefixIter(
|
|||||||
if( pData ){
|
if( pData ){
|
||||||
pData->p = (u8*)&pData[1];
|
pData->p = (u8*)&pData[1];
|
||||||
pData->nn = pData->szLeaf = doclist.n;
|
pData->nn = pData->szLeaf = doclist.n;
|
||||||
memcpy(pData->p, doclist.p, doclist.n);
|
if( doclist.n ) memcpy(pData->p, doclist.p, doclist.n);
|
||||||
fts5MultiIterNew2(p, pData, bDesc, ppIter);
|
fts5MultiIterNew2(p, pData, bDesc, ppIter);
|
||||||
}
|
}
|
||||||
fts5BufferFree(&doclist);
|
fts5BufferFree(&doclist);
|
||||||
@ -5130,10 +5134,10 @@ int sqlite3Fts5IndexBeginWrite(Fts5Index *p, int bDelete, i64 iRowid){
|
|||||||
/*
|
/*
|
||||||
** Commit data to disk.
|
** Commit data to disk.
|
||||||
*/
|
*/
|
||||||
int sqlite3Fts5IndexSync(Fts5Index *p, int bCommit){
|
int sqlite3Fts5IndexSync(Fts5Index *p){
|
||||||
assert( p->rc==SQLITE_OK );
|
assert( p->rc==SQLITE_OK );
|
||||||
fts5IndexFlush(p);
|
fts5IndexFlush(p);
|
||||||
if( bCommit ) fts5CloseReader(p);
|
fts5CloseReader(p);
|
||||||
return fts5IndexReturn(p);
|
return fts5IndexReturn(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5330,7 +5334,7 @@ int sqlite3Fts5IndexQuery(
|
|||||||
|
|
||||||
if( sqlite3Fts5BufferSize(&p->rc, &buf, nToken+1)==0 ){
|
if( sqlite3Fts5BufferSize(&p->rc, &buf, nToken+1)==0 ){
|
||||||
int iIdx = 0; /* Index to search */
|
int iIdx = 0; /* Index to search */
|
||||||
memcpy(&buf.p[1], pToken, nToken);
|
if( nToken ) memcpy(&buf.p[1], pToken, nToken);
|
||||||
|
|
||||||
/* Figure out which index to search and set iIdx accordingly. If this
|
/* 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
|
** is a prefix query for which there is no prefix index, set iIdx to
|
||||||
@ -5379,7 +5383,7 @@ int sqlite3Fts5IndexQuery(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if( p->rc ){
|
if( p->rc ){
|
||||||
sqlite3Fts5IterClose(&pRet->base);
|
sqlite3Fts5IterClose((Fts5IndexIter*)pRet);
|
||||||
pRet = 0;
|
pRet = 0;
|
||||||
fts5CloseReader(p);
|
fts5CloseReader(p);
|
||||||
}
|
}
|
||||||
@ -5829,7 +5833,7 @@ static void fts5IndexIntegrityCheckSegment(
|
|||||||
** ignore this b-tree entry. Otherwise, load it into memory. */
|
** ignore this b-tree entry. Otherwise, load it into memory. */
|
||||||
if( iIdxLeaf<pSeg->pgnoFirst ) continue;
|
if( iIdxLeaf<pSeg->pgnoFirst ) continue;
|
||||||
iRow = FTS5_SEGMENT_ROWID(pSeg->iSegid, iIdxLeaf);
|
iRow = FTS5_SEGMENT_ROWID(pSeg->iSegid, iIdxLeaf);
|
||||||
pLeaf = fts5DataRead(p, iRow);
|
pLeaf = fts5LeafRead(p, iRow);
|
||||||
if( pLeaf==0 ) break;
|
if( pLeaf==0 ) break;
|
||||||
|
|
||||||
/* Check that the leaf contains at least one term, and that it is equal
|
/* Check that the leaf contains at least one term, and that it is equal
|
||||||
|
@ -506,6 +506,7 @@ static void fts5SetUniqueFlag(sqlite3_index_info *pIdxInfo){
|
|||||||
static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
|
static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
|
||||||
Fts5Table *pTab = (Fts5Table*)pVTab;
|
Fts5Table *pTab = (Fts5Table*)pVTab;
|
||||||
Fts5Config *pConfig = pTab->pConfig;
|
Fts5Config *pConfig = pTab->pConfig;
|
||||||
|
const int nCol = pConfig->nCol;
|
||||||
int idxFlags = 0; /* Parameter passed through to xFilter() */
|
int idxFlags = 0; /* Parameter passed through to xFilter() */
|
||||||
int bHasMatch;
|
int bHasMatch;
|
||||||
int iNext;
|
int iNext;
|
||||||
@ -531,24 +532,34 @@ static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
|
|||||||
|
|
||||||
int aColMap[3];
|
int aColMap[3];
|
||||||
aColMap[0] = -1;
|
aColMap[0] = -1;
|
||||||
aColMap[1] = pConfig->nCol;
|
aColMap[1] = nCol;
|
||||||
aColMap[2] = pConfig->nCol+1;
|
aColMap[2] = nCol+1;
|
||||||
|
|
||||||
/* Set idxFlags flags for all WHERE clause terms that will be used. */
|
/* Set idxFlags flags for all WHERE clause terms that will be used. */
|
||||||
for(i=0; i<pInfo->nConstraint; i++){
|
for(i=0; i<pInfo->nConstraint; i++){
|
||||||
struct sqlite3_index_constraint *p = &pInfo->aConstraint[i];
|
struct sqlite3_index_constraint *p = &pInfo->aConstraint[i];
|
||||||
int j;
|
int iCol = p->iColumn;
|
||||||
for(j=0; j<ArraySize(aConstraint); j++){
|
|
||||||
struct Constraint *pC = &aConstraint[j];
|
if( (p->op==SQLITE_INDEX_CONSTRAINT_MATCH && iCol>=0 && iCol<=nCol)
|
||||||
if( p->iColumn==aColMap[pC->iCol] && p->op & pC->op ){
|
|| (p->op==SQLITE_INDEX_CONSTRAINT_EQ && iCol==nCol)
|
||||||
if( p->usable ){
|
){
|
||||||
|
/* 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 ){
|
||||||
pC->iConsIndex = i;
|
pC->iConsIndex = i;
|
||||||
idxFlags |= pC->fts5op;
|
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -872,7 +883,8 @@ static int fts5PrepareStatement(
|
|||||||
if( zSql==0 ){
|
if( zSql==0 ){
|
||||||
rc = SQLITE_NOMEM;
|
rc = SQLITE_NOMEM;
|
||||||
}else{
|
}else{
|
||||||
rc = sqlite3_prepare_v2(pConfig->db, zSql, -1, &pRet, 0);
|
rc = sqlite3_prepare_v3(pConfig->db, zSql, -1,
|
||||||
|
SQLITE_PREPARE_PERSISTENT, &pRet, 0);
|
||||||
if( rc!=SQLITE_OK ){
|
if( rc!=SQLITE_OK ){
|
||||||
*pConfig->pzErrmsg = sqlite3_mprintf("%s", sqlite3_errmsg(pConfig->db));
|
*pConfig->pzErrmsg = sqlite3_mprintf("%s", sqlite3_errmsg(pConfig->db));
|
||||||
}
|
}
|
||||||
@ -1008,7 +1020,8 @@ static int fts5FindRankFunction(Fts5Cursor *pCsr){
|
|||||||
char *zSql = sqlite3Fts5Mprintf(&rc, "SELECT %s", zRankArgs);
|
char *zSql = sqlite3Fts5Mprintf(&rc, "SELECT %s", zRankArgs);
|
||||||
if( zSql ){
|
if( zSql ){
|
||||||
sqlite3_stmt *pStmt = 0;
|
sqlite3_stmt *pStmt = 0;
|
||||||
rc = sqlite3_prepare_v2(pConfig->db, zSql, -1, &pStmt, 0);
|
rc = sqlite3_prepare_v3(pConfig->db, zSql, -1,
|
||||||
|
SQLITE_PREPARE_PERSISTENT, &pStmt, 0);
|
||||||
sqlite3_free(zSql);
|
sqlite3_free(zSql);
|
||||||
assert( rc==SQLITE_OK || pCsr->pRankArgStmt==0 );
|
assert( rc==SQLITE_OK || pCsr->pRankArgStmt==0 );
|
||||||
if( rc==SQLITE_OK ){
|
if( rc==SQLITE_OK ){
|
||||||
@ -1123,6 +1136,7 @@ static int fts5FilterMethod(
|
|||||||
sqlite3_value *pRowidEq = 0; /* rowid = ? expression (or NULL) */
|
sqlite3_value *pRowidEq = 0; /* rowid = ? expression (or NULL) */
|
||||||
sqlite3_value *pRowidLe = 0; /* rowid <= ? expression (or NULL) */
|
sqlite3_value *pRowidLe = 0; /* rowid <= ? expression (or NULL) */
|
||||||
sqlite3_value *pRowidGe = 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;
|
char **pzErrmsg = pConfig->pzErrmsg;
|
||||||
|
|
||||||
UNUSED_PARAM(zUnused);
|
UNUSED_PARAM(zUnused);
|
||||||
@ -1153,6 +1167,8 @@ static int fts5FilterMethod(
|
|||||||
if( BitFlagTest(idxNum, FTS5_BI_ROWID_EQ) ) pRowidEq = apVal[iVal++];
|
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_LE) ) pRowidLe = apVal[iVal++];
|
||||||
if( BitFlagTest(idxNum, FTS5_BI_ROWID_GE) ) pRowidGe = apVal[iVal++];
|
if( BitFlagTest(idxNum, FTS5_BI_ROWID_GE) ) pRowidGe = apVal[iVal++];
|
||||||
|
iCol = (idxNum>>16);
|
||||||
|
assert( iCol>=0 && iCol<=pConfig->nCol );
|
||||||
assert( iVal==nVal );
|
assert( iVal==nVal );
|
||||||
bOrderByRank = ((idxNum & FTS5_BI_ORDER_RANK) ? 1 : 0);
|
bOrderByRank = ((idxNum & FTS5_BI_ORDER_RANK) ? 1 : 0);
|
||||||
pCsr->bDesc = bDesc = ((idxNum & FTS5_BI_ORDER_DESC) ? 1 : 0);
|
pCsr->bDesc = bDesc = ((idxNum & FTS5_BI_ORDER_DESC) ? 1 : 0);
|
||||||
@ -1199,7 +1215,7 @@ static int fts5FilterMethod(
|
|||||||
rc = fts5SpecialMatch(pTab, pCsr, &zExpr[1]);
|
rc = fts5SpecialMatch(pTab, pCsr, &zExpr[1]);
|
||||||
}else{
|
}else{
|
||||||
char **pzErr = &pTab->base.zErrMsg;
|
char **pzErr = &pTab->base.zErrMsg;
|
||||||
rc = sqlite3Fts5ExprNew(pConfig, zExpr, &pCsr->pExpr, pzErr);
|
rc = sqlite3Fts5ExprNew(pConfig, iCol, zExpr, &pCsr->pExpr, pzErr);
|
||||||
if( rc==SQLITE_OK ){
|
if( rc==SQLITE_OK ){
|
||||||
if( bOrderByRank ){
|
if( bOrderByRank ){
|
||||||
pCsr->ePlan = FTS5_PLAN_SORTED_MATCH;
|
pCsr->ePlan = FTS5_PLAN_SORTED_MATCH;
|
||||||
@ -1579,7 +1595,7 @@ static int fts5SyncMethod(sqlite3_vtab *pVtab){
|
|||||||
fts5CheckTransactionState(pTab, FTS5_SYNC, 0);
|
fts5CheckTransactionState(pTab, FTS5_SYNC, 0);
|
||||||
pTab->pConfig->pzErrmsg = &pTab->base.zErrMsg;
|
pTab->pConfig->pzErrmsg = &pTab->base.zErrMsg;
|
||||||
fts5TripCursors(pTab);
|
fts5TripCursors(pTab);
|
||||||
rc = sqlite3Fts5StorageSync(pTab->pStorage, 1);
|
rc = sqlite3Fts5StorageSync(pTab->pStorage);
|
||||||
pTab->pConfig->pzErrmsg = 0;
|
pTab->pConfig->pzErrmsg = 0;
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@ -2390,7 +2406,7 @@ static int fts5SavepointMethod(sqlite3_vtab *pVtab, int iSavepoint){
|
|||||||
UNUSED_PARAM(iSavepoint); /* Call below is a no-op for NDEBUG builds */
|
UNUSED_PARAM(iSavepoint); /* Call below is a no-op for NDEBUG builds */
|
||||||
fts5CheckTransactionState(pTab, FTS5_SAVEPOINT, iSavepoint);
|
fts5CheckTransactionState(pTab, FTS5_SAVEPOINT, iSavepoint);
|
||||||
fts5TripCursors(pTab);
|
fts5TripCursors(pTab);
|
||||||
return sqlite3Fts5StorageSync(pTab->pStorage, 0);
|
return sqlite3Fts5StorageSync(pTab->pStorage);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -2403,7 +2419,7 @@ static int fts5ReleaseMethod(sqlite3_vtab *pVtab, int iSavepoint){
|
|||||||
UNUSED_PARAM(iSavepoint); /* Call below is a no-op for NDEBUG builds */
|
UNUSED_PARAM(iSavepoint); /* Call below is a no-op for NDEBUG builds */
|
||||||
fts5CheckTransactionState(pTab, FTS5_RELEASE, iSavepoint);
|
fts5CheckTransactionState(pTab, FTS5_RELEASE, iSavepoint);
|
||||||
fts5TripCursors(pTab);
|
fts5TripCursors(pTab);
|
||||||
return sqlite3Fts5StorageSync(pTab->pStorage, 0);
|
return sqlite3Fts5StorageSync(pTab->pStorage);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -2593,15 +2609,14 @@ static void fts5ModuleDestroy(void *pCtx){
|
|||||||
static void fts5Fts5Func(
|
static void fts5Fts5Func(
|
||||||
sqlite3_context *pCtx, /* Function call context */
|
sqlite3_context *pCtx, /* Function call context */
|
||||||
int nArg, /* Number of args */
|
int nArg, /* Number of args */
|
||||||
sqlite3_value **apUnused /* Function arguments */
|
sqlite3_value **apArg /* Function arguments */
|
||||||
){
|
){
|
||||||
Fts5Global *pGlobal = (Fts5Global*)sqlite3_user_data(pCtx);
|
Fts5Global *pGlobal = (Fts5Global*)sqlite3_user_data(pCtx);
|
||||||
char buf[8];
|
fts5_api **ppApi;
|
||||||
UNUSED_PARAM2(nArg, apUnused);
|
UNUSED_PARAM(nArg);
|
||||||
assert( nArg==0 );
|
assert( nArg==1 );
|
||||||
assert( sizeof(buf)>=sizeof(pGlobal) );
|
ppApi = (fts5_api**)sqlite3_value_pointer(apArg[0], "fts5_api_ptr");
|
||||||
memcpy(buf, (void*)&pGlobal, sizeof(pGlobal));
|
if( ppApi ) *ppApi = &pGlobal->api;
|
||||||
sqlite3_result_blob(pCtx, buf, sizeof(pGlobal), SQLITE_TRANSIENT);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -2666,7 +2681,7 @@ static int fts5Init(sqlite3 *db){
|
|||||||
if( rc==SQLITE_OK ) rc = sqlite3Fts5VocabInit(pGlobal, db);
|
if( rc==SQLITE_OK ) rc = sqlite3Fts5VocabInit(pGlobal, db);
|
||||||
if( rc==SQLITE_OK ){
|
if( rc==SQLITE_OK ){
|
||||||
rc = sqlite3_create_function(
|
rc = sqlite3_create_function(
|
||||||
db, "fts5", 0, SQLITE_UTF8, p, fts5Fts5Func, 0, 0
|
db, "fts5", 1, SQLITE_UTF8, p, fts5Fts5Func, 0, 0
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if( rc==SQLITE_OK ){
|
if( rc==SQLITE_OK ){
|
||||||
|
@ -136,7 +136,8 @@ static int fts5StorageGetStmt(
|
|||||||
if( zSql==0 ){
|
if( zSql==0 ){
|
||||||
rc = SQLITE_NOMEM;
|
rc = SQLITE_NOMEM;
|
||||||
}else{
|
}else{
|
||||||
rc = sqlite3_prepare_v2(pC->db, zSql, -1, &p->aStmt[eStmt], 0);
|
rc = sqlite3_prepare_v3(pC->db, zSql, -1,
|
||||||
|
SQLITE_PREPARE_PERSISTENT, &p->aStmt[eStmt], 0);
|
||||||
sqlite3_free(zSql);
|
sqlite3_free(zSql);
|
||||||
if( rc!=SQLITE_OK && pzErrMsg ){
|
if( rc!=SQLITE_OK && pzErrMsg ){
|
||||||
*pzErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(pC->db));
|
*pzErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(pC->db));
|
||||||
@ -218,7 +219,7 @@ static void fts5StorageRenameOne(
|
|||||||
|
|
||||||
int sqlite3Fts5StorageRename(Fts5Storage *pStorage, const char *zName){
|
int sqlite3Fts5StorageRename(Fts5Storage *pStorage, const char *zName){
|
||||||
Fts5Config *pConfig = pStorage->pConfig;
|
Fts5Config *pConfig = pStorage->pConfig;
|
||||||
int rc = sqlite3Fts5StorageSync(pStorage, 1);
|
int rc = sqlite3Fts5StorageSync(pStorage);
|
||||||
|
|
||||||
fts5StorageRenameOne(pConfig, &rc, "data", zName);
|
fts5StorageRenameOne(pConfig, &rc, "data", zName);
|
||||||
fts5StorageRenameOne(pConfig, &rc, "idx", zName);
|
fts5StorageRenameOne(pConfig, &rc, "idx", zName);
|
||||||
@ -545,11 +546,6 @@ int sqlite3Fts5StorageDelete(Fts5Storage *p, i64 iDel, sqlite3_value **apVal){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write the averages record */
|
|
||||||
if( rc==SQLITE_OK ){
|
|
||||||
rc = fts5StorageSaveTotals(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -753,11 +749,6 @@ int sqlite3Fts5StorageIndexInsert(
|
|||||||
}
|
}
|
||||||
sqlite3_free(buf.p);
|
sqlite3_free(buf.p);
|
||||||
|
|
||||||
/* Write the averages record */
|
|
||||||
if( rc==SQLITE_OK ){
|
|
||||||
rc = fts5StorageSaveTotals(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1091,13 +1082,18 @@ int sqlite3Fts5StorageRowCount(Fts5Storage *p, i64 *pnRow){
|
|||||||
/*
|
/*
|
||||||
** Flush any data currently held in-memory to disk.
|
** Flush any data currently held in-memory to disk.
|
||||||
*/
|
*/
|
||||||
int sqlite3Fts5StorageSync(Fts5Storage *p, int bCommit){
|
int sqlite3Fts5StorageSync(Fts5Storage *p){
|
||||||
if( bCommit && p->bTotalsValid ){
|
int rc = SQLITE_OK;
|
||||||
int rc = fts5StorageSaveTotals(p);
|
i64 iLastRowid = sqlite3_last_insert_rowid(p->pConfig->db);
|
||||||
|
if( p->bTotalsValid ){
|
||||||
|
rc = fts5StorageSaveTotals(p);
|
||||||
p->bTotalsValid = 0;
|
p->bTotalsValid = 0;
|
||||||
if( rc!=SQLITE_OK ) return rc;
|
|
||||||
}
|
}
|
||||||
return sqlite3Fts5IndexSync(p->pIndex, bCommit);
|
if( rc==SQLITE_OK ){
|
||||||
|
rc = sqlite3Fts5IndexSync(p->pIndex);
|
||||||
|
}
|
||||||
|
sqlite3_set_last_insert_rowid(p->pConfig->db, iLastRowid);
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
int sqlite3Fts5StorageRollback(Fts5Storage *p){
|
int sqlite3Fts5StorageRollback(Fts5Storage *p){
|
||||||
|
@ -99,16 +99,13 @@ static int SQLITE_TCLAPI f5tDbAndApi(
|
|||||||
sqlite3_stmt *pStmt = 0;
|
sqlite3_stmt *pStmt = 0;
|
||||||
fts5_api *pApi = 0;
|
fts5_api *pApi = 0;
|
||||||
|
|
||||||
rc = sqlite3_prepare_v2(db, "SELECT fts5()", -1, &pStmt, 0);
|
rc = sqlite3_prepare_v2(db, "SELECT fts5(?1)", -1, &pStmt, 0);
|
||||||
if( rc!=SQLITE_OK ){
|
if( rc!=SQLITE_OK ){
|
||||||
Tcl_AppendResult(interp, "error: ", sqlite3_errmsg(db), 0);
|
Tcl_AppendResult(interp, "error: ", sqlite3_errmsg(db), 0);
|
||||||
return TCL_ERROR;
|
return TCL_ERROR;
|
||||||
}
|
}
|
||||||
|
sqlite3_bind_pointer(pStmt, 1, (void*)&pApi, "fts5_api_ptr", 0);
|
||||||
if( SQLITE_ROW==sqlite3_step(pStmt) ){
|
sqlite3_step(pStmt);
|
||||||
const void *pPtr = sqlite3_column_blob(pStmt, 0);
|
|
||||||
memcpy((void*)&pApi, pPtr, sizeof(pApi));
|
|
||||||
}
|
|
||||||
|
|
||||||
if( sqlite3_finalize(pStmt)!=SQLITE_OK ){
|
if( sqlite3_finalize(pStmt)!=SQLITE_OK ){
|
||||||
Tcl_AppendResult(interp, "error: ", sqlite3_errmsg(db), 0);
|
Tcl_AppendResult(interp, "error: ", sqlite3_errmsg(db), 0);
|
||||||
|
@ -73,13 +73,10 @@ static int fts5_api_from_db(sqlite3 *db, fts5_api **ppApi){
|
|||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
*ppApi = 0;
|
*ppApi = 0;
|
||||||
rc = sqlite3_prepare(db, "SELECT fts5()", -1, &pStmt, 0);
|
rc = sqlite3_prepare(db, "SELECT fts5(?1)", -1, &pStmt, 0);
|
||||||
if( rc==SQLITE_OK ){
|
if( rc==SQLITE_OK ){
|
||||||
if( SQLITE_ROW==sqlite3_step(pStmt)
|
sqlite3_bind_pointer(pStmt, 1, (void*)ppApi, "fts5_api_ptr", 0);
|
||||||
&& sizeof(fts5_api*)==sqlite3_column_bytes(pStmt, 0)
|
(void)sqlite3_step(pStmt);
|
||||||
){
|
|
||||||
memcpy(ppApi, sqlite3_column_blob(pStmt, 0), sizeof(fts5_api*));
|
|
||||||
}
|
|
||||||
rc = sqlite3_finalize(pStmt);
|
rc = sqlite3_finalize(pStmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -422,4 +419,3 @@ int sqlite3Fts5TestRegisterMatchinfo(sqlite3 *db){
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endif /* SQLITE_ENABLE_FTS5 */
|
#endif /* SQLITE_ENABLE_FTS5 */
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@
|
|||||||
*/
|
*/
|
||||||
#if defined(SQLITE_TEST) && defined(SQLITE_ENABLE_FTS5)
|
#if defined(SQLITE_TEST) && defined(SQLITE_ENABLE_FTS5)
|
||||||
|
|
||||||
#include <fts5.h>
|
#include "fts5.h"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
@ -182,7 +182,7 @@ static int fts5tokConnectMethod(
|
|||||||
Fts5tokTable *pTab = 0;
|
Fts5tokTable *pTab = 0;
|
||||||
int rc;
|
int rc;
|
||||||
char **azDequote = 0;
|
char **azDequote = 0;
|
||||||
int nDequote;
|
int nDequote = 0;
|
||||||
|
|
||||||
rc = sqlite3_declare_vtab(db,
|
rc = sqlite3_declare_vtab(db,
|
||||||
"CREATE TABLE x(input HIDDEN, token, start, end, position)"
|
"CREATE TABLE x(input HIDDEN, token, start, end, position)"
|
||||||
|
@ -89,32 +89,6 @@ input ::= expr(X). { sqlite3Fts5ParseFinished(pParse, X); }
|
|||||||
%destructor expr { sqlite3Fts5ParseNodeFree($$); }
|
%destructor expr { sqlite3Fts5ParseNodeFree($$); }
|
||||||
%destructor exprlist { 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*}
|
%type colset {Fts5Colset*}
|
||||||
%destructor colset { sqlite3_free($$); }
|
%destructor colset { sqlite3_free($$); }
|
||||||
%type colsetlist {Fts5Colset*}
|
%type colsetlist {Fts5Colset*}
|
||||||
@ -138,6 +112,37 @@ colsetlist(A) ::= STRING(X). {
|
|||||||
A = sqlite3Fts5ParseColset(pParse, 0, &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 nearset {Fts5ExprNearset*}
|
||||||
%type nearphrases {Fts5ExprNearset*}
|
%type nearphrases {Fts5ExprNearset*}
|
||||||
%destructor nearset { sqlite3Fts5ParseNearsetFree($$); }
|
%destructor nearset { sqlite3Fts5ParseNearsetFree($$); }
|
||||||
|
@ -441,7 +441,7 @@ db func funk funk
|
|||||||
do_catchsql_test 16.2 {
|
do_catchsql_test 16.2 {
|
||||||
SELECT funk(), bm25(n1), funk() FROM n1 WHERE n1 MATCH 'a+b+c+d'
|
SELECT funk(), bm25(n1), funk() FROM n1 WHERE n1 MATCH 'a+b+c+d'
|
||||||
} {0 {{} -1e-06 {}}}
|
} {0 {{} -1e-06 {}}}
|
||||||
# {1 {SQL logic error or missing database}}
|
# {1 {SQL logic error}}
|
||||||
|
|
||||||
#-------------------------------------------------------------------------
|
#-------------------------------------------------------------------------
|
||||||
#
|
#
|
||||||
@ -561,9 +561,37 @@ do_test 20.1 {
|
|||||||
execsql { SELECT rowid FROM tmp WHERE tmp MATCH 'y' }
|
execsql { SELECT rowid FROM tmp WHERE tmp MATCH 'y' }
|
||||||
} $::ids
|
} $::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
|
finish_test
|
||||||
|
|
||||||
|
|
||||||
|
@ -294,4 +294,3 @@ do_execsql_test 7.0 {
|
|||||||
|
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
|
||||||
|
@ -276,4 +276,3 @@ foreach {tn expr tclexpr} {
|
|||||||
}
|
}
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
|
||||||
|
@ -231,7 +231,6 @@ foreach {T create} {
|
|||||||
set res [lsort -integer -increasing $res]
|
set res [lsort -integer -increasing $res]
|
||||||
}
|
}
|
||||||
set n [llength $res]
|
set n [llength $res]
|
||||||
if {$T==5} breakpoint
|
|
||||||
do_execsql_test $T.$bAsc.$tn.$n $sql $res
|
do_execsql_test $T.$bAsc.$tn.$n $sql $res
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -242,4 +241,3 @@ foreach {T create} {
|
|||||||
}
|
}
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
|
||||||
|
@ -309,4 +309,3 @@ foreach {tn q cnt} {
|
|||||||
}
|
}
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
|
||||||
|
@ -178,4 +178,3 @@ do_execsql_test 5.1 {
|
|||||||
} ;# foreach_detail_mode
|
} ;# foreach_detail_mode
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
|
||||||
|
@ -142,4 +142,3 @@ if {[detail_is_full]} {
|
|||||||
|
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
|
||||||
|
@ -167,4 +167,3 @@ do_execsql_test 1.8.2 {
|
|||||||
#db eval {SELECT rowid, fts5_decode(rowid, block) aS r FROM t1_data} {puts $r}
|
#db eval {SELECT rowid, fts5_decode(rowid, block) aS r FROM t1_data} {puts $r}
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
|
||||||
|
@ -55,4 +55,3 @@ do_execsql_test 1.2 {
|
|||||||
|
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
|
||||||
|
@ -66,4 +66,3 @@ do_execsql_test 2.0 { INSERT INTO t1(t1) VALUES('integrity-check') }
|
|||||||
|
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
|
||||||
|
@ -147,4 +147,3 @@ do_execsql_test 3.1 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
|
||||||
|
@ -77,7 +77,7 @@ foreach {tn defn} {
|
|||||||
} {
|
} {
|
||||||
do_test 2.2.$tn {
|
do_test 2.2.$tn {
|
||||||
catchsql { INSERT INTO ft1(ft1, rank) VALUES('rank', $defn) }
|
catchsql { INSERT INTO ft1(ft1, rank) VALUES('rank', $defn) }
|
||||||
} {1 {SQL logic error or missing database}}
|
} {1 {SQL logic error}}
|
||||||
}
|
}
|
||||||
|
|
||||||
#-------------------------------------------------------------------------
|
#-------------------------------------------------------------------------
|
||||||
@ -297,4 +297,3 @@ do_catchsql_test 4.4.4 {
|
|||||||
|
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
|
||||||
|
@ -89,7 +89,6 @@ do_execsql_test 3.1 {
|
|||||||
BEGIN;
|
BEGIN;
|
||||||
INSERT INTO abc(rowid, a) VALUES(2, 'a');
|
INSERT INTO abc(rowid, a) VALUES(2, 'a');
|
||||||
}
|
}
|
||||||
breakpoint
|
|
||||||
do_execsql_test 3.2 {
|
do_execsql_test 3.2 {
|
||||||
SELECT rowid FROM abc WHERE abc MATCH 'a';
|
SELECT rowid FROM abc WHERE abc MATCH 'a';
|
||||||
} {1 2}
|
} {1 2}
|
||||||
@ -100,4 +99,3 @@ do_execsql_test 3.3 {
|
|||||||
} {1 2}
|
} {1 2}
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
|
||||||
|
@ -342,4 +342,3 @@ foreach {tn expr} {
|
|||||||
|
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
|
||||||
|
@ -240,7 +240,6 @@ foreach {tn lRow res} {
|
|||||||
} {
|
} {
|
||||||
execsql { DELETE FROM x1 }
|
execsql { DELETE FROM x1 }
|
||||||
foreach row $lRow { execsql { INSERT INTO x1 VALUES($row) } }
|
foreach row $lRow { execsql { INSERT INTO x1 VALUES($row) } }
|
||||||
breakpoint
|
|
||||||
do_execsql_test 8.$tn {
|
do_execsql_test 8.$tn {
|
||||||
SELECT highlight(x1, 0, '[', ']') FROM x1 WHERE x1 MATCH 'a OR (b AND d)';
|
SELECT highlight(x1, 0, '[', ']') FROM x1 WHERE x1 MATCH 'a OR (b AND d)';
|
||||||
} $res
|
} $res
|
||||||
@ -279,4 +278,3 @@ do_execsql_test 9.3 {
|
|||||||
|
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
|
||||||
|
@ -112,4 +112,3 @@ db eval {
|
|||||||
}
|
}
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
|
||||||
|
@ -61,4 +61,3 @@ do_test 2.1...slow {
|
|||||||
} {}
|
} {}
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
|
||||||
|
@ -64,5 +64,3 @@ foreach_detail_mode $::testprefix {
|
|||||||
}
|
}
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
|
||||||
|
|
||||||
|
@ -44,16 +44,43 @@ foreach_detail_mode $::testprefix {
|
|||||||
9 "-c : a" {1 2 4}
|
9 "-c : a" {1 2 4}
|
||||||
10 "-\"c\" : a" {1 2 4}
|
10 "-\"c\" : a" {1 2 4}
|
||||||
} {
|
} {
|
||||||
breakpoint
|
|
||||||
do_execsql_test 1.$tn {
|
do_execsql_test 1.$tn {
|
||||||
SELECT rowid FROM t1($q)
|
SELECT rowid FROM t1($q)
|
||||||
} $res
|
} $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
|
finish_test
|
||||||
|
|
||||||
|
|
||||||
|
@ -143,7 +143,6 @@ do_execsql_test 4.1.1 {
|
|||||||
INSERT INTO t5 VALUES('2 4 6 8');
|
INSERT INTO t5 VALUES('2 4 6 8');
|
||||||
}
|
}
|
||||||
|
|
||||||
breakpoint
|
|
||||||
do_execsql_test 4.1.2 {
|
do_execsql_test 4.1.2 {
|
||||||
INSERT INTO t5(t5) VALUES('integrity-check');
|
INSERT INTO t5(t5) VALUES('integrity-check');
|
||||||
}
|
}
|
||||||
|
@ -66,7 +66,7 @@ foreach {tn val} {
|
|||||||
} {
|
} {
|
||||||
do_catchsql_test 3.$tn {
|
do_catchsql_test 3.$tn {
|
||||||
INSERT INTO t1(t1, rank) VALUES('rank', $val);
|
INSERT INTO t1(t1, rank) VALUES('rank', $val);
|
||||||
} {1 {SQL logic error or missing database}}
|
} {1 {SQL logic error}}
|
||||||
}
|
}
|
||||||
|
|
||||||
#-------------------------------------------------------------------------
|
#-------------------------------------------------------------------------
|
||||||
@ -110,7 +110,6 @@ do_catchsql_test 5.1 {
|
|||||||
CREATE VIRTUAL TABLE xx USING fts5(x, tokenize="porter 'ascii");
|
CREATE VIRTUAL TABLE xx USING fts5(x, tokenize="porter 'ascii");
|
||||||
} {1 {parse error in tokenize directive}}
|
} {1 {parse error in tokenize directive}}
|
||||||
|
|
||||||
breakpoint
|
|
||||||
do_catchsql_test 5.2 {
|
do_catchsql_test 5.2 {
|
||||||
CREATE VIRTUAL TABLE xx USING fts5(x, [y[]);
|
CREATE VIRTUAL TABLE xx USING fts5(x, [y[]);
|
||||||
} {0 {}}
|
} {0 {}}
|
||||||
@ -169,33 +168,33 @@ do_execsql_test 9.0 {
|
|||||||
} {}
|
} {}
|
||||||
do_catchsql_test 9.1.1 {
|
do_catchsql_test 9.1.1 {
|
||||||
INSERT INTO abc(abc, rank) VALUES('pgsz', -5);
|
INSERT INTO abc(abc, rank) VALUES('pgsz', -5);
|
||||||
} {1 {SQL logic error or missing database}}
|
} {1 {SQL logic error}}
|
||||||
do_catchsql_test 9.1.2 {
|
do_catchsql_test 9.1.2 {
|
||||||
INSERT INTO abc(abc, rank) VALUES('pgsz', 50000000);
|
INSERT INTO abc(abc, rank) VALUES('pgsz', 50000000);
|
||||||
} {1 {SQL logic error or missing database}}
|
} {1 {SQL logic error}}
|
||||||
do_catchsql_test 9.1.3 {
|
do_catchsql_test 9.1.3 {
|
||||||
INSERT INTO abc(abc, rank) VALUES('pgsz', 66.67);
|
INSERT INTO abc(abc, rank) VALUES('pgsz', 66.67);
|
||||||
} {1 {SQL logic error or missing database}}
|
} {1 {SQL logic error}}
|
||||||
|
|
||||||
do_catchsql_test 9.2.1 {
|
do_catchsql_test 9.2.1 {
|
||||||
INSERT INTO abc(abc, rank) VALUES('automerge', -5);
|
INSERT INTO abc(abc, rank) VALUES('automerge', -5);
|
||||||
} {1 {SQL logic error or missing database}}
|
} {1 {SQL logic error}}
|
||||||
do_catchsql_test 9.2.2 {
|
do_catchsql_test 9.2.2 {
|
||||||
INSERT INTO abc(abc, rank) VALUES('automerge', 50000000);
|
INSERT INTO abc(abc, rank) VALUES('automerge', 50000000);
|
||||||
} {1 {SQL logic error or missing database}}
|
} {1 {SQL logic error}}
|
||||||
do_catchsql_test 9.2.3 {
|
do_catchsql_test 9.2.3 {
|
||||||
INSERT INTO abc(abc, rank) VALUES('automerge', 66.67);
|
INSERT INTO abc(abc, rank) VALUES('automerge', 66.67);
|
||||||
} {1 {SQL logic error or missing database}}
|
} {1 {SQL logic error}}
|
||||||
do_execsql_test 9.2.4 {
|
do_execsql_test 9.2.4 {
|
||||||
INSERT INTO abc(abc, rank) VALUES('automerge', 1);
|
INSERT INTO abc(abc, rank) VALUES('automerge', 1);
|
||||||
} {}
|
} {}
|
||||||
|
|
||||||
do_catchsql_test 9.3.1 {
|
do_catchsql_test 9.3.1 {
|
||||||
INSERT INTO abc(abc, rank) VALUES('crisismerge', -5);
|
INSERT INTO abc(abc, rank) VALUES('crisismerge', -5);
|
||||||
} {1 {SQL logic error or missing database}}
|
} {1 {SQL logic error}}
|
||||||
do_catchsql_test 9.3.2 {
|
do_catchsql_test 9.3.2 {
|
||||||
INSERT INTO abc(abc, rank) VALUES('crisismerge', 66.67);
|
INSERT INTO abc(abc, rank) VALUES('crisismerge', 66.67);
|
||||||
} {1 {SQL logic error or missing database}}
|
} {1 {SQL logic error}}
|
||||||
do_execsql_test 9.3.3 {
|
do_execsql_test 9.3.3 {
|
||||||
INSERT INTO abc(abc, rank) VALUES('crisismerge', 1);
|
INSERT INTO abc(abc, rank) VALUES('crisismerge', 1);
|
||||||
} {}
|
} {}
|
||||||
@ -205,14 +204,14 @@ do_execsql_test 9.3.4 {
|
|||||||
|
|
||||||
do_catchsql_test 9.4.1 {
|
do_catchsql_test 9.4.1 {
|
||||||
INSERT INTO abc(abc, rank) VALUES('nosuchoption', 1);
|
INSERT INTO abc(abc, rank) VALUES('nosuchoption', 1);
|
||||||
} {1 {SQL logic error or missing database}}
|
} {1 {SQL logic error}}
|
||||||
|
|
||||||
do_catchsql_test 9.5.1 {
|
do_catchsql_test 9.5.1 {
|
||||||
INSERT INTO abc(abc, rank) VALUES('hashsize', 'not an integer');
|
INSERT INTO abc(abc, rank) VALUES('hashsize', 'not an integer');
|
||||||
} {1 {SQL logic error or missing database}}
|
} {1 {SQL logic error}}
|
||||||
do_catchsql_test 9.5.2 {
|
do_catchsql_test 9.5.2 {
|
||||||
INSERT INTO abc(abc, rank) VALUES('hashsize', -500000);
|
INSERT INTO abc(abc, rank) VALUES('hashsize', -500000);
|
||||||
} {1 {SQL logic error or missing database}}
|
} {1 {SQL logic error}}
|
||||||
do_catchsql_test 9.5.3 {
|
do_catchsql_test 9.5.3 {
|
||||||
INSERT INTO abc(abc, rank) VALUES('hashsize', 500000);
|
INSERT INTO abc(abc, rank) VALUES('hashsize', 500000);
|
||||||
} {0 {}}
|
} {0 {}}
|
||||||
@ -245,7 +244,7 @@ foreach {tn opt} {
|
|||||||
|
|
||||||
do_catchsql_test 12.1 {
|
do_catchsql_test 12.1 {
|
||||||
INSERT INTO t1(t1, rank) VALUES('rank', NULL);;
|
INSERT INTO t1(t1, rank) VALUES('rank', NULL);;
|
||||||
} {1 {SQL logic error or missing database}}
|
} {1 {SQL logic error}}
|
||||||
|
|
||||||
#-------------------------------------------------------------------------
|
#-------------------------------------------------------------------------
|
||||||
# errors in the 'usermerge' option
|
# errors in the 'usermerge' option
|
||||||
@ -260,8 +259,7 @@ foreach {tn val} {
|
|||||||
4 1
|
4 1
|
||||||
} {
|
} {
|
||||||
set sql "INSERT INTO tt(tt, rank) VALUES('usermerge', $val)"
|
set sql "INSERT INTO tt(tt, rank) VALUES('usermerge', $val)"
|
||||||
do_catchsql_test 13.$tn $sql {1 {SQL logic error or missing database}}
|
do_catchsql_test 13.$tn $sql {1 {SQL logic error}}
|
||||||
}
|
}
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
|
||||||
|
@ -66,5 +66,3 @@ do_execsql_test 2.1 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
|
||||||
|
|
||||||
|
@ -255,4 +255,3 @@ do_execsql_test 6.2 {
|
|||||||
|
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
|
||||||
|
@ -96,4 +96,3 @@ do_catchsql_test 3.1 {
|
|||||||
} {1 {database disk image is malformed}}
|
} {1 {database disk image is malformed}}
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
|
||||||
|
@ -269,4 +269,3 @@ do_catchsql_test 6.2 {
|
|||||||
|
|
||||||
sqlite3_fts5_may_be_corrupt 0
|
sqlite3_fts5_may_be_corrupt 0
|
||||||
finish_test
|
finish_test
|
||||||
|
|
||||||
|
@ -409,4 +409,3 @@ do_catchsql_test 9.2.2 {
|
|||||||
|
|
||||||
sqlite3_fts5_may_be_corrupt 0
|
sqlite3_fts5_may_be_corrupt 0
|
||||||
finish_test
|
finish_test
|
||||||
|
|
||||||
|
53
ext/fts5/test/fts5delete.test
Normal file
53
ext/fts5/test/fts5delete.test
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
# 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,4 +241,3 @@ do_execsql_test 5.3 {
|
|||||||
|
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
|
||||||
|
@ -63,5 +63,3 @@ foreach_detail_mode $::testprefix {
|
|||||||
|
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
|
||||||
|
|
||||||
|
@ -66,7 +66,6 @@ proc do_dlidx_test1 {tn spc1 spc2 nEntry iFirst nStep} {
|
|||||||
}
|
}
|
||||||
execsql COMMIT
|
execsql COMMIT
|
||||||
|
|
||||||
breakpoint
|
|
||||||
do_test $tn.1 {
|
do_test $tn.1 {
|
||||||
execsql { INSERT INTO t1(t1) VALUES('integrity-check') }
|
execsql { INSERT INTO t1(t1) VALUES('integrity-check') }
|
||||||
} {}
|
} {}
|
||||||
@ -124,7 +123,6 @@ proc do_dlidx_test2 {tn nEntry iFirst nStep} {
|
|||||||
do_execsql_test $tn.1 {
|
do_execsql_test $tn.1 {
|
||||||
SELECT rowid FROM t1 WHERE t1 MATCH 'b AND a'
|
SELECT rowid FROM t1 WHERE t1 MATCH 'b AND a'
|
||||||
} {1}
|
} {1}
|
||||||
breakpoint
|
|
||||||
do_execsql_test $tn.2 {
|
do_execsql_test $tn.2 {
|
||||||
SELECT rowid FROM t1 WHERE t1 MATCH 'b AND a' ORDER BY rowid DESC
|
SELECT rowid FROM t1 WHERE t1 MATCH 'b AND a' ORDER BY rowid DESC
|
||||||
} {1}
|
} {1}
|
||||||
@ -197,4 +195,3 @@ foreach v $vocab {
|
|||||||
|
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
|
||||||
|
@ -44,4 +44,3 @@ do_execsql_test 1.2 {
|
|||||||
|
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
|
||||||
|
@ -81,6 +81,3 @@ do_execsql_test 3.3 {
|
|||||||
|
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -351,4 +351,3 @@ do_faultsim_test 9.1 -faults oom-* -prep {
|
|||||||
|
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
|
||||||
|
@ -137,4 +137,3 @@ do_faultsim_test 5.0 -faults oom-* -prep {
|
|||||||
}
|
}
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
|
||||||
|
@ -110,4 +110,3 @@ do_faultsim_test 3.2 -faults oom-* -prep {
|
|||||||
|
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
|
||||||
|
@ -395,4 +395,3 @@ do_faultsim_test 14.1 -faults oom-t* -prep {
|
|||||||
}
|
}
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
|
||||||
|
@ -105,7 +105,6 @@ do_faultsim_test 3.2 -faults oom-t* -body {
|
|||||||
faultsim_test_result {0 {1 10 11 12 13 14 15 16 17 18 19 2}}
|
faultsim_test_result {0 {1 10 11 12 13 14 15 16 17 18 19 2}}
|
||||||
}
|
}
|
||||||
|
|
||||||
breakpoint
|
|
||||||
do_execsql_test 3.3.0 {
|
do_execsql_test 3.3.0 {
|
||||||
SELECT * FROM tv2;
|
SELECT * FROM tv2;
|
||||||
} {
|
} {
|
||||||
@ -130,4 +129,3 @@ do_faultsim_test 3.3 -faults oom-t* -body {
|
|||||||
|
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
|
||||||
|
@ -280,7 +280,6 @@ do_faultsim_test 5.4 -faults oom* -prep {
|
|||||||
|
|
||||||
#-------------------------------------------------------------------------
|
#-------------------------------------------------------------------------
|
||||||
catch { db close }
|
catch { db close }
|
||||||
breakpoint
|
|
||||||
do_faultsim_test 6 -faults oom* -prep {
|
do_faultsim_test 6 -faults oom* -prep {
|
||||||
sqlite_orig db test.db
|
sqlite_orig db test.db
|
||||||
sqlite3_db_config_lookaside db 0 0 0
|
sqlite3_db_config_lookaside db 0 0 0
|
||||||
@ -292,4 +291,3 @@ do_faultsim_test 6 -faults oom* -prep {
|
|||||||
db close
|
db close
|
||||||
}
|
}
|
||||||
finish_test
|
finish_test
|
||||||
|
|
||||||
|
@ -116,4 +116,3 @@ do_faultsim_test 2.2 -faults oom-* -body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
|
||||||
|
@ -82,4 +82,3 @@ do_faultsim_test 4 -faults oom-* -prep {
|
|||||||
|
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
|
||||||
|
@ -153,4 +153,3 @@ do_faultsim_test 6 -faults oom-* -body {
|
|||||||
} ;# foreach_detail_mode...
|
} ;# foreach_detail_mode...
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
|
||||||
|
@ -61,4 +61,3 @@ do_faultsim_test 2 -faults oom* -prep {
|
|||||||
faultsim_test_result {0 {1 2}}
|
faultsim_test_result {0 {1 2}}
|
||||||
}
|
}
|
||||||
finish_test
|
finish_test
|
||||||
|
|
||||||
|
@ -78,6 +78,57 @@ do_faultsim_test 2.4 -faults oom* -body {
|
|||||||
faultsim_test_result {0 {{3 2} {2 3}}}
|
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
|
finish_test
|
||||||
|
|
||||||
|
87
ext/fts5/test/fts5faultD.test
Normal file
87
ext/fts5/test/fts5faultD.test
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
# 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,4 +40,3 @@ do_test 1.1 {
|
|||||||
|
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
|
||||||
|
@ -90,4 +90,3 @@ do_catchsql_test 4.1 {
|
|||||||
} {1 {fts5: syntax error near "`"}}
|
} {1 {fts5: syntax error near "`"}}
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
|
||||||
|
@ -121,7 +121,6 @@ foreach_detail_mode $testprefix {
|
|||||||
}
|
}
|
||||||
|
|
||||||
execsql { CREATE VIRTUAL TABLE t2 USING fts5(x, detail=%DETAIL%) }
|
execsql { CREATE VIRTUAL TABLE t2 USING fts5(x, detail=%DETAIL%) }
|
||||||
breakpoint
|
|
||||||
execsql {
|
execsql {
|
||||||
INSERT INTO t2 VALUES($small || ' ' || $big);
|
INSERT INTO t2 VALUES($small || ' ' || $big);
|
||||||
}
|
}
|
||||||
@ -130,4 +129,3 @@ breakpoint
|
|||||||
} ;# foreach_detail_mode
|
} ;# foreach_detail_mode
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
|
||||||
|
@ -210,4 +210,3 @@ foreach {tn pgsz} {
|
|||||||
}
|
}
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
|
||||||
|
72
ext/fts5/test/fts5lastrowid.test
Normal file
72
ext/fts5/test/fts5lastrowid.test
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
# 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
|
43
ext/fts5/test/fts5leftjoin.test
Normal file
43
ext/fts5/test/fts5leftjoin.test
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
# 2014 June 17
|
||||||
|
#
|
||||||
|
# The author disclaims copyright to this source code. In place of
|
||||||
|
# a legal notice, here is a blessing:
|
||||||
|
#
|
||||||
|
# May you do good and not evil.
|
||||||
|
# May you find forgiveness for yourself and forgive others.
|
||||||
|
# May you share freely, never taking more than you give.
|
||||||
|
#
|
||||||
|
#*************************************************************************
|
||||||
|
# This file implements regression tests for SQLite library. The
|
||||||
|
# focus of this script is testing the FTS5 module.
|
||||||
|
#
|
||||||
|
|
||||||
|
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||||
|
set testprefix fts5leftjoin
|
||||||
|
|
||||||
|
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||||
|
ifcapable !fts5 {
|
||||||
|
finish_test
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
do_execsql_test 1.0 {
|
||||||
|
CREATE VIRTUAL TABLE vt USING fts5(x);
|
||||||
|
INSERT INTO vt VALUES('abc');
|
||||||
|
INSERT INTO vt VALUES('xyz');
|
||||||
|
|
||||||
|
CREATE TABLE t1(a INTEGER PRIMARY KEY);
|
||||||
|
INSERT INTO t1 VALUES(1), (2);
|
||||||
|
}
|
||||||
|
|
||||||
|
do_execsql_test 1.1 {
|
||||||
|
SELECT * FROM t1 LEFT JOIN (
|
||||||
|
SELECT rowid AS rrr, * FROM vt WHERE vt MATCH 'abc'
|
||||||
|
) ON t1.a = rrr
|
||||||
|
} {1 1 abc 2 {} {}}
|
||||||
|
|
||||||
|
do_execsql_test 1.2 {
|
||||||
|
SELECT * FROM t1 LEFT JOIN vt ON (vt MATCH 'abc')
|
||||||
|
} {1 abc 2 abc}
|
||||||
|
|
||||||
|
finish_test
|
@ -472,7 +472,7 @@ do_execsql_test 12.1 {
|
|||||||
#
|
#
|
||||||
reset_db
|
reset_db
|
||||||
proc xyz {} {}
|
proc xyz {} {}
|
||||||
db func fts5 -argcount 0 xyz
|
db func fts5 -argcount 1 xyz
|
||||||
do_test 13.1 {
|
do_test 13.1 {
|
||||||
list [catch { sqlite3_fts5_register_matchinfo db } msg] $msg
|
list [catch { sqlite3_fts5_register_matchinfo db } msg] $msg
|
||||||
} {1 SQLITE_ERROR}
|
} {1 SQLITE_ERROR}
|
||||||
@ -492,4 +492,3 @@ do_catchsql_test 14.2 {
|
|||||||
} {1 {unrecognized matchinfo flag: d}}
|
} {1 {unrecognized matchinfo flag: d}}
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
|
||||||
|
@ -241,4 +241,3 @@ do_execsql_test 6.3 {
|
|||||||
|
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
|
||||||
|
@ -55,4 +55,3 @@ do_execsql_test 1.2 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
|
||||||
|
@ -45,4 +45,3 @@ do_multiclient_test tn {
|
|||||||
};# do_multiclient_test
|
};# do_multiclient_test
|
||||||
};# foreach_detail_mode
|
};# foreach_detail_mode
|
||||||
finish_test
|
finish_test
|
||||||
|
|
||||||
|
@ -68,4 +68,3 @@ do_near_test 1.25 "a b c d e f g h i" { NEAR(i a+b+c+d b+c, 4) } 0
|
|||||||
|
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
|
||||||
|
@ -178,4 +178,3 @@ do_execsql_test 4.3.1 {
|
|||||||
do_test 4.2.2 { fts5_level_segs ttt } {3}
|
do_test 4.2.2 { fts5_level_segs ttt } {3}
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
|
||||||
|
@ -106,4 +106,3 @@ foreach {tn nStep} {
|
|||||||
do_test 2.$tn.6 { fts5_segcount t1 } 1
|
do_test 2.$tn.6 { fts5_segcount t1 } 1
|
||||||
}
|
}
|
||||||
finish_test
|
finish_test
|
||||||
|
|
||||||
|
@ -116,4 +116,3 @@ do_execsql_test 2.0 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ do_eqp_test 1.1 {
|
|||||||
SELECT * FROM t1, f1 WHERE f1 MATCH t1.x
|
SELECT * FROM t1, f1 WHERE f1 MATCH t1.x
|
||||||
} {
|
} {
|
||||||
0 0 0 {SCAN TABLE t1}
|
0 0 0 {SCAN TABLE t1}
|
||||||
0 1 1 {SCAN TABLE f1 VIRTUAL TABLE INDEX 1:}
|
0 1 1 {SCAN TABLE f1 VIRTUAL TABLE INDEX 65537:}
|
||||||
}
|
}
|
||||||
|
|
||||||
do_eqp_test 1.2 {
|
do_eqp_test 1.2 {
|
||||||
@ -43,7 +43,7 @@ do_eqp_test 1.2 {
|
|||||||
do_eqp_test 1.3 {
|
do_eqp_test 1.3 {
|
||||||
SELECT * FROM f1 WHERE f1 MATCH ? ORDER BY ff
|
SELECT * FROM f1 WHERE f1 MATCH ? ORDER BY ff
|
||||||
} {
|
} {
|
||||||
0 0 0 {SCAN TABLE f1 VIRTUAL TABLE INDEX 1:}
|
0 0 0 {SCAN TABLE f1 VIRTUAL TABLE INDEX 65537:}
|
||||||
0 0 0 {USE TEMP B-TREE FOR ORDER BY}
|
0 0 0 {USE TEMP B-TREE FOR ORDER BY}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,4 +64,3 @@ do_eqp_test 1.5 {
|
|||||||
|
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
|
||||||
|
@ -11803,4 +11803,3 @@ foreach {in out} $test_vocab {
|
|||||||
|
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
|
||||||
|
@ -67,4 +67,3 @@ foreach {in out} $test_vocab {
|
|||||||
|
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
#
|
#
|
||||||
#***********************************************************************
|
#***********************************************************************
|
||||||
#
|
#
|
||||||
# This file containst tests focused on prefix indexes.
|
# This file contains tests focused on prefix indexes.
|
||||||
#
|
#
|
||||||
|
|
||||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||||
@ -341,5 +341,3 @@ foreach {tn create} {
|
|||||||
}
|
}
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
|
||||||
|
|
||||||
|
@ -79,5 +79,3 @@ for {set tn 1 ; set pgsz 64} {$tn<32} {incr tn; incr pgsz 16} {
|
|||||||
|
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
|
||||||
|
|
||||||
|
@ -90,6 +90,7 @@ do_test 2.7 {
|
|||||||
execsql { SELECT rowid FROM tt('a') ORDER BY rank; } db
|
execsql { SELECT rowid FROM tt('a') ORDER BY rank; } db
|
||||||
} {1 3 2}
|
} {1 3 2}
|
||||||
|
|
||||||
|
db2 close
|
||||||
|
|
||||||
#--------------------------------------------------------------------------
|
#--------------------------------------------------------------------------
|
||||||
# At one point there was a problem with queries such as:
|
# At one point there was a problem with queries such as:
|
||||||
@ -151,4 +152,3 @@ do_execsql_test 4.1 {
|
|||||||
|
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
|
||||||
|
@ -64,4 +64,3 @@ do_catchsql_test 2.2 {
|
|||||||
INSERT INTO nc(nc) VALUES('rebuild');
|
INSERT INTO nc(nc) VALUES('rebuild');
|
||||||
} {1 {'rebuild' may not be used with a contentless fts5 table}}
|
} {1 {'rebuild' may not be used with a contentless fts5 table}}
|
||||||
finish_test
|
finish_test
|
||||||
|
|
||||||
|
@ -149,4 +149,3 @@ do_test 4.3 {
|
|||||||
|
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
|
||||||
|
@ -216,4 +216,3 @@ do_execsql_test 6.2 {
|
|||||||
|
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
|
||||||
|
@ -411,7 +411,6 @@ do_catchsql_test 19.2 {
|
|||||||
|
|
||||||
#-------------------------------------------------------------------------
|
#-------------------------------------------------------------------------
|
||||||
reset_db
|
reset_db
|
||||||
breakpoint
|
|
||||||
do_execsql_test 20.0 {
|
do_execsql_test 20.0 {
|
||||||
CREATE VIRTUAL TABLE x1 USING fts5(x);
|
CREATE VIRTUAL TABLE x1 USING fts5(x);
|
||||||
INSERT INTO x1(x1, rank) VALUES('pgsz', 32);
|
INSERT INTO x1(x1, rank) VALUES('pgsz', 32);
|
||||||
|
@ -332,7 +332,41 @@ do_execsql_test 16.0 {
|
|||||||
DELETE FROM t2;
|
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}
|
#db eval {SELECT rowid, fts5_decode_none(rowid, block) aS r FROM t2_data} {puts $r}
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
|
||||||
|
@ -116,4 +116,3 @@ do_execsql_test 4.6 {
|
|||||||
|
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
|
||||||
|
@ -152,7 +152,7 @@ foreach {tn expr res} {
|
|||||||
1 {abc} {"abc"}
|
1 {abc} {"abc"}
|
||||||
2 {one} {"one"|"i"|"1"}
|
2 {one} {"one"|"i"|"1"}
|
||||||
3 {3} {"3"|"iii"|"three"}
|
3 {3} {"3"|"iii"|"three"}
|
||||||
4 {3*} {"3"|"iii"|"three" *}
|
4 {3*} {"3" *}
|
||||||
} {
|
} {
|
||||||
do_execsql_test 4.1.$tn {
|
do_execsql_test 4.1.$tn {
|
||||||
SELECT fts5_expr($expr, 'tokenize=tclnum')
|
SELECT fts5_expr($expr, 'tokenize=tclnum')
|
||||||
@ -421,4 +421,3 @@ do_execsql_test 7.1.2 {
|
|||||||
} ;# foreach_detail_mode
|
} ;# foreach_detail_mode
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user